2011-05-26 Pedro Alves <pedro@codesourcery.com>

gdb/
	* breakpoint.h (enum bptype) <bp_hp_step_resume>: 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.
This commit is contained in:
Pedro Alves 2011-05-26 14:59:18 +00:00
parent 51be5b68a5
commit 2c03e5bed3
6 changed files with 173 additions and 36 deletions

View file

@ -1,3 +1,32 @@
2011-05-26 Pedro Alves <pedro@codesourcery.com>
* breakpoint.h (enum bptype) <bp_hp_step_resume>: 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 <pedro@codesourcery.com> 2011-05-26 Pedro Alves <pedro@codesourcery.com>
* breakpoint.c (iterate_over_related_breakpoints): New. * breakpoint.c (iterate_over_related_breakpoints): New.

View file

@ -2415,7 +2415,7 @@ update_breakpoints_after_exec (void)
} }
/* Step-resume breakpoints are meaningless after an exec(). */ /* 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); delete_breakpoint (b);
continue; continue;
@ -3503,6 +3503,7 @@ print_it_typical (bpstat bs)
case bp_exception: case bp_exception:
case bp_exception_resume: case bp_exception_resume:
case bp_step_resume: case bp_step_resume:
case bp_hp_step_resume:
case bp_watchpoint_scope: case bp_watchpoint_scope:
case bp_call_dummy: case bp_call_dummy:
case bp_std_terminate: case bp_std_terminate:
@ -4489,6 +4490,15 @@ bpstat_what (bpstat bs_head)
this_action = BPSTAT_WHAT_SINGLE; this_action = BPSTAT_WHAT_SINGLE;
} }
break; 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_watchpoint_scope:
case bp_thread_event: case bp_thread_event:
case bp_overlay_event: case bp_overlay_event:
@ -4757,6 +4767,7 @@ bptype_string (enum bptype type)
{bp_exception, "exception"}, {bp_exception, "exception"},
{bp_exception_resume, "exception resume"}, {bp_exception_resume, "exception resume"},
{bp_step_resume, "step resume"}, {bp_step_resume, "step resume"},
{bp_hp_step_resume, "high-priority step resume"},
{bp_watchpoint_scope, "watchpoint scope"}, {bp_watchpoint_scope, "watchpoint scope"},
{bp_call_dummy, "call dummy"}, {bp_call_dummy, "call dummy"},
{bp_std_terminate, "std::terminate"}, {bp_std_terminate, "std::terminate"},
@ -4892,6 +4903,7 @@ print_one_breakpoint_location (struct breakpoint *b,
case bp_exception: case bp_exception:
case bp_exception_resume: case bp_exception_resume:
case bp_step_resume: case bp_step_resume:
case bp_hp_step_resume:
case bp_watchpoint_scope: case bp_watchpoint_scope:
case bp_call_dummy: case bp_call_dummy:
case bp_std_terminate: case bp_std_terminate:
@ -5701,6 +5713,7 @@ allocate_bp_location (struct breakpoint *bpt)
case bp_exception: case bp_exception:
case bp_exception_resume: case bp_exception_resume:
case bp_step_resume: case bp_step_resume:
case bp_hp_step_resume:
case bp_watchpoint_scope: case bp_watchpoint_scope:
case bp_call_dummy: case bp_call_dummy:
case bp_std_terminate: case bp_std_terminate:
@ -7227,6 +7240,7 @@ mention (struct breakpoint *b)
case bp_exception: case bp_exception:
case bp_exception_resume: case bp_exception_resume:
case bp_step_resume: case bp_step_resume:
case bp_hp_step_resume:
case bp_call_dummy: case bp_call_dummy:
case bp_std_terminate: case bp_std_terminate:
case bp_watchpoint_scope: case bp_watchpoint_scope:
@ -11459,6 +11473,7 @@ breakpoint_re_set_one (void *bint)
case bp_call_dummy: case bp_call_dummy:
case bp_std_terminate: case bp_std_terminate:
case bp_step_resume: case bp_step_resume:
case bp_hp_step_resume:
case bp_longjmp: case bp_longjmp:
case bp_longjmp_resume: case bp_longjmp_resume:
case bp_exception: case bp_exception:

View file

@ -68,10 +68,13 @@ enum bptype
bp_exception_resume, bp_exception_resume,
/* Used by wait_for_inferior for stepping over subroutine calls, /* Used by wait_for_inferior for stepping over subroutine calls,
for stepping over signal handlers, and for skipping and for skipping prologues. */
prologues. */
bp_step_resume, 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 /* Used to detect when a watchpoint expression has gone out of
scope. These breakpoints are usually not visible to the user. 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_KEEP_CHECKING. */
BPSTAT_WHAT_CLEAR_LONGJMP_RESUME, 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 /* Rather than distinguish between noisy and silent stops here, it
might be cleaner to have bpstat_print make that decision (also might be cleaner to have bpstat_print make that decision (also
taking into account stop_print_frame and source_only). But the taking into account stop_print_frame and source_only). But the
@ -733,8 +739,14 @@ enum bpstat_what_main_action
/* Stop and print. */ /* Stop and print. */
BPSTAT_WHAT_STOP_NOISY, BPSTAT_WHAT_STOP_NOISY,
/* Clear step resume breakpoint, and keep checking. */ /* Clear step resume breakpoint, and keep checking. High-priority
BPSTAT_WHAT_STEP_RESUME, 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 /* An enum indicating the kind of "stack dummy" stop. This is a bit

View file

@ -99,7 +99,7 @@ void _initialize_infrun (void);
void nullify_last_target_wait_ptid (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 *); 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. */ original breakpoint is hit. */
if (tp->control.step_resume_breakpoint == NULL) 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; tp->step_after_step_resume_breakpoint = 1;
} }
@ -4173,7 +4173,7 @@ process_event_stop_test:
"infrun: signal arrived while stepping over " "infrun: signal arrived while stepping over "
"breakpoint\n"); "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; ecs->event_thread->step_after_step_resume_breakpoint = 1;
/* Reset trap_expected to ensure breakpoints are re-inserted. */ /* Reset trap_expected to ensure breakpoints are re-inserted. */
ecs->event_thread->control.trap_expected = 0; ecs->event_thread->control.trap_expected = 0;
@ -4203,7 +4203,7 @@ process_event_stop_test:
"infrun: signal may take us out of " "infrun: signal may take us out of "
"single-step range\n"); "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. */ /* Reset trap_expected to ensure breakpoints are re-inserted. */
ecs->event_thread->control.trap_expected = 0; ecs->event_thread->control.trap_expected = 0;
keep_going (ecs); keep_going (ecs);
@ -4349,6 +4349,24 @@ process_event_stop_test:
where we are stepping and step out of the right range. */ where we are stepping and step out of the right range. */
break; 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: case BPSTAT_WHAT_STOP_NOISY:
if (debug_infrun) if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_STOP_NOISY\n"); fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_STOP_NOISY\n");
@ -4371,9 +4389,9 @@ process_event_stop_test:
stop_stepping (ecs); stop_stepping (ecs);
return; return;
case BPSTAT_WHAT_STEP_RESUME: case BPSTAT_WHAT_HP_STEP_RESUME:
if (debug_infrun) 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); delete_step_resume_breakpoint (ecs->event_thread);
if (ecs->event_thread->step_after_step_resume_breakpoint) if (ecs->event_thread->step_after_step_resume_breakpoint)
@ -4386,17 +4404,6 @@ process_event_stop_test:
keep_going (ecs); keep_going (ecs);
return; 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; break;
case BPSTAT_WHAT_KEEP_CHECKING: 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. */ This is used to both functions and to skip over code. */
static void static void
insert_step_resume_breakpoint_at_sal (struct gdbarch *gdbarch, insert_step_resume_breakpoint_at_sal_1 (struct gdbarch *gdbarch,
struct symtab_and_line sr_sal, struct symtab_and_line sr_sal,
struct frame_id sr_id) struct frame_id sr_id,
enum bptype sr_type)
{ {
/* There should never be more than one step-resume or longjmp-resume /* There should never be more than one step-resume or longjmp-resume
breakpoint per thread, so we should never be setting a new breakpoint per thread, so we should never be setting a new
step_resume_breakpoint when one is already active. */ step_resume_breakpoint when one is already active. */
gdb_assert (inferior_thread ()->control.step_resume_breakpoint == NULL); 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) if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, fprintf_unfiltered (gdb_stdlog,
@ -5223,18 +5232,28 @@ insert_step_resume_breakpoint_at_sal (struct gdbarch *gdbarch,
paddress (gdbarch, sr_sal.pc)); paddress (gdbarch, sr_sal.pc));
inferior_thread ()->control.step_resume_breakpoint 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);
} }
/* Insert a "step-resume breakpoint" at RETURN_FRAME.pc. This is used static void
to skip a potential signal handler. 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 "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 This is called with the interrupted function's frame. The signal
handler, when it returns, will resume the interrupted function at handler, when it returns, will resume the interrupted function at
RETURN_FRAME.pc. */ RETURN_FRAME.pc. */
static void 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 symtab_and_line sr_sal;
struct gdbarch *gdbarch; 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.section = find_pc_overlay (sr_sal.pc);
sr_sal.pspace = get_frame_program_space (return_frame); sr_sal.pspace = get_frame_program_space (return_frame);
insert_step_resume_breakpoint_at_sal (gdbarch, sr_sal, insert_step_resume_breakpoint_at_sal_1 (gdbarch, sr_sal,
get_stack_frame_id (return_frame)); get_stack_frame_id (return_frame),
bp_hp_step_resume);
} }
/* Similar to insert_step_resume_breakpoint_at_frame, except /* Insert a "step-resume breakpoint" at the previous frame's PC. This
but a breakpoint at the previous frame's PC. This is used to is used to skip a function after stepping into it (for "next" or if
skip a function after stepping into it (for "next" or if the called the called function has no debugging information).
function has no debugging information).
The current function has almost always been reached by single The current function has almost always been reached by single
stepping a call or return instruction. NEXT_FRAME belongs to the 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. resume address.
This is a separate function rather than reusing 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 get_prev_frame, which may stop prematurely (see the implementation
of frame_unwind_caller_id for an example). */ of frame_unwind_caller_id for an example). */

View file

@ -1,3 +1,7 @@
2011-05-26 Pedro Alves <pedro@codesourcery.com>
* gdb.reverse/next-reverse-bkpt-over-sr.exp: New test.
2011-05-24 Keith Seitz <keiths@redhat.com> 2011-05-24 Keith Seitz <keiths@redhat.com>
PR breakpoint/12803 PR breakpoint/12803

View file

@ -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 <http://www.gnu.org/licenses/>. */
# 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"