* inferior.h (read_pc, write_pc): Remove.
[deliverable/binutils-gdb.git] / gdb / procfs.c
index 03fcadd017a9f1c9e406a9b28082064ce3e2d248..f62f0752fcfc7e8ae2a1762859e412ef46d6d4fb 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 Free Software Foundation,
-   Inc.
+   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2006, 2007, 2008, 2009
+   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,8 @@ Boston, MA 02110-1301, USA.  */
 #include "elf-bfd.h"           /* for elfcore_write_* */
 #include "gdbcmd.h"
 #include "gdbthread.h"
+#include "regcache.h"
+#include "inf-child.h"
 
 #if defined (NEW_PROC_API)
 #define _STRUCTURED_PROC 1     /* Should be done by configure script. */
@@ -112,34 +112,36 @@ Boston, MA 02110-1301, USA.  */
  * This module defines the GDB target vector and its methods.
  */
 
-static void procfs_open (char *, int);
-static void procfs_attach (char *, int);
-static void procfs_detach (char *, int);
-static void procfs_resume (ptid_t, int, enum target_signal);
-static int procfs_can_run (void);
-static void procfs_stop (void);
+static void procfs_attach (struct target_ops *, char *, int);
+static void procfs_detach (struct target_ops *, char *, int);
+static void procfs_resume (struct target_ops *,
+                          ptid_t, int, enum target_signal);
+static void procfs_stop (ptid_t);
 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 target_ops *,
+                                   struct regcache *, int);
+static void procfs_store_registers (struct target_ops *,
+                                   struct regcache *, int);
 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 **, int);
-static ptid_t procfs_wait (ptid_t, struct target_waitstatus *);
-static int procfs_xfer_memory (CORE_ADDR, char *, int, int,
+static void procfs_kill_inferior (struct target_ops *ops);
+static void procfs_mourn_inferior (struct target_ops *ops);
+static void procfs_create_inferior (struct target_ops *, char *, 
+                                   char *, char **, int);
+static ptid_t procfs_wait (struct target_ops *,
+                          ptid_t, struct target_waitstatus *);
+static int procfs_xfer_memory (CORE_ADDR, gdb_byte *, 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,
+                                   gdb_byte *readbuf, const gdb_byte *writebuf,
                                    ULONGEST offset, LONGEST len);
 
-static int procfs_thread_alive (ptid_t);
+static int procfs_thread_alive (struct target_ops *ops, ptid_t);
 
-void procfs_find_new_threads (void);
-char *procfs_pid_to_str (ptid_t);
+void procfs_find_new_threads (struct target_ops *ops);
+char *procfs_pid_to_str (struct target_ops *, ptid_t);
 
 static int proc_find_memory_regions (int (*) (CORE_ADDR,
                                              unsigned long,
@@ -151,57 +153,74 @@ static char * procfs_make_note_section (bfd *, int *);
 
 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)
+{
+  gdb_byte *ptr = *readptr;
 
-static void
-init_procfs_ops (void)
+  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 struct target_ops *
+procfs_target (void)
 {
-  procfs_ops.to_shortname           = "procfs";
-  procfs_ops.to_longname            = "Unix /proc child process";
-  procfs_ops.to_doc                 =
+  struct target_ops *t = inf_child_target ();
+
+  t->to_shortname           = "procfs";
+  t->to_longname            = "Unix /proc child process";
+  t->to_doc                 =
     "Unix /proc child process (started by the \"run\" command).";
-  procfs_ops.to_open                = procfs_open;
-  procfs_ops.to_can_run             = procfs_can_run;
-  procfs_ops.to_create_inferior     = procfs_create_inferior;
-  procfs_ops.to_kill                = procfs_kill_inferior;
-  procfs_ops.to_mourn_inferior      = procfs_mourn_inferior;
-  procfs_ops.to_attach              = procfs_attach;
-  procfs_ops.to_detach              = procfs_detach;
-  procfs_ops.to_wait                = procfs_wait;
-  procfs_ops.to_resume              = procfs_resume;
-  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_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;
-  procfs_ops.to_files_info          = procfs_files_info;
-  procfs_ops.to_stop                = procfs_stop;
-
-  procfs_ops.to_terminal_init       = terminal_init_inferior;
-  procfs_ops.to_terminal_inferior   = terminal_inferior;
-  procfs_ops.to_terminal_ours_for_output = terminal_ours_for_output;
-  procfs_ops.to_terminal_ours       = terminal_ours;
-  procfs_ops.to_terminal_save_ours  = terminal_save_ours;
-  procfs_ops.to_terminal_info       = child_terminal_info;
-
-  procfs_ops.to_find_new_threads    = procfs_find_new_threads;
-  procfs_ops.to_thread_alive        = procfs_thread_alive;
-  procfs_ops.to_pid_to_str          = procfs_pid_to_str;
-
-  procfs_ops.to_has_all_memory      = 1;
-  procfs_ops.to_has_memory          = 1;
-  procfs_ops.to_has_execution       = 1;
-  procfs_ops.to_has_stack           = 1;
-  procfs_ops.to_has_registers       = 1;
-  procfs_ops.to_stratum             = process_stratum;
-  procfs_ops.to_has_thread_control  = tc_schedlock;
-  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;
-  procfs_ops.to_magic               = OPS_MAGIC;
+  t->to_create_inferior     = procfs_create_inferior;
+  t->to_kill                = procfs_kill_inferior;
+  t->to_mourn_inferior      = procfs_mourn_inferior;
+  t->to_attach              = procfs_attach;
+  t->to_detach              = procfs_detach;
+  t->to_wait                = procfs_wait;
+  t->to_resume              = procfs_resume;
+  t->to_fetch_registers     = procfs_fetch_registers;
+  t->to_store_registers     = procfs_store_registers;
+  t->to_xfer_partial        = procfs_xfer_partial;
+  t->deprecated_xfer_memory = procfs_xfer_memory;
+  t->to_notice_signals      = procfs_notice_signals;
+  t->to_files_info          = procfs_files_info;
+  t->to_stop                = procfs_stop;
+
+  t->to_find_new_threads    = procfs_find_new_threads;
+  t->to_thread_alive        = procfs_thread_alive;
+  t->to_pid_to_str          = procfs_pid_to_str;
+
+  t->to_has_thread_control  = tc_schedlock;
+  t->to_find_memory_regions = proc_find_memory_regions;
+  t->to_make_corefile_notes = procfs_make_note_section;
+  t->to_can_use_hw_breakpoint = procfs_can_use_hw_breakpoint;
+
+#if defined(PR_MODEL_NATIVE) && (PR_MODEL_NATIVE == PR_MODEL_LP64)
+  t->to_auxv_parse = procfs_auxv_parse;
+#endif
+
+  t->to_magic               = OPS_MAGIC;
+
+  return t;
 }
 
 /* =================== END, TARGET_OPS "MODULE" =================== */
@@ -683,7 +702,7 @@ open_procinfo_files (procinfo *pi, int which)
 static procinfo *
 create_procinfo (int pid, int tid)
 {
-  procinfo *pi, *parent;
+  procinfo *pi, *parent = NULL;
 
   if ((pi = find_procinfo (pid, tid)))
     return pi;                 /* Already exists, nothing to do. */
@@ -834,7 +853,7 @@ dead_procinfo (procinfo *pi, char *msg, int kill_p)
     kill (pi->pid, SIGKILL);
 
   destroy_procinfo (pi);
-  error ((msg));
+  error ("%s", msg);
 }
 
 /*
@@ -2486,6 +2505,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 +2530,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;
@@ -2843,10 +2885,12 @@ proc_parent_pid (procinfo *pi)
 static void *
 procfs_address_to_host_pointer (CORE_ADDR addr)
 {
+  struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
   void *ptr;
 
-  gdb_assert (sizeof (ptr) == TYPE_LENGTH (builtin_type_void_data_ptr));
-  ADDRESS_TO_POINTER (builtin_type_void_data_ptr, &ptr, addr);
+  gdb_assert (sizeof (ptr) == TYPE_LENGTH (ptr_type));
+  gdbarch_address_to_pointer (target_gdbarch, ptr_type,
+                             (gdb_byte *) &ptr, addr);
   return ptr;
 }
 
@@ -2896,7 +2940,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 +3032,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:%ld."),
+              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:%ld."),
+              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" =============== */
 
@@ -3507,7 +3589,7 @@ procfs_debug_inferior (procinfo *pi)
 }
 
 static void
-procfs_attach (char *args, int from_tty)
+procfs_attach (struct target_ops *ops, char *args, int from_tty)
 {
   char *exec_file;
   int   pid;
@@ -3533,20 +3615,20 @@ procfs_attach (char *args, int from_tty)
       fflush (stdout);
     }
   inferior_ptid = do_attach (pid_to_ptid (pid));
-  push_target (&procfs_ops);
+  push_target (ops);
 }
 
 static void
-procfs_detach (char *args, int from_tty)
+procfs_detach (struct target_ops *ops, char *args, int from_tty)
 {
   int sig = 0;
+  int pid = PIDGET (inferior_ptid);
 
   if (args)
     sig = atoi (args);
 
   if (from_tty)
     {
-      int pid = PIDGET (inferior_ptid);
       char *exec_file;
 
       exec_file = get_exec_file (0);
@@ -3561,14 +3643,17 @@ procfs_detach (char *args, int from_tty)
   do_detach (sig);
 
   inferior_ptid = null_ptid;
-  unpush_target (&procfs_ops);
+  detach_inferior (pid);
+  unpush_target (ops);
 }
 
 static ptid_t
 do_attach (ptid_t ptid)
 {
   procinfo *pi;
+  struct inferior *inf;
   int fail;
+  int lwpid;
 
   if ((pi = create_procinfo (PIDGET (ptid), 0)) == NULL)
     perror (_("procfs: out of memory in 'attach'"));
@@ -3616,9 +3701,19 @@ do_attach (ptid_t ptid)
   if ((fail = procfs_debug_inferior (pi)) != 0)
     dead_procinfo (pi, "do_attach: failed in procfs_debug_inferior", NOKILL);
 
+  inf = add_inferior (pi->pid);
   /* Let GDB know that the inferior was attached.  */
-  attach_flag = 1;
-  return MERGEPID (pi->pid, proc_get_current_thread (pi));
+  inf->attach_flag = 1;
+
+  /* Create a procinfo for the current lwp.  */
+  lwpid = proc_get_current_thread (pi);
+  create_procinfo (pi->pid, lwpid);
+
+  /* Add it to gdb's thread list.  */
+  ptid = MERGEPID (pi->pid, lwpid);
+  add_thread (ptid);
+
+  return ptid;
 }
 
 static void
@@ -3662,7 +3757,6 @@ do_detach (int signo)
          proc_warn (pi, "do_detach, set_rlc", __LINE__);
       }
 
-  attach_flag = 0;
   destroy_procinfo (pi);
 }
 
@@ -3681,21 +3775,16 @@ do_detach (int signo)
    when the process is resumed.  */
 
 static void
-procfs_fetch_registers (int regnum)
+procfs_fetch_registers (struct target_ops *ops,
+                       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);
-
-  /* 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);
+  pi = find_procinfo_or_die (pid, tid);
 
   if (pi == NULL)
     error (_("procfs: fetch_registers failed to find procinfo for %s"),
@@ -3705,39 +3794,25 @@ 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);
     }
 }
 
-/* Get ready to modify the registers array.  On machines which store
-   individual registers, this doesn't need to do anything.  On
-   machines which store all the registers in one fell swoop, such as
-   /proc, this makes sure that registers contains all the registers
-   from the program being debugged.  */
-
-static void
-procfs_prepare_to_store (void)
-{
-#ifdef CHILD_PREPARE_TO_STORE
-  CHILD_PREPARE_TO_STORE ();
-#endif
-}
-
 /* Store register REGNUM back into the inferior.  If REGNUM is -1, do
    this for all registers.
 
@@ -3749,21 +3824,16 @@ 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 target_ops *ops,
+                       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);
-
-  /* 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);
+  pi = find_procinfo_or_die (pid, tid);
 
   if (pi == NULL)
     error (_("procfs: store_registers: failed to find procinfo for %s"),
@@ -3773,24 +3843,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__);
     }
@@ -3876,7 +3946,8 @@ syscall_is_lwp_create (procinfo *pi, int scall)
  */
 
 static ptid_t
-procfs_wait (ptid_t ptid, struct target_waitstatus *status)
+procfs_wait (struct target_ops *ops,
+            ptid_t ptid, struct target_waitstatus *status)
 {
   /* First cut: loosely based on original version 2.1 */
   procinfo *pi;
@@ -3974,14 +4045,17 @@ 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;
                  }
                else if (syscall_is_exit (pi, what))
                  {
+                   struct inferior *inf;
+
                    /* Handle SYS_exit call only */
                    /* Stopped at entry to SYS_exit.
                       Make it runnable, resume it, then use
@@ -3995,7 +4069,9 @@ wait_again:
                       TARGET_WAITKIND_SPURIOUS.  */
                    if (!proc_run_process (pi, 0, 0))
                      proc_error (pi, "target_wait, run_process", __LINE__);
-                   if (attach_flag)
+
+                   inf = find_inferior_pid (pi->pid);
+                   if (inf->attach_flag)
                      {
                        /* Don't call wait: simulate waiting for exit,
                           return a "success" exit code.  Bogus: what if
@@ -4097,19 +4173,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 +4241,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;
@@ -4208,7 +4278,8 @@ wait_again:
                      then remove it.  See comments in procfs_init_inferior()
                      for more details.  */
                   if (dbx_link_bpt_addr != 0
-                      && dbx_link_bpt_addr == read_pc ())
+                      && dbx_link_bpt_addr
+                        == regcache_read_pc (get_current_regcache ()))
                     remove_dbx_link_breakpoint ();
 
                  wstat = (SIGTRAP << 8) | 0177;
@@ -4258,24 +4329,9 @@ 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));
-
-                 /* In addition, it's possible that this is the first
-                  * new thread we've seen, in which case we may not
-                  * have created entries for inferior_ptid yet.
-                  */
-                 if (TIDGET (inferior_ptid) != 0)
-                   {
-                     if (!in_thread_list (inferior_ptid))
-                       add_thread (inferior_ptid);
-                     if (find_procinfo (PIDGET (inferior_ptid),
-                                        TIDGET (inferior_ptid)) == NULL)
-                       create_procinfo (PIDGET (inferior_ptid),
-                                        TIDGET (inferior_ptid));
-                   }
                }
            }
          else  /* flags do not indicate STOPPED */
@@ -4300,18 +4356,18 @@ wait_again:
 
 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)
+                    const char *annex, gdb_byte *readbuf,
+                    const gdb_byte *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);
+       return (*ops->deprecated_xfer_memory) (offset, readbuf,
+                                              len, 0/*read*/, NULL, ops);
       if (writebuf)
-       return (*ops->deprecated_xfer_memory) (offset, writebuf, len,
-                                              1/*write*/, NULL, ops);
+       return (*ops->deprecated_xfer_memory) (offset, (gdb_byte *) writebuf,
+                                              len, 1/*write*/, NULL, ops);
       return -1;
 
 #ifdef NEW_PROC_API
@@ -4340,7 +4396,7 @@ procfs_xfer_partial (struct target_ops *ops, enum target_object object,
    negative values, but this capability isn't implemented here.) */
 
 static int
-procfs_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int dowrite,
+procfs_xfer_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len, int dowrite,
                    struct mem_attrib *attrib, struct target_ops *target)
 {
   procinfo *pi;
@@ -4414,7 +4470,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)
@@ -4485,7 +4541,8 @@ make_signal_thread_runnable (procinfo *process, procinfo *pi, void *ptr)
  */
 
 static void
-procfs_resume (ptid_t ptid, int step, enum target_signal signo)
+procfs_resume (struct target_ops *ops,
+              ptid_t ptid, int step, enum target_signal signo)
 {
   procinfo *pi, *thread;
   int native_signo;
@@ -4615,49 +4672,12 @@ procfs_notice_signals (ptid_t ptid)
 static void
 procfs_files_info (struct target_ops *ignore)
 {
+  struct inferior *inf = current_inferior ();
   printf_filtered (_("\tUsing the running image of %s %s via /proc.\n"),
-                  attach_flag? "attached": "child",
+                  inf->attach_flag? "attached": "child",
                   target_pid_to_str (inferior_ptid));
 }
 
-/*
- * Function: target_open
- *
- * A dummy: you don't open procfs.
- */
-
-static void
-procfs_open (char *args, int from_tty)
-{
-  error (_("Use the \"run\" command to start a Unix child process."));
-}
-
-/*
- * Function: target_can_run
- *
- * This tells GDB that this target vector can be invoked
- * for "run" or "attach".
- */
-
-int procfs_suppress_run = 0;   /* Non-zero if procfs should pretend not to
-                                  be a runnable target.  Used by targets
-                                  that can sit atop procfs, such as solaris
-                                  thread support.  */
-
-
-static int
-procfs_can_run (void)
-{
-  /* This variable is controlled by modules that sit atop procfs that
-     may layer their own process structure atop that provided here.
-     sol-thread.c does this because of the Solaris two-level thread
-     model.  */
-
-  /* NOTE: possibly obsolete -- use the thread_stratum approach instead. */
-
-  return !procfs_suppress_run;
-}
-
 /*
  * Function: target_stop
  *
@@ -4668,7 +4688,7 @@ procfs_can_run (void)
  */
 
 static void
-procfs_stop (void)
+procfs_stop (ptid_t ptid)
 {
   kill (-inferior_process_group, SIGINT);
 }
@@ -4745,7 +4765,7 @@ unconditionally_kill_inferior (procinfo *pi)
  */
 
 static void
-procfs_kill_inferior (void)
+procfs_kill_inferior (struct target_ops *ops)
 {
   if (!ptid_equal (inferior_ptid, null_ptid)) /* ? */
     {
@@ -4765,7 +4785,7 @@ procfs_kill_inferior (void)
  */
 
 static void
-procfs_mourn_inferior (void)
+procfs_mourn_inferior (struct target_ops *ops)
 {
   procinfo *pi;
 
@@ -4776,7 +4796,7 @@ procfs_mourn_inferior (void)
       if (pi)
        destroy_procinfo (pi);
     }
-  unpush_target (&procfs_ops);
+  unpush_target (ops);
 
   if (dbx_link_bpt != NULL)
     {
@@ -4798,16 +4818,16 @@ procfs_mourn_inferior (void)
  */
 
 static void
-procfs_init_inferior (int pid)
+procfs_init_inferior (struct target_ops *ops, int pid)
 {
   procinfo *pi;
   gdb_sigset_t signals;
   int fail;
+  int lwpid;
 
   /* This routine called on the parent side (GDB side)
      after GDB forks the inferior.  */
-
-  push_target (&procfs_ops);
+  push_target (ops);
 
   if ((pi = create_procinfo (pid, 0)) == NULL)
     perror ("procfs: out of memory in 'init_inferior'");
@@ -4863,9 +4883,17 @@ procfs_init_inferior (int pid)
   if (!proc_set_run_on_last_close (pi))
     proc_error (pi, "init_inferior, set_RLC", __LINE__);
 
-  /* The 'process ID' we return to GDB is composed of
-     the actual process ID plus the lwp ID. */
-  inferior_ptid = MERGEPID (pi->pid, proc_get_current_thread (pi));
+  /* We now have have access to the lwpid of the main thread/lwp.  */
+  lwpid = proc_get_current_thread (pi);
+
+  /* Create a procinfo for the main lwp.  */
+  create_procinfo (pid, lwpid);
+
+  /* We already have a main thread registered in the thread table at
+     this point, but it didn't have any lwp info yet.  Notify the core
+     about it.  This changes inferior_ptid as well.  */
+  thread_change_ptid (pid_to_ptid (pid),
+                     MERGEPID (pid, lwpid));
 
   /* Typically two, one trap to exec the shell, one to exec the
      program being debugged.  Defined by "inferior.h".  */
@@ -5025,11 +5053,13 @@ procfs_set_exec_trap (void)
  */
 
 static void
-procfs_create_inferior (char *exec_file, char *allargs, char **env,
-                       int from_tty)
+procfs_create_inferior (struct target_ops *ops, char *exec_file,
+                       char *allargs, char **env, int from_tty)
 {
   char *shell_file = getenv ("SHELL");
   char *tryname;
+  int pid;
+
   if (shell_file != NULL && strchr (shell_file, '/') == NULL)
     {
 
@@ -5098,8 +5128,10 @@ procfs_create_inferior (char *exec_file, char *allargs, char **env,
       shell_file = tryname;
     }
 
-  fork_inferior (exec_file, allargs, env, procfs_set_exec_trap,
-                procfs_init_inferior, NULL, shell_file);
+  pid = fork_inferior (exec_file, allargs, env, procfs_set_exec_trap,
+                      NULL, NULL, shell_file);
+
+  procfs_init_inferior (ops, pid);
 
 #ifdef SYS_syssgi
   /* Make sure to cancel the syssgi() syscall-exit notifications.  
@@ -5124,7 +5156,7 @@ procfs_notice_thread (procinfo *pi, procinfo *thread, void *ptr)
 {
   ptid_t gdb_threadid = MERGEPID (pi->pid, thread->tid);
 
-  if (!in_thread_list (gdb_threadid))
+  if (!in_thread_list (gdb_threadid) || is_exited (gdb_threadid))
     add_thread (gdb_threadid);
 
   return 0;
@@ -5138,7 +5170,7 @@ procfs_notice_thread (procinfo *pi, procinfo *thread, void *ptr)
  */
 
 void
-procfs_find_new_threads (void)
+procfs_find_new_threads (struct target_ops *ops)
 {
   procinfo *pi;
 
@@ -5158,7 +5190,7 @@ procfs_find_new_threads (void)
  */
 
 static int
-procfs_thread_alive (ptid_t ptid)
+procfs_thread_alive (struct target_ops *ops, ptid_t ptid)
 {
   int proc, thread;
   procinfo *pi;
@@ -5183,7 +5215,7 @@ procfs_thread_alive (ptid_t ptid)
 /* Convert PTID to a string.  Returns the string in a static buffer.  */
 
 char *
-procfs_pid_to_str (ptid_t ptid)
+procfs_pid_to_str (struct target_ops *ops, ptid_t ptid)
 {
   static char buf[80];
 
@@ -5273,7 +5305,8 @@ procfs_can_use_hw_breakpoint (int type, int cnt, int othertype)
      procfs_address_to_host_pointer will reveal that an internal error
      will be generated when the host and target pointer sizes are
      different.  */
-  if (sizeof (void *) != TYPE_LENGTH (builtin_type_void_data_ptr))
+  struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
+  if (sizeof (void *) != TYPE_LENGTH (ptr_type))
     return 0;
 
   /* Other tests here???  */
@@ -5317,46 +5350,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:
  */
@@ -5734,23 +5727,28 @@ mappingflags (long flags)
 static int
 info_mappings_callback (struct prmap *map, int (*ignore) (), void *unused)
 {
-  char *data_fmt_string;
-
-  if (TARGET_ADDR_BIT == 32)
-    data_fmt_string   = "\t%#10lx %#10lx %#10x %#10x %7s\n";
-  else
-    data_fmt_string   = "  %#18lx %#18lx %#10x %#10x %7s\n";
+  unsigned int pr_off;
 
-  printf_filtered (data_fmt_string,
-                  (unsigned long) map->pr_vaddr,
-                  (unsigned long) map->pr_vaddr + map->pr_size - 1,
-                  map->pr_size,
 #ifdef PCAGENT /* Horrible hack: only defined on Solaris 2.6+ */
-                  (unsigned int) map->pr_offset,
+  pr_off = (unsigned int) map->pr_offset;
 #else
-                  map->pr_off,
+  pr_off = map->pr_off;
 #endif
-                  mappingflags (map->pr_mflags));
+
+  if (gdbarch_addr_bit (current_gdbarch) == 32)
+    printf_filtered ("\t%#10lx %#10lx %#10lx %#10x %7s\n",
+                    (unsigned long) map->pr_vaddr,
+                    (unsigned long) map->pr_vaddr + map->pr_size - 1,
+                    (unsigned long) map->pr_size,
+                    pr_off,
+                    mappingflags (map->pr_mflags));
+  else
+    printf_filtered ("  %#18lx %#18lx %#10lx %#10x %7s\n",
+                    (unsigned long) map->pr_vaddr,
+                    (unsigned long) map->pr_vaddr + map->pr_size - 1,
+                    (unsigned long) map->pr_size,
+                    pr_off,
+                    mappingflags (map->pr_mflags));
 
   return 0;
 }
@@ -5764,23 +5762,24 @@ info_mappings_callback (struct prmap *map, int (*ignore) (), void *unused)
 static void
 info_proc_mappings (procinfo *pi, int summary)
 {
-  char *header_fmt_string;
-
-  if (TARGET_PTR_BIT == 32)
-    header_fmt_string = "\t%10s %10s %10s %10s %7s\n";
-  else
-    header_fmt_string = "  %18s %18s %10s %10s %7s\n";
-
   if (summary)
     return;    /* No output for summary mode. */
 
   printf_filtered (_("Mapped address spaces:\n\n"));
-  printf_filtered (header_fmt_string,
-                  "Start Addr",
-                  "  End Addr",
-                  "      Size",
-                  "    Offset",
-                  "Flags");
+  if (gdbarch_ptr_bit (current_gdbarch) == 32)
+    printf_filtered ("\t%10s %10s %10s %10s %7s\n",
+                    "Start Addr",
+                    "  End Addr",
+                    "      Size",
+                    "    Offset",
+                    "Flags");
+  else
+    printf_filtered ("  %18s %18s %10s %10s %7s\n",
+                    "Start Addr",
+                    "  End Addr",
+                    "      Size",
+                    "    Offset",
+                    "Flags");
 
   iterate_over_mappings (pi, NULL, NULL, info_mappings_callback);
   printf_filtered ("\n");
@@ -5807,10 +5806,8 @@ info_proc_cmd (char *args, int from_tty)
   old_chain = make_cleanup (null_cleanup, 0);
   if (args)
     {
-      if ((argv = buildargv (args)) == NULL)
-       nomem (0);
-      else
-       make_cleanup_freeargv (argv);
+      argv = gdb_buildargv (args);
+      make_cleanup_freeargv (argv);
     }
   while (argv != NULL && *argv != NULL)
     {
@@ -5970,8 +5967,12 @@ proc_untrace_sysexit_cmd (char *args, int from_tty)
 void
 _initialize_procfs (void)
 {
-  init_procfs_ops ();
-  add_target (&procfs_ops);
+  struct target_ops * t;
+
+  t = procfs_target ();
+
+  add_target (t);
+
   add_info ("proc", info_proc_cmd, _("\
 Show /proc process information about any running process.\n\
 Specify process id, or use the program being debugged by default.\n\
@@ -6006,21 +6007,45 @@ procfs_first_available (void)
   return pid_to_ptid (procinfo_list ? procinfo_list->pid : -1);
 }
 
+static int
+find_signalled_thread (struct thread_info *info, void *data)
+{
+  if (info->stop_signal != TARGET_SIGNAL_0
+      && ptid_get_pid (info->ptid) == ptid_get_pid (inferior_ptid))
+    return 1;
+
+  return 0;
+}
+
+static enum target_signal
+find_stop_signal (void)
+{
+  struct thread_info *info =
+    iterate_over_threads (find_signalled_thread, NULL);
+
+  if (info)
+    return info->stop_signal;
+  else
+    return TARGET_SIGNAL_0;
+}
+
 /* ===================  GCORE .NOTE "MODULE" =================== */
 #if defined (UNIXWARE) || defined (PIOCOPENLWP) || defined (PCAGENT)
 /* gcore only implemented on solaris and unixware (so far) */
 
 static char *
 procfs_do_thread_registers (bfd *obfd, ptid_t ptid,
-                           char *note_data, int *note_size)
+                           char *note_data, int *note_size,
+                           enum target_signal stop_signal)
 {
+  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 +6061,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,
@@ -6049,6 +6074,7 @@ struct procfs_corefile_thread_data {
   bfd *obfd;
   char *note_data;
   int *note_size;
+  enum target_signal stop_signal;
 };
 
 static int
@@ -6056,13 +6082,14 @@ procfs_corefile_thread_callback (procinfo *pi, procinfo *thread, void *data)
 {
   struct procfs_corefile_thread_data *args = data;
 
-  if (pi != NULL && thread->tid != 0)
+  if (pi != NULL)
     {
       ptid_t saved_ptid = inferior_ptid;
       inferior_ptid = MERGEPID (pi->pid, thread->tid);
       args->note_data = procfs_do_thread_registers (args->obfd, inferior_ptid,
                                                    args->note_data,
-                                                   args->note_size);
+                                                   args->note_size,
+                                                   args->stop_signal);
       inferior_ptid = saved_ptid;
     }
   return 0;
@@ -6080,7 +6107,7 @@ 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;
+  gdb_byte *auxv;
   int auxv_len;
 
   if (get_exec_file (0))
@@ -6107,7 +6134,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);
@@ -6116,21 +6143,15 @@ procfs_make_note_section (bfd *obfd, int *note_size)
   thread_args.obfd = obfd;
   thread_args.note_data = note_data;
   thread_args.note_size = note_size;
+  thread_args.stop_signal = find_stop_signal ();
   proc_iterate_over_threads (pi, procfs_corefile_thread_callback, &thread_args);
 
-  if (thread_args.note_data == note_data)
-    {
-      /* iterate_over_threads didn't come up with any threads;
-        just use inferior_ptid. */
-      note_data = procfs_do_thread_registers (obfd, inferior_ptid,
-                                             note_data, note_size);
-    }
-  else
-    {
-      note_data = thread_args.note_data;
-    }
+  /* There should be always at least one thread.  */
+  gdb_assert (thread_args.note_data != note_data);
+  note_data = thread_args.note_data;
 
-  auxv_len = target_auxv_read (&current_target, &auxv);
+  auxv_len = target_read_alloc (&current_target, TARGET_OBJECT_AUXV,
+                               NULL, &auxv);
   if (auxv_len > 0)
     {
       note_data = elfcore_write_note (obfd, note_data, note_size,
This page took 0.043316 seconds and 4 git commands to generate.