从应用程序的共享对象上分叉“addr2line”以构建堆栈跟踪。这有多安全?

从应用程序的共享对象上分叉“addr2line”以构建堆栈跟踪。这有多安全?

我正在增强在 Linux 上运行的应用程序,以便在进程或线程接收到终端信号(例如 SIGSEGV、SIGABRT)时发出回溯。

backtrace(3)该代码使用、backtrace_symbols(3)、运行良好,dladdr(3)abi::__cxa_demangle回溯生成有用的信息。

除此之外,在尝试生成源文件名和行号时,我发现addr2line当我使用 提供的地址发送可执行文件时效果很好,但是最近,只要符号位于共享对象中,backtrace(3)它就很容易生成??:0。看来backtrace和朋友举报的地址受到了ASLR的影响。这个问题影响了我的大部分(如果不是全部)堆栈跟踪,目前正在减少 forking 的价值addr2line

对于我来说,在如何解决它并获取文件和行号方面,互联网结果开始变得稀疏。但我最近已经足够了解内存映射如何工作来解决以下问题:

  • backtrace_symbols(3)为我提供了一个包含共享对象路径的字符串(dladdr(3)也在 中提供了这一点dli_fname),我可以nm与此共享对象一起使用来查找backtrace_symbols也提供的符号,当我在共享对象中添加此地址和偏移量时,并将其发送给addr2line -e <sharedobjectpath>它,正确地生成文件和行号。
  • /proc/<pid>/maps我可以在共享对象路径中查找r-xp映射地址,并从 和 报告的地址中减去该值,backtrace(3)该值提供了与上面共享对象完全相同的地址。
  • 我也许能够(仍然没有测试过,但有预感)通过 直接获取共享对象映射地址dladdr1(3),这将允许我跳过访问/proc/<pid>/maps.

不管怎样,这里我似乎需要分叉addr2line才能获取文件和行号,这有点痛苦(并且需要数百毫秒),但它似乎是必要的,而不需要将其libbfd作为依赖项引入我的应用程序。

更新:我没有仔细观察,现在我意识到从 找到的地址与的值/proc/<pid>/maps相同。这样就解决了。根本不需要抬头。dli_fbasedladdr(3)/proc/<pid>/maps

有没有更干净或更直接的方法来做到这一点?我希望我的第三个要点可以让我只 fork addr2line。 (编辑: 可以给个地址吗忽略我对 的引用/proc/<pid>/maps。)第二个项目符号已经表明我可以阅读/proc/<pid>/maps以获得我需要的叉子,这只是更糟一点;尽管扫描相当大的内存映射输出需要大量工作,但它的执行速度肯定比后续调用addr2line.问题是(如果第三个项目符号被证明不可行)是否存在与从我的程序访问相关的任何安全/访问/安全问题/proc/<pid>/maps跑步addr2line

答案1

我知道,这是一个很晚的答案,但也许无论如何都会有帮助。我最近一直在研究同样的问题,我认为如果你想避免使用,addr2line你必须使用以下命令提取调试符号和行库文件。另外还有一些项目为你做这个(我还没有机会亲自测试它们)

相关内容