前面一篇博文简单介绍了c++异常处理的流程,但在一些细节上一带而过了,比如,_Unwind_RaiseException是怎样重建函数现场的,personality routine是怎样清理栈上变量的等,这些细节涉及到很多与语言层面无关的东西,本文尝试介绍一下这些细节的具体实现。
相关的数据结构
如前所述,unwind的进行需要编译器生成一定的数据来支持,这些数据保存了与每个可能抛异常的函数相关的信息以供运行时查找,那么,编译器都保存了哪些信息呢?根据Itanium ABI的定义,主要包括以下三类:
1)unwind table,这个表记录了与函数相关的信息,共三个字段:函数的起始地址,函数的结束地址,一个info block指针。
2)unwind descriptor table, 这个列表用于描述函数中需要unwind的区域的相关信息。
3)语言相关的数据(language specific data area),用于上层语言内部的处理。
以上数据结构的描述来自Itanium ABI的标准定义,但在具体实现时,这些数据是怎么组织以及放到了哪里则是由编译器来决定的,对于GCC来说,所有与unwind相关的数据都放到了.eh_frame及.gcc_except_table这两个section里面了,而且它的格式与内容和标准的定义稍稍有些不同。
.eh_frame区域
.eh_frame的格式与.debug_frame是很相似的(不完全相同),属于DWARF标准中的一部分。所有由GCC编译生成的需要支持异常处理的程序都包含了DWARF格式的数据与字节码,这些数据与字节码的主要作用有两个:
1)描述函数调用栈的结构(layout)
2)异常发生后,指导unwinder怎么进行unwind。
DWARF的字节码功能很强大,它是图灵完备的,这意味着仅仅通过DWARF就可以做几乎任何事情。但是从数据的组织上来看,DWARF实在略显复杂晦杂,因此很少有人愿意去碰,本文也只是简单介绍其中与异常处理相关的东西。本质上来说,eh_frame像是一张表,它用于描述怎样根据程序中每一条指令来设置相应的寄存器,从而返回到当前函数的调用函数中去,它的作用可以用如下表格来形象地描述。
program counter | CFA | ebp | ebx | eax | return address |
0xfff0003001 | rsp+32 | *(cfa-16) | *(cfa-24) | eax=edi | *(cfa-8) |
0xfff0003002 | rsp+32 | *(cfa-16) | eax=edi | *(cfa-8) | |
0xfff0003003 | rsp+32 | *(cfa-16) | *(cfa-32) | eax=edi | *(cfa-8 |
上表中,CFA(canonical frame address的缩写)表示一个基地址,用于作为当前函数中的其它地址的起始地址,使得其它地址可以用与该基地址的偏移来表示,由于这个表可能要覆盖很多程序指令,因此这个表的体积有可能是很大的,甚至比程序本身的代码量还要大。而在实际中,为了减少这个表的体积,GCC通常会对它进行压缩编码,以及尽可能减少要覆盖的指令的数量,比如,只对会抛异常的函数里的特定区域指令进行记录。
具体的实现上,eh_frame由一个CIE (Common Information Entry) 及多个 FDE (Frame Description Entry)组成,它们在内存中是连续存放的:
CIE及FDE格式的定义可以参看如下:
CIE结构:
Length | Required |
Extended Length | Optional |
CIE ID | Required |
Version | Required |
Augmentation String | Required |
EH Data | Optional |
Code Alignment Factor | Required |
Data Alignment Factor | Required |
Return Address Register | Required |
Augmentation Data Length | Optional |
Augmentation Data | Optional |
Initial Instructions | Required |
Padding |
FDE结构:
Length | Required |
Extended Length | Optional |
CIE Pointer | Required |
PC Begin | Required |
PC Range | Required |
Augmentation Data Length | Optional |
Augmentation Data | Optional |
Call Frame Instructions | Required |
Padding | 职业规划那些事儿 - zhixing 阅读原文» 前几天写了招聘和面试方面的,也写了带新人方面的,今天我和朋友一起来探讨一下个人对于职业规划方面的理解,希望和朋友们一起分享 本文链接:职业规划那些事儿,转载请注明。
订阅:
博文评论 (Atom)
|
没有评论:
发表评论