来自visual studio的我的MAP文件中的函数地址(Rva + Base)与我在调试器中看到的(或者当我手动检查我的堆栈帧时)不匹配。
导致这种情况的原因是什么?
/A.B。
答案 0 :(得分:2)
可执行文件或DLL中存在问题吗?
如果是DLL,它的首选加载地址是什么?如果这与任何其他DLL发生冲突,那么它将被加载器重新定位,这可能会导致您看到的内容。
作为构建过程的一部分,您应该确保所有DLL都已重新定义(有一个工具来执行此操作),以便它们的地址空间不会发生冲突(这会释放一些页面文件空间以及改善加载时间)。
答案 1 :(得分:1)
除非在链接时指定/ FIXED命令行选项,否则可以重定位exe和dll。我使用以下方法确定真实地址以确定我的exe加载位置,以便我可以计算映射文件的偏移量。
static void KnownFunctionAddress(){}
...
// check an address of a known function
// and compare this to the value read from the map file
intptr_t CheckRelocationOffset(MapFile map)
{
intptr_t mapAddress = map.PhysicalAddress("?KnownFunctionAddress@@YAXXZ");
intptr_t realAddress = (intptr_t)KnownFunctionAddress;
return realAddress-mapAddress;
}
答案 2 :(得分:0)
当您在调试器中并单步执行代码时,是否可以检查代码地址是否在“模块”窗口中看到的范围内?有时,同一段代码可能存在于几个相同/不同名称的模块中。
确定包含代码的“模块”后,使用“模块”窗口中的基址来到达(通过减去)DLL入口点地址。
最后,还有入口跳转表(trampoline)的效果,它是一种可以在编译时或运行时添加的函数调用间接。因此,“入口点”地址可能是烟雾屏幕,并且与功能体的地址不匹配。
(我对DLL结构的理解是有限的,所以我的答案可能不准确。)
答案 3 :(得分:0)
由于某种原因,我无法直接回复Suma的回复,但您也可以执行以下操作:
extern "C" struct IMAGE_DOS_HEADER __ImageBase; // On platforms other than Win32/Win64, this MAY be a different header type...
...
printf_s("base: %p", &__ImageBase);
__ ImageBase由链接器(至少VC ++)定义,并且其地址将为您提供模块的基地址(EXE / DLL),即使它在运行时重新定位。
还有
printf_s("calling module's base: %p\n", GetModuleHandle(NULL));
它可以给你相同的基地址值...但GetModuleHandle还有更多的警告(加上它需要windows.h)所以我建议只坚持__ImageBase。
与其他人提到的一样,您的问题可能与Windows重新定位模块有关。如果模块文件中没有.reloc部分,那么该文件不可重定位,在这种情况下,就像你遇到蹦床或类似rwong建议的那样。