From 25b22b0a6f353d95932f8ee0b9bf861d3eed3261 Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Tue, 8 Jul 2008 10:59:57 +0000 Subject: [PATCH] * breakpoint.c (mark_breakpoints_out): Make public. (update_breakpoints_after_exec): Don't call mark_breakpoints_out here. Update comment. * breakpoint.h (mark_breakpoints_out): Declare. * linux-nat.c (linux_handle_extended_wait): On TARGET_WAITKIND_EXECD, call mark_breakpoints_out. * inf-ttrace.c (inf_ttrace_wait): Likewise. --- gdb/ChangeLog | 11 +++++++++++ gdb/breakpoint.c | 19 ++++++++++++------- gdb/breakpoint.h | 3 +++ gdb/inf-ttrace.c | 6 ++++++ gdb/linux-nat.c | 10 ++++++++++ 5 files changed, 42 insertions(+), 7 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 784ad45cd81..82d805ffb76 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,14 @@ +2008-07-08 Pedro Alves + + * breakpoint.c (mark_breakpoints_out): Make public. + (update_breakpoints_after_exec): Don't call mark_breakpoints_out + here. Update comment. + * breakpoint.h (mark_breakpoints_out): Declare. + + * linux-nat.c (linux_handle_extended_wait): On + TARGET_WAITKIND_EXECD, call mark_breakpoints_out. + * inf-ttrace.c (inf_ttrace_wait): Likewise. + 2008-07-08 Pedro Alves * infrun.c (follow_exec): Reset shared libraries before adding the diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index e774bca940b..9d7bf71576d 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -188,8 +188,6 @@ static int single_step_breakpoint_inserted_here_p (CORE_ADDR pc); static void free_bp_location (struct bp_location *loc); -static void mark_breakpoints_out (void); - static struct bp_location * allocate_bp_location (struct breakpoint *bpt, enum bptype bp_type); @@ -1443,12 +1441,19 @@ update_breakpoints_after_exec (void) { struct breakpoint *b; struct breakpoint *temp; + struct bp_location *bploc; struct cleanup *cleanup; - /* Doing this first prevents the badness of having delete_breakpoint() - write a breakpoint's current "shadow contents" to lift the bp. That - shadow is NOT valid after an exec()! */ - mark_breakpoints_out (); + /* We're about to delete breakpoints from GDB's lists. If the + INSERTED flag is true, GDB will try to lift the breakpoints by + writing the breakpoints' "shadow contents" back into memory. The + "shadow contents" are NOT valid after an exec, so GDB should not + do that. Instead, the target is responsible from marking + breakpoints out as soon as it detects an exec. We don't do that + here instead, because there may be other attempts to delete + breakpoints after detecting an exec and before reaching here. */ + ALL_BP_LOCATIONS (bploc) + gdb_assert (!bploc->inserted); /* The binary we used to debug is now gone, and we're updating breakpoints for the new binary. Until we're done, we should not @@ -1699,7 +1704,7 @@ remove_breakpoint (struct bp_location *b, insertion_state_t is) /* Clear the "inserted" flag in all breakpoints. */ -static void +void mark_breakpoints_out (void) { struct bp_location *bpt; diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h index 2c98d64e8bc..4636a13351c 100644 --- a/gdb/breakpoint.h +++ b/gdb/breakpoint.h @@ -826,6 +826,9 @@ extern void disable_breakpoint (struct breakpoint *); extern void enable_breakpoint (struct breakpoint *); +/* Clear the "inserted" flag in all breakpoints. */ +extern void mark_breakpoints_out (void); + extern void make_breakpoint_permanent (struct breakpoint *); extern struct breakpoint *create_solib_event_breakpoint (CORE_ADDR); diff --git a/gdb/inf-ttrace.c b/gdb/inf-ttrace.c index 8a8399ad956..95c296e4a24 100644 --- a/gdb/inf-ttrace.c +++ b/gdb/inf-ttrace.c @@ -904,6 +904,12 @@ inf_ttrace_wait (ptid_t ptid, struct target_waitstatus *ourstatus) tts.tts_u.tts_exec.tts_pathlen, 0) == -1) perror_with_name (("ttrace")); ourstatus->value.execd_pathname[tts.tts_u.tts_exec.tts_pathlen] = 0; + + /* At this point, all inserted breakpoints are gone. Doing this + as soon as we detect an exec prevents the badness of deleting + a breakpoint writing the current "shadow contents" to lift + the bp. That shadow is NOT valid after an exec. */ + mark_breakpoints_out (); break; case TTEVT_EXIT: diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c index 964337884e0..ce3df53f5db 100644 --- a/gdb/linux-nat.c +++ b/gdb/linux-nat.c @@ -1758,6 +1758,16 @@ linux_handle_extended_wait (struct lwp_info *lp, int status, linux_parent_pid = 0; } + /* At this point, all inserted breakpoints are gone. Doing this + as soon as we detect an exec prevents the badness of deleting + a breakpoint writing the current "shadow contents" to lift + the bp. That shadow is NOT valid after an exec. + + Note that we have to do this after the detach_breakpoints + call above, otherwise breakpoints wouldn't be lifted from the + parent on a vfork, because detach_breakpoints would think + that breakpoints are not inserted. */ + mark_breakpoints_out (); return 0; }