【发布时间】:2008-10-08 09:52:37
【问题描述】:
Visual Studio 的 MAP 文件中的函数地址 (Rva+Base) 与我在调试器中看到的地址(或者当我手动检查堆栈帧时)不匹配。
这可能是什么原因造成的?
/A.B.
【问题讨论】:
标签: c++ visual-studio debugging
Visual Studio 的 MAP 文件中的函数地址 (Rva+Base) 与我在调试器中看到的地址(或者当我手动检查堆栈帧时)不匹配。
这可能是什么原因造成的?
/A.B.
【问题讨论】:
标签: c++ visual-studio debugging
问题出在可执行文件还是 DLL 中?
如果它是一个 DLL,它的首选加载地址是什么?如果这与任何其他 DLL 发生冲突,那么加载程序将重新设置它的基础,这可能会导致您看到的内容。
作为构建过程的一部分,您应该确保所有 DLL 都被重新定位(有一个工具可以做到这一点),以便它们的地址空间不会发生冲突(这会释放一些页面文件空间并缩短加载时间)。
【讨论】:
exe 和 dll 都可以重定位,除非您在链接时指定 /FIXED 命令行选项。我使用以下方法来确定真实地址来确定我的 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;
}
【讨论】:
当您在调试器中并单步执行代码时,您能否检查代码地址是否在您在“模块”窗口中看到的范围内?有时,同一段代码可能存在于多个相同/不同名称的模块中。
一旦您识别出包含代码的“模块”,使用“模块”窗口中的基地址来(通过减去)DLL 入口点地址。
最后还有入口跳转表(trampoline)的效果,这是一种函数调用间接,可以在编译时或运行时添加。因此,“入口点”地址可能是一个烟幕,与函数体的地址不匹配。
(我对DLL结构的理解有限,所以我的回答可能有不准确之处。)
【讨论】:
由于某种原因,我无法直接回复 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 建议的那样。
【讨论】: