我在 Android 1.6 模拟器上调试一个没有符号的程序。在加载 SO 库期间出现崩溃(信号),我正在尝试追踪它。崩溃发生在库启动代码的某个地方,我知道的很多。在控制从加载程序转到 SO 之前,我知道 SO 加载程序代码中的安全位置。我可以在那里设置一个断点,然后一直到 BLX 进入库。加载程序的代码是 Thumb。库启动代码是 ARM。
由于没有符号,我用它set arm force-mode xxx
来让 GDB 知道。在启动导致加载程序停止的序列之前,我将模式设置为 Thumb。
但问题是,当我来到BLX
指令并尝试单步执行 ( si
) 时,调试器不会在下一条指令处停止 - 它一直到信号。即使我set arm force-mode arm
在执行si
BLX 之前做了一个,这似乎也没关系。
在库启动代码中设置断点也无济于事。我不确定 GDB 究竟是如何设置断点的,但看起来当前执行代码的模式与预期的断点目标模式之间的不匹配是一个障碍。
编辑:我什至尝试对正在运行的代码进行猴子修补,以便在正确的位置有一个 BKPT 命令 - GDB 仍然没有中断。
EDIT2:猴子修补代码部分似乎不起作用。不过,我可以将数据部分的一部分用作暂存区。尽管如此,BKPT 不会导致 GDB 崩溃......
EDIT3:对三行代码片段使用临时数据区域,我可以切换出 Thumb 并在信号中返回 GDB。但是,现在我处于 ARM 模式,GDB 由于某种原因无法设置断点。
BLX 进入库命令如下所示:blx r2
. r2 的值为 0x80601b60 - 这是库启动例程。
当我在 BLX 上停下来时,这就是我所做的。我在数据部分有一个暂存区。我将以下 ARM 命令放在那里:
mov r12, 0 ; the value of r12 will be soon ruined by the code anyway
ldr r12, [r12] ; Provoke a SIGSEGV to stop GDB in ARM mode
mov pc, r2 ; To resume back into the library
然后我将r2的值强行设置为我的暂存区,将GDB模式设置为ARM并继续。划痕区的一个 SIGSEGV 自然被抛出。
我在这里,处于 ARM 模式(CPU 和 GDB 的强制模式)。我在 0x80601b60 - 库入口点设置了一个断点。我将 r2 的值改回 0x80601b60 以便第三条命令跳转到那里。我将 r12 的值更改为有效读取地址,以便在重试时不会重新抛出信号。我发出一个signal 0
命令,在没有信号的情况下继续。
我期望控制会转到 0x80601b60 并且会遇到断点。它不是。为什么不?mov
偶然分配给 pc 时的语义是否不同(如ldr rx, [pc]
is)?
在 上设置断点mov pc, r2
也不起作用。在信号模式停止时在 GDB 中设置断点是否有问题?但即使我在信号之前设置断点(在 Thumb 模式下),它也不起作用。
更奇怪的是,我遇到了控制权超出的情况,就mov pc, r2
好像它根本没有执行一样。但是,一旦我修复了 r12,就会执行上一条指令。
有单步模拟signal 0
吗?