2005-01-17 Kelley Cook <kcook@gcc.gnu.org>
[deliverable/binutils-gdb.git] / gdb / procfs.c
index 58ebf973dff9d6a8664b2112f76d5faa30f617b4..29d5c8140f067d4d7f9a01c7b5981e61b8ddb0d6 100644 (file)
@@ -48,6 +48,7 @@ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "gdb_string.h"
 #include "gdb_assert.h"
 #include "inflow.h"
+#include "auxv.h"
 
 /*
  * PROCFS.C
@@ -123,11 +124,16 @@ static void procfs_notice_signals (ptid_t);
 static void procfs_prepare_to_store (void);
 static void procfs_kill_inferior (void);
 static void procfs_mourn_inferior (void);
-static void procfs_create_inferior (char *, char *, char **);
+static void procfs_create_inferior (char *, char *, char **, int);
 static ptid_t procfs_wait (ptid_t, struct target_waitstatus *);
 static int procfs_xfer_memory (CORE_ADDR, char *, int, int,
                               struct mem_attrib *attrib,
                               struct target_ops *);
+static LONGEST procfs_xfer_partial (struct target_ops *ops,
+                                   enum target_object object,
+                                   const char *annex,
+                                   void *readbuf, const void *writebuf,
+                                   ULONGEST offset, LONGEST len);
 
 static int procfs_thread_alive (ptid_t);
 
@@ -165,7 +171,8 @@ init_procfs_ops (void)
   procfs_ops.to_prepare_to_store    = procfs_prepare_to_store;
   procfs_ops.to_fetch_registers     = procfs_fetch_registers;
   procfs_ops.to_store_registers     = procfs_store_registers;
-  procfs_ops.to_xfer_memory         = procfs_xfer_memory;
+  procfs_ops.to_xfer_partial        = procfs_xfer_partial;
+  procfs_ops.deprecated_xfer_memory = procfs_xfer_memory;
   procfs_ops.to_insert_breakpoint   =  memory_insert_breakpoint;
   procfs_ops.to_remove_breakpoint   =  memory_remove_breakpoint;
   procfs_ops.to_notice_signals      = procfs_notice_signals;
@@ -2566,12 +2573,8 @@ proc_clear_current_signal (procinfo *pi)
   return win;
 }
 
-/*
- * Function: proc_get_gregs
- *
- * Get the general registers for the process or LWP.
- * Returns non-zero for success, zero for failure.
- */
+/* Return the general-purpose registers for the process or LWP
+   corresponding to PI.  Upon failure, return NULL.  */
 
 gdb_gregset_t *
 proc_get_gregs (procinfo *pi)
@@ -2580,29 +2583,22 @@ proc_get_gregs (procinfo *pi)
     if (!proc_get_status (pi))
       return NULL;
 
-  /*
-   * OK, sorry about the ifdef's.
-   * There's three cases instead of two, because
-   * in this instance Unixware and Solaris/RW differ.
-   */
+  /* OK, sorry about the ifdef's.  There's three cases instead of two,
+     because in this case Unixware and Solaris/RW differ.  */
 
 #ifdef NEW_PROC_API
-#ifdef UNIXWARE                /* ugh, a true architecture dependency */
+# ifdef UNIXWARE               /* FIXME:  Should be autoconfigured.  */
   return &pi->prstatus.pr_lwp.pr_context.uc_mcontext.gregs;
-#else  /* not Unixware */
+# else
   return &pi->prstatus.pr_lwp.pr_reg;
-#endif /* Unixware */
-#else  /* not NEW_PROC_API */
+# endif
+#else
   return &pi->prstatus.pr_reg;
-#endif /* NEW_PROC_API */
+#endif
 }
 
-/*
- * Function: proc_get_fpregs
- *
- * Get the floating point registers for the process or LWP.
- * Returns non-zero for success, zero for failure.
- */
+/* Return the general-purpose registers for the process or LWP
+   corresponding to PI.  Upon failure, return NULL.  */
 
 gdb_fpregset_t *
 proc_get_fpregs (procinfo *pi)
@@ -2612,25 +2608,24 @@ proc_get_fpregs (procinfo *pi)
     if (!proc_get_status (pi))
       return NULL;
 
-#ifdef UNIXWARE                /* a true architecture dependency */
+# ifdef UNIXWARE               /* FIXME:  Should be autoconfigured.  */
   return &pi->prstatus.pr_lwp.pr_context.uc_mcontext.fpregs;
-#else
+# else
   return &pi->prstatus.pr_lwp.pr_fpreg;
-#endif /* Unixware */
+# endif
 
-#else  /* not NEW_PROC_API */
+#else  /* not NEW_PROC_API */
   if (pi->fpregs_valid)
-    return &pi->fpregset;      /* already got 'em */
+    return &pi->fpregset;      /* Already got 'em.  */
   else
     {
-      if (pi->ctl_fd == 0 &&
-         open_procinfo_files (pi, FD_CTL) == 0)
+      if (pi->ctl_fd == 0 && open_procinfo_files (pi, FD_CTL) == 0)
        {
          return NULL;
        }
       else
        {
-#ifdef PIOCTGFPREG
+# ifdef PIOCTGFPREG
          struct {
            long pr_count;
            tid_t pr_error_thread;
@@ -2640,46 +2635,43 @@ proc_get_fpregs (procinfo *pi)
          thread_fpregs.pr_count = 1;
          thread_fpregs.thread_1.tid = pi->tid;
 
-         if (pi->tid == 0 &&
-             ioctl (pi->ctl_fd, PIOCGFPREG, &pi->fpregset) >= 0)
+         if (pi->tid == 0
+             && ioctl (pi->ctl_fd, PIOCGFPREG, &pi->fpregset) >= 0)
            {
              pi->fpregs_valid = 1;
-             return &pi->fpregset;     /* got 'em now! */
+             return &pi->fpregset; /* Got 'em now!  */
            }
-         else if (pi->tid != 0 &&
-                  ioctl (pi->ctl_fd, PIOCTGFPREG, &thread_fpregs) >= 0)
+         else if (pi->tid != 0
+                  && ioctl (pi->ctl_fd, PIOCTGFPREG, &thread_fpregs) >= 0)
            {
              memcpy (&pi->fpregset, &thread_fpregs.thread_1.pr_fpregs,
                      sizeof (pi->fpregset));
              pi->fpregs_valid = 1;
-             return &pi->fpregset;     /* got 'em now! */
+             return &pi->fpregset; /* Got 'em now!  */
            }
          else
            {
              return NULL;
            }
-#else
+# else
          if (ioctl (pi->ctl_fd, PIOCGFPREG, &pi->fpregset) >= 0)
            {
              pi->fpregs_valid = 1;
-             return &pi->fpregset;     /* got 'em now! */
+             return &pi->fpregset; /* Got 'em now!  */
            }
          else
            {
              return NULL;
            }
-#endif
+# endif
        }
     }
-#endif
+#endif /* NEW_PROC_API */
 }
 
-/*
- * Function: proc_set_gregs
- *
- * Write the general registers back to the process or LWP.
- * Returns non-zero for success, zero for failure.
- */
+/* Write the general-purpose registers back to the process or LWP
+   corresponding to PI.  Return non-zero for success, zero for
+   failure.  */
 
 int
 proc_set_gregs (procinfo *pi)
@@ -2687,11 +2679,11 @@ proc_set_gregs (procinfo *pi)
   gdb_gregset_t *gregs;
   int win;
 
-  if ((gregs = proc_get_gregs (pi)) == NULL)
-    return 0;  /* get_regs has already warned */
+  gregs = proc_get_gregs (pi);
+  if (gregs == NULL)
+    return 0;                  /* proc_get_regs has already warned.  */
 
-  if (pi->ctl_fd == 0 &&
-      open_procinfo_files (pi, FD_CTL) == 0)
+  if (pi->ctl_fd == 0 && open_procinfo_files (pi, FD_CTL) == 0)
     {
       return 0;
     }
@@ -2704,7 +2696,7 @@ proc_set_gregs (procinfo *pi)
        char gregs[sizeof (gdb_gregset_t)];
       } arg;
 
-      arg.cmd   = PCSREG;
+      arg.cmd = PCSREG;
       memcpy (&arg.gregs, gregs, sizeof (arg.gregs));
       win = (write (pi->ctl_fd, (void *) &arg, sizeof (arg)) == sizeof (arg));
 #else
@@ -2712,17 +2704,14 @@ proc_set_gregs (procinfo *pi)
 #endif
     }
 
-  /* Policy: writing the regs invalidates our cache. */
+  /* Policy: writing the registers invalidates our cache.  */
   pi->gregs_valid = 0;
   return win;
 }
 
-/*
- * Function: proc_set_fpregs
- *
- * Modify the floating point register set of the process or LWP.
- * Returns non-zero for success, zero for failure.
- */
+/* Write the floating-pointer registers back to the process or LWP
+   corresponding to PI.  Return non-zero for success, zero for
+   failure.  */
 
 int
 proc_set_fpregs (procinfo *pi)
@@ -2730,11 +2719,11 @@ proc_set_fpregs (procinfo *pi)
   gdb_fpregset_t *fpregs;
   int win;
 
-  if ((fpregs = proc_get_fpregs (pi)) == NULL)
-    return 0;          /* get_fpregs has already warned */
+  fpregs = proc_get_fpregs (pi);
+  if (fpregs == NULL)
+    return 0;                  /* proc_get_fpregs has already warned.  */
 
-  if (pi->ctl_fd == 0 &&
-      open_procinfo_files (pi, FD_CTL) == 0)
+  if (pi->ctl_fd == 0 && open_procinfo_files (pi, FD_CTL) == 0)
     {
       return 0;
     }
@@ -2747,11 +2736,11 @@ proc_set_fpregs (procinfo *pi)
        char fpregs[sizeof (gdb_fpregset_t)];
       } arg;
 
-      arg.cmd   = PCSFPREG;
+      arg.cmd = PCSFPREG;
       memcpy (&arg.fpregs, fpregs, sizeof (arg.fpregs));
       win = (write (pi->ctl_fd, (void *) &arg, sizeof (arg)) == sizeof (arg));
 #else
-#ifdef PIOCTSFPREG
+# ifdef PIOCTSFPREG
       if (pi->tid == 0)
        win = (ioctl (pi->ctl_fd, PIOCSFPREG, fpregs) >= 0);
       else
@@ -2768,13 +2757,13 @@ proc_set_fpregs (procinfo *pi)
                  sizeof (*fpregs));
          win = (ioctl (pi->ctl_fd, PIOCTSFPREG, &thread_fpregs) >= 0);
        }
-#else
+# else
       win = (ioctl (pi->ctl_fd, PIOCSFPREG, fpregs) >= 0);
-#endif /* osf PIOCTSFPREG */
-#endif /* NEW_PROC_API */
+# endif
+#endif /* NEW_PROC_API */
     }
 
-  /* Policy: writing the regs invalidates our cache. */
+  /* Policy: writing the registers invalidates our cache.  */
   pi->fpregs_valid = 0;
   return win;
 }
@@ -3375,6 +3364,17 @@ proc_iterate_over_threads (procinfo *pi,
 static ptid_t do_attach (ptid_t ptid);
 static void do_detach (int signo);
 static int register_gdb_signals (procinfo *, gdb_sigset_t *);
+static void proc_trace_syscalls_1 (procinfo *pi, int syscallnum,
+                                   int entry_or_exit, int mode, int from_tty);
+static int insert_dbx_link_breakpoint (procinfo *pi);
+static void remove_dbx_link_breakpoint (void);
+
+/* On mips-irix, we need to insert a breakpoint at __dbx_link during
+   the startup phase.  The following two variables are used to record
+   the address of the breakpoint, and the code that was replaced by
+   a breakpoint.  */
+static int dbx_link_bpt_addr = 0;
+static char dbx_link_shadow_contents[BREAKPOINT_MAX];
 
 /*
  * Function: procfs_debug_inferior
@@ -3538,24 +3538,29 @@ procfs_attach (char *args, int from_tty)
 static void
 procfs_detach (char *args, int from_tty)
 {
-  char *exec_file;
-  int   signo = 0;
+  int sig = 0;
+
+  if (args)
+    sig = atoi (args);
 
   if (from_tty)
     {
+      int pid = PIDGET (inferior_ptid);
+      char *exec_file;
+
       exec_file = get_exec_file (0);
-      if (exec_file == 0)
+      if (exec_file == NULL)
        exec_file = "";
-      printf_filtered ("Detaching from program: %s %s\n",
-             exec_file, target_pid_to_str (inferior_ptid));
-      fflush (stdout);
+
+      printf_filtered ("Detaching from program: %s, %s\n", exec_file,
+                      target_pid_to_str (pid_to_ptid (pid)));
+      gdb_flush (gdb_stdout);
     }
-  if (args)
-    signo = atoi (args);
 
-  do_detach (signo);
+  do_detach (sig);
+
   inferior_ptid = null_ptid;
-  unpush_target (&procfs_ops);         /* Pop out of handling an inferior */
+  unpush_target (&procfs_ops);
 }
 
 static ptid_t
@@ -3660,57 +3665,58 @@ do_detach (int signo)
   destroy_procinfo (pi);
 }
 
-/*
- * fetch_registers
- *
- * Since the /proc interface cannot give us individual registers,
- * we pay no attention to the (regno) argument, and just fetch them all.
- * This results in the possibility that we will do unnecessarily many
- * fetches, since we may be called repeatedly for individual registers.
- * So we cache the results, and mark the cache invalid when the process
- * is resumed.
- */
+/* Fetch register REGNUM from the inferior.  If REGNUM is -1, do this
+   for all registers.
+
+   ??? Is the following note still relevant?  We can't get individual
+   registers with the PT_GETREGS ptrace(2) request either, yet we
+   don't bother with caching at all in that case.
+
+   NOTE: Since the /proc interface cannot give us individual
+   registers, we pay no attention to REGNUM, and just fetch them all.
+   This results in the possibility that we will do unnecessarily many
+   fetches, since we may be called repeatedly for individual
+   registers.  So we cache the results, and mark the cache invalid
+   when the process is resumed.  */
 
 static void
-procfs_fetch_registers (int regno)
+procfs_fetch_registers (int regnum)
 {
-  gdb_fpregset_t *fpregs;
-  gdb_gregset_t  *gregs;
-  procinfo       *pi;
-  int            pid;
-  int            tid;
-
-  pid = PIDGET (inferior_ptid);
-  tid = TIDGET (inferior_ptid);
+  gdb_gregset_t *gregs;
+  procinfo *pi;
+  int pid = PIDGET (inferior_ptid);
+  int tid = TIDGET (inferior_ptid);
 
-  /* First look up procinfo for the main process. */
-  pi  = find_procinfo_or_die (pid, 0);
+  /* First look up procinfo for the main process.  */
+  pi = find_procinfo_or_die (pid, 0);
 
   /* If the event thread is not the same as GDB's requested thread
      (ie. inferior_ptid), then look up procinfo for the requested
      thread.  */
-  if ((tid != 0) &&
-      (tid != proc_get_current_thread (pi)))
+  if (tid != 0 && tid != proc_get_current_thread (pi))
     pi = find_procinfo_or_die (pid, tid);
 
   if (pi == NULL)
     error ("procfs: fetch_registers failed to find procinfo for %s",
           target_pid_to_str (inferior_ptid));
 
-  if ((gregs = proc_get_gregs (pi)) == NULL)
+  gregs = proc_get_gregs (pi);
+  if (gregs == NULL)
     proc_error (pi, "fetch_registers, get_gregs", __LINE__);
 
   supply_gregset (gregs);
 
-  if (FP0_REGNUM >= 0) /* need floating point? */
+  if (FP0_REGNUM >= 0)         /* Do we have an FPU?  */
     {
-      if ((regno >= 0 && regno < FP0_REGNUM)
-         || regno == PC_REGNUM
-         || regno == DEPRECATED_FP_REGNUM
-         || regno == SP_REGNUM)
-       return;                 /* not a floating point register */
+      gdb_fpregset_t *fpregs;
 
-      if ((fpregs = proc_get_fpregs (pi)) == NULL)
+      if ((regnum >= 0 && regnum < FP0_REGNUM)
+         || regnum == PC_REGNUM
+         || regnum == SP_REGNUM)
+       return;                 /* Not a floating point register.  */
+
+      fpregs = proc_get_fpregs (pi);
+      if (fpregs == NULL)
        proc_error (pi, "fetch_registers, get_fpregs", __LINE__);
 
       supply_fpregset (fpregs);
@@ -3731,62 +3737,59 @@ procfs_prepare_to_store (void)
 #endif
 }
 
-/*
- * store_registers
- *
- * Since the /proc interface will not read individual registers,
- * we will cache these requests until the process is resumed, and
- * only then write them back to the inferior process.
- *
- * FIXME: is that a really bad idea?  Have to think about cases
- * where writing one register might affect the value of others, etc.
- */
+/* Store register REGNUM back into the inferior.  If REGNUM is -1, do
+   this for all registers.
+
+   NOTE: Since the /proc interface will not read individual registers,
+   we will cache these requests until the process is resumed, and only
+   then write them back to the inferior process.
+   FIXME: is that a really bad idea?  Have to think about cases where
+   writing one register might affect the value of others, etc.  */
 
 static void
-procfs_store_registers (int regno)
+procfs_store_registers (int regnum)
 {
-  gdb_fpregset_t *fpregs;
-  gdb_gregset_t  *gregs;
-  procinfo       *pi;
-  int            pid;
-  int            tid;
-
-  pid = PIDGET (inferior_ptid);
-  tid = TIDGET (inferior_ptid);
-
-  /* First find procinfo for main process */
-  pi  = find_procinfo_or_die (pid, 0);
+  gdb_gregset_t *gregs;
+  procinfo *pi;
+  int pid = PIDGET (inferior_ptid);
+  int tid = TIDGET (inferior_ptid);
 
-  /* If current lwp for process is not the same as requested thread
-     (ie. inferior_ptid), then find procinfo for the requested thread.  */
+  /* First find procinfo for main process.  */
+  pi = find_procinfo_or_die (pid, 0);
 
-  if ((tid != 0) &&
-      (tid != proc_get_current_thread (pi)))
+  /* If the event thread is not the same as GDB's requested thread
+     (ie. inferior_ptid), then look up procinfo for the requested
+     thread.  */
+  if (tid != 0 && tid != proc_get_current_thread (pi))
     pi = find_procinfo_or_die (pid, tid);
 
   if (pi == NULL)
     error ("procfs: store_registers: failed to find procinfo for %s",
           target_pid_to_str (inferior_ptid));
 
-  if ((gregs = proc_get_gregs (pi)) == NULL)
+  gregs = proc_get_gregs (pi);
+  if (gregs == NULL)
     proc_error (pi, "store_registers, get_gregs", __LINE__);
 
-  fill_gregset (gregs, regno);
+  fill_gregset (gregs, regnum);
   if (!proc_set_gregs (pi))
     proc_error (pi, "store_registers, set_gregs", __LINE__);
 
-  if (FP0_REGNUM >= 0)         /* need floating point? */
+  if (FP0_REGNUM >= 0)         /* Do we have an FPU?  */
     {
-      if ((regno >= 0 && regno < FP0_REGNUM)
-         || regno == PC_REGNUM
-         || regno == DEPRECATED_FP_REGNUM
-         || regno == SP_REGNUM)
-       return;                 /* not a floating point register */
+      gdb_fpregset_t *fpregs;
+
+      if ((regnum >= 0 && regnum < FP0_REGNUM)
+         || regnum == PC_REGNUM
+         || regnum == SP_REGNUM)
+       return;                 /* Not a floating point register.  */
 
-      if ((fpregs = proc_get_fpregs (pi)) == NULL)
+      fpregs = proc_get_fpregs (pi);
+      if (fpregs == NULL)
        proc_error (pi, "store_registers, get_fpregs", __LINE__);
 
-      fill_fpregset (fpregs, regno);
+      fill_fpregset (fpregs, regnum);
       if (!proc_set_fpregs (pi))
        proc_error (pi, "store_registers, set_fpregs", __LINE__);
     }
@@ -4058,6 +4061,22 @@ wait_again:
                       address. */
                    wstat = (SIGTRAP << 8) | 0177;
                  }
+#ifdef SYS_syssgi
+                else if (what == SYS_syssgi)
+                  {
+                    /* see if we can break on dbx_link().  If yes, then
+                       we no longer need the SYS_syssgi notifications.  */
+                    if (insert_dbx_link_breakpoint (pi))
+                      proc_trace_syscalls_1 (pi, SYS_syssgi, PR_SYSEXIT,
+                                             FLAG_RESET, 0);
+
+                    /* This is an internal event and should be transparent
+                       to wfi, so resume the execution and wait again.  See
+                       comment in procfs_init_inferior() for more details.  */
+                    target_resume (ptid, 0, TARGET_SIGNAL_0);
+                    goto wait_again;
+                  }
+#endif
                else if (syscall_is_lwp_create (pi, what))
                  {
                    /*
@@ -4184,6 +4203,13 @@ wait_again:
 #if (FLTTRACE != FLTBPT)       /* avoid "duplicate case" error */
                case FLTTRACE:
 #endif
+                  /* If we hit our __dbx_link() internal breakpoint,
+                     then remove it.  See comments in procfs_init_inferior()
+                     for more details.  */
+                  if (dbx_link_bpt_addr != 0
+                      && dbx_link_bpt_addr == read_pc ())
+                    remove_dbx_link_breakpoint ();
+
                  wstat = (SIGTRAP << 8) | 0177;
                  break;
                case FLTSTACK:
@@ -4268,6 +4294,40 @@ wait_again:
   return retval;
 }
 
+/* Perform a partial transfer to/from the specified object.  For
+   memory transfers, fall back to the old memory xfer functions.  */
+
+static LONGEST
+procfs_xfer_partial (struct target_ops *ops, enum target_object object,
+                    const char *annex, void *readbuf,
+                    const void *writebuf, ULONGEST offset, LONGEST len)
+{
+  switch (object)
+    {
+    case TARGET_OBJECT_MEMORY:
+      if (readbuf)
+       return (*ops->deprecated_xfer_memory) (offset, readbuf, len,
+                                              0/*write*/, NULL, ops);
+      if (writebuf)
+       return (*ops->deprecated_xfer_memory) (offset, writebuf, len,
+                                              1/*write*/, NULL, ops);
+      return -1;
+
+#ifdef NEW_PROC_API
+    case TARGET_OBJECT_AUXV:
+      return procfs_xfer_auxv (ops, object, annex, readbuf, writebuf,
+                              offset, len);
+#endif
+
+    default:
+      if (ops->beneath != NULL)
+       return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
+                                             readbuf, writebuf, offset, len);
+      return -1;
+    }
+}
+
+
 /* Transfer LEN bytes between GDB address MYADDR and target address
    MEMADDR.  If DOWRITE is non-zero, transfer them to the target,
    otherwise transfer them from the target.  TARGET is unused.
@@ -4798,12 +4858,35 @@ procfs_init_inferior (int pid)
      the actual process ID plus the lwp ID. */
   inferior_ptid = MERGEPID (pi->pid, proc_get_current_thread (pi));
 
-#ifdef START_INFERIOR_TRAPS_EXPECTED
+  /* Typically two, one trap to exec the shell, one to exec the
+     program being debugged.  Defined by "inferior.h".  */
   startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
-#else
-  /* One trap to exec the shell, one to exec the program being debugged.  */
-  startup_inferior (2);
-#endif /* START_INFERIOR_TRAPS_EXPECTED */
+
+#ifdef SYS_syssgi
+  /* On mips-irix, we need to stop the inferior early enough during
+     the startup phase in order to be able to load the shared library
+     symbols and insert the breakpoints that are located in these shared
+     libraries.  Stopping at the program entry point is not good enough
+     because the -init code is executed before the execution reaches
+     that point.
+
+     So what we need to do is to insert a breakpoint in the runtime
+     loader (rld), more precisely in __dbx_link().  This procedure is
+     called by rld once all shared libraries have been mapped, but before
+     the -init code is executed. Unfortuantely, this is not straightforward,
+     as rld is not part of the executable we are running, and thus we need
+     the inferior to run until rld itself has been mapped in memory.
+     
+     For this, we trace all syssgi() syscall exit events.  Each time
+     we detect such an event, we iterate over each text memory maps,
+     get its associated fd, and scan the symbol table for __dbx_link().
+     When found, we know that rld has been mapped, and that we can insert
+     the breakpoint at the symbol address.  Once the dbx_link() breakpoint
+     has been inserted, the syssgi() notifications are no longer necessary,
+     so they should be canceled.  */
+  proc_trace_syscalls_1 (pi, SYS_syssgi, PR_SYSEXIT, FLAG_SET, 0);
+  dbx_link_bpt_addr = 0;
+#endif
 }
 
 /*
@@ -4934,7 +5017,8 @@ procfs_set_exec_trap (void)
  */
 
 static void
-procfs_create_inferior (char *exec_file, char *allargs, char **env)
+procfs_create_inferior (char *exec_file, char *allargs, char **env,
+                       int from_tty)
 {
   char *shell_file = getenv ("SHELL");
   char *tryname;
@@ -5009,6 +5093,16 @@ procfs_create_inferior (char *exec_file, char *allargs, char **env)
   fork_inferior (exec_file, allargs, env, procfs_set_exec_trap,
                 procfs_init_inferior, NULL, shell_file);
 
+#ifdef SYS_syssgi
+  /* Make sure to cancel the syssgi() syscall-exit notifications.  
+     They should normally have been removed by now, but they may still
+     be activated if the inferior doesn't use shared libraries, or if
+     we didn't locate __dbx_link, or if we never stopped in __dbx_link.
+     See procfs_init_inferior() for more details.  */
+  proc_trace_syscalls_1 (find_procinfo_or_die (PIDGET (inferior_ptid), 0),
+                         SYS_syssgi, PR_SYSEXIT, FLAG_RESET, 0);
+#endif
+  
   /* We are at the first instruction we care about.  */
   /* Pedal to the metal... */
 
@@ -5083,29 +5177,19 @@ procfs_thread_alive (ptid_t ptid)
   return 1;
 }
 
-/*
- * Function: target_pid_to_str
- *
- * Return a string to be used to identify the thread in
- * the "info threads" display.
- */
+/* Convert PTID to a string.  Returns the string in a static buffer.  */
 
 char *
 procfs_pid_to_str (ptid_t ptid)
 {
   static char buf[80];
-  int proc, thread;
-  procinfo *pi;
-
-  proc    = PIDGET (ptid);
-  thread  = TIDGET (ptid);
-  pi      = find_procinfo (proc, thread);
 
-  if (thread == 0)
-    sprintf (buf, "Process %d", proc);
+  if (TIDGET (ptid) == 0)
+    sprintf (buf, "process %d", PIDGET (ptid));
   else
-    sprintf (buf, "LWP %d", thread);
-  return &buf[0];
+    sprintf (buf, "LWP %ld", TIDGET (ptid));
+
+  return buf;
 }
 
 /*
@@ -5481,6 +5565,131 @@ proc_find_memory_regions (int (*func) (CORE_ADDR,
                                find_memory_regions_callback);
 }
 
+/* Remove the breakpoint that we inserted in __dbx_link().
+   Does nothing if the breakpoint hasn't been inserted or has already
+   been removed.  */
+
+static void
+remove_dbx_link_breakpoint (void)
+{
+  if (dbx_link_bpt_addr == 0)
+    return;
+
+  if (memory_remove_breakpoint (dbx_link_bpt_addr,
+                                dbx_link_shadow_contents) != 0)
+    warning ("Unable to remove __dbx_link breakpoint.");
+
+  dbx_link_bpt_addr = 0;
+}
+
+/* Return the address of the __dbx_link() function in the file
+   refernced by ABFD by scanning its symbol table.  Return 0 if
+   the symbol was not found.  */
+
+static CORE_ADDR
+dbx_link_addr (bfd *abfd)
+{
+  long storage_needed;
+  asymbol **symbol_table;
+  long number_of_symbols;
+  long i;
+
+  storage_needed = bfd_get_symtab_upper_bound (abfd);
+  if (storage_needed <= 0)
+    return 0;
+
+  symbol_table = (asymbol **) xmalloc (storage_needed);
+  make_cleanup (xfree, symbol_table);
+
+  number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
+
+  for (i = 0; i < number_of_symbols; i++)
+    {
+      asymbol *sym = symbol_table[i];
+
+      if ((sym->flags & BSF_GLOBAL)
+          && sym->name != NULL && strcmp (sym->name, "__dbx_link") == 0)
+        return (sym->value + sym->section->vma);
+    }
+
+  /* Symbol not found, return NULL.  */
+  return 0;
+}
+
+/* Search the symbol table of the file referenced by FD for a symbol
+   named __dbx_link(). If found, then insert a breakpoint at this location,
+   and return nonzero.  Return zero otherwise.  */
+
+static int
+insert_dbx_link_bpt_in_file (int fd, CORE_ADDR ignored)
+{
+  bfd *abfd;
+  long storage_needed;
+  CORE_ADDR sym_addr;
+
+  abfd = bfd_fdopenr ("unamed", 0, fd);
+  if (abfd == NULL)
+    {
+      warning ("Failed to create a bfd: %s.\n", bfd_errmsg (bfd_get_error ()));
+      return 0;
+    }
+
+  if (!bfd_check_format (abfd, bfd_object))
+    {
+      /* Not the correct format, so we can not possibly find the dbx_link
+         symbol in it.  */
+      bfd_close (abfd);
+      return 0;
+    }
+
+  sym_addr = dbx_link_addr (abfd);
+  if (sym_addr != 0)
+    {
+      /* Insert the breakpoint.  */
+      dbx_link_bpt_addr = sym_addr;
+      if (target_insert_breakpoint (sym_addr, dbx_link_shadow_contents) != 0)
+        {
+          warning ("Failed to insert dbx_link breakpoint.");
+          bfd_close (abfd);
+          return 0;
+        }
+      bfd_close (abfd);
+      return 1;
+    }
+
+  bfd_close (abfd);
+  return 0;
+} 
+
+/* If the given memory region MAP contains a symbol named __dbx_link,
+   insert a breakpoint at this location and return nonzero.  Return
+   zero otherwise.  */
+
+static int
+insert_dbx_link_bpt_in_region (struct prmap *map,
+                               int (*child_func) (),
+                               void *data)
+{     
+  procinfo *pi = (procinfo *) data;
+        
+  /* We know the symbol we're looking for is in a text region, so
+     only look for it if the region is a text one.  */
+  if (map->pr_mflags & MA_EXEC)
+    return solib_mappings_callback (map, insert_dbx_link_bpt_in_file, pi);
+  return 0;
+}           
+
+/* Search all memory regions for a symbol named __dbx_link.  If found,
+   insert a breakpoint at its location, and return nonzero.  Return zero
+   otherwise.  */
+
+static int
+insert_dbx_link_breakpoint (procinfo *pi)
+{
+  return iterate_over_mappings (pi, NULL, pi, insert_dbx_link_bpt_in_region);
+}
+
 /*
  * Function: mappingflags
  *
@@ -5669,12 +5878,50 @@ info_proc_cmd (char *args, int from_tty)
   do_cleanups (old_chain);
 }
 
+/* Modify the status of the system call identified by SYSCALLNUM in
+   the set of syscalls that are currently traced/debugged.
+
+   If ENTRY_OR_EXIT is set to PR_SYSENTRY, then the entry syscalls set
+   will be updated. Otherwise, the exit syscalls set will be updated.
+
+   If MODE is FLAG_SET, then traces will be enabled. Otherwise, they
+   will be disabled.  */
+
+static void
+proc_trace_syscalls_1 (procinfo *pi, int syscallnum, int entry_or_exit,
+                      int mode, int from_tty)
+{
+  sysset_t *sysset;
+  
+  if (entry_or_exit == PR_SYSENTRY)
+    sysset = proc_get_traced_sysentry (pi, NULL);
+  else
+    sysset = proc_get_traced_sysexit (pi, NULL);
+
+  if (sysset == NULL)
+    proc_error (pi, "proc-trace, get_traced_sysset", __LINE__);
+
+  if (mode == FLAG_SET)
+    gdb_praddsysset (sysset, syscallnum);
+  else
+    gdb_prdelsysset (sysset, syscallnum);
+
+  if (entry_or_exit == PR_SYSENTRY)
+    {
+      if (!proc_set_traced_sysentry (pi, sysset))
+        proc_error (pi, "proc-trace, set_traced_sysentry", __LINE__);
+    }
+  else
+    {
+      if (!proc_set_traced_sysexit (pi, sysset))
+        proc_error (pi, "proc-trace, set_traced_sysexit", __LINE__);
+    }
+}
+
 static void
 proc_trace_syscalls (char *args, int from_tty, int entry_or_exit, int mode)
 {
   procinfo *pi;
-  sysset_t *sysset;
-  int       syscallnum = 0;
 
   if (PIDGET (inferior_ptid) <= 0)
     error ("you must be debugging a process to use this command.");
@@ -5685,30 +5932,9 @@ proc_trace_syscalls (char *args, int from_tty, int entry_or_exit, int mode)
   pi = find_procinfo_or_die (PIDGET (inferior_ptid), 0);
   if (isdigit (args[0]))
     {
-      syscallnum = atoi (args);
-      if (entry_or_exit == PR_SYSENTRY)
-       sysset = proc_get_traced_sysentry (pi, NULL);
-      else
-       sysset = proc_get_traced_sysexit (pi, NULL);
+      const int syscallnum = atoi (args);
 
-      if (sysset == NULL)
-       proc_error (pi, "proc-trace, get_traced_sysset", __LINE__);
-
-      if (mode == FLAG_SET)
-       gdb_praddsysset (sysset, syscallnum);
-      else
-       gdb_prdelsysset (sysset, syscallnum);
-
-      if (entry_or_exit == PR_SYSENTRY)
-       {
-         if (!proc_set_traced_sysentry (pi, sysset))
-           proc_error (pi, "proc-trace, set_traced_sysentry", __LINE__);
-       }
-      else
-       {
-         if (!proc_set_traced_sysexit (pi, sysset))
-           proc_error (pi, "proc-trace, set_traced_sysexit", __LINE__);
-       }
+      proc_trace_syscalls_1 (pi, syscallnum, entry_or_exit, mode, from_tty);
     }
 }
 
@@ -5850,6 +6076,8 @@ procfs_make_note_section (bfd *obfd, int *note_size)
   char *note_data = NULL;
   char *inf_args;
   struct procfs_corefile_thread_data thread_args;
+  char *auxv;
+  int auxv_len;
 
   if (get_exec_file (0))
     {
@@ -5898,6 +6126,14 @@ procfs_make_note_section (bfd *obfd, int *note_size)
       note_data = thread_args.note_data;
     }
 
+  auxv_len = target_auxv_read (&current_target, &auxv);
+  if (auxv_len > 0)
+    {
+      note_data = elfcore_write_note (obfd, note_data, note_size,
+                                     "CORE", NT_AUXV, auxv, auxv_len);
+      xfree (auxv);
+    }
+
   make_cleanup (xfree, note_data);
   return note_data;
 }
This page took 0.034755 seconds and 4 git commands to generate.