From c4f1ba8ffa817330b194c0aca4d50f56b6a5d578 Mon Sep 17 00:00:00 2001 From: palves Date: Thu, 26 May 2011 14:59:16 +0000 Subject: [PATCH] 2011-05-26 Pedro Alves gdb/ * breakpoint.h (enum bptype) : New. (enum bpstat_what_main_action): Move BPSTAT_WHAT_STEP_RESUME before BPSTAT_WHAT_STOP_SILENT. Add BPSTAT_WHAT_HP_STEP_RESUME at the end. * breakpoint.c (update_breakpoints_after_exec): Also delete hp step-resume breakpoints. (print_it_typical): Handle bp_hp_step_resume. (bpstat_what): Ditto. (bptype_string): Ditto. (print_one_breakpoint_location): Ditto. (allocate_bp_location): Ditto. (mention): Ditto. (breakpoint_re_set_one): Ditto. * infrun.c (handle_inferior_event): Adjust. Split BPSTAT_WHAT_STEP_RESUME handling in BPSTAT_WHAT_STEP_RESUME and BPSTAT_WHAT_HP_STEP_RESUME. (insert_step_resume_breakpoint_at_sal): Rename to ... (insert_step_resume_breakpoint_at_sal_1): ... this. Add bptype parameter. Handle it. (insert_step_resume_breakpoint_at_sal): Reimplement on top of insert_step_resume_breakpoint_at_sal_1. (insert_step_resume_breakpoint_at_frame): Rename to ... (insert_hp_step_resume_breakpoint_at_frame): ... this. Adjust to set a high-priority step-resume breakpoint. (insert_step_resume_breakpoint_at_frame): Adjust comment. (insert_step_resume_breakpoint_at_caller): Ditto. gdb/testsuite/ * gdb.reverse/next-reverse-bkpt-over-sr.exp: New test. --- gdb/ChangeLog | 29 ++++++++ gdb/breakpoint.c | 17 ++++- gdb/breakpoint.h | 20 ++++-- gdb/infrun.c | 81 +++++++++++++--------- gdb/testsuite/ChangeLog | 4 ++ .../gdb.reverse/next-reverse-bkpt-over-sr.exp | 58 ++++++++++++++++ 6 files changed, 173 insertions(+), 36 deletions(-) create mode 100644 gdb/testsuite/gdb.reverse/next-reverse-bkpt-over-sr.exp diff --git a/gdb/ChangeLog b/gdb/ChangeLog index bc5620ce83..fe40345da4 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,34 @@ 2011-05-26 Pedro Alves + * breakpoint.h (enum bptype) : New. + (enum bpstat_what_main_action): Move BPSTAT_WHAT_STEP_RESUME + before BPSTAT_WHAT_STOP_SILENT. Add BPSTAT_WHAT_HP_STEP_RESUME + at the end. + * breakpoint.c (update_breakpoints_after_exec): Also delete hp + step-resume breakpoints. + (print_it_typical): Handle bp_hp_step_resume. + (bpstat_what): Ditto. + (bptype_string): Ditto. + (print_one_breakpoint_location): Ditto. + (allocate_bp_location): Ditto. + (mention): Ditto. + (breakpoint_re_set_one): Ditto. + * infrun.c (handle_inferior_event): Adjust. Split + BPSTAT_WHAT_STEP_RESUME handling in BPSTAT_WHAT_STEP_RESUME and + BPSTAT_WHAT_HP_STEP_RESUME. + (insert_step_resume_breakpoint_at_sal): Rename to ... + (insert_step_resume_breakpoint_at_sal_1): ... this. Add bptype + parameter. Handle it. + (insert_step_resume_breakpoint_at_sal): Reimplement on top of + insert_step_resume_breakpoint_at_sal_1. + (insert_step_resume_breakpoint_at_frame): Rename to ... + (insert_hp_step_resume_breakpoint_at_frame): ... this. Adjust to + set a high-priority step-resume breakpoint. + (insert_step_resume_breakpoint_at_frame): Adjust comment. + (insert_step_resume_breakpoint_at_caller): Ditto. + +2011-05-26 Pedro Alves + * breakpoint.c (iterate_over_related_breakpoints): New. (do_map_delete_breakpoint): New. (delete_command): Pass do_map_delete_breakpoint to diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 5995c649ad..fc30d265b2 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -2415,7 +2415,7 @@ update_breakpoints_after_exec (void) } /* Step-resume breakpoints are meaningless after an exec(). */ - if (b->type == bp_step_resume) + if (b->type == bp_step_resume || b->type == bp_hp_step_resume) { delete_breakpoint (b); continue; @@ -3503,6 +3503,7 @@ print_it_typical (bpstat bs) case bp_exception: case bp_exception_resume: case bp_step_resume: + case bp_hp_step_resume: case bp_watchpoint_scope: case bp_call_dummy: case bp_std_terminate: @@ -4489,6 +4490,15 @@ bpstat_what (bpstat bs_head) this_action = BPSTAT_WHAT_SINGLE; } break; + case bp_hp_step_resume: + if (bs->stop) + this_action = BPSTAT_WHAT_HP_STEP_RESUME; + else + { + /* It is for the wrong frame. */ + this_action = BPSTAT_WHAT_SINGLE; + } + break; case bp_watchpoint_scope: case bp_thread_event: case bp_overlay_event: @@ -4757,6 +4767,7 @@ bptype_string (enum bptype type) {bp_exception, "exception"}, {bp_exception_resume, "exception resume"}, {bp_step_resume, "step resume"}, + {bp_hp_step_resume, "high-priority step resume"}, {bp_watchpoint_scope, "watchpoint scope"}, {bp_call_dummy, "call dummy"}, {bp_std_terminate, "std::terminate"}, @@ -4892,6 +4903,7 @@ print_one_breakpoint_location (struct breakpoint *b, case bp_exception: case bp_exception_resume: case bp_step_resume: + case bp_hp_step_resume: case bp_watchpoint_scope: case bp_call_dummy: case bp_std_terminate: @@ -5701,6 +5713,7 @@ allocate_bp_location (struct breakpoint *bpt) case bp_exception: case bp_exception_resume: case bp_step_resume: + case bp_hp_step_resume: case bp_watchpoint_scope: case bp_call_dummy: case bp_std_terminate: @@ -7227,6 +7240,7 @@ mention (struct breakpoint *b) case bp_exception: case bp_exception_resume: case bp_step_resume: + case bp_hp_step_resume: case bp_call_dummy: case bp_std_terminate: case bp_watchpoint_scope: @@ -11459,6 +11473,7 @@ breakpoint_re_set_one (void *bint) case bp_call_dummy: case bp_std_terminate: case bp_step_resume: + case bp_hp_step_resume: case bp_longjmp: case bp_longjmp_resume: case bp_exception: diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h index 0cbd9dd788..2050c6d1d4 100644 --- a/gdb/breakpoint.h +++ b/gdb/breakpoint.h @@ -68,10 +68,13 @@ enum bptype bp_exception_resume, /* Used by wait_for_inferior for stepping over subroutine calls, - for stepping over signal handlers, and for skipping - prologues. */ + and for skipping prologues. */ bp_step_resume, + /* Used by wait_for_inferior for stepping over signal + handlers. */ + bp_hp_step_resume, + /* Used to detect when a watchpoint expression has gone out of scope. These breakpoints are usually not visible to the user. @@ -721,6 +724,9 @@ enum bpstat_what_main_action BPSTAT_WHAT_KEEP_CHECKING. */ BPSTAT_WHAT_CLEAR_LONGJMP_RESUME, + /* Clear step resume breakpoint, and keep checking. */ + BPSTAT_WHAT_STEP_RESUME, + /* Rather than distinguish between noisy and silent stops here, it might be cleaner to have bpstat_print make that decision (also taking into account stop_print_frame and source_only). But the @@ -733,8 +739,14 @@ enum bpstat_what_main_action /* Stop and print. */ BPSTAT_WHAT_STOP_NOISY, - /* Clear step resume breakpoint, and keep checking. */ - BPSTAT_WHAT_STEP_RESUME, + /* Clear step resume breakpoint, and keep checking. High-priority + step-resume breakpoints are used when even if there's a user + breakpoint at the current PC when we set the step-resume + breakpoint, we don't want to re-handle any breakpoint other + than the step-resume when it's hit; instead we want to move + past the breakpoint. This is used in the case of skipping + signal handlers. */ + BPSTAT_WHAT_HP_STEP_RESUME, }; /* An enum indicating the kind of "stack dummy" stop. This is a bit diff --git a/gdb/infrun.c b/gdb/infrun.c index 1d8932ab21..e8ea53a516 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -99,7 +99,7 @@ void _initialize_infrun (void); void nullify_last_target_wait_ptid (void); -static void insert_step_resume_breakpoint_at_frame (struct frame_info *); +static void insert_hp_step_resume_breakpoint_at_frame (struct frame_info *); static void insert_step_resume_breakpoint_at_caller (struct frame_info *); @@ -1778,7 +1778,7 @@ a command like `return' or `jump' to continue execution.")); original breakpoint is hit. */ if (tp->control.step_resume_breakpoint == NULL) { - insert_step_resume_breakpoint_at_frame (get_current_frame ()); + insert_hp_step_resume_breakpoint_at_frame (get_current_frame ()); tp->step_after_step_resume_breakpoint = 1; } @@ -4173,7 +4173,7 @@ process_event_stop_test: "infrun: signal arrived while stepping over " "breakpoint\n"); - insert_step_resume_breakpoint_at_frame (frame); + insert_hp_step_resume_breakpoint_at_frame (frame); ecs->event_thread->step_after_step_resume_breakpoint = 1; /* Reset trap_expected to ensure breakpoints are re-inserted. */ ecs->event_thread->control.trap_expected = 0; @@ -4203,7 +4203,7 @@ process_event_stop_test: "infrun: signal may take us out of " "single-step range\n"); - insert_step_resume_breakpoint_at_frame (frame); + insert_hp_step_resume_breakpoint_at_frame (frame); /* Reset trap_expected to ensure breakpoints are re-inserted. */ ecs->event_thread->control.trap_expected = 0; keep_going (ecs); @@ -4349,6 +4349,24 @@ process_event_stop_test: where we are stepping and step out of the right range. */ break; + case BPSTAT_WHAT_STEP_RESUME: + if (debug_infrun) + fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_STEP_RESUME\n"); + + delete_step_resume_breakpoint (ecs->event_thread); + if (stop_pc == ecs->stop_func_start + && execution_direction == EXEC_REVERSE) + { + /* We are stepping over a function call in reverse, and + just hit the step-resume breakpoint at the start + address of the function. Go back to single-stepping, + which should take us back to the function call. */ + ecs->event_thread->stepping_over_breakpoint = 1; + keep_going (ecs); + return; + } + break; + case BPSTAT_WHAT_STOP_NOISY: if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_STOP_NOISY\n"); @@ -4371,9 +4389,9 @@ process_event_stop_test: stop_stepping (ecs); return; - case BPSTAT_WHAT_STEP_RESUME: + case BPSTAT_WHAT_HP_STEP_RESUME: if (debug_infrun) - fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_STEP_RESUME\n"); + fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_HP_STEP_RESUME\n"); delete_step_resume_breakpoint (ecs->event_thread); if (ecs->event_thread->step_after_step_resume_breakpoint) @@ -4386,17 +4404,6 @@ process_event_stop_test: keep_going (ecs); return; } - if (stop_pc == ecs->stop_func_start - && execution_direction == EXEC_REVERSE) - { - /* We are stepping over a function call in reverse, and - just hit the step-resume breakpoint at the start - address of the function. Go back to single-stepping, - which should take us back to the function call. */ - ecs->event_thread->stepping_over_breakpoint = 1; - keep_going (ecs); - return; - } break; case BPSTAT_WHAT_KEEP_CHECKING: @@ -5208,14 +5215,16 @@ handle_step_into_function_backward (struct gdbarch *gdbarch, This is used to both functions and to skip over code. */ static void -insert_step_resume_breakpoint_at_sal (struct gdbarch *gdbarch, - struct symtab_and_line sr_sal, - struct frame_id sr_id) +insert_step_resume_breakpoint_at_sal_1 (struct gdbarch *gdbarch, + struct symtab_and_line sr_sal, + struct frame_id sr_id, + enum bptype sr_type) { /* There should never be more than one step-resume or longjmp-resume breakpoint per thread, so we should never be setting a new step_resume_breakpoint when one is already active. */ gdb_assert (inferior_thread ()->control.step_resume_breakpoint == NULL); + gdb_assert (sr_type == bp_step_resume || sr_type == bp_hp_step_resume); if (debug_infrun) fprintf_unfiltered (gdb_stdlog, @@ -5223,18 +5232,28 @@ insert_step_resume_breakpoint_at_sal (struct gdbarch *gdbarch, paddress (gdbarch, sr_sal.pc)); inferior_thread ()->control.step_resume_breakpoint - = set_momentary_breakpoint (gdbarch, sr_sal, sr_id, bp_step_resume); + = set_momentary_breakpoint (gdbarch, sr_sal, sr_id, sr_type); +} + +static void +insert_step_resume_breakpoint_at_sal (struct gdbarch *gdbarch, + struct symtab_and_line sr_sal, + struct frame_id sr_id) +{ + insert_step_resume_breakpoint_at_sal_1 (gdbarch, + sr_sal, sr_id, + bp_step_resume); } -/* Insert a "step-resume breakpoint" at RETURN_FRAME.pc. This is used - to skip a potential signal handler. +/* Insert a "high-priority step-resume breakpoint" at RETURN_FRAME.pc. + This is used to skip a potential signal handler. This is called with the interrupted function's frame. The signal handler, when it returns, will resume the interrupted function at RETURN_FRAME.pc. */ static void -insert_step_resume_breakpoint_at_frame (struct frame_info *return_frame) +insert_hp_step_resume_breakpoint_at_frame (struct frame_info *return_frame) { struct symtab_and_line sr_sal; struct gdbarch *gdbarch; @@ -5247,14 +5266,14 @@ insert_step_resume_breakpoint_at_frame (struct frame_info *return_frame) sr_sal.section = find_pc_overlay (sr_sal.pc); sr_sal.pspace = get_frame_program_space (return_frame); - insert_step_resume_breakpoint_at_sal (gdbarch, sr_sal, - get_stack_frame_id (return_frame)); + insert_step_resume_breakpoint_at_sal_1 (gdbarch, sr_sal, + get_stack_frame_id (return_frame), + bp_hp_step_resume); } -/* Similar to insert_step_resume_breakpoint_at_frame, except - but a breakpoint at the previous frame's PC. This is used to - skip a function after stepping into it (for "next" or if the called - function has no debugging information). +/* Insert a "step-resume breakpoint" at the previous frame's PC. This + is used to skip a function after stepping into it (for "next" or if + the called function has no debugging information). The current function has almost always been reached by single stepping a call or return instruction. NEXT_FRAME belongs to the @@ -5262,7 +5281,7 @@ insert_step_resume_breakpoint_at_frame (struct frame_info *return_frame) resume address. This is a separate function rather than reusing - insert_step_resume_breakpoint_at_frame in order to avoid + insert_hp_step_resume_breakpoint_at_frame in order to avoid get_prev_frame, which may stop prematurely (see the implementation of frame_unwind_caller_id for an example). */ diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index a710243fe4..975a15d48d 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2011-05-26 Pedro Alves + + * gdb.reverse/next-reverse-bkpt-over-sr.exp: New test. + 2011-05-24 Keith Seitz PR breakpoint/12803 diff --git a/gdb/testsuite/gdb.reverse/next-reverse-bkpt-over-sr.exp b/gdb/testsuite/gdb.reverse/next-reverse-bkpt-over-sr.exp new file mode 100644 index 0000000000..9a95dca1ce --- /dev/null +++ b/gdb/testsuite/gdb.reverse/next-reverse-bkpt-over-sr.exp @@ -0,0 +1,58 @@ +# Copyright 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . */ + +# This file is part of the GDB testsuite. It tests reverse stepping. +# Lots of code borrowed from "step-test.exp". + +# +# reverse-next over a function call sets a step-resume breakpoint at +# callee's entry point, runs to it, and then does an extra single-step +# to get at the callee's caller. Test that a user breakpoint set at +# the same location as the step-resume breakpoint isn't ignored. +# + +if ![target_info exists gdb,can_reverse] { + return +} + +set testfile "next-reverse-bkpt-over-sr" +set srcfile step-reverse.c + +if { [prepare_for_testing $testfile.exp $testfile $srcfile] } { + return -1 +} + +if ![runto_main] then { + fail "Can't run to main" + return 0 +} + +if [target_info exists gdb,use_precord] { + # Activate process record/replay + gdb_test_no_output "record" "Turn on process record" +} + +set lineno [gdb_get_line_number "STEP INTO THIS CALL"] +gdb_test "advance $lineno" ".*STEP INTO THIS CALL.*" "get past callee call" + +gdb_test "b \*callee" "" "set breakpoint at callee's entry" + +gdb_test "reverse-next" \ + "Breakpoint.*, callee.*ENTER CALLEE.*" \ + "reverse-next over call trips user breakpoint at function entry" + +gdb_test "up" \ + ".*NEXT OVER THIS CALL.*" \ + "stopped at the right callee call" -- 2.11.0