Source-Changes-HG archive

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

[src/trunk]: src/gnu/dist/toolchain/gdb merge nathanw_sa



details:   https://anonhg.NetBSD.org/src/rev/7802155b2f06
branches:  trunk
changeset: 541820:7802155b2f06
user:      christos <christos%NetBSD.org@localhost>
date:      Sat Jan 18 21:59:41 2003 +0000

description:
merge nathanw_sa

diffstat:

 gnu/dist/toolchain/gdb/nbsd-thread.c |  1322 ++++++++++++++++++++++++++++++++++
 1 files changed, 1322 insertions(+), 0 deletions(-)

diffs (truncated from 1326 to 300 lines):

diff -r cbf8f19ffaa0 -r 7802155b2f06 gnu/dist/toolchain/gdb/nbsd-thread.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/gnu/dist/toolchain/gdb/nbsd-thread.c      Sat Jan 18 21:59:41 2003 +0000
@@ -0,0 +1,1322 @@
+/* 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 <pthread.h>
+#include <pthread_dbg.h>
+
+#include "symtab.h"
+#include "symfile.h"
+#include "objfiles.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>
+
+/* nbsd_thread_present indicates that new_objfile has spotted
+   libpthread and that post_attach() or create_inferior() should fire
+   up thread debugging. */
+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_pid are valid. */
+static int nbsd_thread_active = 0;
+
+static int main_pid;           /* Real process ID */
+
+static int 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;
+
+/* inferior_pid is a global variable that is used by gdb to identify
+   the entity that is under the debugging microscope. In normal
+   operation, it would be the PID of the child process. For threaded
+   programs, the thread module of GDB keeps a "pid" value for each
+   thread and sets inferior_pid to that value when switching
+   threads. Therefore, inferior_pid needs to encode some kind of
+   thread identifier. It can't be the pthread_t, because that's a
+   pointer, and pointers can be larger than ints, so we use the "ID"
+   number given to us by libthread_db.
+
+   Unfortunately, inferior_pid is also used implicitly by the various
+   ptrace target operations, so when we call one of those we have to
+   save the thread-specific inferior_pid, set inferior_pid to
+   main_pid, make the call, and then do the restoration. In order to
+   guarantee that inferior_pid gets restored (in case of errors), we
+   need to call save_inferior_pid before changing it.  At the end of the
+   function, we invoke do_cleanups to restore it. */
+
+static struct cleanup * save_inferior_pid PARAMS ((void));
+static void restore_inferior_pid PARAMS ((void *pid));
+
+static int find_active_thread PARAMS ((void));
+static void nbsd_find_new_threads PARAMS ((void));
+
+static struct cleanup *
+save_inferior_pid ()
+{
+  return make_cleanup (restore_inferior_pid, (void *)(long)inferior_pid);
+}
+
+static void
+restore_inferior_pid (pid)
+     void *pid;
+{
+  /* XXX terrible type punning, but C doesn't have closures... */
+  inferior_pid = (int)(long)pid;
+}
+
+static td_proc_t *main_ta;
+
+static const char *syncnames[] = {"unknown",
+                          "mutex",
+                          "cond var",
+                          "spinlock",
+                          "joining thread"};
+
+struct string_map
+  {
+    int num;
+    char *str;
+  };
+
+static char *
+td_err_string (errcode)
+     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 ()
+{
+  int val;
+
+  val = td_open (&nbsd_thread_callbacks, NULL, &main_ta);
+  if (val != 0)
+    error ("nbsd_thread_create_inferior: td_open: %s",
+         td_err_string (val));
+
+  main_pid = inferior_pid;
+  nbsd_thread_active = 1;
+  nbsd_find_new_threads ();
+  val = find_active_thread ();
+  if (val == -1)
+    error ("No active thread found\n");
+  inferior_pid = val;
+}
+
+static void
+nbsd_thread_deactivate ()
+{
+  inferior_pid = main_pid;
+  main_pid = 0;
+  cached_thread = 0;
+  nbsd_thread_active = 0;
+  init_thread_list ();
+
+  td_close (main_ta);
+}
+
+static void
+nbsd_thread_attach (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  child_ops.to_attach (args, from_tty);
+
+  push_target (&nbsd_thread_ops);
+}
+
+/* Attach to process PID, then initialize for debugging it
+   and wait for the trace-trap that results from attaching.  */
+
+static void
+nbsd_thread_post_attach (pid)
+       int pid;
+{
+  int val;
+
+  child_ops.to_post_attach (pid);
+
+  if (nbsd_thread_present)
+    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 (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  struct cleanup *old_chain;
+  old_chain = save_inferior_pid ();
+
+  if (nbsd_thread_active)
+    nbsd_thread_deactivate ();
+  unpush_target (&nbsd_thread_ops);
+  child_ops.to_detach (args, from_tty);
+
+  do_cleanups (old_chain);
+}
+
+static void
+nbsd_thread_resume (pid, step, signo)
+     int pid;
+     int step;
+     enum target_signal signo;
+{
+  struct cleanup *old_chain;
+  old_chain = save_inferior_pid ();
+
+  if (nbsd_thread_active)
+    inferior_pid = main_pid;
+  pid = inferior_pid;
+
+  child_ops.to_resume (pid, step, signo);
+
+  cached_thread = 0;
+
+  do_cleanups (old_chain);
+}
+
+
+static int
+find_active_thread ()
+{
+  int val;
+  td_thread_t *thread;
+  td_thread_info_t ti;
+
+  val = td_map_lwps (main_ta);
+  if (val != 0)
+    {
+      warning ("find_active_thread: td_map_lwps: %s\n", td_err_string (val));
+      return -1;
+    }
+  if (cached_thread != 0)
+    return cached_thread;
+
+  val = td_map_lwp2thr (main_ta, 0, &thread);
+  if (val != 0)
+    {
+      warning ("find_active_thread: td_map_lwp2thr: %s\n",
+              td_err_string (val));
+      return -1;
+    }
+  val = td_thr_info (thread, &ti);
+  if (val != 0)
+    {
+      warning ("find_active_thread: td_thr_info: %s\n", td_err_string (val));
+      return -1;
+    }
+
+  val = BUILD_THREAD (ti.thread_id, main_pid);
+  cached_thread = val;
+  return val;
+}
+
+
+/* Wait for any threads to stop.  We may have to convert PID from a thread id
+   to a LWP id, and vice versa on the way out.  */
+
+static int
+nbsd_thread_wait (pid, ourstatus)
+     int pid;
+     struct target_waitstatus *ourstatus;
+{



Home | Main Index | Thread Index | Old Index