0

In my code, I have

mov x21, 0
str x21, [x29, 16]

and then later on in the code,

ldr x22, [x29, 16]

which stores 0 into x22. And then, even later in the code, I have

ldr x23, [x29, 16]

which ends up storing 214748364800 into x23 even though there is no str command between the two ldr commands.

My question is how do i set a watchpoint for the [x29, 16] location on the stack so I can see when it is written to?

I am using gdb for debugging.

EDIT: This is a portion of the gdb output when I set a watch on the x29+16 location

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>

later on in the gdb output:

(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

if i were to type p$x24 here, it displays 214748364800 even though it loads from [x29,#16] which is holding 0

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]

Error arises because x24 can only be max of about 54 due to memory allocation

Erick P
  • 87
  • 1
  • 2
  • 9
  • Put a breakpoint on the `str`, then add the watch on whatever the value of `x29+16` is when the breakpoint is hit. Note you also need to ensure `x29` is unchanged. – Jester Mar 04 '17 at 20:48
  • If you did use `watch` with `(int *)` type, can you try in dbg: `(gdb) print sizeof(int)`? If it's 4, and you are using little-endian mode, you are watching only first 4 bytes (which remain zero), the `0x32` happens in fifth byte. – Ped7g Mar 04 '17 at 22:15
  • I typed `print sizeof (int)` and it said 4. also, at the call to `ldr ` where it loads `0x3200000000` instead of 0, just after that I typed `x/4x $x29+16` to see all 4 bytes, and the second byte, instead of being `0x00000000` it is actually `0x00000032`. I'm guessing that's where the change is being made. How do i set a watch specifically on this second byte? Is it just simply setting the hex code that shows when I type `p/x $x29+17`? (16 is the first byte, 17 is second and so on?) – Erick P Mar 04 '17 at 23:39

1 Answers1

0

how do i set a watchpoint for the [x29, 16] location

What you describe isn't a fixed location -- it depends on the value of x29 (are you sure x29 doesn't change between the two instructions?).

At the point of ldr x23, [x29, 16], figure out what the location with the wrong value is:

(gdb) p/x $x29+16  # this is the location you'll want later
(gdb) x/x $x29+16  # should show 0x3200000000 == 214748364800

Now set a breakpoint on the first instruction and re-run the program. Once the breakpoint is hit, verify that the value you expect is really there:

(gdb) x/x 0x...    # should be 0, not 0x3200000000

and set the watchpoint:

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

... GDB should stop when the value changes.

Employed Russian
  • 199,314
  • 34
  • 295
  • 362
  • So that helped with setting the watchpoint. But turns out the issue is not what I thought it was. When I do the initial `x/x $x29+16` where it should be showing `0x3200000000` , it instead shows `0x0`. So setting a watchpoint at that location does nothing for me because it does, in fact, stay 0. What is actually happening somehow is the `ldr x23, [x29, 16]` line, even though it calls to the location holding 0, it stores the value `0x3200000000` – Erick P Mar 04 '17 at 21:38
  • @ErickP `ldr` loads, not stores. And if that memory is still zeroed, then `x29` must be different, you can't load `0x3200000000` from 8 zero bytes. – Ped7g Mar 04 '17 at 21:59
  • @ErickP wait a second ... that watch ... is `int` in gdb 64b or 32b? Does gdb know `int64_t`? Or `qword`? Or maybe put two watches over that memory, if `int` is only 32b. (I don't use gdb, so I'm not sure what is proper answer and solution in case it's 32b) – Ped7g Mar 04 '17 at 22:05