我有一个 android 应用程序在某些情况下在 native 代码中崩溃,我无法重现。 我在使用 visual studio 构建并包含适当的 PDB 文件的可执行文件的崩溃调查方面拥有丰富的经验。不幸的是,我在 gcc 方面没有这样的经验,但是我了解所需的概念。
我没有故障转储,只有调用堆栈(由 google play 控制台报告)。它从 java 代码开始,然后转到 .so 库的公共(public)符号,然后在 native 代码中还有一个调用堆栈。符号自然是不可见的,因为它是一个发布版本,私有(private)符号被剥离。
我使用标准 NDK 的构建脚本。在基于输出的发布构建中,我有以下内容:
- release-version .so 文件,~700KB
- 在中间(临时)文件目录中:
- .so同名文件,8.4MB
- objs 目录,包含各种.o 和.o.d 文件
所以,我需要指导如何找出符号。中间目录中的 .so 文件比发布目录中的同名文件大得多。这些文件几乎相同,直到较小文件的末尾。 看起来更大的文件实际上是一样的,最后附加了调试信息。用 HEX 查看器打开它并搜索一些符号名称(C++ 修饰的函数名称)- 它肯定包含它们。
我尝试在较大的文件上使用 nm -gC
工具。它确实显示了一些符号,但这还不够:它仅包含公共(public)符号(即模块故意导出的 JNI 方法),以及构建过程中使用的标准库中的大量内容(标准 C/C++ 函数、pthread 内容、一些内容与异常和 RTTI 相关)。但是没有内部函数名称,它们肯定存在于文件中。
那么,我是不是漏掉了什么?是否有应指定给 nm
的选项?或者也许应该使用其他工具?
提前致谢。
最佳答案
通常,addr2line
是这项工作的工具。它将查看调试信息并报告行号和功能行。有一些选项可以改进它的输出(处理内联函数、分解符号)。
但是你需要补偿ASLR(地址空间布局随机化)。我从未见过谷歌的崩溃报告,所以我不知道它是否提供了相对于共享对象加载地址的地址,或者是否有一些其他方法来恢复相对地址。绝对地址很难在这种情况下使用。
关于c++ - 崩溃调查,从 .so 文件中恢复符号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46868343/