【问题标题】:How does GCC print a stack trace?GCC 如何打印堆栈跟踪?
【发布时间】:2020-05-07 18:40:24
【问题描述】:

当 gcc/g++ 遇到 ICE(内部编译器错误)时,最新版本的编译器会在退出前打印出整洁的堆栈跟踪。

问题:使用什么技术来实现它? GCC 是用 C++ 编写的,afaik 一些保守的修订版本,如 C++03。

特别是

  • GCC 不使用 Boost。

  • 据我所知,GCC 不使用 linunwind 或 libexcept 等外部库。

  • GCC 不一定使用 glibc。例如,我可以在 linux 上为主机 mingw32 交叉编译 GCC,并且堆栈跟踪工作得很好。


所以在盲目关闭这个问题之前,请确保链接的答案不需要任何这些库。

【问题讨论】:

  • 是什么让您认为 GCC 使用任何公开可用的库来进行堆栈跟踪?如果有的话,我敢打赌这些库是基于 GCC 的实现。
  • @Blindy 我的第一个问题以指向另一个问题的指针结束,该问题提出了 GCC 不使用的所有花哨的东西。 GCC 需要的只是 GMP、MPFR、MPC,它们与所讨论的功能无关。
  • @KamilCuk 据我了解,mingw 使用 msvcrt 而不是 glibc。
  • 你读过GCC的源代码吗?特别是libbacktrace子目录下的代码?

标签: c++ gcc


【解决方案1】:

正如许多人在 cmets 中提到的那样,GCC 静态链接到 libbacktrace,它在 ELF 平台(例如 Linux)上使用 libgcc,在 AIX 和 Windows 上使用自定义代码。假设大多数人都会对 Linux 感兴趣,我将在下面展开。

GCC 运行时库 (libgcc) 包含用于 C++ 异常和错误报告的堆栈展开代码。特别是 Glibc (backtrace(3))、AddressSanitizer 和 GCC 本身使用它。

展开的内部实现高度依赖于目标。例如,在 amd64 上,它使用存储在 .eh_frame 部分(参见 https://uclibc.org/docs/psABI-x86_64.pdf)中的堆栈布局元数据,在 ARM 上它也使用元数据(但格式不同),在 i386 上它手动解析函数序言指令(针对特定于平台的具体可以去https://github.com/gcc-mirror/gcc/tree/master/libgcc学习相关的unwind文件)。

【讨论】:

  • libgcc 是一个目标库,而不是宿主库。它用于展开异常。这意味着只有目标代码会使用该展开,并且在异常处理期间隐式使用它,也可能在非本地 goto 中使用。 GCC 本身只会链接到主机库。
  • @emacsdrivesmenuts "libgcc 是目标库,而不是主机库" - 抱歉,我不确定我理解你的意思(我主机上的所有程序都链接到 libgcc,包括 gcc可执行)。 “它用于展开异常” - 它用于任何堆栈展开,请检查 backtrace(3) 的实现和 Asan 的错误处理代码。
  • 您的 GCC 使用 libgcc 作为 target 库,因为它是由 GCC构建 的。如果您使用与 GCC 不同的构建编译器,则 GCC 将使用该编译器的支持库。在大多数情况下,这将被引导程序掩盖。因此使用不同的构建编译器并使用--disable-bootstrap 进行配置并检查生成的编译器。 .
  • @emacsdrivesmenuts 我已添加说明 libbacktrace 在 AIX 和 Windows 上使用自定义展开器。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-07-27
  • 2020-07-25
  • 2018-07-06
  • 2013-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多