无法理解 x86-64 函数前导码

发布于 2024-09-24 19:15:45 字数 931 浏览 8 评论 0原文

我遇到了崩溃,在调查时我发现自己完全被以下代码阻止:

0000000000000a00 <_IO_vfprintf>:
a00:       55                      push   %rbp
a01:       48 89 e5                mov    %rsp,%rbp
a04:       41 57                   push   %r15
a06:       41 56                   push   %r14
a08:       41 55                   push   %r13
a0a:       41 54                   push   %r12
a0c:       53                      push   %rbx
a0d:       48 81 ec 48 06 00 00    sub    $0x648,%rsp
a14:       48 89 95 98 f9 ff ff    mov    %rdx,0xfffffffffffff998(%rbp)

这是通过在 64 位 Linux x86 上运行 objdump --disassemble /usr/lib64/libc.a 生成的系统,然后搜索输出。这是 AT&T 语法,因此目标位于右侧。

具体来说,我不明白最后一条指令。在函数触及该寄存器之前,它似乎正在将 rdx 寄存器的值写入堆栈上某个位置(很远很远)的内存中。对我来说,这没有任何意义。

我尝试阅读调用约定,现在我最好的理论是 rdx 用于参数,因此代码基本上是直接“返回”参数值。这不是函数的结束,所以当然它并没有真正返回。

I am experiencing a crash, and while investigating I found myself totally blocked by the following code:

0000000000000a00 <_IO_vfprintf>:
a00:       55                      push   %rbp
a01:       48 89 e5                mov    %rsp,%rbp
a04:       41 57                   push   %r15
a06:       41 56                   push   %r14
a08:       41 55                   push   %r13
a0a:       41 54                   push   %r12
a0c:       53                      push   %rbx
a0d:       48 81 ec 48 06 00 00    sub    $0x648,%rsp
a14:       48 89 95 98 f9 ff ff    mov    %rdx,0xfffffffffffff998(%rbp)

This is generated by running objdump --disassemble /usr/lib64/libc.a on a 64-bit Linux x86 system, and then searching through the output. This is AT&T syntax, so destinations are on the right.

Specifically, I don't understand the last instruction. It seems to be writing the value of the rdx register into memory somewhere on the stack (far, far away), before the function has touched that register. To me, this doesn't make any sense.

I tried reading up on the calling conventions, and my best theory now is that rdx is used for a parameter, so the code is basically "returning" the parameter value directly. This is not the end of the function, so it's not really returning, of course.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

残疾 2024-10-01 19:15:45

是的,这是一个参数。 Linux 使用的 ABI 最多分配 6 个“INTEGER”(<= 64位整数或指针)类型参数到寄存器,以明显且易于记住的顺序 %rdi%rsi%rdx%rcx%r8%r9

堆栈帧为 1648 字节(sub $0x648,%rsp 声明 1608 字节,加上之前已推送的 5 个 64 位寄存器),0xfffffffffffff998 为 -1640。

因此,代码将第三个参数存储在堆栈帧底部附近。

(注意:Windows 64 位 ABI 与 Linux 不同。)

Yes, it's a parameter. The ABI used by Linux assigns up to 6 "INTEGER" (<= 64-bit integer, or pointer) type parameters to registers, in the obvious and easy-to-remember order %rdi, %rsi, %rdx, %rcx, %r8, %r9.

The stack frame is 1648 bytes (sub $0x648,%rsp claims 1608 bytes, plus 5 64-bit registers have been pushed before that), and 0xfffffffffffff998 is -1640.

So the code is storing the 3rd parameter near the bottom of the stack frame.

(Note: the Windows 64-bit ABI is different to the Linux one.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文