summaryrefslogtreecommitdiff
path: root/devel/gdb66/files/patch-freebsd-uthread.c
diff options
context:
space:
mode:
Diffstat (limited to 'devel/gdb66/files/patch-freebsd-uthread.c')
-rw-r--r--devel/gdb66/files/patch-freebsd-uthread.c937
1 files changed, 0 insertions, 937 deletions
diff --git a/devel/gdb66/files/patch-freebsd-uthread.c b/devel/gdb66/files/patch-freebsd-uthread.c
deleted file mode 100644
index 9d3fd5453eac..000000000000
--- a/devel/gdb66/files/patch-freebsd-uthread.c
+++ /dev/null
@@ -1,937 +0,0 @@
---- gdb/freebsd-uthread.c Wed Dec 31 16:00:00 1969
-+++ gdb/freebsd-uthread.c Sun Oct 13 13:10:51 2002
-@@ -0,0 +1,934 @@
-+/* $FreeBSD$ */
-+/* Low level interface for debugging FreeBSD user threads for GDB, the GNU debugger.
-+ Copyright 1996, 1999 Free Software Foundation, 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. */
-+
-+/* This module implements a sort of half target that sits between the
-+ machine-independent parts of GDB and the ptrace interface (infptrace.c) to
-+ provide access to the FreeBSD user-mode thread implementation.
-+
-+ FreeBSD threads are true user-mode threads, which are invoked via
-+ the pthread_* interfaces. These are mostly implemented in
-+ user-space, with all thread context kept in various structures that
-+ live in the user's heap. For the most part, the kernel has no
-+ knowlege of these threads.
-+
-+ Based largely on hpux-thread.c
-+
-+ */
-+
-+
-+#include "defs.h"
-+#include <sys/queue.h>
-+#include <signal.h>
-+#include <setjmp.h>
-+#include <string.h>
-+#include "gdbthread.h"
-+#include "target.h"
-+#include "inferior.h"
-+#include <fcntl.h>
-+#include <ucontext.h>
-+#include <unistd.h>
-+#include <sys/stat.h>
-+#include "gdbcore.h"
-+#include "regcache.h"
-+
-+extern int child_suppress_run;
-+extern struct target_ops child_ops; /* target vector for inftarg.c */
-+
-+extern void _initialize_freebsd_uthread PARAMS ((void));
-+
-+/* Set to true while we are part-way through attaching */
-+static int freebsd_uthread_attaching;
-+
-+static int freebsd_uthread_active = 0;
-+static CORE_ADDR P_thread_list;
-+static CORE_ADDR P_thread_run;
-+
-+/* Pointer to the next function on the objfile event chain. */
-+static void (*target_new_objfile_chain) (struct objfile *objfile);
-+
-+static void freebsd_uthread_resume PARAMS ((ptid_t pid, int step,
-+ enum target_signal signo));
-+
-+static void init_freebsd_uthread_ops PARAMS ((void));
-+
-+static struct target_ops freebsd_uthread_ops;
-+
-+static ptid_t find_active_ptid PARAMS ((void));
-+
-+struct cached_pthread {
-+ u_int64_t uniqueid;
-+ int state;
-+ CORE_ADDR name;
-+ union {
-+ ucontext_t uc;
-+ jmp_buf jb;
-+ } ctx;
-+};
-+
-+static ptid_t cached_ptid;
-+static struct cached_pthread cached_pthread;
-+static CORE_ADDR cached_pthread_addr;
-+
-+LIST_HEAD(idmaplist, idmap);
-+
-+struct idmap {
-+ LIST_ENTRY(idmap) link;
-+ u_int64_t uniqueid;
-+ int tid;
-+};
-+
-+#define MAPHASH_SIZE 257
-+#define TID_MIN 1
-+#define TID_MAX 16383
-+
-+static int tid_to_hash[TID_MAX + 1]; /* set to map_hash index */
-+static struct idmaplist map_hash[MAPHASH_SIZE];
-+static int next_free_tid = TID_MIN; /* first available tid */
-+static int last_free_tid = TID_MIN; /* first unavailable */
-+
-+static CORE_ADDR P_thread_next_offset;
-+static CORE_ADDR P_thread_uniqueid_offset;
-+static CORE_ADDR P_thread_state_offset;
-+static CORE_ADDR P_thread_name_offset;
-+static CORE_ADDR P_thread_ctx_offset;
-+static CORE_ADDR P_thread_PS_RUNNING_value;
-+static CORE_ADDR P_thread_PS_DEAD_value;
-+
-+static int next_offset;
-+static int uniqueid_offset;
-+static int state_offset;
-+static int name_offset;
-+static int ctx_offset;
-+static int PS_RUNNING_value;
-+static int PS_DEAD_value;
-+
-+#define UNIQUEID_HASH(id) (id % MAPHASH_SIZE)
-+#define TID_ADD1(tid) (((tid) + 1) == TID_MAX + 1 \
-+ ? TID_MIN : (tid) + 1)
-+#define IS_TID_FREE(tid) (tid_to_hash[tid] == -1)
-+
-+static int
-+get_new_tid(int h)
-+{
-+ int tid = next_free_tid;
-+
-+ tid_to_hash[tid] = h;
-+ next_free_tid = TID_ADD1(next_free_tid);
-+ if (next_free_tid == last_free_tid)
-+ {
-+ int i;
-+
-+ for (i = last_free_tid; TID_ADD1(i) != last_free_tid; i = TID_ADD1(i))
-+ if (IS_TID_FREE(i))
-+ break;
-+ if (TID_ADD1(i) == last_free_tid)
-+ {
-+ error("too many threads");
-+ return 0;
-+ }
-+ next_free_tid = i;
-+ for (i = TID_ADD1(i); IS_TID_FREE(i); i = TID_ADD1(i))
-+ ;
-+ last_free_tid = i;
-+ }
-+
-+ return tid;
-+}
-+
-+static ptid_t
-+find_ptid(u_int64_t uniqueid)
-+{
-+ int h = UNIQUEID_HASH(uniqueid);
-+ struct idmap *im;
-+
-+ LIST_FOREACH(im, &map_hash[h], link)
-+ if (im->uniqueid == uniqueid)
-+ return MERGEPID(PIDGET(inferior_ptid), im->tid);
-+
-+ im = xmalloc(sizeof(struct idmap));
-+ im->uniqueid = uniqueid;
-+ im->tid = get_new_tid(h);
-+ LIST_INSERT_HEAD(&map_hash[h], im, link);
-+
-+ return MERGEPID(PIDGET(inferior_ptid), im->tid);
-+}
-+
-+static void
-+free_ptid(ptid_t ptid)
-+{
-+ int tid = TIDGET(ptid);
-+ int h = tid_to_hash[tid];
-+ struct idmap *im;
-+
-+ if (!tid) return;
-+
-+ LIST_FOREACH(im, &map_hash[h], link)
-+ if (im->tid == tid)
-+ break;
-+
-+ if (!im) return;
-+
-+ LIST_REMOVE(im, link);
-+ tid_to_hash[tid] = -1;
-+ free(im);
-+}
-+
-+#define READ_OFFSET(field) read_memory(P_thread_##field##_offset, \
-+ (char *) &field##_offset, \
-+ sizeof(field##_offset))
-+
-+#define READ_VALUE(name) read_memory(P_thread_##name##_value, \
-+ (char *) &name##_value, \
-+ sizeof(name##_value))
-+
-+static void
-+read_thread_offsets (void)
-+{
-+ READ_OFFSET(next);
-+ READ_OFFSET(uniqueid);
-+ READ_OFFSET(state);
-+ READ_OFFSET(name);
-+ READ_OFFSET(ctx);
-+
-+ READ_VALUE(PS_RUNNING);
-+ READ_VALUE(PS_DEAD);
-+}
-+
-+#define READ_FIELD(ptr, T, field, result) \
-+ read_memory ((ptr) + field##_offset, (char *) &(result), sizeof result)
-+
-+static u_int64_t
-+read_pthread_uniqueid (CORE_ADDR ptr)
-+{
-+ u_int64_t uniqueid;
-+ READ_FIELD(ptr, u_int64_t, uniqueid, uniqueid);
-+ return uniqueid;
-+}
-+
-+static CORE_ADDR
-+read_pthread_next (CORE_ADDR ptr)
-+{
-+ CORE_ADDR next;
-+ READ_FIELD(ptr, CORE_ADDR, next, next);
-+ return next;
-+}
-+
-+static void
-+read_cached_pthread (CORE_ADDR ptr, struct cached_pthread *cache)
-+{
-+ READ_FIELD(ptr, u_int64_t, uniqueid, cache->uniqueid);
-+ READ_FIELD(ptr, int, state, cache->state);
-+ READ_FIELD(ptr, CORE_ADDR, name, cache->name);
-+ READ_FIELD(ptr, ucontext_t, ctx, cache->ctx);
-+}
-+
-+static ptid_t
-+find_active_ptid (void)
-+{
-+ CORE_ADDR ptr;
-+
-+ read_memory ((CORE_ADDR)P_thread_run,
-+ (char *)&ptr,
-+ sizeof ptr);
-+
-+ return find_ptid(read_pthread_uniqueid(ptr));
-+}
-+
-+static CORE_ADDR find_pthread_addr PARAMS ((ptid_t ptid));
-+static struct cached_pthread * find_pthread PARAMS ((ptid_t ptid));
-+
-+static CORE_ADDR
-+find_pthread_addr (ptid_t ptid)
-+{
-+ CORE_ADDR ptr;
-+
-+ if (ptid_equal(ptid, cached_ptid))
-+ return cached_pthread_addr;
-+
-+ read_memory ((CORE_ADDR)P_thread_list,
-+ (char *)&ptr,
-+ sizeof ptr);
-+
-+ while (ptr != 0)
-+ {
-+ if (ptid_equal(find_ptid(read_pthread_uniqueid(ptr)), ptid))
-+ {
-+ cached_ptid = ptid;
-+ cached_pthread_addr = ptr;
-+ read_cached_pthread(ptr, &cached_pthread);
-+ return ptr;
-+ }
-+ ptr = read_pthread_next(ptr);
-+ }
-+
-+ return NULL;
-+}
-+
-+static struct cached_pthread *
-+find_pthread (ptid_t ptid)
-+{
-+ CORE_ADDR ptr;
-+
-+ if (ptid_equal(ptid, cached_ptid))
-+ return &cached_pthread;
-+
-+ read_memory ((CORE_ADDR)P_thread_list,
-+ (char *)&ptr,
-+ sizeof ptr);
-+
-+ while (ptr != 0)
-+ {
-+ if (ptid_equal(find_ptid(read_pthread_uniqueid(ptr)), ptid))
-+ {
-+ cached_ptid = ptid;
-+ cached_pthread_addr = ptr;
-+ read_cached_pthread(ptr, &cached_pthread);
-+ return &cached_pthread;
-+ }
-+ ptr = read_pthread_next(ptr);
-+ }
-+
-+#if 0
-+ error ("Can't find pthread %d,%d", PIDGET(ptid), TIDGET(ptid));
-+#endif
-+ return NULL;
-+}
-+
-+
-+/* Most target vector functions from here on actually just pass through to
-+ inftarg.c, as they don't need to do anything specific for threads. */
-+
-+/* ARGSUSED */
-+static void
-+freebsd_uthread_open (char *arg, int from_tty)
-+{
-+ child_ops.to_open (arg, from_tty);
-+}
-+
-+/* Attach to process PID, then initialize for debugging it
-+ and wait for the trace-trap that results from attaching. */
-+
-+static void
-+freebsd_uthread_attach (char *args, int from_tty)
-+{
-+ child_ops.to_attach (args, from_tty);
-+ push_target (&freebsd_uthread_ops);
-+ freebsd_uthread_attaching = 1;
-+}
-+
-+/* After an attach, see if the target is threaded */
-+
-+static void
-+freebsd_uthread_post_attach (int pid)
-+{
-+ if (freebsd_uthread_active)
-+ {
-+ read_thread_offsets ();
-+ inferior_ptid = find_active_ptid ();
-+ add_thread (inferior_ptid);
-+ }
-+ else
-+ {
-+ unpush_target (&freebsd_uthread_ops);
-+ push_target (&child_ops);
-+ }
-+
-+ freebsd_uthread_attaching = 0;
-+}
-+
-+/* 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
-+freebsd_uthread_detach (char *args, int from_tty)
-+{
-+ child_ops.to_detach (args, from_tty);
-+}
-+
-+/* Resume execution of process PID. If STEP is nozero, then
-+ just single step it. If SIGNAL is nonzero, restart it with that
-+ signal activated. We may have to convert pid from a thread-id to an LWP id
-+ for procfs. */
-+
-+static void
-+freebsd_uthread_resume (ptid_t ptid, int step, enum target_signal signo)
-+{
-+ if (freebsd_uthread_attaching)
-+ {
-+ child_ops.to_resume (ptid, step, signo);
-+ return;
-+ }
-+
-+ child_ops.to_resume (ptid, step, signo);
-+ cached_ptid = MERGEPID(0, 0);
-+}
-+
-+/* 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 ptid_t
-+freebsd_uthread_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
-+{
-+ ptid_t rtnval;
-+
-+ if (freebsd_uthread_attaching)
-+ {
-+ return child_ops.to_wait (ptid, ourstatus);
-+ }
-+
-+ rtnval = child_ops.to_wait (ptid, ourstatus);
-+
-+ if (PIDGET(rtnval) >= 0)
-+ {
-+ rtnval = find_active_ptid ();
-+ if (!in_thread_list (rtnval))
-+ add_thread (rtnval);
-+ }
-+
-+ return rtnval;
-+}
-+
-+/* XXX: this needs to be selected by target, not [build] host */
-+#ifdef __i386__
-+
-+#include "i386-tdep.h"
-+
-+static char sigmap[I386_SSE_NUM_REGS] = /* map reg to sigcontext */
-+{
-+ 12, /* eax */
-+ 11, /* ecx */
-+ 10, /* edx */
-+ 9, /* ebx */
-+ 8, /* esp */
-+ 7, /* ebp */
-+ 6, /* esi */
-+ 5, /* edi */
-+ 15, /* eip */
-+ 17, /* eflags */
-+ 16, /* cs */
-+ 19, /* ss */
-+ 4, /* ds */
-+ 3, /* es */
-+ 2, /* fs */
-+ 1, /* gs */
-+ -1, -1, -1, -1, -1, -1, -1, /* st0-st7 */
-+ -1, -1, -1, -1, -1, -1, -1, /* fctrl-fop */
-+ -1, -1, -1, -1, -1, -1, -1, /* xmm0-xmm7 */
-+ -1, /* mxcsr */
-+};
-+
-+static char jmpmap[I386_SSE_NUM_REGS] = /* map reg to jmp_buf */
-+{
-+ 6, /* eax */
-+ -1, /* ecx */
-+ -1, /* edx */
-+ 1, /* ebx */
-+ 2, /* esp */
-+ 3, /* ebp */
-+ 4, /* esi */
-+ 5, /* edi */
-+ 0, /* eip */
-+ -1, /* eflags */
-+ -1, /* cs */
-+ -1, /* ss */
-+ -1, /* ds */
-+ -1, /* es */
-+ -1, /* fs */
-+ -1, /* gs */
-+ -1, -1, -1, -1, -1, -1, -1, /* st0-st7 */
-+ -1, -1, -1, -1, -1, -1, -1, /* fctrl-fop */
-+ -1, -1, -1, -1, -1, -1, -1, /* xmm0-xmm7 */
-+ -1, /* mxcsr */
-+};
-+
-+#endif
-+
-+#ifdef __alpha__
-+
-+#include "alpha-tdep.h"
-+
-+static char sigmap[ALPHA_NUM_REGS] = /* map reg to sigcontext */
-+{
-+ 1, 2, 3, 4, 5, 6, 7, 8, /* v0 - t6 */
-+ 9, 10, 11, 12, 13, 14, 15, 16, /* t7 - fp */
-+ 17, 18, 19, 20, 21, 22, 23, 24, /* a0 - t9 */
-+ 25, 26, 27, 28, 29, 30, 31, 32, /* t10 - zero */
-+ 38, 39, 40, 41, 42, 43, 44, 45, /* f0 - f7 */
-+ 46, 47, 48, 49, 50, 51, 52, 53, /* f8 - f15 */
-+ 54, 55, 56, 57, 58, 59, 60, 61, /* f16 - f23 */
-+ 62, 63, 64, 65, 66, 67, 68, 69, /* f24 - f31 */
-+ 33, -1 /* pc, vfp */
-+};
-+static char jmpmap[ALPHA_NUM_REGS] = {
-+ 4, 5, 6, 7, 8, 9, 10, 11, /* v0 - t6 */
-+ 12, 13, 14, 15, 16, 17, 18, 19, /* t7 - fp */
-+ 20, 21, 22, 23, 24, 25, 26, 27, /* a0 - t9 */
-+ 28, 29, 30, 31, 32, 33, 34, 35, /* t10 - zero */
-+ 37, 38, 39, 40, 41, 42, 43, 44, /* f0 - f7 */
-+ 45, 46, 47, 48, 49, 50, 51, 52, /* f8 - f15 */
-+ 53, 54, 55, 56, 57, 58, 59, 60, /* f16 - f23 */
-+ 61, 62, 63, 64, 65, 66, 67, 68, /* f24 - f31 */
-+ 2, -1, /* pc, vfp */
-+};
-+
-+#endif
-+
-+#ifdef __sparc64__
-+
-+static char sigmap[125] = /* map reg to sigcontext */
-+{
-+ -1
-+};
-+static char jmpmap[125] = {
-+ -1
-+};
-+
-+#endif
-+
-+static void
-+freebsd_uthread_fetch_registers (int regno)
-+{
-+ struct cached_pthread *thread;
-+ int active;
-+ int first_regno, last_regno;
-+ register_t *regbase;
-+ char *regmap;
-+
-+ if (freebsd_uthread_attaching || TIDGET(inferior_ptid) == 0)
-+ {
-+ child_ops.to_fetch_registers (regno);
-+ return;
-+ }
-+
-+ thread = find_pthread (inferior_ptid);
-+ active = (ptid_equal(inferior_ptid, find_active_ptid()));
-+
-+ if (active)
-+ {
-+ child_ops.to_fetch_registers (regno);
-+ return;
-+ }
-+
-+ if (regno == -1)
-+ {
-+ first_regno = 0;
-+ last_regno = NUM_REGS - 1;
-+ }
-+ else
-+ {
-+ first_regno = regno;
-+ last_regno = regno;
-+ }
-+
-+ regbase = (register_t*) &thread->ctx.jb[0];
-+ regmap = jmpmap;
-+
-+ for (regno = first_regno; regno <= last_regno; regno++)
-+ {
-+ if (regmap[regno] == -1)
-+ child_ops.to_fetch_registers (regno);
-+ else
-+ if (thread)
-+ supply_register (regno, (char*) &regbase[regmap[regno]]);
-+ else
-+ supply_register (regno, NULL);
-+ }
-+}
-+
-+static void
-+freebsd_uthread_store_registers (int regno)
-+{
-+ struct cached_pthread *thread;
-+ CORE_ADDR ptr;
-+ int first_regno, last_regno;
-+ u_int32_t *regbase;
-+ char *regmap;
-+
-+ if (freebsd_uthread_attaching)
-+ {
-+ child_ops.to_store_registers (regno);
-+ return;
-+ }
-+
-+ thread = find_pthread (inferior_ptid);
-+
-+ if (thread->state == PS_RUNNING_value)
-+ {
-+ child_ops.to_store_registers (regno);
-+ return;
-+ }
-+
-+ if (regno == -1)
-+ {
-+ first_regno = 0;
-+ last_regno = NUM_REGS - 1;
-+ }
-+ else
-+ {
-+ first_regno = regno;
-+ last_regno = regno;
-+ }
-+
-+ regbase = (u_int32_t*) &thread->ctx.jb[0];
-+ regmap = jmpmap;
-+
-+ ptr = find_pthread_addr (inferior_ptid);
-+ for (regno = first_regno; regno <= last_regno; regno++)
-+ {
-+ if (regmap[regno] == -1)
-+ child_ops.to_store_registers (regno);
-+ else
-+ {
-+ u_int32_t *reg = &regbase[regmap[regno]];
-+ int off;
-+
-+ /* Hang onto cached value */
-+ memcpy(reg, registers + REGISTER_BYTE (regno),
-+ REGISTER_RAW_SIZE (regno));
-+
-+ /* And push out to inferior */
-+ off = (char *) reg - (char *) thread;
-+ write_memory (ptr + off,
-+ registers + REGISTER_BYTE (regno),
-+ REGISTER_RAW_SIZE (regno));
-+ }
-+ }
-+}
-+
-+/* Get ready to modify the registers array. On machines which store
-+ individual registers, this doesn't need to do anything. On machines
-+ which store all the registers in one fell swoop, this makes sure
-+ that registers contains all the registers from the program being
-+ debugged. */
-+
-+static void
-+freebsd_uthread_prepare_to_store (void)
-+{
-+ child_ops.to_prepare_to_store ();
-+}
-+
-+static int
-+freebsd_uthread_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
-+ int dowrite, struct mem_attrib *attrib,
-+ struct target_ops *target)
-+{
-+ return child_ops.to_xfer_memory (memaddr, myaddr, len, dowrite,
-+ attrib, target);
-+}
-+
-+/* Print status information about what we're accessing. */
-+
-+static void
-+freebsd_uthread_files_info (struct target_ops *ignore)
-+{
-+ child_ops.to_files_info (ignore);
-+}
-+
-+static void
-+freebsd_uthread_kill_inferior (void)
-+{
-+ child_ops.to_kill ();
-+}
-+
-+static void
-+freebsd_uthread_notice_signals (ptid_t ptid)
-+{
-+ child_ops.to_notice_signals (ptid);
-+}
-+
-+/* Fork an inferior process, and start debugging it with /proc. */
-+
-+static void
-+freebsd_uthread_create_inferior (char *exec_file, char *allargs, char **env)
-+{
-+ child_ops.to_create_inferior (exec_file, allargs, env);
-+
-+ if (PIDGET(inferior_ptid) && freebsd_uthread_active)
-+ {
-+ read_thread_offsets ();
-+ push_target (&freebsd_uthread_ops);
-+ inferior_ptid = find_active_ptid ();
-+ add_thread (inferior_ptid);
-+ }
-+}
-+
-+/* This routine is called to find out if the inferior is using threads.
-+ We check for the _thread_run and _thread_list globals. */
-+
-+void
-+freebsd_uthread_new_objfile (struct objfile *objfile)
-+{
-+ struct minimal_symbol *ms;
-+
-+ if (!objfile)
-+ {
-+ freebsd_uthread_active = 0;
-+ return;
-+ }
-+
-+ ms = lookup_minimal_symbol ("_thread_run", NULL, objfile);
-+
-+ if (!ms)
-+ return;
-+
-+ P_thread_run = SYMBOL_VALUE_ADDRESS (ms);
-+
-+ ms = lookup_minimal_symbol ("_thread_list", NULL, objfile);
-+
-+ if (!ms)
-+ return;
-+
-+ P_thread_list = SYMBOL_VALUE_ADDRESS (ms);
-+
-+#define OFFSET_SYM(field) "_thread_" #field "_offset"
-+#define LOOKUP_OFFSET(field) \
-+ do { \
-+ ms = lookup_minimal_symbol (OFFSET_SYM(field), NULL, objfile); \
-+ if (!ms) \
-+ return; \
-+ P_thread_##field##_offset = SYMBOL_VALUE_ADDRESS (ms); \
-+ } while (0);
-+
-+#define VALUE_SYM(name) "_thread_" #name "_value"
-+#define LOOKUP_VALUE(name) \
-+ do { \
-+ ms = lookup_minimal_symbol (VALUE_SYM(name), NULL, objfile); \
-+ if (!ms) \
-+ return; \
-+ P_thread_##name##_value = SYMBOL_VALUE_ADDRESS (ms); \
-+ } while (0);
-+
-+ LOOKUP_OFFSET(next);
-+ LOOKUP_OFFSET(uniqueid);
-+ LOOKUP_OFFSET(state);
-+ LOOKUP_OFFSET(name);
-+ LOOKUP_OFFSET(ctx);
-+
-+ LOOKUP_VALUE(PS_RUNNING);
-+ LOOKUP_VALUE(PS_DEAD);
-+
-+ freebsd_uthread_active = 1;
-+}
-+
-+/* Clean up after the inferior dies. */
-+
-+static void
-+freebsd_uthread_mourn_inferior ()
-+{
-+ child_ops.to_mourn_inferior ();
-+ unpush_target (&freebsd_uthread_ops);
-+}
-+
-+/* Mark our target-struct as eligible for stray "run" and "attach" commands. */
-+
-+static int
-+freebsd_uthread_can_run ()
-+{
-+ return child_suppress_run;
-+}
-+
-+static int
-+freebsd_uthread_thread_alive (ptid_t ptid)
-+{
-+ struct cached_pthread *thread;
-+ int ret = 0;
-+
-+ if (freebsd_uthread_attaching)
-+ return 1;
-+
-+ /*
-+ * We can get called from child_ops.to_wait() which passes the underlying
-+ * pid (without a thread number).
-+ */
-+ if (TIDGET(ptid) == 0)
-+ return 1;
-+
-+ if (find_pthread_addr (ptid) != 0)
-+ {
-+ thread = find_pthread (ptid);
-+ ret = (thread->state != PS_DEAD_value);
-+ }
-+
-+ if (!ret)
-+ free_ptid(ptid);
-+
-+ return ret;
-+}
-+
-+static void
-+freebsd_uthread_stop (void)
-+{
-+ child_ops.to_stop ();
-+}
-+
-+static void
-+freebsd_uthread_find_new_threads (void)
-+{
-+ CORE_ADDR ptr;
-+ int state;
-+ u_int64_t uniqueid;
-+
-+ read_memory ((CORE_ADDR)P_thread_list,
-+ (char *)&ptr,
-+ sizeof ptr);
-+
-+ while (ptr != 0)
-+ {
-+ READ_FIELD(ptr, int, state, state);
-+ READ_FIELD(ptr, u_int64_t, uniqueid, uniqueid);
-+ if (state != PS_DEAD_value &&
-+ !in_thread_list (find_ptid(uniqueid)))
-+ add_thread (find_ptid(uniqueid));
-+ ptr = read_pthread_next(ptr);
-+ }
-+}
-+
-+/* MUST MATCH enum pthread_state */
-+static const char *statenames[] = {
-+ "RUNNING",
-+ "SIGTHREAD",
-+ "MUTEX_WAIT",
-+ "COND_WAIT",
-+ "FDLR_WAIT",
-+ "FDLW_WAIT",
-+ "FDR_WAIT",
-+ "FDW_WAIT",
-+ "POLL_WAIT",
-+ "FILE_WAIT",
-+ "SELECT_WAIT",
-+ "SLEEP_WAIT",
-+ "WAIT_WAIT",
-+ "SIGSUSPEND",
-+ "SIGWAIT",
-+ "SPINBLOCK",
-+ "JOIN",
-+ "SUSPENDED",
-+ "DEAD",
-+ "DEADLOCK",
-+};
-+
-+#if 0
-+
-+static int
-+freebsd_uthread_get_thread_info (ref, selection, info)
-+ gdb_threadref *ref;
-+ int selection;
-+ struct gdb_ext_thread_info *info;
-+{
-+ int pid = *ref;
-+ struct cached_pthread *thread = find_pthread (pid);
-+ struct cleanup *old_chain;
-+
-+ old_chain = save_inferior_pid ();
-+ inferior_pid = main_pid;
-+
-+ memset(&info->threadid, 0, OPAQUETHREADBYTES);
-+
-+ memcpy(&info->threadid, ref, sizeof *ref);
-+ info->active = thread->state == PS_RUNNING_value;
-+ strcpy(info->display, statenames[thread->state]);
-+ if (thread->name)
-+ read_memory ((CORE_ADDR) thread->name, info->shortname, 32);
-+ else
-+ strcpy(info->shortname, "");
-+
-+ do_cleanups (old_chain);
-+ return (0);
-+}
-+
-+#endif
-+
-+char *
-+freebsd_uthread_pid_to_str (ptid_t ptid)
-+{
-+ static char buf[30];
-+
-+ if (STREQ (current_target.to_shortname, "freebsd-uthreads"))
-+ sprintf (buf, "Process %d, Thread %ld",
-+ PIDGET(ptid), TIDGET(ptid));
-+ else
-+ sprintf (buf, "Process %d", PIDGET(ptid));
-+
-+ return buf;
-+}
-+
-+
-+static void
-+init_freebsd_uthread_ops ()
-+{
-+ freebsd_uthread_ops.to_shortname = "freebsd-uthreads";
-+ freebsd_uthread_ops.to_longname = "FreeBSD uthreads";
-+ freebsd_uthread_ops.to_doc = "FreeBSD user threads support.";
-+ freebsd_uthread_ops.to_open = freebsd_uthread_open;
-+ freebsd_uthread_ops.to_attach = freebsd_uthread_attach;
-+ freebsd_uthread_ops.to_post_attach = freebsd_uthread_post_attach;
-+ freebsd_uthread_ops.to_detach = freebsd_uthread_detach;
-+ freebsd_uthread_ops.to_resume = freebsd_uthread_resume;
-+ freebsd_uthread_ops.to_wait = freebsd_uthread_wait;
-+ freebsd_uthread_ops.to_fetch_registers = freebsd_uthread_fetch_registers;
-+ freebsd_uthread_ops.to_store_registers = freebsd_uthread_store_registers;
-+ freebsd_uthread_ops.to_prepare_to_store = freebsd_uthread_prepare_to_store;
-+ freebsd_uthread_ops.to_xfer_memory = freebsd_uthread_xfer_memory;
-+ freebsd_uthread_ops.to_files_info = freebsd_uthread_files_info;
-+ freebsd_uthread_ops.to_insert_breakpoint = memory_insert_breakpoint;
-+ freebsd_uthread_ops.to_remove_breakpoint = memory_remove_breakpoint;
-+ freebsd_uthread_ops.to_terminal_init = terminal_init_inferior;
-+ freebsd_uthread_ops.to_terminal_inferior = terminal_inferior;
-+ freebsd_uthread_ops.to_terminal_ours_for_output = terminal_ours_for_output;
-+ freebsd_uthread_ops.to_terminal_ours = terminal_ours;
-+ freebsd_uthread_ops.to_terminal_info = child_terminal_info;
-+ freebsd_uthread_ops.to_kill = freebsd_uthread_kill_inferior;
-+ freebsd_uthread_ops.to_create_inferior = freebsd_uthread_create_inferior;
-+ freebsd_uthread_ops.to_mourn_inferior = freebsd_uthread_mourn_inferior;
-+ freebsd_uthread_ops.to_can_run = freebsd_uthread_can_run;
-+ freebsd_uthread_ops.to_notice_signals = freebsd_uthread_notice_signals;
-+ freebsd_uthread_ops.to_thread_alive = freebsd_uthread_thread_alive;
-+ freebsd_uthread_ops.to_stop = freebsd_uthread_stop;
-+ freebsd_uthread_ops.to_stratum = process_stratum;
-+ freebsd_uthread_ops.to_has_all_memory = 1;
-+ freebsd_uthread_ops.to_has_memory = 1;
-+ freebsd_uthread_ops.to_has_stack = 1;
-+ freebsd_uthread_ops.to_has_registers = 1;
-+ freebsd_uthread_ops.to_has_execution = 1;
-+ freebsd_uthread_ops.to_has_thread_control = 0;
-+ freebsd_uthread_ops.to_magic = OPS_MAGIC;
-+ freebsd_uthread_ops.to_find_new_threads = freebsd_uthread_find_new_threads;
-+ freebsd_uthread_ops.to_pid_to_str = freebsd_uthread_pid_to_str;
-+#if 0
-+ freebsd_uthread_vec.get_thread_info = freebsd_uthread_get_thread_info;
-+#endif
-+}
-+
-+void
-+_initialize_freebsd_uthread ()
-+{
-+ init_freebsd_uthread_ops ();
-+ add_target (&freebsd_uthread_ops);
-+
-+ target_new_objfile_chain = target_new_objfile_hook;
-+ target_new_objfile_hook = freebsd_uthread_new_objfile;
-+
-+ child_suppress_run = 1;
-+}