gcc输出的.seh_*汇编指令是什么?

13

我使用gcc -S编译hello world程序。这5个.seh_命令是什么?当我搜索时,似乎找不到太多关于它们的信息。

    .file   "hi.c"
    .def    __main; .scl    2;  .type   32; .endef
    .section .rdata,"dr"
.LC0:
    .ascii "Hello World\0"
    .text
    .globl  main
    .def    main;   .scl    2;  .type   32; .endef
    .seh_proc   main
main:
    pushq   %rbp
    .seh_pushreg    %rbp
    movq    %rsp, %rbp
    .seh_setframe   %rbp, 0
    subq    $32, %rsp
    .seh_stackalloc 32
    .seh_endprologue
    call    __main
    leaq    .LC0(%rip), %rcx
    call    puts
    movl    $0, %eax
    addq    $32, %rsp
    popq    %rbp
    ret
    .seh_endproc
    .ident  "GCC: (rubenvb-4.8.0) 4.8.0"
    .def    puts;   .scl    2;  .type   32; .endef

3
"SEH" 是指结构化异常处理,是 Windows 的一个功能。他们正在努力将其实现在4.8版本中,听起来他们已经完成了。这里有一段相关内容的简介(http://qt-project.org/wiki/MinGW-64-bit)。 - Hans Passant
3个回答

11
这是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的深入讨论(以及一堆链接)。


9
我使用以下方法阻止它们被输出:

我使用以下方法阻止它们被输出:

gcc -S -fno-asynchronous-unwind-tables hi.c

所以我可以查找它。但是我很满意只是不再输出它们。


2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接