Here's a simplified version of some code I'm working with right now:
int Do_A_Thing(void)
{
return(42);
}
void Some_Function(void)
{
int (*fn_do_thing)(void) = Do_A_Thing;
fn_do_thing()开发者_JAVA百科;
}
When I compile this in xcode 4.1, the assembler it generates sets the fn_do_thing variable like so:
0x2006: calll 0x200b ;
0x200b: popl %eax ; get EIP
0x200c: movl 1333(%eax), %eax
I.e. it generates a relative address for the place to find the Do_A_Thing function - "current instruction plus 1333", which according to the map file is a "non-lazy pointer" to the function.
When I compile similar code on Windows with Visual Studio, windows generates a fixed address instead of doing it relatively like this. If Do_A_Thing lives at, for example, 0x40050914, it just sets fn_do_thing to 0x40050914. By contrast, xcode sets it to "where I am + some offset".
Is there any way to make xcode generate an absolute address to set the function pointer to, like visual studio does? Or is there some reason that wouldn't work? I have noticed that every time I run the program, the Do_A_Thing function (and all other functions) seem to load at a different address.
You're looking at position independent code (more specifically Position Independent Executable) in action. This, as you noticed, allows the OS to load the binary anywhere in memory, which provides numerous security improvements for potentially insecure code.
You can disable it via removing a linker option in XCode (-Wl,-pie
).
Note that on x86_64 (amd64), instructions can operate relative to the instruction pointer, which improves the efficiency of this technique (and makes it basically "free" in performance cost).
精彩评论