Assembly 如何为堆栈上的变量设置写监视点

Assembly 如何为堆栈上的变量设置写监视点,assembly,gdb,stack,armv8,Assembly,Gdb,Stack,Armv8,在我的代码中,我有 mov x21, 0 str x21, [x29, 16] ldr x23, [x29, 16] 后来在代码中 ldr x22, [x29, 16] 它将0存储到x22中。 然后,甚至在代码的后面,我 mov x21, 0 str x21, [x29, 16] ldr x23, [x29, 16] 即使两个ldr命令之间没有str命令,也会将214748364800存储到x23中 我的问题是如何为堆栈上的[x29,16]位置设置观察点,以便在写入时看到它 我正在使用

在我的代码中,我有

mov x21, 0
str x21, [x29, 16]
ldr x23, [x29, 16]
后来在代码中

ldr x22, [x29, 16]
它将0存储到x22中。 然后,甚至在代码的后面,我

mov x21, 0
str x21, [x29, 16]
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>
出现错误的原因是由于内存分配,
x24
最多只能是约
54

如何为[x29,16]位置设置观察点

您所描述的并不是一个固定的位置——它取决于
x29
的值(您确定
x29
在这两条指令之间没有变化吗?)

ldr x23[x29,16]
点,找出错误值的位置:

(gdb) p/x $x29+16  # this is the location you'll want later
(gdb) x/x $x29+16  # should show 0x3200000000 == 214748364800
现在在第一条指令上设置一个断点,然后重新运行程序。命中断点后,请验证预期值是否确实存在:

并设置观察点:

(gdb) watch *(int*)0x....
(gdb) continue

。。。当值发生变化时,GDB应该停止。

str
上设置一个断点,然后在到达断点时将手表添加到
x29+16
的任何值上。注意:您还需要确保
x29
保持不变。如果您确实将
watch
(int*)
类型一起使用,是否可以尝试在dbg:
(gdb)打印大小(int)
?如果是4,并且您使用的是little endian模式,那么您只查看前4个字节(保持为零),则
0x32
发生在第五个字节中。我键入
print sizeof(int)
,它显示为4。另外,在调用
ldr
加载
0x32000000
而不是0时,我键入
x/4x$x29+16
查看所有4个字节,第二个字节不是
0x00000000
实际上是
0x00000032
。我猜这就是改变的地方。如何专门在第二个字节上设置手表?是否只是简单地设置我键入
p/x$x29+17
时显示的十六进制代码?(16是第一个字节,17是第二个字节,依此类推)这样有助于设置观察点。但事实证明问题并不是我想象的那样。当我执行初始的
x/x$x29+16
时,它应该显示
0x32000000000
,而不是显示
0x0
。因此,在那个位置设置一个观察点对我来说毫无用处,因为它实际上保持0。实际发生的是
ldr x23[x29,16]
行,即使它调用了持有0的位置,它也存储值
0x3200000
@ErickP
ldr
加载,而不是存储。如果内存仍然为零,则
x29
必须不同,您不能从8个零字节加载
0x32000000000
。@ErickP请稍候。。。那只表。。。
int
在GDB64B还是32b中?gdb是否知道
int64\t
?还是
qword
?或者,如果
int
仅为32b,则可以在该内存上放置两块手表。(我不使用gdb,所以我不确定在32b的情况下什么是正确的答案和解决方案)
(gdb) watch *(int*)0x....
(gdb) continue