[英]Printing backtrace within signal handler in a release/optimized binary on Linux
问题是关于在优化的二进制文件中以编程方式打印有意义的堆栈跟踪。 例如,我们可以使用backtrace
、 backtrace_symbols
、 abi::__cxa_demangle
来打印堆栈跟踪。 但据我所知,我们需要使用编译器标志-g
构建二进制文件,而不是高于-O1
优化标志。 我可以做到这一点。
我期待在发布二进制文件中生成具有正确函数名称的回溯,例如使用-O3
标志编译。
它可行吗? 我对此做了很多研究,但没有得到任何实质性的东西。
更新 1:有没有办法让我们可以有一个包含一些符号的辅助文件,并且可以引用它从优化的二进制过程中生成堆栈跟踪?
在信号处理程序中打印回溯
无论优化级别如何,在信号处理程序中调用backtrace
1 、 backtrace_symbols
1或abi::__cxa_demangle
。 它们不是异步安全函数,如果在信号处理程序中使用,可能会导致程序崩溃、损坏内存或冻结。 关于打印,如果您计划使用任何printf
系列函数,请知道在信号处理程序中使用它们也不安全(至少是 POSIX 指定的所有函数)。
有一些库/函数承诺信号安全堆栈展开,以及使这成为可能的去重、格式化和输出。
1,根据手册页,使用backtrace
应该是OK,只要共享libgcc中已预先加载。 backtrace_symbols
有一个更安全的替代backtrace_symbols_fd
,它与 libgcc 有相同的警告。
有没有办法让我们可以有一个包含一些符号的辅助文件
您可以使用objcopy
从可执行文件中复制调试符号,并使用strip
从可执行文件中strip
。
GDB 支持外部符号文件,但我不知道是否/如何在程序中使用它们。 我使用SymtabAPI从二进制文件中挖掘符号; 这也可能适用于外部符号文件。 但据我所知,该库并不能保证信号安全。 也就是说,目前还不清楚为什么需要分离。 调试符号不会影响性能。
我只会在进程崩溃时打印堆栈
在这种情况下,可能更好的方法可能是简单地让操作系统生成核心转储,并让单独的进程侦听文件系统事件,一旦创建核心转储,生成回溯并写入某些日志。 无需担心信号安全,生成trace时无需延迟原进程重启,无需额外依赖服务端进程。
就优化级别而言,无论您使用什么方法来生成跟踪,您都可以尝试-O3 -fno-omit-frame-pointer
并希望获得最佳效果,但通常最好不要使用高于-O2
的调试。 -Og
是理想的,但没有那么快。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.