堆栈跟踪停止在叶寄存器lr处

问题描述

我经常看到ARM堆栈跟踪(阅读:Android NDK堆栈跟踪)以“ 0”指针终止,如下所示:
      #00  pc 001c6c20  /data/data/com.audia.dev.qt/lib/libQtGui.so
      #01  lr 80a356cc  /data/data/com.audia.dev.rta/lib/librta.so
我知道在ARM和其他体系结构上ѭ0代表ѭ3,并且它是存储返回地址的快速方法,但是我不明白为什么它似乎总是存储无用的地址。在此示例中,
80a356cc
不能使用
addr2line
gdb
映射到任何代码。 有什么办法获取更多信息吗?为什么跟踪必须在“ 0”地址处停止?     

解决方法

        终于迷失了答案。我只需要更加细心。查看以下简短的堆栈跟踪以及其后的信息:
         #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
地址仍然是a10ѭ地址,对我们没有用。 它从
pc
打印的地址是
000099d6
,但请看下一节
code around pc
。第一列是地址的列表(您可以从中得知每次都增加16。),除非您将前16位切掉,否则这些地址看上去都不像
pc
地址。然后您会注意到ѭ15必须与ѭ16相对应,并且程序停止处的代码位于其中两个字节之后。 Android的堆栈跟踪对我来说似乎已将“ 11”地址的前2个字节“砍掉了”,但是由于某种原因,它不对叶寄存器中的地址执行此操作。这带给我们解决方案: 简而言之,我能够从
80b6c17c
地址中砍掉前16位,使其变为
0000c17c
,到目前为止,每次我可以用
gdb
addr2line
查找时,它都为我提供了一个有效的代码地址。 (编辑:我发现它实际上通常是前12位或前3个十六进制数字。您可以通过查看如上所述的堆栈跟踪输出来自己决定。)我可以确认它是正确的代码地址。这无疑使调试变得非常容易!     ,        您是否已打开所有调试信息(
-g3
)? Gcc喜欢将“ 0”用作普通寄存器。请记住,非叶函数看起来像
push {lr}
; .. setup args here etc.
bl foo  ; call a function foo
; .. work with function results
pop {pc}
将lr压入堆栈后,编译器几乎可以自由使用它-
lr
仅会被函数调用覆盖。因此,ѭ0中很可能存在中间值。 这应该在编译器生成的调试信息中说明,以便让调试器知道它必须查看堆栈值而不是“ 0”。     

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...