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