use _filtered routines for printing so symbolic addresses show up in the right place
[deliverable/binutils-gdb.git] / gdb / infrun.c
index 07083f0757b0ca7807dc3115851e546c2950ab98..b8464443ce907b0054aa2a01953ac90e67c3ab39 100644 (file)
@@ -109,7 +109,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #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"
@@ -133,7 +132,7 @@ extern int original_stack_limit;
 /* Prototypes for local functions */
 
 static void
-signals_info PARAMS ((char *));
+signals_info PARAMS ((char *, int));
 
 static void
 handle_command PARAMS ((char *, int));
@@ -191,6 +190,18 @@ extern struct target_ops child_ops;        /* In inftarg.c */
 #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"
@@ -200,9 +211,25 @@ extern dc_dcontext_t current_context;
 
 /* 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 unsigned char *signal_stop;
+static unsigned char *signal_print;
+static unsigned char *signal_program;
+
+#define SET_SIGS(nsigs,sigs,flags) \
+  do { \
+    int signum = (nsigs); \
+    while (signum-- > 0) \
+      if ((sigs)[signum]) \
+       (flags)[signum] = 1; \
+  } while (0)
+
+#define UNSET_SIGS(nsigs,sigs,flags) \
+  do { \
+    int signum = (nsigs); \
+    while (signum-- > 0) \
+      if ((sigs)[signum]) \
+       (flags)[signum] = 0; \
+  } while (0)
 
 /* Nonzero if breakpoints are now inserted in the inferior.  */
 /* Nonstatic for initialization during xxx_create_inferior. FIXME. */
@@ -460,8 +487,6 @@ child_create_inferior (exec_file, allargs, env)
 {
   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;
@@ -572,9 +597,11 @@ child_create_inferior (exec_file, allargs, env)
         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
@@ -586,7 +613,7 @@ child_create_inferior (exec_file, allargs, env)
       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);
     }
@@ -652,22 +679,11 @@ child_create_inferior (exec_file, allargs, env)
      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 */
-  insert_step_breakpoint ();
-  breakpoints_failed = insert_breakpoints ();
-  if (!breakpoints_failed)
-    {
-      breakpoints_inserted = 1;
-      target_terminal_inferior();
-      /* Start the child program going on its first instruction, single-
-        stepping if we need to.  */
-      resume (bpstat_should_step (), 0);
-      wait_for_inferior ();
-      normal_stop ();
-    }
+  /* Pedal to the metal.  Away we go.  */
+  proceed ((CORE_ADDR) -1, 0, 0);
 }
 
 /* Start remote-debugging of a machine over a serial link.  */
@@ -722,6 +738,9 @@ child_attach (args, from_tty)
 #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? "))
@@ -791,16 +810,24 @@ wait_for_inferior ()
 
       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
@@ -816,16 +843,13 @@ wait_for_inferior ()
          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;
@@ -848,8 +872,7 @@ wait_for_inferior ()
       stop_func_name = 0;
       /* Don't care about return value; stop_func_start and stop_func_name
         will both be 0 if it doesn't work.  */
-      (void) find_pc_partial_function (stop_pc, &stop_func_name,
-                                      &stop_func_start);
+      find_pc_partial_function (stop_pc, &stop_func_name, &stop_func_start);
       stop_func_start += FUNCTION_START_OFFSET;
       another_trap = 0;
       bpstat_clear (&stop_bpstat);
@@ -881,7 +904,10 @@ wait_for_inferior ()
       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)
@@ -986,11 +1012,8 @@ wait_for_inferior ()
 #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);
            }
@@ -1114,7 +1137,7 @@ wait_for_inferior ()
 #if 0
            if (* step_frame_address == 0
                || (step_frame_address == stop_frame_address))
-#endif 0
+#endif
              {
                remove_step_breakpoint ();
                step_resume_break_address = 0;
@@ -1201,10 +1224,11 @@ wait_for_inferior ()
 
          /* ==> See comments at top of file on this algorithm.  <==*/
          
-         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.
                 (0)  If we are not stepping over any calls ("stepi"), we
@@ -1232,7 +1256,7 @@ wait_for_inferior ()
                goto step_over_function;
 
              tmp = SKIP_TRAMPOLINE_CODE (stop_pc);
-             if (tmp != NULL)
+             if (tmp != 0)
                stop_func_start = tmp;
 
              if (find_pc_function (stop_func_start) != 0)
@@ -1316,7 +1340,7 @@ step_into_function:
            step_range_end = sal.end;
            goto save_pc;
          }
-       abort();                /* We never fall through here */
+         /* We never fall through here */
        }
 
       if (trap_expected
@@ -1471,7 +1495,7 @@ normal_stop ()
     {
       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");
     }
 
@@ -1482,7 +1506,7 @@ 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");
       }
@@ -1564,6 +1588,24 @@ remove_step_breakpoint ()
                              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 ()
 {
@@ -1574,15 +1616,16 @@ static void
 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.  */
@@ -1592,108 +1635,176 @@ handle_command (args, from_tty)
      char *args;
      int from_tty;
 {
-  register char *p = args;
-  int signum = 0;
-  register int digits, wordlen;
-  char *nextarg;
+  char **argv;
+  int digits, wordlen;
+  int sigfirst, signum, siglast;
+  int allsigs;
+  int nsigs;
+  unsigned char *sigs;
+  struct cleanup *old_chain;
+
+  if (args == NULL)
+    {
+      error_no_arg ("signal to handle");
+    }
 
-  if (!args)
-    error_no_arg ("signal to handle");
+  /* Allocate and zero an array of flags for which signals to handle. */
+
+  nsigs = signo_max () + 1;
+  sigs = (unsigned char *) alloca (nsigs);
+  memset (sigs, 0, nsigs);
+
+  /* Break the command line up into args. */
 
-  while (*p)
+  argv = buildargv (args);
+  if (argv == NULL)
     {
-      /* Find the end of the next word in the args.  */
-      for (wordlen = 0;
-          p[wordlen] && p[wordlen] != ' ' && p[wordlen] != '\t';
-          wordlen++);
-      /* Set nextarg to the start of the word after the one we just
-        found, and null-terminate this one.  */
-      if (p[wordlen] == '\0')
-       nextarg = p + wordlen;
-      else
-       {
-         p[wordlen] = '\0';
-         nextarg = p + wordlen + 1;
-       }
-      
+      nomem (0);
+    }
+  old_chain = make_cleanup (freeargv, (char *) argv);
 
-      for (digits = 0; p[digits] >= '0' && p[digits] <= '9'; digits++);
+  /* Walk through the args, looking for signal numbers, signal names, and
+     actions.  Signal numbers and signal names may be interspersed with
+     actions, with the actions being performed for all signals cumulatively
+     specified.  Signal ranges can be specified as <LOW>-<HIGH>. */
+
+  while (*argv != NULL)
+    {
+      wordlen = strlen (*argv);
+      for (digits = 0; isdigit ((*argv)[digits]); digits++) {;}
+      allsigs = 0;
+      sigfirst = siglast = -1;
 
-      if (signum == 0)
+      if (wordlen >= 1 && !strncmp (*argv, "all", wordlen))
        {
-         /* It is the first argument--must be the signal to operate on.  */
-         if (digits == wordlen)
+         /* Apply action to all signals except those used by the
+            debugger.  Silently skip those. */
+         allsigs = 1;
+         sigfirst = 0;
+         siglast = nsigs - 1;
+       }
+      else if (wordlen >= 1 && !strncmp (*argv, "stop", wordlen))
+       {
+         SET_SIGS (nsigs, sigs, signal_stop);
+         SET_SIGS (nsigs, sigs, signal_print);
+       }
+      else if (wordlen >= 1 && !strncmp (*argv, "ignore", wordlen))
+       {
+         UNSET_SIGS (nsigs, sigs, signal_program);
+       }
+      else if (wordlen >= 2 && !strncmp (*argv, "print", wordlen))
+       {
+         SET_SIGS (nsigs, sigs, signal_print);
+       }
+      else if (wordlen >= 2 && !strncmp (*argv, "pass", wordlen))
+       {
+         SET_SIGS (nsigs, sigs, signal_program);
+       }
+      else if (wordlen >= 3 && !strncmp (*argv, "nostop", wordlen))
+       {
+         UNSET_SIGS (nsigs, sigs, signal_stop);
+       }
+      else if (wordlen >= 3 && !strncmp (*argv, "noignore", wordlen))
+       {
+         SET_SIGS (nsigs, sigs, signal_program);
+       }
+      else if (wordlen >= 4 && !strncmp (*argv, "noprint", wordlen))
+       {
+         UNSET_SIGS (nsigs, sigs, signal_print);
+         UNSET_SIGS (nsigs, sigs, signal_stop);
+       }
+      else if (wordlen >= 4 && !strncmp (*argv, "nopass", wordlen))
+       {
+         UNSET_SIGS (nsigs, sigs, signal_program);
+       }
+      else if (digits > 0)
+       {
+         sigfirst = siglast = atoi (*argv);
+         if ((*argv)[digits] == '-')
            {
-             /* Numeric.  */
-             signum = atoi (p);
-             if (signum <= 0 || signum >= NSIG)
-               {
-                 p[wordlen] = '\0';
-                 error ("Invalid signal %s given as argument to \"handle\".", p);
-               }
+             siglast = atoi ((*argv) + digits + 1);
            }
-         else
+         if (sigfirst > siglast)
            {
-             /* Symbolic.  */
-             signum = sig_number (p);
-             if (signum == -1)
-               error ("No such signal \"%s\"", p);
+             /* Bet he didn't figure we'd think of this case... */
+             signum = sigfirst;
+             sigfirst = siglast;
+             siglast = signum;
            }
-
-         if (signum == SIGTRAP || signum == SIGINT)
+         if (sigfirst < 0 || sigfirst >= nsigs)
            {
-             if (!query ("SIG%s is used by the debugger.\nAre you sure you want to change it? ", sig_abbrev (signum)))
-               error ("Not confirmed.");
+             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, if already got a signal number, look for flag words
-        saying what to do for it.  */
-      else if (!strncmp (p, "stop", wordlen))
+      else if ((signum = strtosigno (*argv)) != 0)
        {
-         signal_stop[signum] = 1;
-         signal_print[signum] = 1;
+         sigfirst = siglast = signum;
        }
-      else if (wordlen >= 2 && !strncmp (p, "print", wordlen))
-       signal_print[signum] = 1;
-      else if (wordlen >= 2 && !strncmp (p, "pass", wordlen))
-       signal_program[signum] = 1;
-      else if (!strncmp (p, "ignore", wordlen))
-       signal_program[signum] = 0;
-      else if (wordlen >= 3 && !strncmp (p, "nostop", wordlen))
-       signal_stop[signum] = 0;
-      else if (wordlen >= 4 && !strncmp (p, "noprint", wordlen))
+      else
        {
-         signal_print[signum] = 0;
-         signal_stop[signum] = 0;
+         /* Not a number and not a recognized flag word => complain.  */
+         error ("Unrecognized or ambiguous flag word: \"%s\".", *argv);
        }
-      else if (wordlen >= 4 && !strncmp (p, "nopass", wordlen))
-       signal_program[signum] = 0;
-      else if (wordlen >= 3 && !strncmp (p, "noignore", wordlen))
-       signal_program[signum] = 1;
-      /* Not a number and not a recognized flag word => complain.  */
-      else
+
+      /* If any signal numbers or symbol names were found, set flags for
+        which signals to apply actions to. */
+
+      for (signum = sigfirst; signum >= 0 && signum <= siglast; signum++)
        {
-         error ("Unrecognized flag word: \"%s\".", p);
+         switch (signum)
+           {
+             case SIGTRAP:
+             case SIGINT:
+               if (!allsigs && !sigs[signum])
+                 {
+                   if (query ("%s is used by the debugger.\nAre you sure you want to change it? ", strsigno (signum)))
+                     {
+                       sigs[signum] = 1;
+                     }
+                   else
+                     {
+                       printf ("Not confirmed, unchanged.\n");
+                       fflush (stdout);
+                     }
+                 }
+               break;
+             default:
+               sigs[signum] = 1;
+               break;
+           }
        }
 
-      /* Find start of next word.  */
-      p = nextarg;
-      while (*p == ' ' || *p == '\t') p++;
+      argv++;
     }
 
+  NOTICE_SIGNAL_HANDLING_CHANGE;
+
   if (from_tty)
     {
       /* Show the results.  */
       sig_print_header ();
-      sig_print_info (signum);
+      for (signum = 0; signum < nsigs; signum++)
+       {
+         if (sigs[signum])
+           {
+             sig_print_info (signum);
+           }
+       }
     }
+
+  do_cleanups (old_chain);
 }
 
 /* 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 ();
@@ -1701,8 +1812,8 @@ signals_info (signum_exp)
   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.  */
@@ -1758,7 +1869,7 @@ save_inferior_status (inf_status, restore_stack_info)
   inf_status->restore_stack_info = restore_stack_info;
   inf_status->proceed_to_finish = proceed_to_finish;
   
-  bcopy (stop_registers, inf_status->stop_registers, REGISTER_BYTES);
+  memcpy (inf_status->stop_registers, stop_registers, REGISTER_BYTES);
   
   record_selected_frame (&(inf_status->selected_frame_address),
                         &(inf_status->selected_level));
@@ -1792,7 +1903,7 @@ restore_inferior_status (inf_status)
   breakpoint_proceeded = inf_status->breakpoint_proceeded;
   proceed_to_finish = inf_status->proceed_to_finish;
 
-  bcopy (inf_status->stop_registers, stop_registers, REGISTER_BYTES);
+  memcpy (stop_registers, inf_status->stop_registers, REGISTER_BYTES);
 
   /* The inferior can be gone if the user types "print exit(0)"
      (and perhaps other times).  */
@@ -1830,22 +1941,36 @@ void
 _initialize_infrun ()
 {
   register int i;
+  register int numsigs;
 
   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.");
+  add_info_alias ("handle", "signals", 0);
 
   add_com ("handle", class_run, handle_command,
           "Specify how to handle a signal.\n\
-Args are signal number followed by flags.\n\
-Flags allowed are \"stop\", \"print\", \"pass\",\n\
- \"nostop\", \"noprint\" or \"nopass\".\n\
-Print means print a message if this signal happens.\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\
+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\
+\"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.");
 
-  for (i = 0; i < NSIG; i++)
+  numsigs = signo_max () + 1;
+  signal_stop    = (unsigned char *)    
+                  xmalloc (sizeof (signal_stop[0]) * numsigs);
+  signal_print   = (unsigned char *)
+                  xmalloc (sizeof (signal_print[0]) * numsigs);
+  signal_program = (unsigned char *)
+                  xmalloc (sizeof (signal_program[0]) * numsigs);
+  for (i = 0; i < numsigs; i++)
     {
       signal_stop[i] = 1;
       signal_print[i] = 1;
This page took 0.030945 seconds and 4 git commands to generate.