.cfi_remember_state的实现

lib*_*o.1 5 x86 assembly gcc x86-64 gnu-assembler

我想知道究竟.cfi_remember_state是如何实施的.我知道这是一个伪操作,所以我想它在组装时会转换成几条指令.我感兴趣的是用于实现它的确切指令.我尝试了很多方法来弄明白.即:

  • 阅读GAS源代码.但没有找到任何有用的东西.
  • 阅读GAS文档.但这个.cfi_remember_state条目只是一个简单的笑话(字面意思).
  • 试图找到一个gcc开关,使gcc从C代码生成asm,伪操作"扩展".无法为x86/x86-64找到这样的开关.(如果有人能指出我这样的开关会很好,假设它存在,BTW.)
  • Google-fu &&搜索SO并没有产生任何有用的东西.

在我看来,唯一的其他解决方案是读取已组装的可执行文件的二进制文件并尝试推断出指令.但我想避免这样一项艰巨的任务.有谁知道,启发我,它是如何在x86和/或x86-64上实现的?也许与分享获取信息的方式/位置一起,所以我可以检查其他伪操作,如果我有需要的话?

Kon*_*rov 3

该指令是 DWARF 信息的一部分(实际上它所做的只是发出 DW_CFA_remember_state 指令)。摘自 DWARF3 标准:

DW_CFA_remember_state 指令不采用操作数。所需的操作是将每个寄存器的规则集推送到隐式堆栈上。

您可以使用 objdump 来处理 DWARF 信息。让我们从简单的 void 汇编程序文件开始:

  .text
.globl main
  .type main, @function
main:
.LFB0:
.cfi_startproc
#.cfi_remember_state
.cfi_endproc
.LFE0:
  .size main, .-main
Run Code Online (Sandbox Code Playgroud)

编译它gcc cfirem.s -c -o cfirem.o

现在反汇编生成的 DWARF 部分,objdump --dwarf cfirem.o 您将得到:

00000018 00000014 0000001c FDE cie=00000000 pc=00000000..00000000
  DW_CFA_nop
  DW_CFA_nop
  ...
Run Code Online (Sandbox Code Playgroud)

如果取消注释 .cfi_remember_state,您将看到:

00000018 00000014 0000001c FDE cie=00000000 pc=00000000..00000000
  DW_CFA_remember_state
  DW_CFA_nop
  DW_CFA_nop
  ...
Run Code Online (Sandbox Code Playgroud)

所以它并没有真正转换成汇编指令(尝试objdump -d看看我们的示例中根本没有汇编指令)。它被转换为 DWARF 伪指令,当 GDB 等调试器处理变量位置、堆栈信息等时使用这些伪指令。