Address of function is not actual code address
Asked Answered
S

3

24

Debugging some code in Visual Studio 2008 (C++), I noticed that the address in my function pointer variable is not the actual address of the function itself. This is an extern "C" function.

int main() {
   void (*printaddr)(const char *) = &print; // debug shows printaddr == 0x013C1429

}

Address: 0x013C4F10
void print() {
  ...
}

The disassembly of taking the function address is:

   void (*printaddr)(const char *) = &print;
013C7465 C7 45 BC 29 14 3C 01 mov         dword ptr [printaddr],offset print (13C1429h) 

EDIT: I viewed the code at address 013C4F10 and the compiler is apparently inserting a "jmp" instruction at that address.

013C4F10 E9 C7 3F 00 00   jmp         print (013C1429h) 

There is actually a whole jump table of every method in the .exe.

Can someone expound on why it does this? Is it a debugging "feature" ?

Spot answered 21/3, 2010 at 0:35 Comment(8)
Hmm, what is telling you the address of print is 0x013C4F10 ? Looking at the disassembly it seems like the address of print is indeed 0x013C1429 and that's the value being stored in printaddrFetid
The disassembly in Visual Studio shows print at address 0x013C4F10Spot
@Martin: When I switch to release mode the jump table goes away and the address is indeed the actual function address.Spot
There's a book called 'Linkers and Loaders' (amazon.com/Linkers-Kaufmann-Software-Engineering-Programming/dp/…) which explains about this. It's a while since I read it, and the MS environment wasn't of primary interest - but there is indeed a jump table which allows for dynamic loading of shared libraries.Quirites
it's probably to do with the interaction between the linker, and the need to call code in DLLs This article talks about it, I'm not 100% sure how it applied to your example but it seems like it might help you understand msdn.microsoft.com/en-us/library/aa271769(VS.60).aspxMilone
@mrjoltcola: I upvoted @Martin's original comment because it asked a sensible question about information that was lacking in your question.Lanny
@Jonathan: I happen to have that book. I will check it. Thanks. @Troubadour: The information wasn't lacking, it just wasn't in the format that perhaps you trusted. The address I gave was a cut-and-paste from the disassembly session, so you had to trust me. :)Spot
If the problem is 'incremental linking', I don't think the book covers that. OTOH, I am not convinced the problem is incremental linking - but I've not gone and read the referenced chunk of the MSDN.Quirites
K
21

That is caused by 'Incremental Linking'. If you disable that in your compiler/linker settings the jumps will go away.

http://msdn.microsoft.com/en-us/library/4khtbfyf(VS.80).aspx

Kos answered 21/3, 2010 at 16:15 Comment(0)
E
7

I'm going to hazard a guess here, but it's possibly to enable Edit-and-Continue.

Say you need to recompile that function, you only need to change the indirection table, not all callers. That would dramatically reduce the amount of work to do when the Edit-and-Continue feature is being exercised.

Easygoing answered 21/3, 2010 at 13:11 Comment(4)
sounds reasonable, but then the function pointer printaddr would still point to the old (non-edited) print function... perhaps there's a bug in the debugger? :)Fetid
@Martin: no, the function pointer always points to the jump table, so that when edit and continue recompiles the function, only the jump table gets modified. The function pointer value does not change, ever. That's the beauty of it, really. Imagine your code stores a function pointer somewhere in memory. Edit and Continue has no way to update that. But by pointing it to a jump table, modifying the jump table catches all the potential usages of the function at once.Easygoing
that's not what the disassembly above looks like since the pointer isn't set to point at the jump table but directly to the function insteadFetid
@Martin: Doh. I guess I wanted to believe too much. Thanks for pointing it out.Easygoing
S
2

The compiler is inserting a "jmp" instruction at that address to the real method.

013C4F10 E9 C7 3F 00 00   jmp         print (013C1429h)

There is actually a whole jump table of every method in the .exe.

It is a Debugging feature. When I switch to release mode the jump table goes away and the address is indeed the actual function address.

Spot answered 21/3, 2010 at 1:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.