forked from Imagelibrary/binutils-gdb
gdb/
* breakpoint.h (struct breakpoint) <watchpoint_thread>: New field. * breakpoint.c (watchpoint_in_thread_scope): New. (update_watchpoint): Skip if the local watchpoint's thread doesn't match the current thread, or if the current thread is running. (watchpoint_check): Ditto. (watch_command_1): Set the watchpoint's watchpoint_thread field. gdb/testsuite/ * gdb.threads/local-watch-wrong-thread.c, gdb.threads/local-watch-wrong-thread.exp: New files.
This commit is contained in:
@@ -985,6 +985,24 @@ fetch_watchpoint_value (struct expression *exp, struct value **valp,
|
||||
}
|
||||
}
|
||||
|
||||
/* Assuming that B is a watchpoint: returns true if the current thread
|
||||
and its running state are safe to evaluate or update watchpoint B.
|
||||
Watchpoints on local expressions need to be evaluated in the
|
||||
context of the thread that was current when the watchpoint was
|
||||
created, and, that thread needs to be stopped to be able to select
|
||||
the correct frame context. Watchpoints on global expressions can
|
||||
be evaluated on any thread, and in any state. It is presently left
|
||||
to the target allowing memory accesses when threads are
|
||||
running. */
|
||||
|
||||
static int
|
||||
watchpoint_in_thread_scope (struct breakpoint *b)
|
||||
{
|
||||
return (ptid_equal (b->watchpoint_thread, null_ptid)
|
||||
|| (ptid_equal (inferior_ptid, b->watchpoint_thread)
|
||||
&& !is_executing (inferior_ptid)));
|
||||
}
|
||||
|
||||
/* Assuming that B is a watchpoint:
|
||||
- Reparse watchpoint expression, if REPARSE is non-zero
|
||||
- Evaluate expression and store the result in B->val
|
||||
@@ -1043,6 +1061,12 @@ update_watchpoint (struct breakpoint *b, int reparse)
|
||||
bpstat bs;
|
||||
struct program_space *frame_pspace;
|
||||
|
||||
/* If this is a local watchpoint, we only want to check if the
|
||||
watchpoint frame is in scope if the current thread is the thread
|
||||
that was used to create the watchpoint. */
|
||||
if (!watchpoint_in_thread_scope (b))
|
||||
return;
|
||||
|
||||
/* We don't free locations. They are stored in bp_location array and
|
||||
update_global_locations will eventually delete them and remove
|
||||
breakpoints if needed. */
|
||||
@@ -3124,6 +3148,12 @@ watchpoint_check (void *p)
|
||||
|
||||
b = bs->breakpoint_at->owner;
|
||||
|
||||
/* If this is a local watchpoint, we only want to check if the
|
||||
watchpoint frame is in scope if the current thread is the thread
|
||||
that was used to create the watchpoint. */
|
||||
if (!watchpoint_in_thread_scope (b))
|
||||
return WP_VALUE_NOT_CHANGED;
|
||||
|
||||
if (b->exp_valid_block == NULL)
|
||||
within_current_scope = 1;
|
||||
else
|
||||
@@ -7190,9 +7220,15 @@ watch_command_1 (char *arg, int accessflag, int from_tty)
|
||||
b->cond_string = 0;
|
||||
|
||||
if (frame)
|
||||
b->watchpoint_frame = get_frame_id (frame);
|
||||
{
|
||||
b->watchpoint_frame = get_frame_id (frame);
|
||||
b->watchpoint_thread = inferior_ptid;
|
||||
}
|
||||
else
|
||||
b->watchpoint_frame = null_frame_id;
|
||||
{
|
||||
b->watchpoint_frame = null_frame_id;
|
||||
b->watchpoint_thread = null_ptid;
|
||||
}
|
||||
|
||||
if (scope_breakpoint != NULL)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user