Karim Agha
Karim Agha

Reputation: 3625

Inconsistent function pointer address with what the debugger shows

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

Upvotes: 2

Views: 521

Answers (1)

Necrolis
Necrolis

Reputation: 26171

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.

Upvotes: 4

Related Questions