汇编,CFA,CFI
1)来源
.cfi_def_cfa_offset directives in assembly generated by GCC
不知道intel有没有。
main()
is called from somewhere else (in the libc
C runtime support code), and, at the time the call
instruction is executed, %rsp
will point to the top of the stack (which is the lowest address - the stack grows downwards)
CFI(calling frame info
)的作用是出现异常时stack
的回滚(unwind
)。而回滚的过程是一级级CFA往上回退,直到异常被catch
。
.cfi指令解读(一)_Alan的修炼的博客-CSDN博客_cfi_def_cfa_offset
上面这个网址其实讲得挺好的。
CFA定义为执行call xxx
时SP(stack pointer
)所指向的地址。
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
表示执行完pushl %ebp
后SP与CFA偏了8
字节(4
字节return address
,4
字节ebp
)
movl %esp, %ebp
.cfi_def_cfa_register 5
表示执行完movl %esp, %ebp
后cfa_register
不再是esp
,而是ebp
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
表示执行完leave
后ebp
的值已经恢复到初始状态,并且CFA的计算方式应该是esp+4
其中寄存器对应的数字是架构相关的,详细参考xxx_map_dwarf_register
:
5d8067c60… Jace*0760 static unsigned x86_64_map_dwarf_register(unsigned regno, const struct module* module, BOOL eh_frame) e2b62c91d… Eric*0761 {0762 unsigned reg;0763 0764 if (regno >= 17 && regno <= 24)0765 reg = CV_AMD64_XMM0 + regno - 17;0766 else if (regno >= 25 && regno <= 32)0767 reg = CV_AMD64_XMM8 + regno - 25;0768 else if (regno >= 33 && regno <= 40)0769 reg = CV_AMD64_ST0 + regno - 33;0770 else switch (regno)0771 {0772 case 0: reg = CV_AMD64_RAX; break;0773 case 1: reg = CV_AMD64_RDX; break;0774 case 2: reg = CV_AMD64_RCX; break;0775 case 3: reg = CV_AMD64_RBX; break;0776 case 4: reg = CV_AMD64_RSI; break;0777 case 5: reg = CV_AMD64_RDI; break;0778 case 6: reg = CV_AMD64_RBP; break;0779 case 7: reg = CV_AMD64_RSP; break;0780 case 8: reg = CV_AMD64_R8; break;0781 case 9: reg = CV_AMD64_R9; break;0782 case 10: reg = CV_AMD64_R10; break;0783 case 11: reg = CV_AMD64_R11; break;0784 case 12: reg = CV_AMD64_R12; break;0785 case 13: reg = CV_AMD64_R13; break;0786 case 14: reg = CV_AMD64_R14; break;0787 case 15: reg = CV_AMD64_R15; break;0788 case 16: reg = CV_AMD64_RIP; break;0789 case 49: reg = CV_AMD64_EFLAGS; break;0790 case 50: reg = CV_AMD64_ES; break;0791 case 51: reg = CV_AMD64_CS; break;0792 case 52: reg = CV_AMD64_SS; break;0793 case 53: reg = CV_AMD64_DS; break;0794 case 54: reg = CV_AMD64_FS; break;0795 case 55: reg = CV_AMD64_GS; break;0796 case 62: reg = CV_AMD64_TR; break;0797 case 63: reg = CV_AMD64_LDTR; break;0798 case 64: reg = CV_AMD64_MXCSR; break;0799 case 65: reg = CV_AMD64_CTRL; break;0800 case 66: reg = CV_AMD64_STAT; break;0801 /*0802 * 56-57 reserved0803 * 58 %fs.base0804 * 59 %gs.base0805 * 60-61 reserved0806 */0807 default:0808 FIXME("Don't know how to map register %d\n", regno);0809 return 0;0810 }0811 return reg;0812 }0813
/wine-7.5/dlls/dbghelp/cpu_x86_64.c
基本上解释清楚了。
7.12.13 .cfi_offset register, offset
Previous value of register is saved at offset offset from CFA.
这里的register是一个编号,真是莫名其妙的规定。
2)
We refer to this address as the Canonical Frame Address or CFA
CFA是个地址,与RSP之间的距离,有什么用?
As the call
instruction is executed, it will push a 64-bit (8 byte) return address onto the stack:
: :
| whatever | <--- CFA
+----------------+
| return address | <--- %rsp == CFA - 8
+----------------+
Now we are running the code at main
, which executes subq $8, %rsp
to reserve another 8 bytes of stack for itself:
: :
| whatever | <--- CFA
+----------------+
| return address |
+----------------+
| reserved space | <--- %rsp == CFA - 16
+----------------+
#include <stdio.h>int main(int argc, char** argv)
{printf("%d", 0);return 0;
}
The generated assembly:
.file "test.c".section .rodata.str1.1,"aMS",@progbits,1
.LC0:.string "%d".text.p2align 4,,15
.globl main.type main, @function
main:
.LFB22:.cfi_startprocsubq $8, %rsp.cfi_def_cfa_offset 16xorl %edx, %edxmovl $.LC0, %esimovl $1, %edixorl %eax, %eaxcall __printf_chkxorl %eax, %eaxaddq $8, %rsp.cfi_def_cfa_offset 8ret.cfi_endproc
.LFE22:.size main, .-main.ident "GCC: (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2".section .note.GNU-stack,"",@progbits
这个.cfi_def_cfa_offset 是解释得清楚了。
rsp 栈顶,低地址。rbp 栈底,高地址。向下生长。
.cfi_def_cfa_offset
modifies a rule for computing CFA. Register remains the same, but offset is new. Note that it is the absolute offset that will be added to a defined register to compute CFA address.
不知道有什么用。
https://sourceware.org/binutils/docs/as/CFI-directives.html#CFI-directives
7.12.11 .cfi_def_cfa_offset offset
.cfi_def_cfa_offset
modifies a rule for computing CFA. Register remains the same, but offset is new. Note that it is the absolute offset that will be added to a defined register to compute CFA address.
7.12.13 .cfi_offset register, offset
Previous value of register is saved at offset offset from CFA.
寄存器的前一个值被保存在CFA的偏移地址?什么意思嘛?
3)
8.12. .cfi_def_cfa_offset offset
.cfi_def_cfa_offset modifies a rule for computing CFA. Register remains the same, but offset is new. Note that it is the absolute offset that will be added to a defined register to compute CFA address.
绝对位置,问题是CFA有什么用?
8.14. .cfi_offset register, offset
Previous value of register is saved at offset offset from CFA.
都属于Assembler Directives,编译指导语句。
做啥用的嘛?
8.3. .align abs-expr, abs-expr, abs-expr
Pad the location counter (in the current subsection) to a particular storage boundary. The first expression (which must be absolute) is the alignment required, as described below.
对齐方式,具体是怎么回事嘛?其实要举例子才行。
http://web.mit.edu/rhel-doc/3/rhel-as-en-3/index.html
桢的概念
4)
Pseudo Ops (Using as)
5)
CFI 即 Call Frame Information,是 DWARF 2.0 定义的函数栈信息,DWARF 即 Debugging With Attributed Record Formats ,是一种调试信息格式。
.cfi_ 开头的汇编指示符,例如 .cfi_startproc 、.cfi_undefined 、.cfi_endproc 等,CFI 即 Call Frame Information,是 DWARF 2.0 定义的函数栈信息,DWARF 即 Debugging With Attributed Record Formats ,是一种调试信息格式。 .cfi_ 开头的汇编指示符用来告诉汇编器生成相应的 DWARF 调试信息,主要是和函数有关。.cfi_startproc 定义函数开始,.cfi_endproc 定义函数结束。
意思可以全部删掉?
汇编,CFA,CFI相关推荐
- Unwind 栈回溯详解:libunwind
目录 1. 历史背景 1.1 frame pointers 1.2 .debug_frame (DWARF) 1.3 .eh_frame (LSB) 1.4 CFI directives 2. .de ...
- Unwind 栈回溯详解
文章目录 1. 历史背景 1.1 frame pointers 1.2 .debug_frame (DWARF) 1.3 .eh_frame (LSB) 1.4 CFI directives 2. . ...
- ATT伪指令 以及对于CFI CFA的解释
包含了所有我遇到的伪指令,网上这种资料比较少,所以整理记录下来.阅读本文善用Ctrl+F. 文章目录 第一部分 无序 第二部分 分类 第三部分 CFI伪指令 第四部分 对于CFI和CFA的解释 第一部 ...
- 分析.cpp文件编译生成的汇编文件里语句的作用
1 2 3 4 int main(int argc,char** argv) { return 1; } 1 g++ -S test.cpp 生成test.s汇编文件 .file"null- ...
- linux下的汇编,linux下的汇编分析
计算机是怎样工作的 中科大 SA6272 柏云鹏 实验一 实验目标: 请使用Example的c代码分别生成.cpp,.s,.o和ELF可执行文件,并加载运行,分析.s汇编代码在CPU上的执行过程 通过 ...
- C语言汇编查看笔记(一)
#include <stdio.h>int sum(int x, int y){int t = x + y;return t; }int main(void){sum(1,2); } 利用 ...
- CFI/CFG 安全防护原理详解(ROP攻击、DOP攻击、插装检测)
1. 简介 CFI: Control-Flow Integrity(控制流完整性) CFG: Control Flow Guard(Windows的CFI实现) CFG: Control-Flow G ...
- 分析一个简单的汇编代码
分析一个简单的汇编代码 部分常见的寄存器 寄存器 16位 32位 64位 累加寄存器 AX EAX RAX 基址寄存器 BX EBX RBX 计数寄存器 CX ECX RCX 数据寄存器 DX EDX ...
- Task 6:CFA | Amos Mplus | 道德、人格、身份的测量模型
CFA | Amos & Mplus | 道德.人格.身份的测量模型 1 文章介绍 1.1 数据获取 1.2 论文内容 2 理论模型 2.1 文章主要验证的结构方程模型: 2.2 以上模型中的 ...
最新文章
- 新手做自媒体运营了解这几个步骤,运营效率提高5倍!(附教程)
- 数据结构源码笔记(C语言):堆排序
- mysql删除数据表show_数据库与表显示、创建、删除
- SQL注入学习——Bool盲注详解 sqli-labs(Less 8)
- boost::contract模块实现throw on failure的测试程序
- 学习office add-in
- Qt对话框的事件循环实例分析
- 机器学习接口和代码之 KNN
- 图解PCB板元器件焊接流程
- 手机芯片 AI 之争:高通、联发科均超华为!
- HDU2561 第二小整数【水题+序列处理】
- 设计模式之GOF23代理模式02
- 【解决idea谷歌翻译失败问题】
- excel不使用科学计数法
- 用优盘装系统看不到计算机本身的硬盘,如果U盘安装系统找不到硬盘怎么办
- 黑马程序员Android28期视频下载
- SAP库存盘点必要知识
- SpringMVC数据校验、文件上传
- Windows环境下msysgit下安装gitflow步骤。
- DOS里的NET命令用法