使用-funwind-tables进行编译时究竟发生了什么?

时间:2018-11-01 13:22:04

标签: c++ c gcc compilation backtrace

发件人:https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html

  

-fexceptions :启用异常处理。生成传播异常所需的额外代码。对于某些目标,这意味着GCC会为所有功能生成帧展开信息,

     

-funwind-tables -fexceptions相似,除了它只生成任何需要的静态数据,而不会影响任何生成的代码。   另一种方式。您通常不需要启用此选项;而是   需要这种处理的语言处理器会代您启用它。

有人可以从-funwind-tables解释“任何需要的静态数据”是什么意思。他们指的是什么数据。为什么需要生成数据?如果未生成该数据会怎样?该数据用于哪里?

它也说“类似于-fexception”。因此,我认为它还会生成帧展开信息。什么是帧展开信息?谁使用帧信息,如何使用?

在某些SO帖子中,我读到必须使用此标志编译程序,以使_Unwind_Backtrace必须正常工作。请说明_Unwind_Backtrace如何使用-funwind-tables生成的信息。

1 个答案:

答案 0 :(得分:5)

-funwind-tables选项提及的静态数据是帧展开信息,即,允许正在运行的程序从给定执行点向后退函数调用堆栈的数据。向后走函数调用栈意味着从被调用函数的执行上下文移到调用者的上下文,即从函数中 return 时通常发生的情况,除了框架展开信息允许您执行从函数体内任意点的那个;同样,您也不必递归地退出调用函数,您可以简单地“窥视”调用者上下文(例如,从中检索已调用函数的位置),然后继续执行正常的执行流程。称为函数。

要执行上述操作,您需要获得有关编译后代码的更多信息,而不是程序遵循“正常”执行流程所必需的信息。该信息(即帧展开信息)由链接器放入专用于此目的的特殊链接器部分(例如x86平台的.eh_frame部分或ARM平台的ARM.exidx和.ARM.extab部分)中;这些链接器节与实现异常处理的C ++等语言所需要的链接器节相同,在这种情况下,由于引发异常,执行流可能从被调用函数跳转到其调用者。如果使用-fno-unwind-tables选项禁用了此数据的生成,则将无法返回函数调用堆栈或使用C ++异常。

值得注意的是,libunwind使用了帧展开信息,它是一个跨平台的库,支持生成回溯,跳转到调用堆栈中的任意点等等。

_Unwind_Backtrace()是在GCC核心库(更具体地在libgcc_s中)中实现的函数,该函数允许为调用堆栈中的每个帧执行回调函数(作为参数提供),即从调用者的上下文开始功能,移至其调用方等。参见https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/baselib--unwind-backtrace.html。再次,此功能要能够完成工作,需要从相应的链接器部分访问帧展开信息。