This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[rfa] Be more careful when checking watchpoints
- From: Daniel Jacobowitz <drow at false dot org>
- To: gdb-patches at sourceware dot org
- Date: Tue, 17 Oct 2006 15:49:04 -0400
- Subject: [rfa] Be more careful when checking watchpoints
Software watchpoints of local variables are a very hard test of frame
unwinding: you have to be correct in the prologue, in the dynamic linker, in
the epilogue, and so on. This is one failure case I encountered recently.
It doesn't trigger in mainline GDB, but does in an older one.
We step into a PowerPC GNU/Linux PLT entry. There's no associated symbol.
The frame ends up with an id of {stack = $sp, code = 0}, which is considered
to match the frame where this was created, which had {stack = $sp, code =
funcaddr} (because code == 0 is a wildcard). So, we go and try to read the
value of that variable using the current frame. Eventually, there was a
segfault deep in the dwarf location list code, because the stub frame for
the PLT entry didn't have a frame base.
This is a bit of defensive programming. If we find a frame with the "same"
ID as the one we're looking for, but it's pointing at a different function,
then assume the unwinding has gotten confused and the watchpoint has gone
out of scope.
Does this look OK? Tested x86_64-pc-linux-gnu, no regressions.
--
Daniel Jacobowitz
CodeSourcery
2006-10-17 Daniel Jacobowitz <dan@codesourcery.com>
* breakpoint.c (watchpoint_check): Double-check the found frame.
Index: breakpoint.c
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.c,v
retrieving revision 1.229
diff -u -p -r1.229 breakpoint.c
--- breakpoint.c 8 Aug 2006 21:32:37 -0000 1.229
+++ breakpoint.c 17 Oct 2006 19:43:36 -0000
@@ -2492,6 +2492,13 @@ watchpoint_check (void *p)
reinit_frame_cache ();
fr = frame_find_by_id (b->watchpoint_frame);
within_current_scope = (fr != NULL);
+
+ /* If we've gotten confused in the unwinder, we might have
+ returned a frame that can't describe this variable. */
+ if (within_current_scope
+ && block_function (b->exp_valid_block) != get_frame_function (fr))
+ within_current_scope = 0;
+
/* in_function_epilogue_p() returns a non-zero value if we're still
in the function but the stack frame has already been invalidated.
Since we can't rely on the values of local variables after the