问题
I'm struggling with mapping addresses to their symbols for debugging purposes (getting the callstack). The MS dbghelp.dll can tell the symbol from an address (see SymFromAddr
, MSDN). However, it doesn't work and I wonder how this could ever work, because addresses seem to change with every run of the program:
#include <iostream>
void Foo() {}
int _tmain(int argc, _TCHAR* argv[])
{
const long unsigned int addr = reinterpret_cast<long unsigned int>(&Foo);
std::cout << "Address: " << std::hex << addr << std::endl;
return 0;
}
Output:
D:\dev\Sandbox\Debug>Sandbox.exe
Address: 901320
D:\dev\Sandbox\Debug>Sandbox.exe
Address: ce1320
D:\dev\Sandbox\Debug>Sandbox.exe
Address: 3a1320
D:\dev\Sandbox\Debug>Sandbox.exe
Address: 3f1320
How could a different program ever read address like from a stacktrace and map it to functions? This sounds like magic to me. I didn't find anything in the linked documentation which says I would have to subtract something from the address or whatever.
In my understanding since we overcome the real-mode every process has a virtual memory space anyway, so no need to roll the dice for a load address any more. I would understand uncertainties of absolute address in case of DLLs, but not the main executable.
Tried on Win7 with VS2008.
回答1:
Address Space Layout Randomization
回答2:
Because your code is compiled to use Address Space Layout Randomization, which makes code less vulnerable to attacks from "StackOverflows".
If you really want to change that, there is a linker option for that.
回答3:
There is a security feature that randomises some addresses, so a potential attacker can not exploit a known fixed relative position of things.
回答4:
It's ASLR in action, as others have already mentioned.
Looks like what you need to do is to specify the image base for your executable when calling SymLoadModuleEx(). It's the BaseOfDll
parameter.
I don't know where exactly it's stored in the crash dump (if that's something that that other program has to work with), but a running program can obtain its own image base address using GetModuleHandle() (discussed here).
You probably want to save the names and base addresses of all the DLLs loaded into the process as well, not just those of the EXE itself.
来源:https://stackoverflow.com/questions/16214502/why-does-the-address-of-a-function-change-with-every-run