C++函数调用栈回溯初探

本文约 800 字,阅读需 2 分钟。

背景

之前在解决一个Flutter Engine的C++ Crash问题时,就曾受困于一个问题:如何回溯C++的 函数调用栈?最近频繁使用C++的过程中,这个诉求日益突出。 遂下定决心彻底解决之。

过程

在stackoverflow上,有两个比较有参考价值的问题:

具体来说,问题是Android平台、ARM64架构下的C++回溯。

其中, Eugene Shapovalov的回答试了下,效果比较接近,但是无法通过addr2line还原。

一番查找后,发现 -funwind-tables-fno-omit-frame-pointer 在构建时必需加上:

此时,仍无法还原,addr2line无法解析。经过一番探索之后,发现是因为unwind直接得到的是实际的运行地址,而 addr2line 的 输入应该是so内部的偏移值,具体的做法下面的文章有提及:

此时,得到的堆栈就可以正常回溯了。

以上方法是直接在代码中获取so基址,然后进行处理。其实也可以通过adb手动获取:

  1. 首先获取目标应用的进程id
  2. 通过 run as 的方式获取maps文件内容: adb shell "run-as com.tencent.**** sh -c 'cat /proc/18454/maps'"
  3. 找到对应so的加载基址,即可计算出偏移值,用addr2line还原

参考文章:

其他参考文章:

这个问题,说难也不难,只是需要一些背景知识的积累,这也算是使用C++这门语言进行开发的典型特征了。

总阅读量次。