【发布时间】:2017-07-24 21:04:12
【问题描述】:
在我的代码中,我有
mov x21, 0
str x21, [x29, 16]
然后在代码中,
ldr x22, [x29, 16]
将 0 存储到 x22 中。 然后,即使在代码的后面,我也有
ldr x23, [x29, 16]
即使两个 ldr 命令之间没有 str 命令,它最终也会将 214748364800 存储到 x23 中。
我的问题是如何为堆栈上的[x29, 16] 位置设置观察点,以便我可以看到它何时被写入?
我正在使用 gdb 进行调试。
编辑: 这是我在 x29+16 位置设置手表时 gdb 输出的一部分
Breakpoint 2, 0x0000000000400668 in inittest ()
1: x/i $pc
=> 0x400668 <inittest+8>: mov x21, #0x0 // #0
(gdb) ni
0x000000000040066c in inittest ()
1: x/i $pc
=> 0x40066c <inittest+12>: str x21, [x29,#16]
(gdb) p/x $x29+16
$1 = 0x3fffffff340
(gdb) x/x $x29+16
0x3fffffff340: 0xb8002d40
(gdb) watch *(int*)0x3fffffff340
Hardware watchpoint 5: *(int*)0x3fffffff340
(gdb) c
Continuing.
Hardware watchpoint 5: *(int*)0x3fffffff340
Old value = -1207947968
New value = 0
0x0000000000400670 in inittest ()
1: x/i $pc
=> 0x400670 <inittest+16>: b 0x4006d8 <testOut>
稍后在 gdb 输出中:
(gdb) p $x24
$4 = 103
(gdb) x/x $x29+24
0x3fffffff348: 0x00000000
(gdb) ni
0x00000000004006b4 in testIn ()
1: x/i $pc
=> 0x4006b4 <testIn+16>: ldr x24, [x29,#16]
(gdb) x/x $x29+16
0x3fffffff340: 0x00000000
(gdb) ni
如果我在这里输入p$x24,它会显示214748364800,即使它是从持有0 的[x29,#16] 加载的
0x00000000004006b8 in testIn ()
1: x/i $pc
=> 0x4006b8 <testIn+20>: ldr w23, [x19,x21,lsl #2]
(gdb) ni
0x00000000004006bc in testIn ()
1: x/i $pc
=> 0x4006bc <testIn+24>: str w23, [x29,#28]
(gdb)
0x00000000004006c0 in testIn ()
1: x/i $pc
=> 0x4006c0 <testIn+28>: ldr w23, [x19,x24,lsl #2]
(gdb)
Program received signal SIGSEGV, Segmentation fault.
0x00000000004006c0 in testIn ()
1: x/i $pc
=> 0x4006c0 <testIn+28>: ldr w23, [x19,x24,lsl #2]
由于内存分配,x24 的最大值只能约为 54,因此出现错误
【问题讨论】:
-
在
str上放置一个断点,然后在遇到断点时在x29+16的任何值上添加监视。请注意,您还需要确保x29未更改。 -
如果你确实使用
watch和(int *)类型,你可以在dbg 中尝试:(gdb) print sizeof(int)吗?如果它是 4,并且您使用的是 little-endian 模式,那么您只看到前 4 个字节(仍然为零),0x32发生在第五个字节。 -
我输入了
print sizeof (int),它说 4。此外,在调用ldr时它加载0x3200000000而不是 0,之后我输入x/4x $x29+16以查看所有 4 个字节,第二个字节,而不是0x00000000,实际上是0x00000032。我猜这就是改变的地方。如何在第二个字节上专门设置手表?它只是简单地设置当我输入p/x $x29+17时显示的十六进制代码吗? (16 是第一个字节,17 是第二个等等?)