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