daily update
[deliverable/binutils-gdb.git] / gdb / procfs.c
index 1250ff96dced81553e2033f4286b398f4d02227f..da9fd4cbbe4d63de99549d5984c30eea7aacc247 100644 (file)
@@ -1,27 +1,25 @@
 /* Machine independent support for SVR4 /proc (process file system) for GDB.
 
-   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2006, 2007
+   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2006, 2007, 2008
    Free Software Foundation, Inc.
 
    Written by Michael Snyder at Cygnus Solutions.
    Based on work by Fred Fish, Stu Grossman, Geoff Noer, and others.
 
-This file is part of GDB.
+   This file is part of GDB.
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
 
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-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., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
 #include "inferior.h"
@@ -30,6 +28,7 @@ Boston, MA 02110-1301, USA.  */
 #include "elf-bfd.h"           /* for elfcore_write_* */
 #include "gdbcmd.h"
 #include "gdbthread.h"
+#include "regcache.h"
 
 #if defined (NEW_PROC_API)
 #define _STRUCTURED_PROC 1     /* Should be done by configure script. */
@@ -119,10 +118,10 @@ static void procfs_resume (ptid_t, int, enum target_signal);
 static int procfs_can_run (void);
 static void procfs_stop (void);
 static void procfs_files_info (struct target_ops *);
-static void procfs_fetch_registers (int);
-static void procfs_store_registers (int);
+static void procfs_fetch_registers (struct regcache *, int);
+static void procfs_store_registers (struct regcache *, int);
 static void procfs_notice_signals (ptid_t);
-static void procfs_prepare_to_store (void);
+static void procfs_prepare_to_store (struct regcache *);
 static void procfs_kill_inferior (void);
 static void procfs_mourn_inferior (void);
 static void procfs_create_inferior (char *, char *, char **, int);
@@ -153,6 +152,35 @@ static int procfs_can_use_hw_breakpoint (int, int, int);
 
 struct target_ops procfs_ops;          /* the target vector */
 
+#if defined (PR_MODEL_NATIVE) && (PR_MODEL_NATIVE == PR_MODEL_LP64)
+/* When GDB is built as 64-bit application on Solaris, the auxv data is
+   presented in 64-bit format.  We need to provide a custom parser to handle 
+   that.  */
+static int
+procfs_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
+                  gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
+{
+  const int pointer_size = TYPE_LENGTH (builtin_type_void_data_ptr);
+  gdb_byte *ptr = *readptr;
+
+  if (endptr == ptr)
+    return 0;
+  
+  if (endptr - ptr < 8 * 2)
+    return -1;
+
+  *typep = extract_unsigned_integer (ptr, 4);
+  ptr += 8;
+  /* The size of data is always 64-bit.  If the application is 32-bit,
+     it will be zero extended, as expected.  */
+  *valp = extract_unsigned_integer (ptr, 8);
+  ptr += 8;
+
+  *readptr = ptr;
+  return 1;
+}
+#endif
+
 static void
 init_procfs_ops (void)
 {
@@ -201,6 +229,11 @@ init_procfs_ops (void)
   procfs_ops.to_find_memory_regions = proc_find_memory_regions;
   procfs_ops.to_make_corefile_notes = procfs_make_note_section;
   procfs_ops.to_can_use_hw_breakpoint = procfs_can_use_hw_breakpoint;
+
+#if defined(PR_MODEL_NATIVE) && (PR_MODEL_NATIVE == PR_MODEL_LP64)
+  procfs_ops.to_auxv_parse = procfs_auxv_parse;
+#endif
+
   procfs_ops.to_magic               = OPS_MAGIC;
 }
 
@@ -2486,6 +2519,8 @@ proc_set_current_signal (procinfo *pi, int signo)
     char sinfo[sizeof (gdb_siginfo_t)];
   } arg;
   gdb_siginfo_t *mysinfo;
+  ptid_t wait_ptid;
+  struct target_waitstatus wait_status;
 
   /*
    * We should never have to apply this operation to any procinfo
@@ -2509,10 +2544,31 @@ proc_set_current_signal (procinfo *pi, int signo)
 
   /* The pointer is just a type alias.  */
   mysinfo = (gdb_siginfo_t *) &arg.sinfo;
-  mysinfo->si_signo = signo;
-  mysinfo->si_code  = 0;
-  mysinfo->si_pid   = getpid ();       /* ?why? */
-  mysinfo->si_uid   = getuid ();       /* ?why? */
+  get_last_target_status (&wait_ptid, &wait_status);
+  if (ptid_equal (wait_ptid, inferior_ptid)
+      && wait_status.kind == TARGET_WAITKIND_STOPPED
+      && wait_status.value.sig == target_signal_from_host (signo)
+      && proc_get_status (pi)
+#ifdef NEW_PROC_API
+      && pi->prstatus.pr_lwp.pr_info.si_signo == signo
+#else
+      && pi->prstatus.pr_info.si_signo == signo
+#endif
+      )
+    /* Use the siginfo associated with the signal being
+       redelivered.  */
+#ifdef NEW_PROC_API
+    memcpy (mysinfo, &pi->prstatus.pr_lwp.pr_info, sizeof (gdb_siginfo_t));
+#else
+    memcpy (mysinfo, &pi->prstatus.pr_info, sizeof (gdb_siginfo_t));
+#endif
+  else
+    {
+      mysinfo->si_signo = signo;
+      mysinfo->si_code  = 0;
+      mysinfo->si_pid   = getpid ();       /* ?why? */
+      mysinfo->si_uid   = getuid ();       /* ?why? */
+    }
 
 #ifdef NEW_PROC_API
   arg.cmd = PCSSIG;
@@ -2846,7 +2902,8 @@ procfs_address_to_host_pointer (CORE_ADDR addr)
   void *ptr;
 
   gdb_assert (sizeof (ptr) == TYPE_LENGTH (builtin_type_void_data_ptr));
-  ADDRESS_TO_POINTER (builtin_type_void_data_ptr, &ptr, addr);
+  gdbarch_address_to_pointer (current_gdbarch, builtin_type_void_data_ptr,
+                             &ptr, addr);
   return ptr;
 }
 
@@ -2896,7 +2953,7 @@ proc_set_watchpoint (procinfo *pi, CORE_ADDR addr, int len, int wflags)
 #endif
 }
 
-#ifdef TM_I386SOL2_H           /* Is it hokey to use this? */
+#if (defined(__i386__) || defined(__x86_64__)) && defined (sun)
 
 #include <sys/sysi86.h>
 
@@ -2988,7 +3045,45 @@ proc_get_LDT_entry (procinfo *pi, int key)
 #endif
 }
 
-#endif /* TM_I386SOL2_H */
+/*
+ * Function: procfs_find_LDT_entry
+ *
+ * Input:
+ *   ptid_t ptid;      // The GDB-style pid-plus-LWP.
+ *
+ * Return:
+ *   pointer to the corresponding LDT entry.
+ */
+
+struct ssd *
+procfs_find_LDT_entry (ptid_t ptid)
+{
+  gdb_gregset_t *gregs;
+  int            key;
+  procinfo      *pi;
+
+  /* Find procinfo for the lwp. */
+  if ((pi = find_procinfo (PIDGET (ptid), TIDGET (ptid))) == NULL)
+    {
+      warning (_("procfs_find_LDT_entry: could not find procinfo for %d:%d."),
+              PIDGET (ptid), TIDGET (ptid));
+      return NULL;
+    }
+  /* get its general registers. */
+  if ((gregs = proc_get_gregs (pi)) == NULL)
+    {
+      warning (_("procfs_find_LDT_entry: could not read gregs for %d:%d."),
+              PIDGET (ptid), TIDGET (ptid));
+      return NULL;
+    }
+  /* Now extract the GS register's lower 16 bits. */
+  key = (*gregs)[GS] & 0xffff;
+
+  /* Find the matching entry and return it. */
+  return proc_get_LDT_entry (pi, key);
+}
+
+#endif
 
 /* =============== END, non-thread part of /proc  "MODULE" =============== */
 
@@ -3681,12 +3776,13 @@ do_detach (int signo)
    when the process is resumed.  */
 
 static void
-procfs_fetch_registers (int regnum)
+procfs_fetch_registers (struct regcache *regcache, int regnum)
 {
   gdb_gregset_t *gregs;
   procinfo *pi;
   int pid = PIDGET (inferior_ptid);
   int tid = TIDGET (inferior_ptid);
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
 
   /* First look up procinfo for the main process.  */
   pi = find_procinfo_or_die (pid, 0);
@@ -3705,22 +3801,22 @@ procfs_fetch_registers (int regnum)
   if (gregs == NULL)
     proc_error (pi, "fetch_registers, get_gregs", __LINE__);
 
-  supply_gregset (gregs);
+  supply_gregset (regcache, (const gdb_gregset_t *) gregs);
 
-  if (FP0_REGNUM >= 0)         /* Do we have an FPU?  */
+  if (gdbarch_fp0_regnum (gdbarch) >= 0) /* Do we have an FPU?  */
     {
       gdb_fpregset_t *fpregs;
 
-      if ((regnum >= 0 && regnum < FP0_REGNUM)
-         || regnum == PC_REGNUM
-         || regnum == SP_REGNUM)
+      if ((regnum >= 0 && regnum < gdbarch_fp0_regnum (gdbarch))
+         || regnum == gdbarch_pc_regnum (gdbarch)
+         || regnum == gdbarch_sp_regnum (gdbarch))
        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);
+      supply_fpregset (regcache, (const gdb_fpregset_t *) fpregs);
     }
 }
 
@@ -3731,11 +3827,8 @@ procfs_fetch_registers (int regnum)
    from the program being debugged.  */
 
 static void
-procfs_prepare_to_store (void)
+procfs_prepare_to_store (struct regcache *regcache)
 {
-#ifdef CHILD_PREPARE_TO_STORE
-  CHILD_PREPARE_TO_STORE ();
-#endif
 }
 
 /* Store register REGNUM back into the inferior.  If REGNUM is -1, do
@@ -3749,12 +3842,13 @@ procfs_prepare_to_store (void)
    writing one register might affect the value of others, etc.  */
 
 static void
-procfs_store_registers (int regnum)
+procfs_store_registers (struct regcache *regcache, int regnum)
 {
   gdb_gregset_t *gregs;
   procinfo *pi;
   int pid = PIDGET (inferior_ptid);
   int tid = TIDGET (inferior_ptid);
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
 
   /* First find procinfo for main process.  */
   pi = find_procinfo_or_die (pid, 0);
@@ -3773,24 +3867,24 @@ procfs_store_registers (int regnum)
   if (gregs == NULL)
     proc_error (pi, "store_registers, get_gregs", __LINE__);
 
-  fill_gregset (gregs, regnum);
+  fill_gregset (regcache, gregs, regnum);
   if (!proc_set_gregs (pi))
     proc_error (pi, "store_registers, set_gregs", __LINE__);
 
-  if (FP0_REGNUM >= 0)         /* Do we have an FPU?  */
+  if (gdbarch_fp0_regnum (gdbarch) >= 0) /* Do we have an FPU?  */
     {
       gdb_fpregset_t *fpregs;
 
-      if ((regnum >= 0 && regnum < FP0_REGNUM)
-         || regnum == PC_REGNUM
-         || regnum == SP_REGNUM)
+      if ((regnum >= 0 && regnum < gdbarch_fp0_regnum (gdbarch))
+         || regnum == gdbarch_pc_regnum (gdbarch)
+         || regnum == gdbarch_sp_regnum (gdbarch))
        return;                 /* Not a floating point register.  */
 
       fpregs = proc_get_fpregs (pi);
       if (fpregs == NULL)
        proc_error (pi, "store_registers, get_fpregs", __LINE__);
 
-      fill_fpregset (fpregs, regnum);
+      fill_fpregset (regcache, fpregs, regnum);
       if (!proc_set_fpregs (pi))
        proc_error (pi, "store_registers, set_fpregs", __LINE__);
     }
@@ -3974,8 +4068,9 @@ wait_again:
              case PR_SYSENTRY:
                if (syscall_is_lwp_exit (pi, what))
                  {
-                   printf_filtered (_("[%s exited]\n"),
-                                    target_pid_to_str (retval));
+                   if (print_thread_events)
+                     printf_unfiltered (_("[%s exited]\n"),
+                                        target_pid_to_str (retval));
                    delete_thread (retval);
                    status->kind = TARGET_WAITKIND_SPURIOUS;
                    return retval;
@@ -4097,19 +4192,17 @@ wait_again:
                    temp_ptid = MERGEPID (pi->pid, temp_tid);
                    /* If not in GDB's thread list, add it.  */
                    if (!in_thread_list (temp_ptid))
-                     {
-                       printf_filtered (_("[New %s]\n"),
-                                        target_pid_to_str (temp_ptid));
-                       add_thread (temp_ptid);
-                     }
+                     add_thread (temp_ptid);
+
                    /* Return to WFI, but tell it to immediately resume. */
                    status->kind = TARGET_WAITKIND_SPURIOUS;
                    return inferior_ptid;
                  }
                else if (syscall_is_lwp_exit (pi, what))
                  {
-                   printf_filtered (_("[%s exited]\n"),
-                                    target_pid_to_str (retval));
+                   if (print_thread_events)
+                     printf_unfiltered (_("[%s exited]\n"),
+                                        target_pid_to_str (retval));
                    delete_thread (retval);
                    status->kind = TARGET_WAITKIND_SPURIOUS;
                    return retval;
@@ -4167,11 +4260,7 @@ wait_again:
                    /* If not in GDB's thread list, add it.  */
                    temp_ptid = MERGEPID (pi->pid, temp_tid);
                    if (!in_thread_list (temp_ptid))
-                     {
-                       printf_filtered (_("[New %s]\n"),
-                                        target_pid_to_str (temp_ptid));
-                       add_thread (temp_ptid);
-                     }
+                     add_thread (temp_ptid);
 
                    status->kind = TARGET_WAITKIND_STOPPED;
                    status->value.sig = 0;
@@ -4258,7 +4347,6 @@ wait_again:
                   * If we don't create a procinfo, resume may be unhappy
                   * later.
                   */
-                 printf_filtered (_("[New %s]\n"), target_pid_to_str (retval));
                  add_thread (retval);
                  if (find_procinfo (PIDGET (retval), TIDGET (retval)) == NULL)
                    create_procinfo (PIDGET (retval), TIDGET (retval));
@@ -4308,7 +4396,7 @@ procfs_xfer_partial (struct target_ops *ops, enum target_object object,
     case TARGET_OBJECT_MEMORY:
       if (readbuf)
        return (*ops->deprecated_xfer_memory) (offset, readbuf, len,
-                                              0/*write*/, NULL, ops);
+                                              0/*read*/, NULL, ops);
       if (writebuf)
        return (*ops->deprecated_xfer_memory) (offset, writebuf, len,
                                               1/*write*/, NULL, ops);
@@ -4414,7 +4502,7 @@ invalidate_cache (procinfo *parent, procinfo *pi, void *ptr)
       if (!proc_set_gregs (pi))        /* flush gregs cache */
        proc_warn (pi, "target_resume, set_gregs",
                   __LINE__);
-  if (FP0_REGNUM >= 0)
+  if (gdbarch_fp0_regnum (current_gdbarch) >= 0)
     if (pi->fpregs_dirty)
       if (parent == NULL ||
          proc_get_current_thread (parent) != pi->tid)
@@ -5317,46 +5405,6 @@ procfs_stopped_by_watchpoint (ptid_t ptid)
   return 0;
 }
 
-#ifdef TM_I386SOL2_H
-/*
- * Function: procfs_find_LDT_entry
- *
- * Input:
- *   ptid_t ptid;      // The GDB-style pid-plus-LWP.
- *
- * Return:
- *   pointer to the corresponding LDT entry.
- */
-
-struct ssd *
-procfs_find_LDT_entry (ptid_t ptid)
-{
-  gdb_gregset_t *gregs;
-  int            key;
-  procinfo      *pi;
-
-  /* Find procinfo for the lwp. */
-  if ((pi = find_procinfo (PIDGET (ptid), TIDGET (ptid))) == NULL)
-    {
-      warning (_("procfs_find_LDT_entry: could not find procinfo for %d:%d."),
-              PIDGET (ptid), TIDGET (ptid));
-      return NULL;
-    }
-  /* get its general registers. */
-  if ((gregs = proc_get_gregs (pi)) == NULL)
-    {
-      warning (_("procfs_find_LDT_entry: could not read gregs for %d:%d."),
-              PIDGET (ptid), TIDGET (ptid));
-      return NULL;
-    }
-  /* Now extract the GS register's lower 16 bits. */
-  key = (*gregs)[GS] & 0xffff;
-
-  /* Find the matching entry and return it. */
-  return proc_get_LDT_entry (pi, key);
-}
-#endif /* TM_I386SOL2_H */
-
 /*
  * Memory Mappings Functions:
  */
@@ -5736,7 +5784,7 @@ info_mappings_callback (struct prmap *map, int (*ignore) (), void *unused)
 {
   char *data_fmt_string;
 
-  if (TARGET_ADDR_BIT == 32)
+  if (gdbarch_addr_bit (current_gdbarch) == 32)
     data_fmt_string   = "\t%#10lx %#10lx %#10x %#10x %7s\n";
   else
     data_fmt_string   = "  %#18lx %#18lx %#10x %#10x %7s\n";
@@ -5766,7 +5814,7 @@ info_proc_mappings (procinfo *pi, int summary)
 {
   char *header_fmt_string;
 
-  if (TARGET_PTR_BIT == 32)
+  if (gdbarch_ptr_bit (current_gdbarch) == 32)
     header_fmt_string = "\t%10s %10s %10s %10s %7s\n";
   else
     header_fmt_string = "  %18s %18s %10s %10s %7s\n";
@@ -6014,13 +6062,14 @@ static char *
 procfs_do_thread_registers (bfd *obfd, ptid_t ptid,
                            char *note_data, int *note_size)
 {
+  struct regcache *regcache = get_thread_regcache (ptid);
   gdb_gregset_t gregs;
   gdb_fpregset_t fpregs;
   unsigned long merged_pid;
 
   merged_pid = TIDGET (ptid) << 16 | PIDGET (ptid);
 
-  fill_gregset (&gregs, -1);
+  fill_gregset (regcache, &gregs, -1);
 #if defined (UNIXWARE)
   note_data = (char *) elfcore_write_lwpstatus (obfd,
                                                note_data,
@@ -6036,7 +6085,7 @@ procfs_do_thread_registers (bfd *obfd, ptid_t ptid,
                                               stop_signal,
                                               &gregs);
 #endif
-  fill_fpregset (&fpregs, -1);
+  fill_fpregset (regcache, &fpregs, -1);
   note_data = (char *) elfcore_write_prfpreg (obfd,
                                              note_data,
                                              note_size,
@@ -6107,7 +6156,7 @@ procfs_make_note_section (bfd *obfd, int *note_size)
                                               psargs);
 
 #ifdef UNIXWARE
-  fill_gregset (&gregs, -1);
+  fill_gregset (get_current_regcache (), &gregs, -1);
   note_data = elfcore_write_pstatus (obfd, note_data, note_size,
                                     PIDGET (inferior_ptid),
                                     stop_signal, &gregs);
This page took 0.030772 seconds and 4 git commands to generate.