/* Target-struct-independent code to start (run) and stop an inferior process.
- Copyright 1986, 1987, 1988, 1989, 1991, 1992, 1993
+ Copyright 1986, 1987, 1988, 1989, 1991, 1992, 1993, 1994
Free Software Foundation, Inc.
This file is part of GDB.
#define SKIP_TRAMPOLINE_CODE(pc) 0
#endif
-/* On Irix 5, some function calls automatically skip the first few
- instructions, so we need a more complicated test to see if we are
- the start of a function. */
-#ifndef AT_FUNCTION_START
-#define AT_FUNCTION_START(pc,func_name,func_addr) 0
-#endif
-
/* For SVR4 shared libraries, each call goes through a small piece of
- trampoline code in the ".init" section. IN_SOLIB_TRAMPOLINE evaluates
+ trampoline code in the ".plt" section. IN_SOLIB_TRAMPOLINE evaluates
to nonzero if we are current stopped in one of these. */
#ifndef IN_SOLIB_TRAMPOLINE
#define IN_SOLIB_TRAMPOLINE(pc,name) 0
if (breakpoint_here_p (read_pc ()))
oneproc = 1;
+
+#ifdef STEP_SKIPS_DELAY
+ /* Check breakpoint_here_p first, because breakpoint_here_p is fast
+ (it just checks internal GDB data structures) and STEP_SKIPS_DELAY
+ is slow (it needs to read memory from the target). */
+ if (breakpoint_here_p (read_pc () + 4)
+ && STEP_SKIPS_DELAY (read_pc ()))
+ oneproc = 1;
+#endif /* STEP_SKIPS_DELAY */
}
else
write_pc (addr);
breakpoints_inserted = 1;
}
- if (siggnal >= 0)
+ if (siggnal != TARGET_SIGNAL_DEFAULT)
stop_signal = siggnal;
/* If this signal should not be seen by program,
give it zero. Used for debugging signals. */
else if (!signal_program[stop_signal])
- stop_signal= 0;
+ stop_signal = TARGET_SIGNAL_0;
/* Resume inferior. */
resume (oneproc || step || bpstat_should_step (), stop_signal);
static CORE_ADDR prev_sp;
static CORE_ADDR prev_func_start;
static char *prev_func_name;
+static CORE_ADDR prev_frame_address;
\f
/* Start remote-debugging of a machine over a serial link. */
prev_sp = 0;
prev_func_start = 0;
prev_func_name = NULL;
+ prev_frame_address = 0;
trap_expected_after_continue = 0;
breakpoints_inserted = 0;
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)
{
pid = target_wait (-1, &w);
-#ifdef SIGTRAP_STOP_AFTER_LOAD
-
- /* Somebody called load(2), and it gave us a "trap signal after load".
- Ignore it gracefully. */
+ switch (w.kind)
+ {
+ case TARGET_WAITKIND_LOADED:
+ /* Ignore it gracefully. */
+ if (breakpoints_inserted)
+ {
+ mark_breakpoints_out ();
+ insert_breakpoints ();
+ }
+ resume (0, TARGET_SIGNAL_0);
+ continue;
- SIGTRAP_STOP_AFTER_LOAD (w);
-#endif
+ case TARGET_WAITKIND_SPURIOUS:
+ resume (0, TARGET_SIGNAL_0);
+ continue;
- /* See if the process still exists; clean up if it doesn't. */
- if (w.kind == TARGET_WAITKIND_EXITED)
- {
+ case TARGET_WAITKIND_EXITED:
target_terminal_ours (); /* Must do this before mourn anyway */
if (w.value.integer)
printf_filtered ("\nProgram exited with code 0%o.\n",
one_stepped = 0;
#endif
stop_print_frame = 0;
- break;
- }
- else if (w.kind == TARGET_WAITKIND_SIGNALLED)
- {
- char *signame;
+ goto stop_stepping;
+ case TARGET_WAITKIND_SIGNALLED:
stop_print_frame = 0;
stop_signal = w.value.sig;
target_terminal_ours (); /* Must do this before mourn anyway */
#ifdef NO_SINGLE_STEP
one_stepped = 0;
#endif
+ goto stop_stepping;
+
+ case TARGET_WAITKIND_STOPPED:
+ /* This is the only case in which we keep going; the above cases
+ end in a continue or goto. */
break;
}
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;
single_step (0); /* This actually cleans up the ss */
#endif /* NO_SINGLE_STEP */
-/* If PC is pointing at a nullified instruction, then step beyond it so that
- the user won't be confused when GDB appears to be ready to execute it. */
+ /* If PC is pointing at a nullified instruction, then step beyond
+ it so that the user won't be confused when GDB appears to be ready
+ to execute it. */
if (INSTRUCTION_NULLIFIED)
{
continue;
}
- set_current_frame ( create_new_frame (read_fp (), stop_pc));
+ set_current_frame (create_new_frame (read_fp (), stop_pc));
+ select_frame (get_current_frame (), 0);
+
+#ifdef HAVE_STEPPABLE_WATCHPOINT
+ /* It may not be necessary to disable the watchpoint to stop over
+ it. For example, the PA can (with some kernel cooperation)
+ single step over a watchpoint without disabling the watchpoint. */
+ if (STOPPED_BY_WATCHPOINT (w))
+ {
+ resume (1, 0);
+ continue;
+ }
+#endif
+
+#ifdef HAVE_NONSTEPPABLE_WATCHPOINT
+ /* It is far more common to need to disable a watchpoint
+ to step the inferior over it. FIXME. What else might
+ a debug register or page protection watchpoint scheme need
+ here? */
+ if (STOPPED_BY_WATCHPOINT (w))
+ {
+ remove_breakpoints ();
+ resume (1, 0);
+ insert_breakpoints ();
+ continue;
+ }
+#endif
stop_frame_address = FRAME_FP (get_current_frame ());
stop_sp = read_sp ();
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
{
{
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
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. */
- goto stop_stepping;
- case BPSTAT_WHAT_LAST:
- /* Not a real code, but listed here to shut up gcc -Wall. */
+ /* 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. */
- case BPSTAT_WHAT_KEEP_CHECKING:
- break;
- }
+ goto stop_stepping;
- if (what.step_resume)
- {
+ 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;
}
}
/* 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)
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 could probably be setting the frame to
+ prev_frame_address; the reason we don't is that it didn't used
+ to exist. */
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 ();
}
/* If we do a call, we will be at the start of a function... */
|| stop_pc == stop_func_start
-#if 0
- /* Should be taken care of by the stop_pc < prologue_pc check
- below. Also, on irix5 where this checks for stop_pc
- equal to stop_func_start plus 12, it would seem to be
- wrong for a function with a 4 byte prologue, and an 8 byte
- call; a "return" could end up at stop_func_start+12. */
-
- || AT_FUNCTION_START (stop_pc, stop_func_name, stop_func_start)
-#endif
/* ...except on the Alpha with -O (and also Irix 5 and
perhaps others), in which we might call the address
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 ();
}
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 ();
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. */
to one-proceed past a breakpoint. */
/* If we've just finished a special step resume and we don't
want to hit a breakpoint, pull em out. */
- if (step_resume_breakpoint == NULL &&
- remove_breakpoints_on_following_step)
+ if (step_resume_breakpoint == NULL
+ && through_sigtramp_breakpoint == NULL
+ && remove_breakpoints_on_following_step)
{
remove_breakpoints_on_following_step = 0;
remove_breakpoints ();
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)
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);
}
if we have one. */
if (!stop_stack_dummy)
{
- select_frame (get_current_frame (), 0);
-
if (stop_print_frame)
{
int source_only;
POP_FRAME ends with a setting of the current frame, so we
can use that next. */
POP_FRAME;
+ /* Set stop_pc to what it was before we called the function. Can't rely
+ on restore_inferior_status because that only gets called if we don't
+ stop in the called function. */
+ stop_pc = read_pc();
select_frame (get_current_frame (), 0);
}
}
error ("Signal %d not in range 0-%d", siglast, nsigs - 1);
}
}
- else if ((oursig = target_signal_from_name (*argv))
- != TARGET_SIGNAL_UNKNOWN)
- {
- sigfirst = siglast = (int)oursig;
- }
else
{
- /* Not a number and not a recognized flag word => complain. */
- error ("Unrecognized or ambiguous flag word: \"%s\".", *argv);
+ oursig = target_signal_from_name (*argv);
+ if (oursig != TARGET_SIGNAL_UNKNOWN)
+ {
+ sigfirst = siglast = (int)oursig;
+ }
+ else
+ {
+ /* Not a number and not a recognized flag word => complain. */
+ error ("Unrecognized or ambiguous flag word: \"%s\".", *argv);
+ }
}
/* If any signal numbers or symbol names were found, set flags for
int i = parse_and_eval_address (signum_exp);
if (i >= (int)TARGET_SIGNAL_LAST
|| i < 0
- || i == TARGET_SIGNAL_UNKNOWN)
+ || i == (int)TARGET_SIGNAL_UNKNOWN
+ || i == (int)TARGET_SIGNAL_DEFAULT)
error ("Signal number out of bounds.");
oursig = (enum target_signal)i;
}
}
printf_filtered ("\n");
- for (oursig = 0; oursig < TARGET_SIGNAL_LAST; ++oursig)
+ /* These ugly casts brought to you by the native VAX compiler. */
+ for (oursig = TARGET_SIGNAL_FIRST;
+ (int)oursig < (int)TARGET_SIGNAL_LAST;
+ oursig = (enum target_signal)((int)oursig + 1))
{
QUIT;
- if (oursig != TARGET_SIGNAL_UNKNOWN)
+ if (oursig != TARGET_SIGNAL_UNKNOWN
+ && oursig != TARGET_SIGNAL_DEFAULT
+ && oursig != TARGET_SIGNAL_0)
sig_print_info (oursig);
}
signal_print[TARGET_SIGNAL_CHLD] = 0;
signal_stop[TARGET_SIGNAL_IO] = 0;
signal_print[TARGET_SIGNAL_IO] = 0;
+ signal_stop[TARGET_SIGNAL_POLL] = 0;
+ signal_print[TARGET_SIGNAL_POLL] = 0;
signal_stop[TARGET_SIGNAL_URG] = 0;
signal_print[TARGET_SIGNAL_URG] = 0;
}