函数指针地址与调试器显示的不一致
首先 - 如果这个问题表现出我的无知或者我不知道某些事情,我深表歉意。 我正在尝试做一些涉及读取函数地址下的指令的事情,并且我已经通过检查编译器生成的 .pdb 文件来设法获取函数生成的代码大小。
但有一些事情让我感到困惑,请看下面的例子:
int function(int a, int b)
{
return a + b;
}
int main(int argc, char* argv[])
{
// (...)
void* address = &function;
function(10, 20);
// (...)
}
对于在调试器下的特定运行,我将 0x00c011f4 存储在 void* 地址中,并且 VS 的反汇编窗口相应地显示:
int main(int argc, char* argv[])
{
00C04B00 push ebp
00C04B01 mov ebp,esp
00C04B03 sub esp,178h
00C04B09 push ebx
00C04B0A push esi
00C04B0B push edi
00C04B0C lea edi,[ebp-178h]
00C04B12 mov ecx,5Eh
00C04B17 mov eax,0CCCCCCCCh
00C04B1C rep stos dword ptr es:[edi]
void* address = &function;
00C04B1E mov dword ptr [address],offset function (0C011F4h)
function(10, 20);
00C04B25 push 14h
00C04B27 push 0Ah
00C04B29 call function (0C011F4h)
00C04B2E add esp,8
根据 00C04B1E 下的指令,对应的地址function
的开头位于 0C011F4 下 - 这正是存储在 void* 地址中的内容。
现在使用调试器单步执行并跳转到 function(int, int) 给出以下反汇编结果:
int function(int a, int b)
{
00C019C0 push ebp
00C019C1 mov ebp,esp
00C019C3 sub esp,0C0h
00C019C9 push ebx
00C019CA push esi
00C019CB push edi
00C019CC lea edi,[ebp-0C0h]
00C019D2 mov ecx,30h
00C019D7 mov eax,0CCCCCCCCh
00C019DC rep stos dword ptr es:[edi]
return a + b;
00C019DE mov eax,dword ptr [a]
00C019E1 add eax,dword ptr [b]
}
00C019E4 pop edi
00C019E5 pop esi
00C019E6 pop ebx
00C019E7 mov esp,ebp
00C019E9 pop ebp
00C019EA ret
这里 function(int, int) 的请求位于 0x00C019C0 下。这是为什么?相差 1996 个字节。我试图找到任何相关性,但我认为我在这里遗漏了一些基本的东西。有人可以告诉我为什么这两个地址不同吗?
另外,当我复制 void* 地址 (0C011F4) 指向的区域时,我没有获得与 function(int, int) 下的 asm 指令相对应的机器代码。
提前致谢!
环境:Windows x64、VC10
First of all - I apologize if this question shows ignorance or I'm not aware of something.
I'm trying to do something that involves reading the instructions under a function's address and I've already managed to get function's generated code size by examining the .pdb file generated by the compiler.
But there is something that confuses me, look at the following example:
int function(int a, int b)
{
return a + b;
}
int main(int argc, char* argv[])
{
// (...)
void* address = &function;
function(10, 20);
// (...)
}
For a particular run under a debugger I've got 0x00c011f4 stored in void* address and VS's dissassembly window was showing accordingly:
int main(int argc, char* argv[])
{
00C04B00 push ebp
00C04B01 mov ebp,esp
00C04B03 sub esp,178h
00C04B09 push ebx
00C04B0A push esi
00C04B0B push edi
00C04B0C lea edi,[ebp-178h]
00C04B12 mov ecx,5Eh
00C04B17 mov eax,0CCCCCCCCh
00C04B1C rep stos dword ptr es:[edi]
void* address = &function;
00C04B1E mov dword ptr [address],offset function (0C011F4h)
function(10, 20);
00C04B25 push 14h
00C04B27 push 0Ah
00C04B29 call function (0C011F4h)
00C04B2E add esp,8
According to the instruction under 00C04B1E, the address that corresponds to the beginning of function
is under 0C011F4 - which is exactly what gets stored in void* address.
Now stepping through with the debugger and following the jump to function(int, int) gives me the following disassembly:
int function(int a, int b)
{
00C019C0 push ebp
00C019C1 mov ebp,esp
00C019C3 sub esp,0C0h
00C019C9 push ebx
00C019CA push esi
00C019CB push edi
00C019CC lea edi,[ebp-0C0h]
00C019D2 mov ecx,30h
00C019D7 mov eax,0CCCCCCCCh
00C019DC rep stos dword ptr es:[edi]
return a + b;
00C019DE mov eax,dword ptr [a]
00C019E1 add eax,dword ptr [b]
}
00C019E4 pop edi
00C019E5 pop esi
00C019E6 pop ebx
00C019E7 mov esp,ebp
00C019E9 pop ebp
00C019EA ret
Here the begging of function(int, int) is under 0x00C019C0. Why is that? that's 1996 bytes apart. I've tried to find any correlation but I think that I'm missing something fundamental here. Could someone please tell me why these two addresses are different?
Also when I copy the area pointed by void* address (0C011F4) I don't get the machine code that corresponds to the asm instructions that are under function(int, int).
Thanks in advance!
Env: Windows x64, VC10
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是因为您在调试模式下编译了二进制文件,导致 MSVC 在调用和实际函数之间放置中间跳转(供“编辑并继续”使用)。因此,您获得的地址(和程序集)是指向您的函数的跳转地址。
您可以通过使用发布模式或禁用“编辑和编辑”来删除它。继续。或者,您可以采取长路线并仅反汇编跳转(它应该是 32 位相对跳转),并使用跳转所需的相对位移来调整地址。
This is cause you have compiled the binary in Debug mode, causing MSVC to put an intermediary jump between the call and the actual function (for use by Edit & Continue). So the address that you are getting (and the assembly) is the address of the jump that points to your function.
You can remove this by either using release mode or disabling Edit & Continue. Alternatively you can take the long route and just disassemble the jump (it should be a 32-bit relative jump), and adjust the address using the relative displacement the jump would you.