don't worry about this; it will make calls look like simple
jumps (and the stack frames will be printed when the frame
pointer moves), which is a reasonably non-violent response.
-
-#if 0
- We skip this; it causes more problems than it's worth.
-#ifdef SUN4_COMPILER_FEATURE
- We do a special ifdef for the sun 4, forcing it to single step
- into calls which don't have prologues. This means that we can't
- nexti over leaf nodes, we can probably next over them (since they
- won't have debugging symbols, usually), and we can next out of
- functions returning structures (with a "call .stret4" at the end).
-#endif
-#endif
*/
-
-
-
-
-#include <stdio.h>
-#include <string.h>
#include "defs.h"
+#include <string.h>
#include "symtab.h"
#include "frame.h"
#include "inferior.h"
#include "breakpoint.h"
#include "wait.h"
#include "gdbcore.h"
-#include "signame.h"
#include "command.h"
#include "terminal.h" /* For #ifdef TIOCGPGRP and new_tty */
#include "target.h"
/* Prototypes for local functions */
static void
-signals_info PARAMS ((char *));
+signals_info PARAMS ((char *, int));
static void
handle_command PARAMS ((char *, int));
#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 ".init" 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
+#endif
+
+/* Notify other parts of gdb that might care that signal handling may
+ have changed for one or more signals. */
+#ifndef NOTICE_SIGNAL_HANDLING_CHANGE
+#define NOTICE_SIGNAL_HANDLING_CHANGE /* No actions */
+#endif
+
+#ifdef TDESC
+#include "tdesc.h"
+int safe_to_init_tdesc_context = 0;
+extern dc_dcontext_t current_context;
+#endif
+
/* Tables of how to react to signals; the user sets them. */
-static char signal_stop[NSIG];
-static char signal_print[NSIG];
-static char signal_program[NSIG];
+static char *signal_stop;
+static char *signal_print;
+static char *signal_program;
/* Nonzero if breakpoints are now inserted in the inferior. */
/* Nonstatic for initialization during xxx_create_inferior. FIXME. */
#ifdef NO_SINGLE_STEP
if (step) {
- single_step(); /* Do it the hard way, w/temp breakpoints */
+ single_step(sig); /* Do it the hard way, w/temp breakpoints */
step = 0; /* ...and don't ask hardware to do it. */
}
#endif
normal_stop ();
}
-#if 0
-/* This might be useful (not sure), but isn't currently used. See also
- write_pc(). */
-/* Writing the inferior pc as a register calls this function
- to inform infrun that the pc has been set in the debugger. */
-
-void
-writing_pc (val)
- CORE_ADDR val;
-{
- stop_pc = val;
- pc_changed = 1;
-}
-#endif
-
/* Record the pc and sp of the program the last time it stopped.
These are just used internally by wait_for_inferior, but need
to be preserved over calls to it and cleared when the inferior
{
int pid;
char *shell_command;
- extern int sys_nerr;
- extern char *sys_errlist[];
char *shell_file;
static char default_shell_file[] = SHELL_FILE;
int len;
#ifdef NEED_POSIX_SETPGID
debug_setpgrp = setpgid (0, 0);
#else
-#ifdef USG
+#if defined(USG) && !defined(SETPGRP_ARGS)
debug_setpgrp = setpgrp ();
#else
debug_setpgrp = setpgrp (getpid (), getpid ());
for the inferior. */
#ifdef USE_PROC_FS
- proc_set_exec_trap (); /* Use SVR4 /proc interface */
+ /* Use SVR4 /proc interface */
+ proc_set_exec_trap ();
#else
- call_ptrace (0, 0, 0, 0); /* "Trace me, Dr. Memory!" */
+ /* "Trace me, Dr. Memory!" */
+ call_ptrace (0, 0, (PTRACE_ARG3_TYPE) 0, 0);
#endif
/* There is no execlpe call, so we have to set the environment
execlp (shell_file, shell_file, "-c", shell_command, (char *)0);
fprintf (stderr, "Cannot exec %s: %s.\n", shell_file,
- errno < sys_nerr ? sys_errlist[errno] : "unknown error");
+ safe_strerror (errno));
fflush (stderr);
_exit (0177);
}
correct program, and are poised at the first instruction of the
new program. */
#ifdef SOLIB_CREATE_INFERIOR_HOOK
- SOLIB_CREATE_INFERIOR_HOOK ();
+ SOLIB_CREATE_INFERIOR_HOOK (pid);
#endif
/* Should this perhaps just be a "proceed" call? FIXME */
#else
pid = atoi (args);
+ if (pid == getpid()) /* Trying to masturbate? */
+ error ("I refuse to debug myself!");
+
if (target_has_execution)
{
if (query ("A program is being debugged already. Kill it? "))
CORE_ADDR stop_sp;
CORE_ADDR stop_func_start;
char *stop_func_name;
- CORE_ADDR prologue_pc;
+ CORE_ADDR prologue_pc, tmp;
int stop_step_resume_break;
struct symtab_and_line sal;
int remove_breakpoints_on_following_step = 0;
target_wait (&w);
+#ifdef SIGTRAP_STOP_AFTER_LOAD
+
+ /* Somebody called load(2), and it gave us a "trap signal after load".
+ Ignore it gracefully. */
+
+ SIGTRAP_STOP_AFTER_LOAD (w);
+#endif
+
/* See if the process still exists; clean up if it doesn't. */
if (WIFEXITED (w))
{
target_terminal_ours (); /* Must do this before mourn anyway */
if (WEXITSTATUS (w))
- printf ("\nProgram exited with code 0%o.\n",
+ printf_filtered ("\nProgram exited with code 0%o.\n",
(unsigned int)WEXITSTATUS (w));
else
if (!batch_mode())
- printf ("\nProgram exited normally.\n");
+ printf_filtered ("\nProgram exited normally.\n");
fflush (stdout);
target_mourn_inferior ();
#ifdef NO_SINGLE_STEP
target_terminal_ours (); /* Must do this before mourn anyway */
target_kill (); /* kill mourns as well */
#ifdef PRINT_RANDOM_SIGNAL
- printf ("\nProgram terminated: ");
+ printf_filtered ("\nProgram terminated: ");
PRINT_RANDOM_SIGNAL (stop_signal);
#else
- printf ("\nProgram terminated with signal %d, %s\n",
- stop_signal,
- stop_signal < NSIG
- ? sys_siglist[stop_signal]
- : "(undocumented)");
+ printf_filtered ("\nProgram terminated with signal %d, %s\n",
+ stop_signal, safe_strsignal (stop_signal));
#endif
- printf ("The inferior process no longer exists.\n");
+ printf_filtered ("The inferior process no longer exists.\n");
fflush (stdout);
#ifdef NO_SINGLE_STEP
one_stepped = 0;
if (stop_signal == SIGTRAP
|| (breakpoints_inserted &&
(stop_signal == SIGILL
- || stop_signal == SIGEMT))
+#ifdef SIGEMT
+ || stop_signal == SIGEMT
+#endif
+ ))
|| stop_soon_quietly)
{
if (stop_signal == SIGTRAP && stop_after_trap)
will be set and we should check whether we've hit the
step breakpoint. */
if (stop_signal == SIGTRAP && trap_expected
- && step_resume_break_address == NULL)
+ && step_resume_break_address == 0)
bpstat_clear (&stop_bpstat);
else
{
/* End of a stack dummy. Some systems (e.g. Sony
news) give another signal besides SIGTRAP,
so check here as well as above. */
- || (stop_sp INNER_THAN stop_pc
- && stop_pc INNER_THAN stop_frame_address)
+ || PC_IN_CALL_DUMMY (stop_pc, stop_sp, stop_frame_address)
);
if (!random_signal)
stop_signal = SIGTRAP;
#ifdef PRINT_RANDOM_SIGNAL
PRINT_RANDOM_SIGNAL (stop_signal);
#else
- printf ("\nProgram received signal %d, %s\n",
- stop_signal,
- stop_signal < NSIG
- ? sys_siglist[stop_signal]
- : "(undocumented)");
+ printf_filtered ("\nProgram received signal %d, %s\n",
+ stop_signal, safe_strsignal (stop_signal));
#endif /* PRINT_RANDOM_SIGNAL */
fflush (stdout);
}
/* Need to blow away step-resume breakpoint, as it
interferes with us */
remove_step_breakpoint ();
- step_resume_break_address = NULL;
+ step_resume_break_address = 0;
stop_step_resume_break = 0;
#if 0 /* FIXME - Need to implement nested temporary breakpoints */
#if 0
if (* step_frame_address == 0
|| (step_frame_address == stop_frame_address))
-#endif 0
+#endif
{
remove_step_breakpoint ();
step_resume_break_address = 0;
&& (stop_sp INNER_THAN prev_sp
|| stop_frame_address != step_frame_address)))
{
-#if 0
- /* When "next"ing through a function,
- This causes an extra stop at the end.
- Is there any reason for this?
- It's confusing to the user. */
- /* Don't step through the return from a function
- unless that is the first instruction stepped through. */
- if (ABOUT_TO_RETURN (stop_pc))
- {
- stop_step = 1;
- break;
- }
-#endif
+ ;
}
/* We stepped out of the stepping range. See if that was due
if (step_range_end == 1)
step_range_end = (step_range_start = prev_pc) + 1;
remove_breakpoints_on_following_step = 1;
+ goto save_pc;
}
/* ==> See comments at top of file on this algorithm. <==*/
- else if (stop_pc == stop_func_start
- && (stop_func_start != prev_func_start
- || prologue_pc != stop_func_start
- || stop_sp != prev_sp))
+ if ((stop_pc == stop_func_start
+ || IN_SOLIB_TRAMPOLINE (stop_pc, stop_func_name))
+ && (stop_func_start != prev_func_start
+ || prologue_pc != stop_func_start
+ || stop_sp != prev_sp))
{
- /* It's a subroutine call */
- if (step_over_calls > 0
- || (step_over_calls && find_pc_function (stop_pc) == 0))
+ /* It's a subroutine call.
+ (0) If we are not stepping over any calls ("stepi"), we
+ just stop.
+ (1) If we're doing a "next", we want to continue through
+ the call ("step over the call").
+ (2) If we are in a function-call trampoline (a stub between
+ the calling routine and the real function), locate
+ the real function and change stop_func_start.
+ (3) If we're doing a "step", and there are no debug symbols
+ at the target of the call, we want to continue through
+ it ("step over the call").
+ (4) Otherwise, we want to stop soon, after the function
+ prologue ("step into the call"). */
+
+ if (step_over_calls == 0)
{
- /* A subroutine call has happened. */
- /* Set a special breakpoint after the return */
+ /* I presume that step_over_calls is only 0 when we're
+ supposed to be stepping at the assembly language level. */
+ stop_step = 1;
+ break;
+ }
- step_resume_break_address =
- ADDR_BITS_REMOVE (
- SAVED_PC_AFTER_CALL (
- get_current_frame ()));
+ if (step_over_calls > 0)
+ goto step_over_function;
- step_resume_break_duplicate
- = breakpoint_here_p (step_resume_break_address);
- if (breakpoints_inserted)
- insert_step_breakpoint ();
- }
+ tmp = SKIP_TRAMPOLINE_CODE (stop_pc);
+ if (tmp != 0)
+ stop_func_start = tmp;
+
+ if (find_pc_function (stop_func_start) != 0)
+ goto step_into_function;
+
+step_over_function:
+ /* A subroutine call has happened. */
+ /* Set a special breakpoint after the return */
+ step_resume_break_address =
+ ADDR_BITS_REMOVE
+ (SAVED_PC_AFTER_CALL (get_current_frame ()));
+ step_resume_break_duplicate
+ = breakpoint_here_p (step_resume_break_address);
+ if (breakpoints_inserted)
+ insert_step_breakpoint ();
+ goto save_pc;
+
+step_into_function:
/* Subroutine call with source code we should not step over.
Do step to the first line of code in it. */
- else if (step_over_calls)
- {
- 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
- (as it seems to on the vax under 4.2). */
- /* If the prologue ends in the middle of a source line,
- continue to the end of that source line.
- Otherwise, just go to end of prologue. */
+ 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
+ (as it seems to on the vax under 4.2). */
+ /* If the prologue ends in the middle of a source line,
+ continue to the end of that source line.
+ Otherwise, just go to end of prologue. */
#ifdef PROLOGUE_FIRSTLINE_OVERLAP
- /* no, don't either. It skips any code that's
- legitimately on the first line. */
+ /* no, don't either. It skips any code that's
+ legitimately on the first line. */
#else
- if (sal.end && sal.pc != stop_func_start)
- stop_func_start = sal.end;
+ if (sal.end && sal.pc != stop_func_start)
+ stop_func_start = sal.end;
#endif
-
- if (stop_func_start == stop_pc)
- {
- /* We are already there: stop now. */
- stop_step = 1;
- break;
- }
- else
- /* Put the step-breakpoint there and go until there. */
- {
- step_resume_break_address = stop_func_start;
-
- step_resume_break_duplicate
- = breakpoint_here_p (step_resume_break_address);
- if (breakpoints_inserted)
- insert_step_breakpoint ();
- /* 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_frame_address = 0;
- /* And make sure stepping stops right away then. */
- step_range_end = step_range_start;
- }
- }
- else
- {
- /* We get here only if step_over_calls is 0 and we
- just stepped into a subroutine. I presume
- that step_over_calls is only 0 when we're
- supposed to be stepping at the assembly
- language level.*/
- stop_step = 1;
- break;
- }
- }
- /* No subroutine call; stop now. */
- else
- {
- /* We've wandered out of the step range (but we haven't done a
- subroutine call or return (that's handled elsewhere)). We
- don't really want to stop until we encounter the start of a
- new statement. If so, we stop. Otherwise, we reset
- step_range_start and step_range_end, and just continue. */
- sal = find_pc_line(stop_pc, 0);
-
- if (step_range_end == 1 /* Don't do this for stepi/nexti */
- || sal.line == 0 /* Stop now if no line # info */
- || (current_line != sal.line
- && stop_pc == sal.pc))
+
+ if (stop_func_start == stop_pc)
{
+ /* We are already there: stop now. */
stop_step = 1;
break;
- }
- else if (sal.line != 0)
+ }
+ else
+ /* Put the step-breakpoint there and go until there. */
{
- /* This is probably not necessary, but it probably makes
- stepping more efficient, as we avoid calling
- find_pc_line() for each instruction we step over. */
- step_range_start = sal.pc;
- step_range_end = sal.end;
+ step_resume_break_address = stop_func_start;
+
+ step_resume_break_duplicate
+ = breakpoint_here_p (step_resume_break_address);
+ if (breakpoints_inserted)
+ insert_step_breakpoint ();
+ /* 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_frame_address = 0;
+ /* And make sure stepping stops right away then. */
+ step_range_end = step_range_start;
}
+ goto save_pc;
}
+
+ /* We've wandered out of the step range (but haven't done a
+ subroutine call or return). */
+
+ sal = find_pc_line(stop_pc, 0);
+
+ if (step_range_end == 1 || /* stepi or nexti */
+ sal.line == 0 || /* ...or no line # info */
+ (stop_pc == sal.pc /* ...or we're at the start */
+ && current_line != sal.line)) { /* of a different line */
+ /* Stop because we're done stepping. */
+ stop_step = 1;
+ break;
+ } else {
+ /* We aren't done stepping, and we have line number info for $pc.
+ Optimize by setting the step_range for the line.
+ (We might not be in the original line, but if we entered a
+ new line in mid-statement, we continue stepping. This makes
+ things like for(;;) statements work better.) */
+ step_range_start = sal.pc;
+ step_range_end = sal.end;
+ goto save_pc;
+ }
+ /* We never fall through here */
}
- else if (trap_expected
- && IN_SIGTRAMP (stop_pc, stop_func_name)
- && !IN_SIGTRAMP (prev_pc, prev_func_name))
+ if (trap_expected
+ && IN_SIGTRAMP (stop_pc, stop_func_name)
+ && !IN_SIGTRAMP (prev_pc, prev_func_name))
{
/* What has happened here is that we have just stepped the inferior
with a signal (because it is a signal which shouldn't make
keep_going:
+save_pc:
/* Save the pc before execution, to compare with pc after stop. */
prev_pc = read_pc (); /* Might have been DECR_AFTER_BREAK */
prev_func_start = stop_func_start; /* Ok, since if DECR_PC_AFTER
breakpoints_inserted = 0;
}
else if (!breakpoints_inserted &&
- (step_resume_break_address != NULL || !another_trap))
+ (step_resume_break_address != 0 || !another_trap))
{
insert_step_breakpoint ();
breakpoints_failed = insert_breakpoints ();
{
target_terminal_ours_for_output ();
print_sys_errmsg ("ptrace", breakpoints_failed);
- printf ("Stopped; cannot insert breakpoints.\n\
+ printf_filtered ("Stopped; cannot insert breakpoints.\n\
The same program may be running in another process.\n");
}
if (remove_breakpoints ())
{
target_terminal_ours_for_output ();
- printf ("Cannot remove breakpoints because program is no longer writable.\n\
+ printf_filtered ("Cannot remove breakpoints because program is no longer writable.\n\
It might be running in another process.\n\
Further execution is probably impossible.\n");
}
step_resume_break_shadow);
}
\f
+int signal_stop_state (signo)
+ int signo;
+{
+ return ((signo >= 0 && signo < NSIG) ? signal_stop[signo] : 0);
+}
+
+int signal_print_state (signo)
+ int signo;
+{
+ return ((signo >= 0 && signo < NSIG) ? signal_print[signo] : 0);
+}
+
+int signal_pass_state (signo)
+ int signo;
+{
+ return ((signo >= 0 && signo < NSIG) ? signal_program[signo] : 0);
+}
+
static void
sig_print_header ()
{
sig_print_info (number)
int number;
{
- char *abbrev = sig_abbrev(number);
- if (abbrev == NULL)
+ char *name;
+
+ if ((name = strsigno (number)) == NULL)
printf_filtered ("%d\t\t", number);
else
- printf_filtered ("SIG%s (%d)\t", abbrev, number);
+ printf_filtered ("%s (%d)\t", name, number);
printf_filtered ("%s\t", signal_stop[number] ? "Yes" : "No");
printf_filtered ("%s\t", signal_print[number] ? "Yes" : "No");
printf_filtered ("%s\t\t", signal_program[number] ? "Yes" : "No");
- printf_filtered ("%s\n", sys_siglist[number]);
+ printf_filtered ("%s\n", safe_strsignal (number));
}
/* Specify how various signals in the inferior should be handled. */
{
/* Numeric. */
signum = atoi (p);
- if (signum <= 0 || signum >= NSIG)
+ if (signum <= 0 || signum > signo_max ())
{
p[wordlen] = '\0';
error ("Invalid signal %s given as argument to \"handle\".", p);
else
{
/* Symbolic. */
- signum = sig_number (p);
- if (signum == -1)
+ signum = strtosigno (p);
+ if (signum == 0)
error ("No such signal \"%s\"", p);
}
if (signum == SIGTRAP || signum == SIGINT)
{
- if (!query ("SIG%s is used by the debugger.\nAre you sure you want to change it? ", sig_abbrev (signum)))
+ if (!query ("%s is used by the debugger.\nAre you sure you want to change it? ", strsigno (signum)))
error ("Not confirmed.");
}
}
/* Not a number and not a recognized flag word => complain. */
else
{
- error ("Unrecognized flag word: \"%s\".", p);
+ error ("Unrecognized or ambiguous flag word: \"%s\".", p);
}
/* Find start of next word. */
while (*p == ' ' || *p == '\t') p++;
}
+ NOTICE_SIGNAL_HANDLING_CHANGE;
+
if (from_tty)
{
/* Show the results. */
/* Print current contents of the tables set by the handle command. */
static void
-signals_info (signum_exp)
+signals_info (signum_exp, from_tty)
char *signum_exp;
+ int from_tty;
{
register int i;
sig_print_header ();
if (signum_exp)
{
/* First see if this is a symbol name. */
- i = sig_number (signum_exp);
- if (i == -1)
+ i = strtosigno (signum_exp);
+ if (i == 0)
{
/* Nope, maybe it's an address which evaluates to a signal
number. */
FRAME_FP (fid) != inf_status->selected_frame_address ||
level != 0)
{
-#if 0
+#if 1
/* I'm not sure this error message is a good idea. I have
only seen it occur after "Can't continue previously
requested operation" (we get called from do_cleanups), in
_initialize_infrun ()
{
register int i;
+ register int numsigs;
add_info ("signals", signals_info,
"What debugger does when program gets various signals.\n\
Pass means let program see this signal; otherwise program doesn't know.\n\
Pass and Stop may be combined.");
- for (i = 0; i < NSIG; i++)
+ numsigs = signo_max () + 1;
+ signal_stop = xmalloc (sizeof (signal_stop[0]) * numsigs);
+ signal_print = xmalloc (sizeof (signal_print[0]) * numsigs);
+ signal_program = xmalloc (sizeof (signal_program[0]) * numsigs);
+ for (i = 0; i < numsigs; i++)
{
signal_stop[i] = 1;
signal_print[i] = 1;