* breakpoint.h (enum bptype): New type bp_through_sigtramp.
(bpstat_what_main_action): New code BPSTAT_WHAT_THROUGH_SIGTRAMP. * breakpoint.c (bpstat_what): Return BPSTAT_WHAT_THROUGH_SIGTRAMP if we hit a bp_through_sigtramp breakpoint. Remove kludge which ignored bs->stop for a bp_step_resume breakpoint. * infrun.c (wait_for_inferior): Make a through_sigtramp_breakpoint which performs one (the check_sigtramp2 one) of the functions which had been handled by the step_resume_breakpoint. For each use of the step_resume_breakpoint, make it still use the step_resume_breakpoint, use the through_sigtramp_breakpoint, or operate on both. Deal with BPSTAT_WHAT_THROUGH_SIGTRAMP return from bpstat_what. When setting the frame address of the step resume breakpoint, set it to the address for frame *before* the call instruction is executed, not after.
This commit is contained in:
parent
3fed1c4a60
commit
bcc3771841
4 changed files with 140 additions and 64 deletions
|
@ -1,5 +1,21 @@
|
|||
Thu Feb 24 08:30:33 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
|
||||
|
||||
* breakpoint.h (enum bptype): New type bp_through_sigtramp.
|
||||
(bpstat_what_main_action): New code BPSTAT_WHAT_THROUGH_SIGTRAMP.
|
||||
* breakpoint.c (bpstat_what): Return BPSTAT_WHAT_THROUGH_SIGTRAMP
|
||||
if we hit a bp_through_sigtramp breakpoint. Remove kludge which
|
||||
ignored bs->stop for a bp_step_resume breakpoint.
|
||||
* infrun.c (wait_for_inferior): Make a through_sigtramp_breakpoint
|
||||
which performs one (the check_sigtramp2 one) of the functions
|
||||
which had been handled by the step_resume_breakpoint. For each
|
||||
use of the step_resume_breakpoint, make it still use the
|
||||
step_resume_breakpoint, use the through_sigtramp_breakpoint, or
|
||||
operate on both.
|
||||
Deal with BPSTAT_WHAT_THROUGH_SIGTRAMP return from bpstat_what.
|
||||
When setting the frame address of the step resume breakpoint, set
|
||||
it to the address for frame *before* the call instruction is
|
||||
executed, not after.
|
||||
|
||||
* mips-tdep.c (mips_print_register): Print integers using
|
||||
print_scalar_formatted rather than duplicating all the
|
||||
CC_HAS_LONG_LONG and so on.
|
||||
|
|
|
@ -1267,6 +1267,9 @@ bpstat_what (bs)
|
|||
/* We hit the step_resume breakpoint. */
|
||||
step_resume,
|
||||
|
||||
/* We hit the through_sigtramp breakpoint. */
|
||||
through_sig,
|
||||
|
||||
/* This is just used to count how many enums there are. */
|
||||
class_last
|
||||
};
|
||||
|
@ -1282,6 +1285,7 @@ bpstat_what (bs)
|
|||
#define clrlr BPSTAT_WHAT_CLEAR_LONGJMP_RESUME
|
||||
#define clrlrs BPSTAT_WHAT_CLEAR_LONGJMP_RESUME_SINGLE
|
||||
#define sr BPSTAT_WHAT_STEP_RESUME
|
||||
#define ts BPSTAT_WHAT_THROUGH_SIGTRAMP
|
||||
|
||||
/* "Can't happen." Might want to print an error message.
|
||||
abort() is not out of the question, but chances are GDB is just
|
||||
|
@ -1299,22 +1303,25 @@ bpstat_what (bs)
|
|||
/* step_resume entries: a step resume breakpoint overrides another
|
||||
breakpoint of signal handling (see comment in wait_for_inferior
|
||||
at first IN_SIGTRAMP where we set the step_resume breakpoint). */
|
||||
/* We handle the through_sigtramp_breakpoint the same way; having both
|
||||
one of those and a step_resume_breakpoint is probably very rare (?). */
|
||||
|
||||
static const enum bpstat_what_main_action
|
||||
table[(int)class_last][(int)BPSTAT_WHAT_LAST] =
|
||||
{
|
||||
/* old action */
|
||||
/* keep_c stop_s stop_n single setlr clrlr clrlrs sr */
|
||||
|
||||
/*no_effect*/ {keep_c, stop_s, stop_n, single, setlr , clrlr , clrlrs, sr},
|
||||
/*wp_silent*/ {stop_s, stop_s, stop_n, stop_s, stop_s, stop_s, stop_s, sr},
|
||||
/*wp_noisy*/ {stop_n, stop_n, stop_n, stop_n, stop_n, stop_n, stop_n, sr},
|
||||
/*bp_nostop*/ {single, stop_s, stop_n, single, setlr , clrlrs, clrlrs, sr},
|
||||
/*bp_silent*/ {stop_s, stop_s, stop_n, stop_s, stop_s, stop_s, stop_s, sr},
|
||||
/*bp_noisy*/ {stop_n, stop_n, stop_n, stop_n, stop_n, stop_n, stop_n, sr},
|
||||
/*long_jump*/ {setlr , stop_s, stop_n, setlr , err , err , err , sr},
|
||||
/*long_resume*/ {clrlr , stop_s, stop_n, clrlrs, err , err , err , sr},
|
||||
/*step_resume*/ {sr , sr , sr , sr , sr , sr , sr , sr}
|
||||
/* keep_c stop_s stop_n single setlr clrlr clrlrs sr ts
|
||||
*/
|
||||
/*no_effect*/ {keep_c,stop_s,stop_n,single, setlr , clrlr , clrlrs, sr, ts},
|
||||
/*wp_silent*/ {stop_s,stop_s,stop_n,stop_s, stop_s, stop_s, stop_s, sr, ts},
|
||||
/*wp_noisy*/ {stop_n,stop_n,stop_n,stop_n, stop_n, stop_n, stop_n, sr, ts},
|
||||
/*bp_nostop*/ {single,stop_s,stop_n,single, setlr , clrlrs, clrlrs, sr, ts},
|
||||
/*bp_silent*/ {stop_s,stop_s,stop_n,stop_s, stop_s, stop_s, stop_s, sr, ts},
|
||||
/*bp_noisy*/ {stop_n,stop_n,stop_n,stop_n, stop_n, stop_n, stop_n, sr, ts},
|
||||
/*long_jump*/ {setlr ,stop_s,stop_n,setlr , err , err , err , sr, ts},
|
||||
/*long_resume*/ {clrlr ,stop_s,stop_n,clrlrs, err , err , err , sr, ts},
|
||||
/*step_resume*/ {sr ,sr ,sr ,sr , sr , sr , sr , sr, ts},
|
||||
/*through_sig*/ {ts ,ts ,ts ,ts , ts , ts , ts , ts, ts}
|
||||
};
|
||||
#undef keep_c
|
||||
#undef stop_s
|
||||
|
@ -1324,6 +1331,8 @@ bpstat_what (bs)
|
|||
#undef clrlr
|
||||
#undef clrlrs
|
||||
#undef err
|
||||
#undef sr
|
||||
#undef ts
|
||||
enum bpstat_what_main_action current_action = BPSTAT_WHAT_KEEP_CHECKING;
|
||||
struct bpstat_what retval;
|
||||
|
||||
|
@ -1370,21 +1379,16 @@ bpstat_what (bs)
|
|||
bs_class = long_resume;
|
||||
break;
|
||||
case bp_step_resume:
|
||||
#if 0
|
||||
/* Need to temporarily disable this until we can fix the bug
|
||||
with nexting over a breakpoint with ->stop clear causing
|
||||
an infinite loop. For now, treat the breakpoint as having
|
||||
been hit even if the frame is wrong. */
|
||||
if (bs->stop)
|
||||
{
|
||||
#endif
|
||||
bs_class = step_resume;
|
||||
#if 0
|
||||
}
|
||||
else
|
||||
/* It is for the wrong frame. */
|
||||
bs_class = bp_nostop;
|
||||
#endif
|
||||
break;
|
||||
case bp_through_sigtramp:
|
||||
bs_class = through_sig;
|
||||
break;
|
||||
case bp_call_dummy:
|
||||
/* Make sure the action is stop (silent or noisy), so infrun.c
|
||||
|
@ -1468,6 +1472,7 @@ breakpoint_1 (bnum, allflag)
|
|||
case bp_longjmp:
|
||||
case bp_longjmp_resume:
|
||||
case bp_step_resume:
|
||||
case bp_through_sigtramp:
|
||||
case bp_call_dummy:
|
||||
if (addressprint)
|
||||
printf_filtered ("%s ", local_hex_string_custom ((unsigned long) b->address, "08l"));
|
||||
|
@ -1498,6 +1503,7 @@ breakpoint_1 (bnum, allflag)
|
|||
printf_filtered ("\tstop only in stack frame at ");
|
||||
print_address_numeric (b->frame, gdb_stdout);
|
||||
printf_filtered ("\n");
|
||||
}
|
||||
if (b->cond)
|
||||
{
|
||||
printf_filtered ("\tstop only if ");
|
||||
|
@ -1824,7 +1830,7 @@ mention (b)
|
|||
break;
|
||||
case bp_breakpoint:
|
||||
printf_filtered ("Breakpoint %d at ", b->number);
|
||||
print_address_numeric (b->address);
|
||||
print_address_numeric (b->address, gdb_stdout);
|
||||
if (b->source_file)
|
||||
printf_filtered (": file %s, line %d.",
|
||||
b->source_file, b->line_number);
|
||||
|
@ -1834,6 +1840,7 @@ mention (b)
|
|||
case bp_longjmp:
|
||||
case bp_longjmp_resume:
|
||||
case bp_step_resume:
|
||||
case bp_through_sigtramp:
|
||||
case bp_call_dummy:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -49,6 +49,9 @@ enum bptype {
|
|||
stepping over signal handlers, and for skipping prologues. */
|
||||
bp_step_resume,
|
||||
|
||||
/* Used by wait_for_inferior for stepping over signal handlers. */
|
||||
bp_through_sigtramp,
|
||||
|
||||
/* The breakpoint at the end of a call dummy. */
|
||||
/* FIXME: What if the function we are calling longjmp()s out of the
|
||||
call, or the user gets out with the "return" command? We currently
|
||||
|
@ -145,6 +148,8 @@ struct breakpoint
|
|||
struct block *exp_valid_block;
|
||||
/* Value of the watchpoint the last time we checked it. */
|
||||
value val;
|
||||
/* Thread number for thread-specific breakpoint, or -1 if don't care */
|
||||
int thread;
|
||||
};
|
||||
|
||||
/* The following stuff is an abstract data type "bpstat" ("breakpoint status").
|
||||
|
@ -205,23 +210,25 @@ enum bpstat_what_main_action {
|
|||
/* Clear longjmp_resume breakpoint, then handle as BPSTAT_WHAT_SINGLE. */
|
||||
BPSTAT_WHAT_CLEAR_LONGJMP_RESUME_SINGLE,
|
||||
|
||||
/* Clear step resume breakpoint, and keep checking. */
|
||||
BPSTAT_WHAT_STEP_RESUME,
|
||||
|
||||
/* Clear through_sigtramp breakpoint, muck with trap_expected, and keep
|
||||
checking. */
|
||||
BPSTAT_WHAT_THROUGH_SIGTRAMP,
|
||||
|
||||
/* This is just used to keep track of how many enums there are. */
|
||||
BPSTAT_WHAT_LAST
|
||||
};
|
||||
|
||||
struct bpstat_what {
|
||||
enum bpstat_what_main_action main_action : 4;
|
||||
|
||||
/* Did we hit the step resume breakpoint? This is separate from the
|
||||
main_action to allow for it to be combined with any of the main
|
||||
actions. */
|
||||
unsigned int step_resume : 1;
|
||||
enum bpstat_what_main_action main_action;
|
||||
|
||||
/* Did we hit a call dummy breakpoint? This only goes with a main_action
|
||||
of BPSTAT_WHAT_STOP_SILENT or BPSTAT_WHAT_STOP_NOISY (the concept of
|
||||
continuing from a call dummy without popping the frame is not a
|
||||
useful one). */
|
||||
unsigned int call_dummy : 1;
|
||||
int call_dummy;
|
||||
};
|
||||
|
||||
/* Tell what to do about this bpstat. */
|
||||
|
@ -292,8 +299,11 @@ struct bpstat
|
|||
struct frame_info;
|
||||
#endif
|
||||
|
||||
extern int
|
||||
breakpoint_here_p PARAMS ((CORE_ADDR));
|
||||
extern int breakpoint_here_p PARAMS ((CORE_ADDR));
|
||||
|
||||
extern int frame_in_dummy PARAMS ((struct frame_info *));
|
||||
|
||||
extern int breakpoint_thread_match PARAMS ((CORE_ADDR, int));
|
||||
|
||||
extern void
|
||||
until_break_command PARAMS ((char *, int));
|
||||
|
|
113
gdb/infrun.c
113
gdb/infrun.c
|
@ -335,6 +335,7 @@ static CORE_ADDR prev_pc;
|
|||
static CORE_ADDR prev_sp;
|
||||
static CORE_ADDR prev_func_start;
|
||||
static char *prev_func_name;
|
||||
static CORE_ADDR prev_frame_address;
|
||||
|
||||
|
||||
/* Start remote-debugging of a machine over a serial link. */
|
||||
|
@ -360,6 +361,7 @@ init_wait_for_inferior ()
|
|||
prev_sp = 0;
|
||||
prev_func_start = 0;
|
||||
prev_func_name = NULL;
|
||||
prev_frame_address = 0;
|
||||
|
||||
trap_expected_after_continue = 0;
|
||||
breakpoints_inserted = 0;
|
||||
|
@ -402,20 +404,24 @@ wait_for_inferior ()
|
|||
struct symtab *current_symtab;
|
||||
int handling_longjmp = 0; /* FIXME */
|
||||
struct breakpoint *step_resume_breakpoint = NULL;
|
||||
struct breakpoint *through_sigtramp_breakpoint = NULL;
|
||||
int pid;
|
||||
|
||||
old_cleanups = make_cleanup (delete_breakpoint_current_contents,
|
||||
&step_resume_breakpoint);
|
||||
make_cleanup (delete_breakpoint_current_contents,
|
||||
&through_sigtramp_breakpoint);
|
||||
sal = find_pc_line(prev_pc, 0);
|
||||
current_line = sal.line;
|
||||
current_symtab = sal.symtab;
|
||||
|
||||
/* Are we stepping? */
|
||||
#define CURRENTLY_STEPPING() ((step_resume_breakpoint == NULL \
|
||||
&& !handling_longjmp \
|
||||
&& (step_range_end \
|
||||
|| trap_expected)) \
|
||||
|| bpstat_should_step ())
|
||||
#define CURRENTLY_STEPPING() \
|
||||
((through_sigtramp_breakpoint == NULL \
|
||||
&& !handling_longjmp \
|
||||
&& ((step_range_end && step_resume_breakpoint == NULL) \
|
||||
|| trap_expected)) \
|
||||
|| bpstat_should_step ())
|
||||
|
||||
while (1)
|
||||
{
|
||||
|
@ -571,6 +577,15 @@ switch_thread:
|
|||
delete_breakpoint (step_resume_breakpoint);
|
||||
step_resume_breakpoint = NULL;
|
||||
}
|
||||
|
||||
/* Not sure whether we need to blow this away too,
|
||||
but probably it is like the step-resume
|
||||
breakpoint. */
|
||||
if (through_sigtramp_breakpoint)
|
||||
{
|
||||
delete_breakpoint (through_sigtramp_breakpoint);
|
||||
through_sigtramp_breakpoint = NULL;
|
||||
}
|
||||
prev_pc = 0;
|
||||
prev_sp = 0;
|
||||
prev_func_name = NULL;
|
||||
|
@ -663,11 +678,11 @@ switch_thread:
|
|||
if just proceeded over a breakpoint.
|
||||
|
||||
However, if we are trying to proceed over a breakpoint
|
||||
and end up in sigtramp, then step_resume_breakpoint
|
||||
and end up in sigtramp, then through_sigtramp_breakpoint
|
||||
will be set and we should check whether we've hit the
|
||||
step breakpoint. */
|
||||
if (stop_signal == TARGET_SIGNAL_TRAP && trap_expected
|
||||
&& step_resume_breakpoint == NULL)
|
||||
&& through_sigtramp_breakpoint == NULL)
|
||||
bpstat_clear (&stop_bpstat);
|
||||
else
|
||||
{
|
||||
|
@ -786,7 +801,13 @@ switch_thread:
|
|||
{
|
||||
delete_breakpoint (step_resume_breakpoint);
|
||||
step_resume_breakpoint = NULL;
|
||||
what.step_resume = 0;
|
||||
}
|
||||
/* Not sure whether we need to blow this away too, but probably
|
||||
it is like the step-resume breakpoint. */
|
||||
if (through_sigtramp_breakpoint != NULL)
|
||||
{
|
||||
delete_breakpoint (through_sigtramp_breakpoint);
|
||||
through_sigtramp_breakpoint = NULL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
@ -831,33 +852,43 @@ switch_thread:
|
|||
|
||||
case BPSTAT_WHAT_STOP_NOISY:
|
||||
stop_print_frame = 1;
|
||||
/* We are about to nuke the step_resume_breakpoint via the
|
||||
cleanup chain, so no need to worry about it here. */
|
||||
|
||||
/* We are about to nuke the step_resume_breakpoint and
|
||||
through_sigtramp_breakpoint via the cleanup chain, so
|
||||
no need to worry about it here. */
|
||||
|
||||
goto stop_stepping;
|
||||
|
||||
case BPSTAT_WHAT_STOP_SILENT:
|
||||
stop_print_frame = 0;
|
||||
/* We are about to nuke the step_resume_breakpoint via the
|
||||
cleanup chain, so no need to worry about it here. */
|
||||
|
||||
/* We are about to nuke the step_resume_breakpoint and
|
||||
through_sigtramp_breakpoint via the cleanup chain, so
|
||||
no need to worry about it here. */
|
||||
|
||||
goto stop_stepping;
|
||||
|
||||
case BPSTAT_WHAT_STEP_RESUME:
|
||||
delete_breakpoint (step_resume_breakpoint);
|
||||
step_resume_breakpoint = NULL;
|
||||
break;
|
||||
|
||||
case BPSTAT_WHAT_THROUGH_SIGTRAMP:
|
||||
delete_breakpoint (through_sigtramp_breakpoint);
|
||||
through_sigtramp_breakpoint = NULL;
|
||||
|
||||
/* If were waiting for a trap, hitting the step_resume_break
|
||||
doesn't count as getting it. */
|
||||
if (trap_expected)
|
||||
another_trap = 1;
|
||||
break;
|
||||
|
||||
case BPSTAT_WHAT_LAST:
|
||||
/* Not a real code, but listed here to shut up gcc -Wall. */
|
||||
|
||||
case BPSTAT_WHAT_KEEP_CHECKING:
|
||||
break;
|
||||
}
|
||||
|
||||
if (what.step_resume)
|
||||
{
|
||||
delete_breakpoint (step_resume_breakpoint);
|
||||
step_resume_breakpoint = NULL;
|
||||
|
||||
/* If were waiting for a trap, hitting the step_resume_break
|
||||
doesn't count as getting it. */
|
||||
if (trap_expected)
|
||||
another_trap = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* We come here if we hit a breakpoint but should not
|
||||
|
@ -892,10 +923,8 @@ switch_thread:
|
|||
/* Having a step-resume breakpoint overrides anything
|
||||
else having to do with stepping commands until
|
||||
that breakpoint is reached. */
|
||||
/* I suspect this could/should be keep_going, because if the
|
||||
check_sigtramp2 check succeeds, then it will put in another
|
||||
step_resume_breakpoint, and we aren't (yet) prepared to nest
|
||||
them. */
|
||||
/* I'm not sure whether this needs to be check_sigtramp2 or
|
||||
whether it could/should be keep_going. */
|
||||
goto check_sigtramp2;
|
||||
|
||||
if (step_range_end == 0)
|
||||
|
@ -928,20 +957,29 @@ switch_thread:
|
|||
if (IN_SIGTRAMP (stop_pc, stop_func_name)
|
||||
&& !IN_SIGTRAMP (prev_pc, prev_func_name))
|
||||
{
|
||||
/* We've just taken a signal; go until we are back to
|
||||
the point where we took it and one more. */
|
||||
|
||||
/* This code is needed at least in the following case:
|
||||
The user types "next" and then a signal arrives (before
|
||||
the "next" is done). */
|
||||
/* We've just taken a signal; go until we are back to
|
||||
the point where we took it and one more. */
|
||||
|
||||
/* Note that if we are stopped at a breakpoint, then we need
|
||||
the step_resume breakpoint to override any breakpoints at
|
||||
the same location, so that we will still step over the
|
||||
breakpoint even though the signal happened. */
|
||||
|
||||
{
|
||||
struct symtab_and_line sr_sal;
|
||||
|
||||
sr_sal.pc = prev_pc;
|
||||
sr_sal.symtab = NULL;
|
||||
sr_sal.line = 0;
|
||||
/* We perhaps could set the frame if we kept track of what
|
||||
the frame corresponding to prev_pc was. But we don't,
|
||||
so don't. */
|
||||
step_resume_breakpoint =
|
||||
set_momentary_breakpoint (sr_sal, get_current_frame (),
|
||||
bp_step_resume);
|
||||
set_momentary_breakpoint (sr_sal, NULL, bp_step_resume);
|
||||
if (breakpoints_inserted)
|
||||
insert_breakpoints ();
|
||||
}
|
||||
|
@ -1054,6 +1092,7 @@ step_over_function:
|
|||
step_resume_breakpoint =
|
||||
set_momentary_breakpoint (sr_sal, get_current_frame (),
|
||||
bp_step_resume);
|
||||
step_resume_breakpoint->frame = prev_frame_address;
|
||||
if (breakpoints_inserted)
|
||||
insert_breakpoints ();
|
||||
}
|
||||
|
@ -1180,9 +1219,11 @@ step_into_function:
|
|||
sr_sal.pc = prev_pc;
|
||||
sr_sal.symtab = NULL;
|
||||
sr_sal.line = 0;
|
||||
step_resume_breakpoint =
|
||||
set_momentary_breakpoint (sr_sal, get_current_frame (),
|
||||
bp_step_resume);
|
||||
/* We perhaps could set the frame if we kept track of what
|
||||
the frame corresponding to prev_pc was. But we don't,
|
||||
so don't. */
|
||||
through_sigtramp_breakpoint =
|
||||
set_momentary_breakpoint (sr_sal, NULL, bp_through_sigtramp);
|
||||
if (breakpoints_inserted)
|
||||
insert_breakpoints ();
|
||||
|
||||
|
@ -1204,6 +1245,7 @@ step_into_function:
|
|||
function. */
|
||||
prev_func_name = stop_func_name;
|
||||
prev_sp = stop_sp;
|
||||
prev_frame_address = stop_frame_address;
|
||||
|
||||
/* If we did not do break;, it means we should keep
|
||||
running the inferior and not return to debugger. */
|
||||
|
@ -1238,7 +1280,7 @@ step_into_function:
|
|||
breakpoints_inserted = 0;
|
||||
}
|
||||
else if (!breakpoints_inserted &&
|
||||
(step_resume_breakpoint != NULL || !another_trap))
|
||||
(through_sigtramp_breakpoint != NULL || !another_trap))
|
||||
{
|
||||
breakpoints_failed = insert_breakpoints ();
|
||||
if (breakpoints_failed)
|
||||
|
@ -1278,6 +1320,7 @@ step_into_function:
|
|||
prev_func_start = stop_func_start;
|
||||
prev_func_name = stop_func_name;
|
||||
prev_sp = stop_sp;
|
||||
prev_frame_address = stop_frame_address;
|
||||
}
|
||||
do_cleanups (old_cleanups);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue