exception handle CFI CFA
改进此文档
09 Aug 2015
前言
在GAS(GNU Assembler)汇编代码中经常能看到关于cfi、cfa的伪码,例如: 补充:关于GAS语法与NASM语法区别参见Linux 汇编器:对比 GAS 和 NASM,写得很好
LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8 # cfa偏移了8字节
.cfi_offset 5, -8 # ebp(代号5) 向栈顶偏移了8字节
movl %esp, %ebp
.cfi_def_cfa_register 5 # cfa_register不再是esp,而是ebp
subl $16, %esp
movl $0, -8(%ebp)
movl $0, -4(%ebp)
jmp L2
L3:
# 子程序执行代码,略
L2:
cmpl $15, -4(%ebp)
jle L3
movl -8(%ebp), %eax
# 子程序返回代码
leave
.cfi_restore 5 # ebp的值回复到初始状态
.cfi_def_cfa 4, 4 # esp + 4
ret
.cfi_endproc
CFI和CFA用途
这些有着cfi和cfa关键字的代码到底有什么用呢? 以下内容参考自:
https://lambertyang.blog.ustc.edu.cn/
CFI(Calling Frame Info)的作用是出现异常时stack的回滚unwind(unwind 英文有 放松,release的意思),而回滚的过程是一级级CFA往上回退,直到异常被catch。也就是说CFA定义为执行call ***的时候栈指针(Stack Pointer)所指向的地址。 eg:
pushl %ebp
.cfi_def_cfa_offset 8 # cfa偏移了8字节
.cfi_offset 5, -8 # ebp(代号5) 向栈顶偏移了8字节
表示的是执行完pushl %ebp
之后的SP与CFA偏移了8个字节长度。
movl %esp, %ebp
.cfi_def_cfa_register 5 #cfa_register为ebp(代号5)
表示执行完movl %esp,%ebp
后cfa_register不再是esp,而是ebp。
leave
.cfi_restore 5 # ebp返回
.cfi_def_cfa 4, 4 # esp + 4
表示执行完leave后ebp的值回复到初始状态,并CFA的计算方法是esp+4。
CFI和CFA用途补充-stackoverflow
参见:关于.cfi_def_cfa_offset
的用途 以及答案中提到的DWARF Debugging Information Format文档第六章
CFA(Canonical Frame Address)保存的是函数调用栈上的每个“call frame”的地址。
-----EOF-----