Re: recurse.exp: watch on local variable that goes out of scope

Orjan Friberg
2004-07-22T09:44:18Z

Eli Zaretskii wrote:
>
> No, it shouldn't return a stale address, it should return zero.
>
> I reproduce the entire source of i386_stopped_data_address below; as
> you see, it starts by zeroing out `addr' and assigns it a non-zero
> value _only_ if I386_DR_WATCH_HIT(i) returns non-zero for some value
> of i. This is supposed to query the debuggee about its debug
> registers, and assumes that one of the debug registers will show that
> a watchpoint has been hit only if a watchpoint has indeed been hit.

Bad wording on my part there; I didn't mean to assume that the function
i386_stopped_data_address itself retained the address, but that somehow the i386
watchpoint registers kept the last address and that was what was reported.
(Needless to say, I'm not intimately familiar with the i386 watchpoint registers.)

> Can you step thru i386_stopped_data_address and see what exactly
> happens there in your case?

Absolutely. The situation is the same as previously (watch on local variable b,
hit twice by the time we get to the return statement):

recurse (a=5) at ../../../src/gdb/testsuite/gdb.base/recurse.c:20
20 return b;
(gdb) c
Continuing.

Breakpoint 4, i386_stopped_data_address () at ../../src/gdb/i386-nat.c:576
576 dr_status_mirror = I386_DR_LOW_GET_STATUS ();

Inside i386_stopped_data_address dr_status_mirror = 0xffff4ff1, which satisfies
the condition for I386_DR_WATCH_HIT (i) for i == 0. The reported address is
0xbffff488 (the address of local variable b).

Conversely, if I don't set the watchpoint on b until I reach the return
statement, the behaviour is what I expect: i386_stopped_data_address returns 0
when the watchpoint scope del breakpoint is hit. Notice the difference in the
following two sessions:

Mimicking recurse.exp
=====================

Breakpoint 1, recurse (a=5) at ../../../src/gdb/testsuite/gdb.base/recurse.c:13
13 int b = 0;
(gdb) n
15 if (a == 1)
(gdb) watch b
Hardware watchpoint 8: b
(gdb) c
Continuing.
Hardware watchpoint 8: b

Old value = 0
New value = 5
recurse (a=5) at ../../../src/gdb/testsuite/gdb.base/recurse.c:19
19 b *= recurse (a - 1);
(gdb) c
Continuing.
Hardware watchpoint 8: b

Old value = 5
New value = 120
recurse (a=5) at ../../../src/gdb/testsuite/gdb.base/recurse.c:20
20 return b;
(gdb) maintenance info breakpoints
Num Type Disp Enb Address What

[snip]

-78 watchpoint scope del y 0x08048403 <recurse+51>
stop only in stack frame at 0xbffff4c4
breakpoint already hit 4 times
(gdb) c
Continuing.

Watchpoint 8 deleted because the program has left the block in
which its expression is valid.
0x08048403 in recurse (a=6) at ../../../src/gdb/testsuite/gdb.base/recurse.c:19
19 b *= recurse (a - 1);
(gdb)

Watch on return statement
=========================

Breakpoint 1, recurse (a=5) at ../../../src/gdb/testsuite/gdb.base/recurse.c:13
13 int b = 0;
(gdb) until 20
recurse (a=5) at ../../../src/gdb/testsuite/gdb.base/recurse.c:20
20 return b;
(gdb) watch b
Hardware watchpoint 9: b
(gdb) maintenance info breakpoints
Num Type Disp Enb Address What

[snip]

-99 watchpoint scope del y 0x08048403 <recurse+51>
stop only in stack frame at 0xbffff4c4
(gdb) c
Continuing.
Hardware watchpoint 9 deleted because the program has left the block
in which its expression is valid.

Program exited normally.
(gdb)

I fail to see why these two cases should be different.