c++ - 堆栈跟踪在叶寄存器 (lr) 处停止

标签 c++ arm android-ndk

我经常看到以 lr 指针终止的 ARM 堆栈跟踪(阅读:Android NDK 堆栈跟踪),如下所示:

      #00  pc 001c6c20  /data/data/com.audia.dev.qt/lib/libQtGui.so
      #01  lr 80a356cc  /data/data/com.audia.dev.rta/lib/librta.so

我知道 lr 在 ARM 和其他架构上代表 link register ,这是一种存储返回地址的快速方法,但我不明白为什么它似乎总是存储一个无用的地址。在此示例中,80a356cc 无法使用 addr2linegdb 映射到任何代码。

有什么办法可以得到更多的信息吗?为什么跟踪必须停在 lr 地址?

最佳答案

终于找到答案了。我只需要更加细心。查看以下简短堆栈跟踪及其后的信息:

         #00  pc 000099d6  /system/lib/libandroid.so
         #01  lr 80b6c17c  /data/data/com.audia.dev.rta/lib/librta.so

code around pc:
a9d899b4 bf00bd0e 2102b507 aa016d43 28004798 
a9d899c4 9801bfa8 bf00bd0e 460eb573 93004615 
a9d899d4 6d842105 462b4632 200047a0 bf00bd7c 
a9d899e4 b100b510 f7fe3808 2800edf4 f04fbf14 
a9d899f4 200030ff bf00bd10 b097b5f0 4614af01 

code around lr:
80b6c15c e51b3078 e5933038 e5932024 e51b302c 
80b6c16c e1a00002 e3a01000 e3a02000 ebfeee5c 
80b6c17c e1a03000 e50b303c e51b303c e1a03fa3 
80b6c18c e6ef3073 e3530000 0a000005 e59f34fc 
80b6c19c e08f3003 e1a00003 e51b103c ebfeebe6 

现在 lr 地址仍然是一个对我们没有用的 80xxxxxx 地址。

它从 pc 打印的地址是 000099d6,但请看下一节,code around pc。第一列是地址列表(您可以从它每次递增 16 的事实中看出。)这些地址都不像 pc 地址,除非您砍掉前 16 位。然后你会注意到 a9d899d4 必须对应于 000099d4,程序停止的代码是从那里开始的两个字节。

Android 的堆栈跟踪似乎已经为我“截断”了 pc 地址的前 2 个字节,但无论出于何种原因,它都没有对叶寄存器中的地址执行此操作。这给我们带来了解决方案:

简而言之,我能够从 80b6c17c 地址砍掉前 16 位,使其成为 0000c17c,到目前为止每次我可以使用 gdbaddr2line 查找时,都给了我一个有效的代码地址。 (编辑:我发现它实际上通常前 12 位 或前 3 个十六进制数字。您可以通过查看自己来决定堆栈跟踪输出就像我上面描述的那样。)我可以确认它也是正确的代码地址。这无疑使调试变得更加容易!

关于c++ - 堆栈跟踪在叶寄存器 (lr) 处停止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6460094/

相关文章:

c++ - 对一个类/文件的 undefined reference 错误

c++ - 父进程 "listening"到子消息

c++ - 修复关于 C/C++ 和寄存器访问的知识差距

linux - ARM Linux Atags 与设备树

gcc - 当 --sysroot 指向另一个目录时,如何让 FFmpeg 找到已安装的库?

C++ 平台特定包括

c++ - Travis CI 从源日志限制错误安装 boost

networking - 带有 TCP/IP、SSL、USB 和对 ARM 的基本文件系统支持的最小 FOSS RTOS

用于构建 OpenCV 3.2 的 Android.mk 和 Application.mk

Android native 窗口时间戳