/* Prototypes for local functions */
-static void
-signals_info PARAMS ((char *, int));
+static void signals_info PARAMS ((char *, int));
-static void
-handle_command PARAMS ((char *, int));
+static void handle_command PARAMS ((char *, int));
static void sig_print_info PARAMS ((enum target_signal));
-static void
-sig_print_header PARAMS ((void));
+static void sig_print_header PARAMS ((void));
-static void
-resume_cleanups PARAMS ((int));
+static void resume_cleanups PARAMS ((int));
-static int
-hook_stop_stub PARAMS ((char *));
+static int hook_stop_stub PARAMS ((char *));
/* GET_LONGJMP_TARGET returns the PC at which longjmp() will resume the
program. It needs to examine the jmp_buf argument and extract the PC
from it. The return value is non-zero on success, zero otherwise. */
+
#ifndef GET_LONGJMP_TARGET
#define GET_LONGJMP_TARGET(PC_ADDR) 0
#endif
/* Some machines have trampoline code that sits between function callers
and the actual functions themselves. If this machine doesn't have
such things, disable their processing. */
+
#ifndef SKIP_TRAMPOLINE_CODE
#define SKIP_TRAMPOLINE_CODE(pc) 0
#endif
/* For SVR4 shared libraries, each call goes through a small piece of
- trampoline code in the ".plt" section. IN_SOLIB_TRAMPOLINE evaluates
+ trampoline code in the ".plt" section. IN_SOLIB_CALL_TRAMPOLINE evaluates
to nonzero if we are current stopped in one of these. */
-#ifndef IN_SOLIB_TRAMPOLINE
-#define IN_SOLIB_TRAMPOLINE(pc,name) 0
+
+#ifndef IN_SOLIB_CALL_TRAMPOLINE
+#define IN_SOLIB_CALL_TRAMPOLINE(pc,name) 0
+#endif
+
+/* In some shared library schemes, the return path from a shared library
+ call may need to go through a trampoline too. */
+
+#ifndef IN_SOLIB_RETURN_TRAMPOLINE
+#define IN_SOLIB_RETURN_TRAMPOLINE(pc,name) 0
#endif
/* On some systems, the PC may be left pointing at an instruction that won't
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);
void
start_remote ()
{
+ init_thread_list ();
init_wait_for_inferior ();
clear_proceed_status ();
stop_soon_quietly = 1;
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);
+ have_waited:
+
flush_cached_frames ();
/* If it's a new process, add it to the thread database */
stop_signal = w.value.sig;
target_terminal_ours (); /* Must do this before mourn anyway */
annotate_signalled ();
+
+ /* This looks pretty bogus to me. Doesn't TARGET_WAITKIND_SIGNALLED
+ mean it is already dead? This has been here since GDB 2.8, so
+ perhaps it means rms didn't understand unix waitstatuses?
+ For the moment I'm just kludging around this in remote.c
+ rather than trying to change it here --kingdon, 5 Dec 1994. */
target_kill (); /* kill mourns as well */
+
printf_filtered ("\nProgram terminated with signal ");
annotate_signal_name ();
printf_filtered ("%s", target_signal_to_name (stop_signal));
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;
}
}
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
call. I'm not completely sure this is necessary now that we
have the above checks with stop_func_start (and now that
find_pc_partial_function is pickier). */
- || IN_SOLIB_TRAMPOLINE (stop_pc, stop_func_name)
+ || IN_SOLIB_CALL_TRAMPOLINE (stop_pc, stop_func_name)
/* If none of the above apply, it is a jump within a function,
or a return from a subroutine. The other case is longjmp,
break;
}
+ /* If we're in the return path from a shared library trampoline,
+ we want to proceed through the trampoline when stepping. */
+ if (IN_SOLIB_RETURN_TRAMPOLINE(stop_pc, stop_func_name))
+ {
+ CORE_ADDR tmp;
+
+ /* Determine where this trampoline returns. */
+ tmp = SKIP_TRAMPOLINE_CODE (stop_pc);
+
+ /* Only proceed through if we know where it's going. */
+ if (tmp)
+ {
+ /* And put the step-breakpoint there and go until there. */
+ struct symtab_and_line sr_sal;
+
+ sr_sal.pc = tmp;
+ sr_sal.symtab = NULL;
+ sr_sal.line = 0;
+ /* Do not specify what the fp should be when we stop
+ since on some machines the prologue
+ is where the new fp value is established. */
+ step_resume_breakpoint =
+ set_momentary_breakpoint (sr_sal, NULL, bp_step_resume);
+ if (breakpoints_inserted)
+ insert_breakpoints ();
+
+ /* Restart without fiddling with the step ranges or
+ other state. */
+ goto keep_going;
+ }
+ }
+
if (sal.line == 0)
{
/* We have no line number information. That means to stop
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;
}
struct restore_selected_frame_args {
- FRAME_ADDR frame_address;
+ CORE_ADDR frame_address;
int level;
};
restore_selected_frame_args * (declared as char * for catch_errors)
telling us what frame to restore. Returns 1 for success, or 0 for
failure. An error message will have been printed on error. */
+
static int
restore_selected_frame (args)
char *args;
{
struct restore_selected_frame_args *fr =
(struct restore_selected_frame_args *) args;
- FRAME fid;
+ struct frame_info *frame;
int level = fr->level;
- fid = find_relative_frame (get_current_frame (), &level);
+ frame = find_relative_frame (get_current_frame (), &level);
/* If inf_status->selected_frame_address is NULL, there was no
previously selected frame. */
- if (fid == 0 ||
- FRAME_FP (fid) != fr->frame_address ||
+ if (frame == NULL ||
+ FRAME_FP (frame) != fr->frame_address ||
level != 0)
{
warning ("Unable to restore previously selected frame.\n");
return 0;
}
- select_frame (fid, fr->level);
+ select_frame (frame, fr->level);
return(1);
}
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\