崩溃调查,从 .so 文件中恢复符号
Crash investigation, recovering symbols from .so file
我有一个 android 应用程序在某些情况下在本机代码中崩溃,我无法重现。
我在使用 visual studio 构建并包含适当的 PDB 文件的可执行文件的崩溃调查方面拥有丰富的经验。不幸的是,我在 gcc 中没有这样的经验,但是我了解所需的概念。
我没有故障转储,只有调用堆栈(由 google 游戏控制台报告)。它从 java 代码开始,然后转到 .so 库的 public 符号,然后在本机代码中还有一个调用堆栈。自然符号是不可见的,因为它是一个发布版本,私有符号被剥离。
我使用标准 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(地址 space 布局随机化)。我从未见过 Google 崩溃报告,所以我不知道它是否提供了相对于共享对象加载地址的地址,或者是否有一些其他方法来恢复相对地址。绝对地址很难在这种情况下使用。
我有一个 android 应用程序在某些情况下在本机代码中崩溃,我无法重现。 我在使用 visual studio 构建并包含适当的 PDB 文件的可执行文件的崩溃调查方面拥有丰富的经验。不幸的是,我在 gcc 中没有这样的经验,但是我了解所需的概念。
我没有故障转储,只有调用堆栈(由 google 游戏控制台报告)。它从 java 代码开始,然后转到 .so 库的 public 符号,然后在本机代码中还有一个调用堆栈。自然符号是不可见的,因为它是一个发布版本,私有符号被剥离。
我使用标准 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(地址 space 布局随机化)。我从未见过 Google 崩溃报告,所以我不知道它是否提供了相对于共享对象加载地址的地址,或者是否有一些其他方法来恢复相对地址。绝对地址很难在这种情况下使用。