You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "defs.h"
-#include <string.h>
+#include "gdb_string.h"
#include <ctype.h>
#include "symtab.h"
#include "frame.h"
static int trap_expected;
+#ifdef HP_OS_BUG
/* Nonzero if the next time we try to continue the inferior, it will
step one instruction and generate a spurious trace trap.
This is used to compensate for a bug in HP-UX. */
static int trap_expected_after_continue;
+#endif
/* Nonzero means expecting a trace trap
and should stop the inferior and return silently when it happens. */
oneproc = 1;
#endif /* PREPARE_TO_PROCEED */
+#ifdef HP_OS_BUG
if (trap_expected_after_continue)
{
/* If (step == 0), a trap will be automatically generated after
oneproc = 1;
trap_expected_after_continue = 0;
}
+#endif /* HP_OS_BUG */
if (oneproc)
/* We will get a trace trap after one instruction.
annotate_starting ();
+ /* Make sure that output from GDB appears before output from the
+ inferior. */
+ gdb_flush (gdb_stdout);
+
/* Resume inferior. */
resume (oneproc || step || bpstat_should_step (), stop_signal);
prev_func_start = 0;
prev_func_name = NULL;
+#ifdef HP_OS_BUG
trap_expected_after_continue = 0;
+#endif
breakpoints_inserted = 0;
breakpoint_init_inferior ();
else
pid = target_wait (-1, &w);
+#ifdef HAVE_NONSTEPPABLE_WATCHPOINT
+ have_waited:
+#endif
+
flush_cached_frames ();
/* If it's a new process, add it to the thread database */
(unsigned int)w.value.integer);
else
printf_filtered ("\nProgram exited normally.\n");
+
+ /* Record the exit code in the convenience variable $_exitcode, so
+ that the user can inspect this again later. */
+ set_internalvar (lookup_internalvar ("_exitcode"),
+ value_from_longest (builtin_type_int,
+ (LONGEST) w.value.integer));
gdb_flush (gdb_stdout);
target_mourn_inferior ();
#ifdef NO_SINGLE_STEP
if (!breakpoint_thread_match (stop_pc - DECR_PC_AFTER_BREAK, pid))
{
/* Saw a breakpoint, but it was hit by the wrong thread. Just continue. */
- write_pc (stop_pc - DECR_PC_AFTER_BREAK);
+ write_pc_pid (stop_pc - DECR_PC_AFTER_BREAK, pid);
remove_breakpoints ();
target_resume (pid, 1, TARGET_SIGNAL_0); /* Single step */
else
target_wait (pid, &w);
insert_breakpoints ();
- target_resume (pid, 0, TARGET_SIGNAL_0);
+
+ /* We need to restart all the threads now. */
+ target_resume (-1, 0, TARGET_SIGNAL_0);
continue;
}
}
/* It's a SIGTRAP or a signal we're interested in. Switch threads,
and fall into the rest of wait_for_inferior(). */
+ /* Save infrun state for the old thread. */
+ save_infrun_state (inferior_pid, prev_pc,
+ prev_func_start, prev_func_name,
+ trap_expected, step_resume_breakpoint,
+ through_sigtramp_breakpoint,
+ step_range_start, step_range_end,
+ step_frame_address, handling_longjmp,
+ another_trap);
+
inferior_pid = pid;
+
+ /* Load infrun state for the new thread. */
+ load_infrun_state (inferior_pid, &prev_pc,
+ &prev_func_start, &prev_func_name,
+ &trap_expected, &step_resume_breakpoint,
+ &through_sigtramp_breakpoint,
+ &step_range_start, &step_range_end,
+ &step_frame_address, &handling_longjmp,
+ &another_trap);
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
here? */
if (STOPPED_BY_WATCHPOINT (w))
{
+/* At this point, we are stopped at an instruction which has attempted to write
+ to a piece of memory under control of a watchpoint. The instruction hasn't
+ actually executed yet. If we were to evaluate the watchpoint expression
+ now, we would get the old value, and therefore no change would seem to have
+ occurred.
+
+ In order to make watchpoints work `right', we really need to complete the
+ memory write, and then evaluate the watchpoint expression. The following
+ code does that by removing the watchpoint (actually, all watchpoints and
+ breakpoints), single-stepping the target, re-inserting watchpoints, and then
+ falling through to let normal single-step processing handle proceed. Since
+ this includes evaluating watchpoints, things will come to a stop in the
+ correct manner. */
+
+ write_pc (stop_pc - DECR_PC_AFTER_BREAK);
+
remove_breakpoints ();
- resume (1, 0);
+ target_resume (pid, 1, TARGET_SIGNAL_0); /* Single step */
- /* 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. */
+ if (target_wait_hook)
+ target_wait_hook (pid, &w);
+ else
+ target_wait (pid, &w);
insert_breakpoints ();
-
- continue;
+ /* FIXME-maybe: is this cleaner than setting a flag? Does it
+ handle things like signals arriving and other things happening
+ in combination correctly? */
+ goto have_waited;
}
#endif
/* If stepping through a line, keep going if still within it. */
if (stop_pc >= step_range_start
&& stop_pc < step_range_end
+#if 0
+/* I haven't a clue what might trigger this clause, and it seems wrong anyway,
+ so I've disabled it until someone complains. -Stu 10/24/95 */
+
/* The step range might include the start of the
function, so if we are at the start of the
step range and either the stack or frame pointers
&& !(stop_pc == step_range_start
&& FRAME_FP (get_current_frame ())
&& (read_sp () INNER_THAN step_sp
- || FRAME_FP (get_current_frame ()) != step_frame_address)))
+ || FRAME_FP (get_current_frame ()) != step_frame_address))
+#endif
+)
{
/* We might be doing a BPSTAT_WHAT_SINGLE and getting a signal.
So definately need to check for sigtramp here. */
goto keep_going;
}
-#if 1
+#if 0
+ /* I disabled this test because it was too complicated and slow. The
+ SKIP_PROLOGUE was especially slow, because it caused unnecessary
+ prologue examination on various architectures. The code in the #else
+ clause has been tested on the Sparc, Mips, PA, and Power
+ architectures, so it's pretty likely to be correct. -Stu 10/24/95 */
+
/* See if we left the step range due to a subroutine call that
we should proceed to the end of. */
/* 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))
+ if (stop_pc == stop_func_start /* Quick test */
+ || in_prologue (stop_pc, stop_func_start)
+ || IN_SOLIB_CALL_TRAMPOLINE (stop_pc, stop_func_name)
+ || stop_func_start == 0)
#endif
+
{
/* It's a subroutine call. */
anyway, and the common ones like SIGHUP, SIGINT, SIGALRM, etc.
will work right anyway. */
- sigfirst = siglast = atoi (*argv);
+ sigfirst = siglast = (int) target_signal_from_command (atoi (*argv));
if ((*argv)[digits] == '-')
{
- siglast = atoi ((*argv) + digits + 1);
+ siglast =
+ (int) target_signal_from_command (atoi ((*argv) + digits + 1));
}
if (sigfirst > siglast)
{
sigfirst = siglast;
siglast = signum;
}
- if (sigfirst < 0 || sigfirst >= nsigs)
- {
- error ("Signal %d not in range 0-%d", sigfirst, nsigs - 1);
- }
- if (siglast < 0 || siglast >= nsigs)
- {
- error ("Signal %d not in range 0-%d", siglast, nsigs - 1);
- }
}
else
{
}
}
break;
+ case TARGET_SIGNAL_0:
+ case TARGET_SIGNAL_DEFAULT:
+ case TARGET_SIGNAL_UNKNOWN:
+ /* Make sure that "all" doesn't print these. */
+ break;
default:
sigs[signum] = 1;
break;
oursig = target_signal_from_name (signum_exp);
if (oursig == TARGET_SIGNAL_UNKNOWN)
{
- /* Nope, maybe it's an address which evaluates to a signal
- number. */
- /* The numeric signal refers to our own internal
- signal numbering from target.h, not to host/target signal number.
- This is a feature; users really should be using symbolic names
- anyway, and the common ones like SIGHUP, SIGINT, SIGALRM, etc.
- will work right anyway. */
- int i = parse_and_eval_address (signum_exp);
- if (i >= (int)TARGET_SIGNAL_LAST
- || i < 0
- || i == (int)TARGET_SIGNAL_UNKNOWN
- || i == (int)TARGET_SIGNAL_DEFAULT)
- error ("Signal number out of bounds.");
- oursig = (enum target_signal)i;
+ /* No, try numeric. */
+ oursig =
+ target_signal_from_command (parse_and_eval_address (signum_exp));
}
sig_print_info (oursig);
return;
add_info ("signals", signals_info,
"What debugger does when program gets various signals.\n\
-Specify a signal number as argument to print info on that signal only.");
+Specify a signal as argument to print info on that signal only.");
add_info_alias ("handle", "signals", 0);
add_com ("handle", class_run, handle_command,
- "Specify how to handle a signal.\n\
-Args are signal numbers and actions to apply to those signals.\n\
-Signal numbers may be numeric (ex. 11) or symbolic (ex. SIGSEGV).\n\
-Numeric ranges may be specified with the form LOW-HIGH (ex. 14-21).\n\
+ concat ("Specify how to handle a signal.\n\
+Args are signals and actions to apply to those signals.\n\
+Symbolic signals (e.g. SIGSEGV) are recommended but numeric signals\n\
+from 1-15 are allowed for compatibility with old versions of GDB.\n\
+Numeric ranges may be specified with the form LOW-HIGH (e.g. 1-5).\n\
The special arg \"all\" is recognized to mean all signals except those\n\
-used by the debugger, typically SIGTRAP and SIGINT.\n\
-Recognized actions include \"stop\", \"nostop\", \"print\", \"noprint\",\n\
+used by the debugger, typically SIGTRAP and SIGINT.\n",
+"Recognized actions include \"stop\", \"nostop\", \"print\", \"noprint\",\n\
\"pass\", \"nopass\", \"ignore\", or \"noignore\".\n\
Stop means reenter debugger if this signal happens (implies print).\n\
Print means print a message if this signal happens.\n\
Pass means let program see this signal; otherwise program doesn't know.\n\
Ignore is a synonym for nopass and noignore is a synonym for pass.\n\
-Pass and Stop may be combined.");
+Pass and Stop may be combined.", NULL));
stop_command = add_cmd ("stop", class_obscure, not_just_help_class_command,
"There is no `stop' command, but you can set a hook on `stop'.\n\