2
votes

I'm writing some low level code and I noticed some unnecessary level of indirection of a function call and I simply don't get what's the reason for that indirection. Here's dummy code that reveals that behavior:

__declspec(noinline) int get_alignment(void * ptr)
{
    return 1;
}

__declspec(noinline) int test123()
{
    char buf[123];
    return get_alignment(buf);
}

Then, when I step through the code inside function test() in debugger in asm mode (Ctrl+F11) I see this:

__declspec(noinline) int test123()
{
0041FA70  sub         esp,7Ch 
    char buf[123];
    return get_alignment(buf);
0041FA73  lea         eax,[esp] 
0041FA76  push        eax  
0041FA77  call        get_alignment (40A38Fh) 
}
...
get_alignment:
0040A38F  jmp         get_alignment (41FA60h) 
...
__declspec(noinline) int get_alignment(void * ptr)
{
    return 1;
0041FA60  mov         eax,1 
}

So, the question is about that extra level of indirection: get_alignment: 0040A38F jmp get_alignment (41FA60h)

WTF is that about?! I just don't get it, it's not imported function from dll, it's a local function defined in executable. This executable compiled with all kinds of optimizations (except link time code generation). If I add static to the declaration of that get_alignment, then that extra indirection disappears. But I'm not looking for a "fix", I just wanted to understand why is that extra jump is there at all!

In my real app I actually use a function written in .asm file and I just don't get why there is extra jump generated. It seems that If I compile my code in C-mode (not C++) then I don't see that level of indirection anymore...

anybody can shed some light on that weird behavior?

Thank you!

3

3 Answers

2
votes

You probably have incremental linking enabled. An incrementally linked module "May contain jump thunks to handle relocation of functions to new addresses." http://msdn.microsoft.com/en-US/library/4khtbfyf(v=VS.80).aspx

2
votes

This is a side-effect of the linker's /INCREMENTAL option. Which enables incremental linking and Edit + Continue. The jump is used when you edit the code while the program is running. The replacement function is compiled to another address and the jmp target is patched to point to the new function. Incremental linking uses it as well to avoid having to recreate the binary image from scratch.

1
votes

In short, in my case incremental linking was enabled because I didn't explicitly disabled it for my build. In general linker options incremental linking has be be disabled to avoid that extra jump (/INCREMENTAL:NO option)