为什么有些函数位置密集,而另一些函数则用 int 3 指令对齐和填充?
我使用 Visual C++ 10 编译以下程序:
include <Windows.h>
int _tmain(int /*argc*/, _TCHAR* /*argv*/[])
{
Sleep( 0 );
return 0;
}
并研究反汇编。程序映像中有很多C++运行时函数。有些函数位置密集 - 某些函数的ret
后面跟着下一个函数的第一条指令。例如,
` __declspec(noreturn) void __cdecl __report_gsfailure(ULONGLONG StackCookie)`
以地址 004013B7
结束(有一条 ret
指令),而地址 004013B8
包含一些调试器无法找到的其他函数来源。同时
BOOL __cdecl _ValidateImageBase(PBYTE pImageBase)
在地址 00401554
结束,但下一个函数
PIMAGE_SECTION_HEADER __cdecl _FindPESection( PBYTE pImageBase, DWORD_PTR rva )
从地址 00401560
开始,并且后两个地址之间有多个 int 3
指令。
为什么有区别?为什么有的函数放得很密,有的函数却用不可达的代码隔开?
I compile the following program with Visual C++ 10:
include <Windows.h>
int _tmain(int /*argc*/, _TCHAR* /*argv*/[])
{
Sleep( 0 );
return 0;
}
and look into disassembly. There're lots of C++ runtime functions in the program image. Some functions are located densely - ret
of some function is followed by the first instruction of the next function. For example,
` __declspec(noreturn) void __cdecl __report_gsfailure(ULONGLONG StackCookie)`
ends at address 004013B7
(there's a ret
instruction) and address 004013B8
contains some other function for which the debugger can't find the source. Meanwhile
BOOL __cdecl _ValidateImageBase(PBYTE pImageBase)
ends at address 00401554
but the next function
PIMAGE_SECTION_HEADER __cdecl _FindPESection( PBYTE pImageBase, DWORD_PTR rva )
starts at address 00401560
and there're multiple int 3
instructions between the latter two addresses.
Why the difference? Why some functions are put densely and others are separated with unreachable code?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我重现了这种行为。您还可以注意到这些函数以 mov edi,edi 指令开头。
int 3 指令以及函数开头的 mov edi,edi 指令允许热修补。
当函数需要热修补时,mov edi,edi 被替换为在函数入口点之前跳转的短跳转指令,并且 int 3 指令被替换为到修补函数的长跳转。
请参阅有人知道“mov edi,edi”的作用吗?
Don不知道为什么 __report_gsfailure 前面只有 2 int 3 即使它以 mov edi,edi 指令开头...
I reproduced this behavior. You can notice as well that these functions start with a mov edi,edi intruction.
The int 3 instructions, along with the mov edi,edi instruction at the beginning of the function allows hotpatching.
When a function needs to be hotpatched, the mov edi,edi is replaced by a short jump instruction that jumps before the entry point of the function and the int 3 instructions are replaced by a long jump to the patched function.
Refer to Anyone knows what "mov edi,edi " does?
Don't know why __report_gsfailure is only preceeded by 2 int 3 even if it starts with a mov edi,edi instruction...
Raymond Chen 讲述了您需要了解的所有信息:为什么Windows函数都是以毫无意义的MOV EDI、EDI指令开头?
Raymond Chen tells all you need to know about this: Why do Windows functions all begin with a pointless MOV EDI, EDI instruction?