Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/external/gpl3/gdb/dist/gdb Resurrect old thread debugging co...



details:   https://anonhg.NetBSD.org/src/rev/eb4fe980383d
branches:  trunk
changeset: 769911:eb4fe980383d
user:      christos <christos%NetBSD.org@localhost>
date:      Mon Sep 26 18:55:56 2011 +0000

description:
Resurrect old thread debugging code. Not hooked in, compiles.

diffstat:

 external/gpl3/gdb/dist/gdb/nbsd-thread.c |  1297 ++++++++++++++++++++++++++++++
 1 files changed, 1297 insertions(+), 0 deletions(-)

diffs (truncated from 1301 to 300 lines):

diff -r b07631f4ddaf -r eb4fe980383d external/gpl3/gdb/dist/gdb/nbsd-thread.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/gpl3/gdb/dist/gdb/nbsd-thread.c  Mon Sep 26 18:55:56 2011 +0000
@@ -0,0 +1,1297 @@
+/* Thread debugging back-end code for NetBSD, for GDB.
+   Copyright 2002
+   Wasabi Systems, Inc.
+
+   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 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., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+
+#include "defs.h"
+
+#include <sys/types.h>
+#include <sys/ptrace.h>
+
+#include <pthread.h>
+#include <pthread_dbg.h>
+
+#include "symtab.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "solib.h"
+#include "gdbthread.h"
+#include "bfd.h"
+#include "elf-bfd.h"
+#include "target.h"
+#include "inferior.h"
+#include "gdbcmd.h"
+#include "gdbcore.h"
+
+#include <machine/reg.h>
+
+#ifndef HAVE_GREGSET_T
+typedef struct reg gregset_t;
+#endif
+
+#ifndef HAVE_FPREGSET_T
+typedef struct fpreg fpregset_t;
+#endif
+
+#include "gregset.h"
+
+/* nbsd_thread_present indicates that new_objfile has spotted
+   libpthread and that post_attach() or create_inferior() should fire
+   up thread debugging if it isn't already active. */
+static int nbsd_thread_present = 0;
+
+/* nbsd_thread_active indicates that thread debugging is up and running, and
+   in particular that main_ta and main_ptid are valid. */
+static int nbsd_thread_active = 0;
+
+/* nbsd_thread_core indicates that we're working on a corefile, not a
+   live process. */ 
+static int nbsd_thread_core = 0;
+
+static ptid_t main_ptid;               /* Real process ID */
+
+static ptid_t cached_thread;
+
+struct target_ops nbsd_thread_ops;
+struct target_ops nbsd_core_ops;
+
+struct td_proc_callbacks_t nbsd_thread_callbacks;
+struct td_proc_callbacks_t nbsd_core_callbacks;
+
+/* place to store core_ops before we overwrite it */
+static struct target_ops orig_core_ops;
+
+extern struct target_ops child_ops;  /* target vector for inftarg.c */
+extern struct target_ops core_ops; /* target vector for corelow.c */
+
+extern int child_suppress_run;
+
+static ptid_t find_active_thread (void);
+static void nbsd_find_new_threads (struct target_ops *);
+
+#define GET_PID(ptid)          ptid_get_pid (ptid)
+#define GET_LWP(ptid)          ptid_get_lwp (ptid)
+#define GET_THREAD(ptid)       ptid_get_tid (ptid)
+
+#define IS_LWP(ptid)           (GET_LWP (ptid) != 0)
+#define IS_THREAD(ptid)                (GET_THREAD (ptid) != 0)
+
+#define BUILD_LWP(lwp, ptid)   ptid_build (GET_PID(ptid), lwp, 0)
+#define BUILD_THREAD(tid, ptid)        ptid_build (GET_PID(ptid), 0, tid)
+
+static td_proc_t *main_ta;
+
+struct nbsd_thread_proc_arg {
+  struct target_ops *ops;
+  struct regcache *cache;
+} main_arg;
+
+static const char *syncnames[] = {
+  "unknown", "mutex", "cond var", "spinlock", "thread"
+};
+
+struct string_map
+  {
+    int num;
+    char *str;
+  };
+
+static char *
+td_err_string (int errcode)
+{
+  static struct string_map
+    td_err_table[] =
+  {
+    {TD_ERR_OK, "generic \"call succeeded\""},
+    {TD_ERR_ERR, "generic error."},
+    {TD_ERR_NOSYM, "symbol not found"},
+    {TD_ERR_NOOBJ, "no object can be found to satisfy query"},
+    {TD_ERR_BADTHREAD, "thread can not answer request"},
+    {TD_ERR_INUSE, "debugging interface already in use for this process"},
+    {TD_ERR_NOLIB, "process is not using libpthread"},
+    {TD_ERR_NOMEM, "out of memory"},
+    {TD_ERR_IO, "process callback error"},
+    {TD_ERR_INVAL, "invalid argument"},
+  };
+  const int td_err_size = sizeof td_err_table / sizeof (struct string_map);
+  int i;
+  static char buf[90];
+
+  for (i = 0; i < td_err_size; i++)
+    if (td_err_table[i].num == errcode)
+      return td_err_table[i].str;
+
+  sprintf (buf, "Unknown thread_db error code: %d", errcode);
+
+  return buf;
+}
+
+static void
+nbsd_thread_activate (void)
+{
+  nbsd_thread_active = 1;
+  main_ptid = inferior_ptid;
+  cached_thread = minus_one_ptid;
+  nbsd_find_new_threads (NULL);
+  inferior_ptid = find_active_thread ();
+}
+
+static void
+nbsd_thread_deactivate (void)
+{
+  td_close (main_ta);
+
+  inferior_ptid = main_ptid;
+  main_ptid = minus_one_ptid;
+  cached_thread = main_ptid;
+  nbsd_thread_active = 0;
+  nbsd_thread_present = 0;
+  init_thread_list ();
+}
+
+static void
+nbsd_thread_attach (struct target_ops *ops, char *args, int from_tty)
+{
+  nbsd_thread_core = 0;
+
+  if (nbsd_thread_present && !nbsd_thread_active)
+    push_target(&nbsd_thread_ops);
+
+  child_ops.to_attach (ops, args, from_tty);
+
+  /* seems like a good place to activate, but isn't. Let it happen in
+     nbsd_thread_post_attach(), after a wait has occurred. */
+}
+
+static void
+nbsd_thread_post_attach (int pid)
+{
+  child_ops.to_post_attach (pid);
+
+  if (nbsd_thread_present && !nbsd_thread_active)
+    nbsd_thread_activate ();
+}
+
+
+/* Take a program previously attached to and detaches it.
+   The program resumes execution and will no longer stop
+   on signals, etc.  We'd better not have left any breakpoints
+   in the program or it'll die when it hits one.  For this
+   to work, it may be necessary for the process to have been
+   previously attached.  It *might* work if the program was
+   started via the normal ptrace (PTRACE_TRACEME).  */
+
+static void
+nbsd_thread_detach (struct target_ops *ops, char *args, int from_tty)
+{
+  struct target_ops *beneath = find_target_beneath (ops);
+  nbsd_thread_deactivate ();
+  unpush_target (ops);
+  /* Ordinairly, gdb caches solib information, but this means that it
+     won't call the new_obfile hook on a reattach. Clear the symbol file
+     cache so that attach -> detach -> attach works. */
+  clear_solib();
+  symbol_file_clear(0);
+  child_ops.to_detach (beneath, args, from_tty);
+}
+
+static int nsusp;
+static int nsuspalloc;
+static td_thread_t **susp;
+
+static int
+thread_resume_suspend_cb (td_thread_t *th, void *arg)
+{
+  int val;
+  ptid_t *pt = arg;
+  td_thread_info_t ti;
+
+  if (td_thr_info (th, &ti) != 0)
+      return -1;
+
+  if ((ti.thread_id != GET_THREAD (*pt)) &&
+      (ti.thread_type == TD_TYPE_USER) &&
+      (ti.thread_state != TD_STATE_SUSPENDED) &&
+      (ti.thread_state != TD_STATE_ZOMBIE))
+    {
+      val = td_thr_suspend(th);
+      if (val != 0)
+       error ("thread_resume_suspend_cb: td_thr_suspend(%p): %s", th,
+              td_err_string (val));
+       
+      if (nsusp == nsuspalloc)
+       {
+         if (nsuspalloc == 0)
+           {
+             nsuspalloc = 32;
+             susp = malloc (nsuspalloc * sizeof(td_thread_t *));
+             if (susp == NULL)
+               error ("thread_resume_suspend_cb: out of memory\n");
+           }
+         else
+           {
+             static td_thread_t **newsusp;
+             nsuspalloc *= 2;
+             newsusp = realloc (susp, nsuspalloc * sizeof(td_thread_t *));
+             if (newsusp == NULL)
+               error ("thread_resume_suspend_cb: out of memory\n");
+             susp = newsusp;
+           }
+       }
+      susp[nsusp] = th;
+      nsusp++;
+    }
+  
+  return 0;
+}
+
+static void
+nbsd_thread_resume (struct target_ops *ops, ptid_t ptid, int step,
+    enum target_signal signo)
+{
+
+  /* If a particular thread is specified, then gdb wants to resume or
+     step just that thread. If it isn't on a processor, then it needs
+     to be put on one, and nothing else can be on the runnable list.
+     XXX If GDB asks us to step a LWP rather than a thread, there
+     isn't anything we can do but pass it down to the ptrace call;
+     given the flexibility of the LWP-to-thread mapping, this might or
+     might not accomplish what the user wanted. */
+  if (GET_PID (ptid) != -1 && IS_THREAD (ptid))
+    {
+      int val;
+
+      val = td_thr_iter (main_ta, thread_resume_suspend_cb, &ptid);
+      if (val != 0)
+       error ("nbsd_thread_resume td_thr_iter: %s", td_err_string (val));
+
+       child_ops.to_resume (ops, ptid, step, signo);
+
+      /* can't un-suspend just yet, child may not be stopped */
+    }
+  else
+    child_ops.to_resume (ops, ptid, step, signo);
+
+  cached_thread = minus_one_ptid;
+}
+
+
+static void



Home | Main Index | Thread Index | Old Index