28

魔法咒语

LD_PRELOAD=/lib/libSegFault.so someapp

与 libSegFault.so 一起运行someapp,提供关于 SIGSEGV 的回溯信息,如许多 不同的 地方所述。

除了使用类似signal(7)方法SIGABRT来调用SIGSEGV处理程序之外,还有什么方法可以让 libSegFault 为assert(3)失败提供回溯信息?

4

2 回答 2

36
env SEGFAULT_SIGNALS="abrt segv" LD_PRELOAD=/lib/libSegFault.so someapp

请注意,预加载库的实际路径可能不同。在我的机器上,我会使用

env SEGFAULT_SIGNALS="abrt segv" LD_PRELOAD=/lib/x86_64-linux-gnu/libSegFault.so some-64bit-app

或者

env SEGFAULT_SIGNALS="abrt segv" LD_PRELOAD=/lib/i386-linux-gnu/libSegFault.so some-32bit-app

取决于我正在运行的应用程序是 64 位还是 32 位编译的。(您可以file用来检查。)


源代码告诉我们,有三个环境变量定义了libSegFault.so行为方式:

  • SEGFAULT_SIGNALS:导致堆栈跟踪的信号列表。默认值为SIGSEGV. 已定义但为空SEGFAULT_SIGNALS意味着没有信号会导致堆栈跟踪。支持的值为segv, ill, abrt, fpe,bus在具有 SIGBUS 信号stkflt的系统上,在具有 SIGSTKFLT 信号的系统上,以及all所有这些值。

  • SEGFAULT_USE_ALTSTACK:如果在环境中定义,则libSegFault.so使用替代堆栈作为堆栈跟踪信号。如果您正在调试堆栈损坏,这可能会派上用场。

  • SEGFAULT_OUTPUT_NAME:如果在环境中定义,堆栈跟踪将写入此文件而不是标准错误。

老实说,我最初是通过使用strings /lib/libSegFault.so | sed -e '/[^0-9A-Z_]/ d'. 所有标准库(libSegFault.so已成为 GNU C 库的一部分)都可以通过环境变量进行调整,因此使用类似该命令的命令来转储任何看起来像环境变量名称的字符串是查找要搜索的内容的快速方法。进行网络搜索"SEGFAULT_SIGNALS" "SEGFAULT_OUTPUT_NAME"会产生许多有用的链接;看到它现在是 GNU C 库的一部分,我去了git 档案,找到了库的实际源文件,并发布了我的答案。

于 2013-09-22T18:00:07.077 回答
4

类似地,glibc 异常处理程序将堆栈转储写入/dev/console堆损坏错误。

如果您在非 tty(即 systemd 进程或其他分离的进程)中运行可执行文件,则崩溃输出会转到/dev/null,这不是那么有用。

有一个未记录的功能将输出重定向到/dev/stderr. 设置以下环境变量:

export LIBC_FATAL_STDERR_=1

这可以与 libSegFault.so 结合使用,以实现最大程度的取证。

还值得一提的是,如果您还为 SIGABRT 启用回溯,这可能会给您两个堆栈跟踪,因为 glibc 首先进行堆栈跟踪,然后发出信号 SIGABRT ...然后 libSegFault 给出第二个堆栈跟踪。

于 2015-09-14T20:22:17.847 回答