*** empty log message ***
[deliverable/binutils-gdb.git] / gdb / procfs.c
index f40b3883b4c64ebff767d3a188e8c6a2dbed5bfd..703415c98f7cab9a26c850d91d5e3cf1d659277b 100644 (file)
@@ -116,7 +116,7 @@ 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_stop (ptid_t);
 static void procfs_files_info (struct target_ops *);
 static void procfs_fetch_registers (struct regcache *, int);
 static void procfs_store_registers (struct regcache *, int);
@@ -152,6 +152,34 @@ 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;
+
+  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)
 {
@@ -200,6 +228,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;
 }
 
@@ -2865,11 +2898,11 @@ 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));
-  gdbarch_address_to_pointer (current_gdbarch, builtin_type_void_data_ptr,
-                             &ptr, addr);
+  gdb_assert (sizeof (ptr) == TYPE_LENGTH (ptr_type));
+  gdbarch_address_to_pointer (target_gdbarch, ptr_type, &ptr, addr);
   return ptr;
 }
 
@@ -3630,6 +3663,7 @@ do_attach (ptid_t ptid)
 {
   procinfo *pi;
   int fail;
+  int lwpid;
 
   if ((pi = create_procinfo (PIDGET (ptid), 0)) == NULL)
     perror (_("procfs: out of memory in 'attach'"));
@@ -3679,7 +3713,16 @@ do_attach (ptid_t ptid)
 
   /* Let GDB know that the inferior was attached.  */
   attach_flag = 1;
-  return MERGEPID (pi->pid, proc_get_current_thread (pi));
+
+  /* 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
@@ -3750,14 +3793,7 @@ procfs_fetch_registers (struct regcache *regcache, int regnum)
   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"),
@@ -3816,14 +3852,7 @@ procfs_store_registers (struct regcache *regcache, int regnum)
   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"),
@@ -4316,20 +4345,6 @@ wait_again:
                  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 */
@@ -4722,7 +4737,7 @@ procfs_can_run (void)
  */
 
 static void
-procfs_stop (void)
+procfs_stop (ptid_t ptid)
 {
   kill (-inferior_process_group, SIGINT);
 }
@@ -4857,6 +4872,7 @@ procfs_init_inferior (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.  */
@@ -4917,9 +4933,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".  */
@@ -5178,7 +5202,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;
@@ -5327,7 +5351,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???  */
@@ -6020,13 +6045,36 @@ 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;
@@ -6064,6 +6112,7 @@ struct procfs_corefile_thread_data {
   bfd *obfd;
   char *note_data;
   int *note_size;
+  enum target_signal stop_signal;
 };
 
 static int
@@ -6071,13 +6120,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;
@@ -6131,19 +6181,12 @@ 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_read_alloc (&current_target, TARGET_OBJECT_AUXV,
                                NULL, &auxv);
This page took 0.028483 seconds and 4 git commands to generate.