diff options
author | Jan Kratochvil <jan.kratochvil@redhat.com> | 2012-06-18 17:28:38 +0000 |
---|---|---|
committer | Jan Kratochvil <jan.kratochvil@redhat.com> | 2012-06-18 17:28:38 +0000 |
commit | e2e4d78b2216962789c8a982d3e889ba6933321a (patch) | |
tree | cd9aa71e52f6bb308e2b82e5b23ec1949d043518 /gdb/breakpoint.c | |
parent | 09d5912c6f5be8d8935ff45941bf957209bd42a6 (diff) | |
download | gdb-e2e4d78b2216962789c8a982d3e889ba6933321a.zip gdb-e2e4d78b2216962789c8a982d3e889ba6933321a.tar.gz gdb-e2e4d78b2216962789c8a982d3e889ba6933321a.tar.bz2 |
gdb/
Remove stale dummy frames.
* breakpoint.c: Include dummy-frame.h.
(longjmp_breakpoint_ops): New variable.
(update_breakpoints_after_exec, breakpoint_init_inferior): Delete also
bp_longjmp_call_dummy.
(bpstat_what, bptype_string, print_one_breakpoint_location)
(init_bp_location): Support bp_longjmp_call_dummy.
(set_longjmp_breakpoint): Use longjmp_breakpoint_ops. Comment why.
(set_longjmp_breakpoint_for_call_dummy)
(check_longjmp_breakpoint_for_call_dummy, longjmp_bkpt_dtor): New
functions.
(initialize_breakpoint_ops): Initialize longjmp_breakpoint_ops.
* breakpoint.h (enum bptype): New item bp_longjmp_call_dummy. Delete
FIXME comment and extend the other comment for bp_call_dummy.
(set_longjmp_breakpoint_for_call_dummy)
(check_longjmp_breakpoint_for_call_dummy): New declarations.
* dummy-frame.c: Include gdbthread.h.
(pop_dummy_frame_bpt): New function.
(pop_dummy_frame): Call pop_dummy_frame_bpt.
(dummy_frame_discard): New function.
(cleanup_dummy_frames): Update the comment about longjmps.
* dummy-frame.h (dummy_frame_discard): New declaration.
* gdbthread.h (struct thread_info): Extend initiating_frame comment.
* infcall.c (call_function_by_hand): New variable longjmp_b. Call
set_longjmp_breakpoint_for_call_dummy. Chain its breakpoints with BPT.
* infrun.c (handle_inferior_event) <BPSTAT_WHAT_CLEAR_LONGJMP_RESUME>:
Add case 4 comment. Call check_longjmp_breakpoint_for_call_dummy and
keep_going if IS_LONGJMP and there is no other reason to stop.
gdb/testsuite/
Remove stale dummy frames.
* gdb.base/call-signal-resume.exp (maintenance print dummy-frames)
(maintenance info breakpoints): New tests.
* gdb.base/stale-infcall.c: New file.
* gdb.base/stale-infcall.exp: New file.
Diffstat (limited to 'gdb/breakpoint.c')
-rw-r--r-- | gdb/breakpoint.c | 106 |
1 files changed, 104 insertions, 2 deletions
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 82265cc..12ab271 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -68,6 +68,7 @@ #include "skip.h" #include "gdb_regex.h" #include "ax-gdb.h" +#include "dummy-frame.h" /* readline include files */ #include "readline/readline.h" @@ -287,6 +288,9 @@ static struct breakpoint_ops internal_breakpoint_ops; /* Momentary breakpoints class type. */ static struct breakpoint_ops momentary_breakpoint_ops; +/* Momentary breakpoints for bp_longjmp and bp_exception class type. */ +static struct breakpoint_ops longjmp_breakpoint_ops; + /* The breakpoint_ops structure to be used in regular user created breakpoints. */ struct breakpoint_ops bkpt_breakpoint_ops; @@ -3204,6 +3208,7 @@ update_breakpoints_after_exec (void) /* Longjmp and longjmp-resume breakpoints are also meaningless after an exec. */ if (b->type == bp_longjmp || b->type == bp_longjmp_resume + || b->type == bp_longjmp_call_dummy || b->type == bp_exception || b->type == bp_exception_resume) { delete_breakpoint (b); @@ -3495,6 +3500,7 @@ breakpoint_init_inferior (enum inf_context context) switch (b->type) { case bp_call_dummy: + case bp_longjmp_call_dummy: /* If the call dummy breakpoint is at the entry point it will cause problems when the inferior is rerun, so we better get @@ -5154,9 +5160,10 @@ bpstat_what (bpstat bs_head) } break; case bp_longjmp: + case bp_longjmp_call_dummy: case bp_exception: this_action = BPSTAT_WHAT_SET_LONGJMP_RESUME; - retval.is_longjmp = bptype == bp_longjmp; + retval.is_longjmp = bptype != bp_exception; break; case bp_longjmp_resume: case bp_exception_resume: @@ -5489,6 +5496,7 @@ bptype_string (enum bptype type) {bp_access_watchpoint, "acc watchpoint"}, {bp_longjmp, "longjmp"}, {bp_longjmp_resume, "longjmp resume"}, + {bp_longjmp_call_dummy, "longjmp for call dummy"}, {bp_exception, "exception"}, {bp_exception_resume, "exception resume"}, {bp_step_resume, "step resume"}, @@ -5631,6 +5639,7 @@ print_one_breakpoint_location (struct breakpoint *b, case bp_finish: case bp_longjmp: case bp_longjmp_resume: + case bp_longjmp_call_dummy: case bp_exception: case bp_exception_resume: case bp_step_resume: @@ -6494,6 +6503,7 @@ init_bp_location (struct bp_location *loc, const struct bp_location_ops *ops, case bp_finish: case bp_longjmp: case bp_longjmp_resume: + case bp_longjmp_call_dummy: case bp_exception: case bp_exception_resume: case bp_step_resume: @@ -6797,8 +6807,10 @@ set_longjmp_breakpoint (struct thread_info *tp, struct frame_id frame) enum bptype type = b->type == bp_longjmp_master ? bp_longjmp : bp_exception; struct breakpoint *clone; + /* longjmp_breakpoint_ops ensures INITIATING_FRAME is cleared again + after their removal. */ clone = momentary_breakpoint_from_master (b, type, - &momentary_breakpoint_ops); + &longjmp_breakpoint_ops); clone->thread = thread; } @@ -6832,6 +6844,75 @@ delete_longjmp_breakpoint_at_next_stop (int thread) } } +/* Place breakpoints of type bp_longjmp_call_dummy to catch longjmp for + INFERIOR_PTID thread. Chain them all by RELATED_BREAKPOINT and return + pointer to any of them. Return NULL if this system cannot place longjmp + breakpoints. */ + +struct breakpoint * +set_longjmp_breakpoint_for_call_dummy (void) +{ + struct breakpoint *b, *retval = NULL; + + ALL_BREAKPOINTS (b) + if (b->pspace == current_program_space && b->type == bp_longjmp_master) + { + struct breakpoint *new_b; + + new_b = momentary_breakpoint_from_master (b, bp_longjmp_call_dummy, + &momentary_breakpoint_ops); + new_b->thread = pid_to_thread_id (inferior_ptid); + + /* Link NEW_B into the chain of RETVAL breakpoints. */ + + gdb_assert (new_b->related_breakpoint == new_b); + if (retval == NULL) + retval = new_b; + new_b->related_breakpoint = retval; + while (retval->related_breakpoint != new_b->related_breakpoint) + retval = retval->related_breakpoint; + retval->related_breakpoint = new_b; + } + + return retval; +} + +/* Verify all existing dummy frames and their associated breakpoints for + THREAD. Remove those which can no longer be found in the current frame + stack. + + You should call this function only at places where it is safe to currently + unwind the whole stack. Failed stack unwind would discard live dummy + frames. */ + +void +check_longjmp_breakpoint_for_call_dummy (int thread) +{ + struct breakpoint *b, *b_tmp; + + ALL_BREAKPOINTS_SAFE (b, b_tmp) + if (b->type == bp_longjmp_call_dummy && b->thread == thread) + { + struct breakpoint *dummy_b = b->related_breakpoint; + + while (dummy_b != b && dummy_b->type != bp_call_dummy) + dummy_b = dummy_b->related_breakpoint; + if (dummy_b->type != bp_call_dummy + || frame_find_by_id (dummy_b->frame_id) != NULL) + continue; + + dummy_frame_discard (dummy_b->frame_id); + + while (b->related_breakpoint != b) + { + if (b_tmp == b->related_breakpoint) + b_tmp = b->related_breakpoint->next; + delete_breakpoint (b->related_breakpoint); + } + delete_breakpoint (b); + } +} + void enable_overlay_breakpoints (void) { @@ -12821,6 +12902,22 @@ momentary_bkpt_print_mention (struct breakpoint *b) /* Nothing to mention. These breakpoints are internal. */ } +/* Ensure INITIATING_FRAME is cleared when no such breakpoint exists. + + It gets cleared already on the removal of the first one of such placed + breakpoints. This is OK as they get all removed altogether. */ + +static void +longjmp_bkpt_dtor (struct breakpoint *self) +{ + struct thread_info *tp = find_thread_id (self->thread); + + if (tp) + tp->initiating_frame = null_frame_id; + + momentary_breakpoint_ops.dtor (self); +} + /* Specific methods for probe breakpoints. */ static int @@ -15409,6 +15506,11 @@ initialize_breakpoint_ops (void) ops->print_it = momentary_bkpt_print_it; ops->print_mention = momentary_bkpt_print_mention; + /* Momentary breakpoints for bp_longjmp and bp_exception. */ + ops = &longjmp_breakpoint_ops; + *ops = momentary_breakpoint_ops; + ops->dtor = longjmp_bkpt_dtor; + /* Probe breakpoints. */ ops = &bkpt_probe_breakpoint_ops; *ops = bkpt_breakpoint_ops; |