#include "gdbcmd.h"
#include "target.h"
#include "thread.h"
+#include "annotate.h"
#include <signal.h>
#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);
+#ifdef PREPARE_TO_PROCEED
+ /* In a multi-threaded task we may select another thread and then continue.
+
+ In this case the thread that stopped at a breakpoint will immediately
+ cause another stop, if it is not stepped over first. On the other hand,
+ if (ADDR != -1) we only want to single step over the breakpoint if we did
+ switch to another thread.
+
+ If we are single stepping, don't do any of the above.
+ (Note that in the current implementation single stepping another
+ thread after a breakpoint and then continuing will cause the original
+ breakpoint to be hit again, but you can always continue, so it's not
+ a big deal.) */
+
+ if (! step && PREPARE_TO_PROCEED (1) && breakpoint_here_p (read_pc ()))
+ oneproc = 1;
+#endif /* PREPARE_TO_PROCEED */
+
if (trap_expected_after_continue)
{
/* If (step == 0), a trap will be automatically generated after
else if (!signal_program[stop_signal])
stop_signal = TARGET_SIGNAL_0;
+ annotate_starting ();
+
/* Resume inferior. */
resume (oneproc || step || bpstat_should_step (), stop_signal);
to be preserved over calls to it and cleared when the inferior
is started. */
static CORE_ADDR prev_pc;
-static CORE_ADDR prev_sp;
static CORE_ADDR prev_func_start;
static char *prev_func_name;
{
/* These are meaningless until the first time through wait_for_inferior. */
prev_pc = 0;
- prev_sp = 0;
prev_func_start = 0;
prev_func_name = NULL;
struct target_waitstatus w;
int another_trap;
int random_signal;
- CORE_ADDR stop_sp = 0;
CORE_ADDR stop_func_start;
CORE_ADDR stop_func_end;
char *stop_func_name;
struct symtab *current_symtab;
int handling_longjmp = 0; /* FIXME */
struct breakpoint *step_resume_breakpoint = NULL;
+ struct breakpoint *through_sigtramp_breakpoint = NULL;
int pid;
+ int update_step_sp = 0;
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)
{
- /* Clean up saved state that will become invalid. */
- flush_cached_frames ();
+ /* We have to invalidate the registers BEFORE calling target_wait because
+ they can be loaded from the target while in target_wait. This makes
+ remote debugging a bit more efficient for those targets that provide
+ critical registers as part of their normal status mechanism. */
+
registers_changed ();
- pid = target_wait (-1, &w);
+ if (target_wait_hook)
+ pid = target_wait_hook (-1, &w);
+ else
+ pid = target_wait (-1, &w);
+
+ flush_cached_frames ();
+
+ /* If it's a new process, add it to the thread database */
+
+ if (pid != inferior_pid
+ && !in_thread_list (pid))
+ {
+ fprintf_unfiltered (gdb_stderr, "[New %s]\n", target_pid_to_str (pid));
+ add_thread (pid);
+
+ /* We may want to consider not doing a resume here in order to give
+ the user a chance to play with the new thread. It might be good
+ to make that a user-settable option. */
+
+ /* At this point, all threads are stopped (happens automatically in
+ either the OS or the native code). Therefore we need to continue
+ all threads in order to make progress. */
+
+ target_resume (-1, 0, TARGET_SIGNAL_0);
+ continue;
+ }
switch (w.kind)
{
case TARGET_WAITKIND_EXITED:
target_terminal_ours (); /* Must do this before mourn anyway */
+ annotate_exited (w.value.integer);
if (w.value.integer)
printf_filtered ("\nProgram exited with code 0%o.\n",
(unsigned int)w.value.integer);
else
- if (!batch_mode())
- printf_filtered ("\nProgram exited normally.\n");
+ printf_filtered ("\nProgram exited normally.\n");
gdb_flush (gdb_stdout);
target_mourn_inferior ();
#ifdef NO_SINGLE_STEP
stop_print_frame = 0;
stop_signal = w.value.sig;
target_terminal_ours (); /* Must do this before mourn anyway */
+ annotate_signalled ();
target_kill (); /* kill mourns as well */
- printf_filtered ("\nProgram terminated with signal %s, %s.\n",
- target_signal_to_name (stop_signal),
- target_signal_to_string (stop_signal));
+ printf_filtered ("\nProgram terminated with signal ");
+ annotate_signal_name ();
+ printf_filtered ("%s", target_signal_to_name (stop_signal));
+ annotate_signal_name_end ();
+ printf_filtered (", ");
+ annotate_signal_string ();
+ printf_filtered ("%s", target_signal_to_string (stop_signal));
+ annotate_signal_string_end ();
+ printf_filtered (".\n");
printf_filtered ("The program no longer exists.\n");
gdb_flush (gdb_stdout);
stop_signal = w.value.sig;
- if (pid != inferior_pid)
- {
- int save_pid = inferior_pid;
+ stop_pc = read_pc_pid (pid);
- inferior_pid = pid; /* Setup for target memory/regs */
- registers_changed ();
- stop_pc = read_pc ();
- inferior_pid = save_pid;
- registers_changed ();
- }
- else
- stop_pc = read_pc ();
+ /* See if a thread hit a thread-specific breakpoint that was meant for
+ another thread. If so, then step that thread past the breakpoint,
+ and continue it. */
if (stop_signal == TARGET_SIGNAL_TRAP
+ && breakpoints_inserted
&& breakpoint_here_p (stop_pc - DECR_PC_AFTER_BREAK))
{
+ random_signal = 0;
if (!breakpoint_thread_match (stop_pc - DECR_PC_AFTER_BREAK, pid))
{
/* Saw a breakpoint, but it was hit by the wrong thread. Just continue. */
- if (breakpoints_inserted)
- {
- if (pid != inferior_pid)
- {
- int save_pid = inferior_pid;
-
- inferior_pid = pid;
- registers_changed ();
- write_pc (stop_pc - DECR_PC_AFTER_BREAK);
- inferior_pid = save_pid;
- registers_changed ();
- }
- else
- write_pc (stop_pc - DECR_PC_AFTER_BREAK);
-
- remove_breakpoints ();
- target_resume (pid, 1, TARGET_SIGNAL_0); /* Single step */
- /* FIXME: What if a signal arrives instead of the single-step
- happening? */
- target_wait (pid, &w);
- insert_breakpoints ();
- }
- target_resume (-1, 0, TARGET_SIGNAL_0);
+ write_pc (stop_pc - DECR_PC_AFTER_BREAK);
+
+ remove_breakpoints ();
+ target_resume (pid, 1, TARGET_SIGNAL_0); /* Single step */
+ /* FIXME: What if a signal arrives instead of the single-step
+ happening? */
+
+ if (target_wait_hook)
+ target_wait_hook (pid, &w);
+ else
+ target_wait (pid, &w);
+ insert_breakpoints ();
+ target_resume (pid, 0, TARGET_SIGNAL_0);
continue;
}
- else
- if (pid != inferior_pid)
- goto switch_thread;
}
+ else
+ random_signal = 1;
+
+ /* See if something interesting happened to the non-current thread. If
+ so, then switch to that thread, and eventually give control back to
+ the user. */
if (pid != inferior_pid)
{
int printed = 0;
- if (!in_thread_list (pid))
+ /* If it's a random signal for a non-current thread, notify user
+ if he's expressed an interest. */
+
+ if (random_signal
+ && signal_print[stop_signal])
+ {
+ printed = 1;
+ target_terminal_ours_for_output ();
+ printf_filtered ("\nProgram received signal %s, %s.\n",
+ target_signal_to_name (stop_signal),
+ target_signal_to_string (stop_signal));
+ gdb_flush (gdb_stdout);
+ }
+
+ /* If it's not SIGTRAP and not a signal we want to stop for, then
+ continue the thread. */
+
+ if (stop_signal != TARGET_SIGNAL_TRAP
+ && !signal_stop[stop_signal])
{
- fprintf_unfiltered (gdb_stderr, "[New %s]\n", target_pid_to_str (pid));
- add_thread (pid);
+ if (printed)
+ target_terminal_inferior ();
- target_resume (-1, 0, TARGET_SIGNAL_0);
+ /* Clear the signal if it should not be passed. */
+ if (signal_program[stop_signal] == 0)
+ stop_signal = TARGET_SIGNAL_0;
+
+ target_resume (pid, 0, stop_signal);
continue;
}
- else
- {
- if (signal_print[stop_signal])
- {
- char *signame;
-
- printed = 1;
- target_terminal_ours_for_output ();
- printf_filtered ("\nProgram received signal %s, %s.\n",
- target_signal_to_name (stop_signal),
- target_signal_to_string (stop_signal));
- gdb_flush (gdb_stdout);
- }
-
- if (stop_signal == TARGET_SIGNAL_TRAP
- || signal_stop[stop_signal])
- {
-switch_thread:
- inferior_pid = pid;
- printf_filtered ("[Switching to %s]\n", target_pid_to_str (pid));
-
- flush_cached_frames ();
- registers_changed ();
- trap_expected = 0;
- if (step_resume_breakpoint)
- {
- delete_breakpoint (step_resume_breakpoint);
- step_resume_breakpoint = NULL;
- }
- prev_pc = 0;
- prev_sp = 0;
- prev_func_name = NULL;
- step_range_start = 0;
- step_range_end = 0;
- step_frame_address = 0;
- handling_longjmp = 0;
- another_trap = 0;
- }
- else
- {
- if (printed)
- target_terminal_inferior ();
- /* Clear the signal if it should not be passed. */
- if (signal_program[stop_signal] == 0)
- stop_signal = TARGET_SIGNAL_0;
+ /* It's a SIGTRAP or a signal we're interested in. Switch threads,
+ and fall into the rest of wait_for_inferior(). */
- target_resume (pid, 0, stop_signal);
- continue;
- }
+ inferior_pid = pid;
+ printf_filtered ("[Switching to %s]\n", target_pid_to_str (pid));
+
+ flush_cached_frames ();
+ trap_expected = 0;
+ if (step_resume_breakpoint)
+ {
+ 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_func_name = NULL;
+ step_range_start = 0;
+ step_range_end = 0;
+ step_frame_address = 0;
+ handling_longjmp = 0;
+ another_trap = 0;
}
#ifdef NO_SINGLE_STEP
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));
+#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);
+
+ /* FIXME: This is bogus. You can't interact with the
+ inferior except when it is stopped. It apparently
+ happens to work on Irix4, but it depends on /proc
+ allowing us to muck with the memory of a running process,
+ and the kernel deciding to run one instruction of the
+ inferior before it executes our insert_breakpoints code,
+ which seems like an awfully dubious assumption. */
+ insert_breakpoints ();
+
+ continue;
+ }
+#endif
+
+#ifdef HAVE_CONTINUABLE_WATCHPOINT
+ /* It may be possible to simply continue after a watchpoint. */
+ STOPPED_BY_WATCHPOINT (w);
+#endif
- stop_frame_address = FRAME_FP (get_current_frame ());
- stop_sp = read_sp ();
stop_func_start = 0;
stop_func_name = 0;
/* Don't care about return value; stop_func_start and stop_func_name
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
{
/* See if there is a breakpoint at the current PC. */
stop_bpstat = bpstat_stop_status
- (&stop_pc, stop_frame_address,
+ (&stop_pc,
#if DECR_PC_AFTER_BREAK
/* Notice the case of stepping through a jump
that lands just after a breakpoint.
= !(bpstat_explains_signal (stop_bpstat)
|| trap_expected
#ifndef CALL_DUMMY_BREAKPOINT_OFFSET
- || PC_IN_CALL_DUMMY (stop_pc, stop_sp, stop_frame_address)
+ || PC_IN_CALL_DUMMY (stop_pc, read_sp (),
+ FRAME_FP (get_current_frame ()))
#endif /* No CALL_DUMMY_BREAKPOINT_OFFSET. */
|| (step_range_end && step_resume_breakpoint == NULL));
else
news) give another signal besides SIGTRAP,
so check here as well as above. */
#ifndef CALL_DUMMY_BREAKPOINT_OFFSET
- || PC_IN_CALL_DUMMY (stop_pc, stop_sp, stop_frame_address)
+ || PC_IN_CALL_DUMMY (stop_pc, read_sp (),
+ FRAME_FP (get_current_frame ()))
#endif /* No CALL_DUMMY_BREAKPOINT_OFFSET. */
);
if (!random_signal)
if (signal_print[stop_signal])
{
- char *signame;
printed = 1;
target_terminal_ours_for_output ();
- printf_filtered ("\nProgram received signal %s, %s.\n",
- target_signal_to_name (stop_signal),
- target_signal_to_string (stop_signal));
+ annotate_signal ();
+ printf_filtered ("\nProgram received signal ");
+ annotate_signal_name ();
+ printf_filtered ("%s", target_signal_to_name (stop_signal));
+ annotate_signal_name_end ();
+ printf_filtered (", ");
+ annotate_signal_string ();
+ printf_filtered ("%s", target_signal_to_string (stop_signal));
+ annotate_signal_string_end ();
+ printf_filtered (".\n");
gdb_flush (gdb_stdout);
}
if (signal_stop[stop_signal])
{
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
#if 0
/* FIXME - Need to implement nested temporary breakpoints */
if (step_over_calls
- && (stop_frame_address
+ && (FRAME_FP (get_current_frame ())
INNER_THAN step_frame_address))
{
another_trap = 1;
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:
+ if (through_sigtramp_breakpoint)
+ 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;
}
}
just stop silently, unless the user was doing an si/ni, in which
case she'd better know what she's doing. */
- if (PC_IN_CALL_DUMMY (stop_pc, stop_sp, stop_frame_address)
+ if (PC_IN_CALL_DUMMY (stop_pc, read_sp (), FRAME_FP (get_current_frame ()))
&& !step_range_end)
{
stop_print_frame = 0;
/* 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)
step range and either the stack or frame pointers
just changed, we've stepped outside */
&& !(stop_pc == step_range_start
- && stop_frame_address
- && (stop_sp INNER_THAN prev_sp
- || stop_frame_address != step_frame_address)))
+ && FRAME_FP (get_current_frame ())
+ && (read_sp () INNER_THAN step_sp
+ || FRAME_FP (get_current_frame ()) != step_frame_address)))
{
/* We might be doing a BPSTAT_WHAT_SINGLE and getting a signal.
So definately need to check for sigtramp here. */
goto check_sigtramp2;
}
- /* We stepped out of the stepping range. See if that was due
- to a subroutine call that we should proceed to the end of. */
+ /* We stepped out of the stepping range. */
+
+ /* We can't update step_sp every time through the loop, because
+ reading the stack pointer would slow down stepping too much.
+ But we can update it every time we leave the step range. */
+ update_step_sp = 1;
/* Did we just take a signal? */
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
+ step_frame_address; I don't think anyone thought to try it. */
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 ();
}
goto keep_going;
}
+#if 1
+ /* See if we left the step range due to a subroutine call that
+ we should proceed to the end of. */
+
if (stop_func_start)
{
+ struct symtab *s;
+
/* Do this after the IN_SIGTRAMP check; it might give
an error. */
prologue_pc = stop_func_start;
- SKIP_PROLOGUE (prologue_pc);
+
+ /* Don't skip the prologue if this is assembly source */
+ s = find_pc_symtab (stop_pc);
+ if (s && s->language != language_asm)
+ SKIP_PROLOGUE (prologue_pc);
}
if ((/* Might be a non-recursive call. If the symbols are missing
/* Might be a recursive call if either we have a prologue
or the call instruction itself saves the PC on the stack. */
|| prologue_pc != stop_func_start
- || stop_sp != prev_sp)
+ || read_sp () != step_sp)
&& (/* PC is completely out of bounds of any known objfiles. Treat
like a subroutine call. */
! stop_func_start
/* 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
|| stop_pc < prologue_pc
+ /* ...and if it is a leaf function, the prologue might
+ consist of gp loading only, so the call transfers to
+ the first instruction after the prologue. */
+ || (stop_pc == prologue_pc
+
+ /* Distinguish this from the case where we jump back
+ to the first instruction after the prologue,
+ within a function. */
+ && stop_func_start != prev_func_start)
+
/* If we end up in certain places, it means we did a subroutine
call. I'm not completely sure this is necessary now that we
have the above checks with stop_func_start (and now that
which can no longer happen here as long as the
handling_longjmp stuff is working. */
))
+#else
+/* This is experimental code which greatly simplifies the subroutine call
+ test. I've actually tested on the Alpha, and it works great. -Stu */
+
+ if (in_prologue (stop_pc, NULL)
+ || (prev_func_start != 0
+ && stop_func_start == 0))
+#endif
{
/* It's a subroutine call. */
step_resume_breakpoint =
set_momentary_breakpoint (sr_sal, get_current_frame (),
bp_step_resume);
+ step_resume_breakpoint->frame = step_frame_address;
if (breakpoints_inserted)
insert_breakpoints ();
}
step_into_function:
/* Subroutine call with source code we should not step over.
Do step to the first line of code in it. */
- SKIP_PROLOGUE (stop_func_start);
+ {
+ struct symtab *s;
+
+ s = find_pc_symtab (stop_pc);
+ if (s && s->language != language_asm)
+ SKIP_PROLOGUE (stop_func_start);
+ }
sal = find_pc_line (stop_func_start, 0);
/* Use the step_resume_break to step until
the end of the prologue, even if that involves jumps
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 ();
been at the start of a
function. */
prev_func_name = stop_func_name;
- prev_sp = stop_sp;
+
+ if (update_step_sp)
+ step_sp = read_sp ();
+ update_step_sp = 0;
/* 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_pc = read_pc ();
prev_func_start = stop_func_start;
prev_func_name = stop_func_name;
- prev_sp = stop_sp;
}
do_cleanups (old_cleanups);
}
disable_current_display ();
if (step_multi && stop_step)
- return;
+ goto done;
target_terminal_ours ();
}
if (!target_has_stack)
- return;
+ goto done;
/* Select innermost stack frame except on return from a stack dummy routine,
or if the program has exited. Print it without a level number if
source_only = bpstat_print (stop_bpstat);
source_only = source_only ||
( stop_step
- && step_frame_address == stop_frame_address
+ && step_frame_address == FRAME_FP (get_current_frame ())
&& step_start_function == find_pc_function (stop_pc));
print_stack_frame (selected_frame, -1, source_only? -1: 1);
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);
}
+ done:
+ annotate_stopped ();
}
static int
}
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;
{
inf_status->stop_signal = stop_signal;
inf_status->stop_pc = stop_pc;
- inf_status->stop_frame_address = stop_frame_address;
inf_status->stop_step = stop_step;
inf_status->stop_stack_dummy = stop_stack_dummy;
inf_status->stopped_by_random_signal = stopped_by_random_signal;
{
stop_signal = inf_status->stop_signal;
stop_pc = inf_status->stop_pc;
- stop_frame_address = inf_status->stop_frame_address;
stop_step = inf_status->stop_step;
stop_stack_dummy = inf_status->stop_stack_dummy;
stopped_by_random_signal = inf_status->stopped_by_random_signal;
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;
}