如何利用 release 版本的 backtrace 来定位 android NDK 程序的崩溃位置

早过忘川 提交于 2020-07-28 05:46:17

我们知道 android NDK 程序在崩溃时会生成一个 tombstone 的 backtrace (也可利用 ADB logcat 抓取),从这个 backtrace 中我们可以了解是哪个函数引发的崩溃,但是通常由于我们发布时都是 release 版,无法利用 backtrace 中的地址信息直接定位到源码和行号,当引发崩溃的错误不是很明显时,对于我们解决问题的帮助就不大。

这时通常我们是重编一个 debug 版本并设法重现 crash。这样做有两个问题,一是如果我们不知道复现步骤,或者复现概率很低时,效率不高;二是我们不一定总能满足 crash 产生的条件,而一旦版本发布后,使用 debug 版本去替换用户场景中的 release 版又非常麻烦(甚至可能无法实现)。

事实上,有一个办法可以解决这个问题。我们知道,release 版本的库文件也是有 DYNAMIC SYMBOL TABLE 的,你可以使用命令 objdump -T -R <your so> (并重定向到一个文本文件中)来查看,然后你可以用同样的命令去查看 debug 版本的 DYNAMIC SYMBOL TABLE,通过比较,不难发现,他们的格式是一样的,你需要关注的只是第一列(symbol address)和最后一列(symbol name)。

接下来,你在 debug 版本的 DYNAMIC SYMBOL TABLE 中搜索引发崩溃的函数名,并记下它的 symbol address,然后,你只需要在这个地址上增加一个偏移量,就可以使用 addr2line 命令来定位源码和行号了。这个偏移量是多少?请注意 backtrace 中 #00  pc 的最后一列(使用括号括住),其中在函数名的后面有一个+N,这个N就是崩溃位置的偏移量(注意它是10进制数,而 symbol address 是16进制数,你需要先做转换才能相加)。

需要说明的是,由于 release 版通常都经过了优化,backtrace 中的偏移量并不一定非常准确,但离实际值差得不会太远,你可以使用 debug 版做一个对比测试就可以验证。现在你可以去试试这个方法了,希望这个方法能帮助你提高解决 crash 问题的效率。
————————————————
版权声明:本文为CSDN博主「vault13」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/banqingzi/article/details/26357029

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!