这是
gas
实现MASM的
帧处理伪指令以生成可执行文件的.pdata和.xdata部分(结构化异常处理内容)。还请查看
原始伪操作。显然,如果您的代码可能在SEH解开操作期间位于堆栈中,则应使用它们。
我在
https://sourceware.org/ml/binutils/2009-08/msg00193.html找到了
稍微更多的信息。此线程似乎是向
gas
添加支持所有.set_*伪操作的原始检入。
我想展示通过gas生成pe-coff目标文件的.pdata和.xdata补丁,并获得一些反馈。此补丁包括对arm、ppc、arm、sh(3&4)、mips和x64的支持。至于x86,没有运行时函数信息的操作系统支持,因此我省略了这部分。这只会增加x86 PE的可执行文件大小,并且对于该目标没有真正的收益。
简要概述:
目前有三种不同的函数入口格式。
第一种是MIPS。第二个版本主要针对Windows CE的ARM、PPC、SH3和SH4。第三个是IA64和x64版本。请注意,IA64尚未实现,但要查找有关它的信息,请参阅
http://download.intel.com/design/Itanium/Downloads/245358.pdf文件中关于IA64的规范。
第一个版本在pdata部分中仅具有条目:BeginAddress、EndAddress、ExceptionHandler、HandlerData和PrologueEndAddress。每个值都是指向相应数据的指针,大小为4个字节。
第二个版本在pdata部分中具有以下条目。BeginAddress、PrologueLength(8位)、EndAddress(22位)、Use-32-bit-instruction(1位)和Exception-Handler-Exists(1位)。如果FunctionLength为零,或者Exception-Handler-Exists位为true,则在函数入口之前直接放置DATA_EH块。
第三个版本具有一个函数入口块,其中包括BeginAddress(RVA)、EndAddress(RVA)和UnwindData(RVA)。在xdata部分的UNWIND_DATA字段中存储了序言、异常处理程序和其他SEH数据的描述。
.seh_proc
这表明针对函数开始一个SEH块。这适用于所有目标。
.seh_endprologue
通过此伪指令,指定了序言结尾地址(由当前代码地址的出现位置获取)。适用于所有目标。
.seh_handler [,]
此伪指令指定要使用的处理程序函数。对于版本2,处理程序数据字段指定用户可选数据块。对于版本3,如果名称为@unwind,则生成UHANDLER展开块,如果名称为@except(或根本未指定),则生成EHANDLER异常块。
.seh_eh
此伪指令用于版本2,以指示汇编中函数开始的位置。这里可以存储PDATA_EH数据。
.seh_32/.seh_no32
该伪指令仅用于版本2(请参见上述描述)。如果未指定,它目前默认为no32。
.seh_endproc
通过此伪指令指定SEH块的结束。
.seh_setframe ,
通过此伪指令,可以指定框架寄存器和偏移量(0-240之间的值,具有16字节对齐)。这仅由版本3使用。
.seh_stackalloc
通过此伪指令描述代码中的堆栈分配,适用于版本3。
.seh_pushreg
通过此伪指令描述代码中的通用寄存器推送,适用于版本3。
.seh_savereg
通过此伪指令描述将通用寄存器保存到内存中的代码,适用于版本3。
.seh_savemm
通过此伪指令描述将mm寄存器保存到内存中的代码,适用于版本3。
.seh_savexmm
该伪指令描述了将xmm寄存器保存到内存中的代码,适用于版本3。
.seh_pushframe
通过此信息可以描述有关入口类型的信息,适用于版本3。
.seh_scope ,,,
通过此伪
此外,在https://sourceware.org/ml/binutils/2009-04/msg00181.html上还有一些关于.xdata和.pdata的深入讨论(以及一堆链接)。