函数调用的奇怪间接级别 [英] strange level of indirection of a function call

查看:29
本文介绍了函数调用的奇怪间接级别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一些低级代码,我注意到函数调用的一些不必要的间接级别,我只是不明白该间接的原因是什么.以下是显示该行为的虚拟代码:

__declspec(noinline) int get_alignment(void * ptr){返回 1;}__declspec(noinline) int test123(){字符缓冲区[123];返回 get_alignment(buf);}

然后,当我以 asm 模式(Ctrl+F11)在调试器中单步执行函数 test() 中的代码时,我看到:

<前>__declspec(noinline) int test123(){0041FA70 sub esp,7Ch字符缓冲区[123];返回 get_alignment(buf);0041FA73 lea eax,[esp]0041FA76 推eax0041FA77 调用 get_alignment (40A38Fh)}...获取对齐:0040A38F jmp get_alignment (41FA60h)...__declspec(noinline) int get_alignment(void * ptr){返回 1;0041FA60 mov eax,1}

所以,问题在于额外的间接级别:获取对齐:0040A38F jmp get_alignment (41FA60h)

这是关于WTF的吗?!我只是不明白,它不是从 dll 导入的函数,它是在可执行文件中定义的本地函数.这个可执行文件经过各种优化编译(链接时间代码生成除外).如果我将 static 添加到该 get_alignment 的声明中,那么额外的间接性就会消失.但我不是在寻找修复",我只是想了解为什么会有额外的跳跃!

在我的真实应用中,我实际上使用了一个用 .asm 文件编写的函数,但我不明白为什么会生成额外的跳转.似乎如果我在 C 模式(不是 C++)中编译我的代码,那么我就看不到那种间接级别了...

谁能解释一下这种奇怪的行为?

谢谢!

解决方案

这是链接器的/INCREMENTAL 选项的副作用.它启用增量链接和编辑 + 继续.在程序运行时编辑代码时使用跳转.替换函数被编译到另一个地址,并且 jmp 目标被修补以指向新函数.增量链接也使用它来避免从头开始重新创建二进制图像.

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!

解决方案

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.

这篇关于函数调用的奇怪间接级别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆