Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 21 Aug 2004 10:35:33 GMT
From:      David Xu <davidxu@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 60189 for review
Message-ID:  <200408211035.i7LAZXvA065768@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=60189

Change 60189 by davidxu@davidxu_alona on 2004/08/21 10:34:57

	Add code to support .core for threaded program.

Affected files ...

.. //depot/projects/davidxu_ksedbg/src/gnu/usr.bin/gdb/libgdb/fbsd-threads.c#21 edit

Differences ...

==== //depot/projects/davidxu_ksedbg/src/gnu/usr.bin/gdb/libgdb/fbsd-threads.c#21 (text+ko) ====

@@ -27,6 +27,8 @@
 #include "thread_db.h"
 
 #include "bfd.h"
+#include "elf-bfd.h"
+#include "gdbcore.h"
 #include "gdbthread.h"
 #include "inferior.h"
 #include "symfile.h"
@@ -51,7 +53,12 @@
 extern struct target_ops child_ops;
 
 /* This module's target vector.  */
-static struct target_ops thread_db_ops;
+static struct target_ops fbsd_thread_ops;
+static struct target_ops fbsd_core_ops;
+
+/* Saved copy of orignal core_ops */
+static struct target_ops orig_core_ops;
+extern struct target_ops core_ops;
 
 /* Pointer to the next function on the objfile event chain.  */
 static void (*target_new_objfile_chain) (struct objfile *objfile);
@@ -60,7 +67,9 @@
 static int fbsd_thread_present;
 
 /* Non-zero if we're using this module's target vector.  */
-static int using_thread_db;
+static int fbsd_thread_active;
+
+static int fbsd_thread_core = 0;
 
 /* Non-zero if we have to keep this module's target vector active
    across re-runs.  */
@@ -123,7 +132,6 @@
 /* Prototypes for local functions.  */
 static void fbsd_thread_find_new_threads (void);
 static int fbsd_thread_alive (ptid_t ptid);
-static void fbsd_thread_activate(void);
 
 /* Building process ids.  */
 
@@ -227,7 +235,7 @@
  
   gdb_assert (IS_LWP (ptid));
 
-  if (using_thread_db)
+  if (fbsd_thread_active)
     {
       err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), &th);
       if (err == TD_OK)
@@ -243,11 +251,30 @@
   return BUILD_LWP (GET_LWP (ptid), GET_PID (ptid));
 }
 
+static void
+fbsd_core_get_first_lwp (bfd *abfd, asection *asect, void *obj)
+{
+  if (strncmp (bfd_section_name (abfd, asect), ".reg/", 5) != 0)
+    return;
+
+  if (*(lwpid_t *)obj != 0)
+    return;
+
+  *(lwpid_t *)obj = atoi (bfd_section_name (abfd, asect) + 5);
+}
+
 static long
 get_current_lwp (int pid)
 {
   struct ptrace_lwpinfo pl;
+  lwpid_t lwpid;
 
+  if (!target_has_execution)
+    {
+      lwpid = 0;
+      bfd_map_over_sections (core_bfd, fbsd_core_get_first_lwp, &lwpid);
+      return lwpid;
+    }
   if (ptrace (PT_LWPINFO, pid, (caddr_t)&pl, sizeof(pl)))
     perror_with_name("PT_LWPINFO");
 
@@ -271,6 +298,27 @@
 }
 
 static void
+fbsd_thread_activate (void)
+{
+  fbsd_thread_active = 1;
+  init_thread_list();
+  fbsd_thread_find_new_threads ();
+  get_current_thread ();
+}
+
+static void
+fbsd_thread_deactivate (void)
+{
+  td_ta_delete_p (thread_agent);
+
+  inferior_ptid = pid_to_ptid (proc_handle.pid);
+  proc_handle.pid = 0;
+  fbsd_thread_active = 0;
+  fbsd_thread_present = 0;
+  init_thread_list ();
+}
+
+static void
 fbsd_thread_new_objfile (struct objfile *objfile)
 {
   td_err_e err;
@@ -281,10 +329,10 @@
     {
       /* All symbols have been discarded.  If the thread_db target is
          active, deactivate it now.  */
-      if (using_thread_db)
+      if (fbsd_thread_active)
         {
           gdb_assert (proc_handle.pid == 0);
-          using_thread_db = 0;
+          fbsd_thread_active = 0;
         }
 
       goto quit;
@@ -293,7 +341,7 @@
   if (!child_suppress_run)
     goto quit;
 
-  if (using_thread_db)
+  if (fbsd_thread_active)
     /* Nothing to do.  The thread library was already detected and the
        target vector was already activated.  */
     goto quit;
@@ -318,16 +366,15 @@
       /* We can only poke around if there actually is a child process.
          If there is no child process alive, postpone the steps below
          until one has been created.  */
-      if (proc_handle.pid != 0)
+      if (fbsd_thread_core == 0 && proc_handle.pid != 0)
         {
-          push_target(&thread_db_ops);
+          push_target(&fbsd_thread_ops);
           fbsd_thread_activate();
         }
       else
         {
           td_ta_delete_p(thread_agent);
           thread_agent = NULL;
-          printf_filtered("%s postpone processing\n", __func__);
         }
       break;
 
@@ -345,23 +392,41 @@
 static void
 fbsd_thread_attach (char *args, int from_tty)
 {
+  fbsd_thread_core = 0;
+
   child_ops.to_attach (args, from_tty);
 
-  /* Destroy thread info; it's no longer valid.  */
-  init_thread_list ();
+  /* Must get symbols from solibs before libthread_db can run! */
+  SOLIB_ADD ((char *) 0, from_tty, (struct target_ops *) 0, auto_solib_add);
+
+  if (fbsd_thread_present && !fbsd_thread_active)
+    push_target(&fbsd_thread_ops);
+}
 
-  /* The child process is now the actual multi-threaded
-     program.  Snatch its process ID...  */
-  proc_handle.pid = GET_PID (inferior_ptid);
+static void
+fbsd_thread_post_attach (int pid)
+{
+  child_ops.to_post_attach (pid);
 
-  /* ...and perform the remaining initialization steps.  */
-  fbsd_thread_find_new_threads();
-  get_current_thread ();
+  if (fbsd_thread_present && !fbsd_thread_active)
+    {
+      proc_handle.pid = GET_PID (inferior_ptid);
+      fbsd_thread_activate ();
+    }
 }
 
 static void
 fbsd_thread_detach (char *args, int from_tty)
 {
+  fbsd_thread_deactivate ();
+  unpush_target (&fbsd_thread_ops);
+
+  /* Clear gdb solib information and symbol file
+     cache, so that after detach and re-attach, new_objfile
+     hook will be called */
+
+  clear_solib();
+  symbol_file_clear(0);
   proc_handle.pid = 0;
   child_ops.to_detach (args, from_tty);
 }
@@ -401,7 +466,7 @@
 	GET_THREAD(inferior_ptid));
 #endif
 
-  if (!using_thread_db)
+  if (!fbsd_thread_active)
     {
       child_ops.to_resume (ptid, step, signo);
       return;
@@ -523,17 +588,32 @@
 fbsd_thread_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
                         struct mem_attrib *attrib, struct target_ops *target)
 {
-  return child_ops.to_xfer_memory (memaddr, myaddr, len, write,
-                                  attrib, target);
+  int err;
+
+  if (target_has_execution)
+    err = child_ops.to_xfer_memory (memaddr, myaddr, len, write, attrib,
+	target);
+  else
+    err = orig_core_ops.to_xfer_memory (memaddr, myaddr, len, write, attrib,
+	target);
+
+  return (err);
 }
 
 static void
 fbsd_lwp_fetch_registers (int regno)
 {
+  struct cleanup *old_chain;
   gregset_t gregs;
   fpregset_t fpregs;
   lwpid_t lwp;
 
+  if (!target_has_execution)
+    {
+      orig_core_ops.to_fetch_registers (-1);
+      return;
+    }
+
   lwp = GET_LWP (inferior_ptid);
 
   if (ptrace (PT_GETREGS, lwp, (caddr_t) &gregs, 0) == -1)
@@ -679,19 +759,10 @@
 }
 
 static void
-fbsd_thread_activate (void)
-{
-  using_thread_db = 1;
-  init_thread_list();
-  fbsd_thread_find_new_threads ();
-  get_current_thread ();
-}
-
-static void
 fbsd_thread_create_inferior (char *exec_file, char *allargs, char **env)
 {
-  if (fbsd_thread_present && !using_thread_db)
-    push_target(&thread_db_ops);
+  if (fbsd_thread_present && !fbsd_thread_active)
+    push_target(&fbsd_thread_ops);
 
   child_ops.to_create_inferior (exec_file, allargs, env);
 }
@@ -699,7 +770,7 @@
 static void
 fbsd_thread_post_startup_inferior (ptid_t ptid)
 {
-  if (fbsd_thread_present && !using_thread_db)
+  if (fbsd_thread_present && !fbsd_thread_active)
     {
       /*
        * The child process is now the actual multi-threaded
@@ -723,6 +794,23 @@
   child_ops.to_mourn_inferior ();
 }
 
+static void
+fbsd_core_check_lwp (bfd *abfd, asection *asect, void *obj)
+{
+  lwpid_t lwp;
+
+  if (strncmp (bfd_section_name (abfd, asect), ".reg/", 5) != 0)
+    return;
+
+  /* already found */
+  if (*(lwpid_t *)obj == 0)
+    return;
+
+  lwp = atoi (bfd_section_name (abfd, asect) + 5);
+  if (*(lwpid_t *)obj == lwp)
+    *(lwpid_t *)obj = 0;
+}
+
 static int
 fbsd_thread_alive (ptid_t ptid)
 {
@@ -730,6 +818,7 @@
   td_thrinfo_t ti;
   td_err_e err;
   gregset_t gregs;
+  lwpid_t lwp;
 
   if (IS_THREAD (ptid))
     {
@@ -753,7 +842,7 @@
       return 1;
     }
 
-  if (using_thread_db)
+  if (fbsd_thread_active)
     {
       err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), &th);
 
@@ -765,10 +854,23 @@
         return 0;
     }
 
+  if (!target_has_execution)
+    {
+      lwp = GET_LWP (ptid);
+      bfd_map_over_sections (core_bfd, fbsd_core_check_lwp, &lwp);
+      return (lwp == 0); 
+    }
+
   /* check lwp in kernel */
   return ptrace (PT_GETREGS, GET_LWP (ptid), (caddr_t)&gregs, 0) == 0;
 }
 
+static void
+fbsd_thread_files_info (struct target_ops *ignore)
+{
+  child_ops.to_files_info (ignore);
+}
+
 static int
 find_new_threads_callback (const td_thrhandle_t *th_p, void *data)
 {
@@ -784,11 +886,10 @@
   if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE)
     return 0;
 
-  ptid = BUILD_THREAD (ti.ti_tid, GET_PID (inferior_ptid));
+  ptid = BUILD_THREAD (ti.ti_tid, proc_handle.pid);
 
   if (!in_thread_list (ptid))
       add_thread (ptid);
- 
   return 0;
 }
 
@@ -797,7 +898,7 @@
 {
   td_err_e err;
 
-  if (!using_thread_db)
+  if (!fbsd_thread_active)
     return;
 
   /* Iterate over all user-space threads to discover new threads. */
@@ -922,42 +1023,136 @@
 static void
 fbsd_thread_tsd_cmd (char *exp, int from_tty)
 {
-  if (using_thread_db)
+  if (fbsd_thread_active)
     td_ta_tsd_iter_p (thread_agent, tsd_cb, NULL);
 }
 
+static int
+ignore (CORE_ADDR addr, char *contents)
+{
+  return 0;
+}
+
+static void
+fbsd_core_open (char *filename, int from_tty)
+{
+  int err;
+
+  fbsd_thread_core = 1;
+
+  orig_core_ops.to_open (filename, from_tty);
+
+  if (fbsd_thread_present)
+    {
+      err = td_ta_new_p (&proc_handle, &thread_agent);
+      if (err == TD_OK)
+        {
+          proc_handle.pid = elf_tdata (core_bfd)->core_pid;
+          fbsd_thread_activate ();
+        }
+      else
+        error ("fbsd_core_open: td_open: %s", thread_db_err_str (err));
+    }
+}
+
+static void
+fbsd_core_close (int quitting)
+{
+  orig_core_ops.to_close (quitting);
+}
+
+static void
+fbsd_core_detach (char *args, int from_tty)
+{
+  if (fbsd_thread_active)
+    fbsd_thread_deactivate ();
+  unpush_target (&fbsd_thread_ops);
+  orig_core_ops.to_detach (args, from_tty);
+ 
+  /* Clear gdb solib information and symbol file
+     cache, so that after detach and re-attach, new_objfile
+     hook will be called */
+  clear_solib();
+  symbol_file_clear(0);
+}
+
+static void
+fbsd_core_files_info (struct target_ops *ignore)
+{
+  orig_core_ops.to_files_info (ignore);
+}
+
+static void
+init_fbsd_core_ops (void)
+{
+  fbsd_core_ops.to_shortname = "FreeBSD-core";
+  fbsd_core_ops.to_longname = "FreeBSD core thread.";
+  fbsd_core_ops.to_doc = "FreeBSD thread support for core files.";
+  fbsd_core_ops.to_open = fbsd_core_open;
+  fbsd_core_ops.to_close = fbsd_core_close;
+  fbsd_core_ops.to_attach = 0;
+  fbsd_core_ops.to_post_attach = 0;
+  fbsd_core_ops.to_detach = fbsd_core_detach;
+  /* fbsd_core_ops.to_resume  = 0; */
+  /* fbsd_core_ops.to_wait  = 0;  */
+  fbsd_core_ops.to_fetch_registers = fbsd_thread_fetch_registers;
+  /* fbsd_core_ops.to_store_registers  = 0; */
+  /* fbsd_core_ops.to_prepare_to_store  = 0; */
+  fbsd_core_ops.to_xfer_memory = fbsd_thread_xfer_memory;
+  fbsd_core_ops.to_files_info = fbsd_core_files_info;
+  fbsd_core_ops.to_insert_breakpoint = ignore;
+  fbsd_core_ops.to_remove_breakpoint = ignore;
+  /* fbsd_core_ops.to_lookup_symbol  = 0; */
+  fbsd_core_ops.to_create_inferior = fbsd_thread_create_inferior;
+  fbsd_core_ops.to_stratum = core_stratum;
+  fbsd_core_ops.to_has_all_memory = 0;
+  fbsd_core_ops.to_has_memory = 1;
+  fbsd_core_ops.to_has_stack = 1;
+  fbsd_core_ops.to_has_registers = 1;
+  fbsd_core_ops.to_has_execution = 0;
+  fbsd_core_ops.to_has_thread_control = tc_none;
+  fbsd_core_ops.to_thread_alive = fbsd_thread_alive;
+  fbsd_core_ops.to_pid_to_str = fbsd_thread_pid_to_str;
+  fbsd_core_ops.to_find_new_threads = fbsd_thread_find_new_threads;
+  fbsd_core_ops.to_sections = 0;
+  fbsd_core_ops.to_sections_end = 0;
+  fbsd_core_ops.to_magic = OPS_MAGIC;
+}
+
 static void
-init_thread_db_ops (void)
+init_fbsd_thread_ops (void)
 {
-  thread_db_ops.to_shortname = "multi-thread";
-  thread_db_ops.to_longname = "multi-threaded child process.";
-  thread_db_ops.to_doc = "Threads and pthreads support.";
-  thread_db_ops.to_attach = fbsd_thread_attach;
-  thread_db_ops.to_detach = fbsd_thread_detach;
-  thread_db_ops.to_resume = fbsd_thread_resume;
-  thread_db_ops.to_wait = fbsd_thread_wait;
-  thread_db_ops.to_fetch_registers = fbsd_thread_fetch_registers;
-  thread_db_ops.to_store_registers = fbsd_thread_store_registers;
-  thread_db_ops.to_xfer_memory = fbsd_thread_xfer_memory;
-  thread_db_ops.to_kill = fbsd_thread_kill;
-  thread_db_ops.to_create_inferior = fbsd_thread_create_inferior;
-  thread_db_ops.to_post_startup_inferior = fbsd_thread_post_startup_inferior;
-  thread_db_ops.to_mourn_inferior = fbsd_thread_mourn_inferior;
-  thread_db_ops.to_can_run = fbsd_thread_can_run;
-  thread_db_ops.to_thread_alive = fbsd_thread_alive;
-  thread_db_ops.to_find_new_threads = fbsd_thread_find_new_threads;
-  thread_db_ops.to_pid_to_str = fbsd_thread_pid_to_str;
-  thread_db_ops.to_stratum = thread_stratum;
-  thread_db_ops.to_has_thread_control = tc_none;
-  thread_db_ops.to_has_all_memory = 1;
-  thread_db_ops.to_has_memory = 1;
-  thread_db_ops.to_has_stack = 1;
-  thread_db_ops.to_has_registers = 1;
-  thread_db_ops.to_has_execution = 1;
-  thread_db_ops.to_insert_breakpoint = memory_insert_breakpoint;
-  thread_db_ops.to_remove_breakpoint = memory_remove_breakpoint;
-  thread_db_ops.to_get_thread_local_address = fbsd_thread_get_local_address;
-  thread_db_ops.to_magic = OPS_MAGIC;
+  fbsd_thread_ops.to_shortname = "freebsd-threads";
+  fbsd_thread_ops.to_longname = "FreeBSD multithreaded child process.";
+  fbsd_thread_ops.to_doc = "FreeBSD threads support.";
+  fbsd_thread_ops.to_attach = fbsd_thread_attach;
+  fbsd_thread_ops.to_detach = fbsd_thread_detach;
+  fbsd_thread_ops.to_post_attach = fbsd_thread_post_attach;
+  fbsd_thread_ops.to_resume = fbsd_thread_resume;
+  fbsd_thread_ops.to_wait = fbsd_thread_wait;
+  fbsd_thread_ops.to_fetch_registers = fbsd_thread_fetch_registers;
+  fbsd_thread_ops.to_store_registers = fbsd_thread_store_registers;
+  fbsd_thread_ops.to_xfer_memory = fbsd_thread_xfer_memory;
+  fbsd_thread_ops.to_files_info = fbsd_thread_files_info;
+  fbsd_thread_ops.to_kill = fbsd_thread_kill;
+  fbsd_thread_ops.to_create_inferior = fbsd_thread_create_inferior;
+  fbsd_thread_ops.to_post_startup_inferior = fbsd_thread_post_startup_inferior;
+  fbsd_thread_ops.to_mourn_inferior = fbsd_thread_mourn_inferior;
+  fbsd_thread_ops.to_can_run = fbsd_thread_can_run;
+  fbsd_thread_ops.to_thread_alive = fbsd_thread_alive;
+  fbsd_thread_ops.to_find_new_threads = fbsd_thread_find_new_threads;
+  fbsd_thread_ops.to_pid_to_str = fbsd_thread_pid_to_str;
+  fbsd_thread_ops.to_stratum = thread_stratum;
+  fbsd_thread_ops.to_has_thread_control = tc_none;
+  fbsd_thread_ops.to_has_all_memory = 1;
+  fbsd_thread_ops.to_has_memory = 1;
+  fbsd_thread_ops.to_has_stack = 1;
+  fbsd_thread_ops.to_has_registers = 1;
+  fbsd_thread_ops.to_has_execution = 1;
+  fbsd_thread_ops.to_insert_breakpoint = memory_insert_breakpoint;
+  fbsd_thread_ops.to_remove_breakpoint = memory_remove_breakpoint;
+  fbsd_thread_ops.to_get_thread_local_address = fbsd_thread_get_local_address;
+  fbsd_thread_ops.to_magic = OPS_MAGIC;
 }
 
 static int
@@ -1047,14 +1242,22 @@
   return 1;
 }
 
+/* we suppress the call to add_target of core_ops in corelow because
+   if there are two targets in the stratum core_stratum, find_core_target
+   won't know which one to return.  see corelow.c for an additonal
+   comment on coreops_suppress_target. */
+
+int coreops_suppress_target = 1;
+
 void
 _initialize_thread_db (void)
 {
-  /* Only initialize the module if we can load libthread_db. */
+  init_fbsd_thread_ops ();
+  init_fbsd_core_ops ();
+
   if (thread_db_load ())
     {
-      init_thread_db_ops ();
-      add_target (&thread_db_ops);
+      add_target (&fbsd_thread_ops);
 
       /* "thread tsd" command */
       add_cmd ("tsd", class_run, fbsd_thread_tsd_cmd,
@@ -1062,15 +1265,24 @@
             "for the process.\n",
            &thread_cmd_list);
 
+      memcpy (&orig_core_ops, &core_ops, sizeof (struct target_ops));
+      memcpy (&core_ops, &fbsd_core_ops, sizeof (struct target_ops));
+      add_target (&core_ops);
+
       /* Add ourselves to objfile event chain. */
       target_new_objfile_chain = target_new_objfile_hook;
       target_new_objfile_hook = fbsd_thread_new_objfile;
+
+      child_suppress_run = 1;
     }
   else
     {
-      printf_filtered("%s: can not load %s.\n", __func__, LIBTHREAD_DB_SO);
+      fprintf_unfiltered (gdb_stderr,
+        "[GDB will not be able to debug user-mode threads: %s]\n", dlerror());
+     
+      /* allow the user to debug non-threaded core files */
+      add_target (&core_ops);
     }
-  child_suppress_run = 1;
 }
 
 /* proc service functions */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200408211035.i7LAZXvA065768>