summaryrefslogtreecommitdiff
path: root/libpthread/nptl_db
diff options
context:
space:
mode:
Diffstat (limited to 'libpthread/nptl_db')
-rw-r--r--libpthread/nptl_db/ChangeLog207
-rw-r--r--libpthread/nptl_db/Makefile13
-rw-r--r--libpthread/nptl_db/Makefile.in71
-rw-r--r--libpthread/nptl_db/db_info.c103
-rw-r--r--libpthread/nptl_db/fetch-value.c284
-rw-r--r--libpthread/nptl_db/proc_service.h87
-rw-r--r--libpthread/nptl_db/structs.def88
-rw-r--r--libpthread/nptl_db/td_init.c32
-rw-r--r--libpthread/nptl_db/td_log.c32
-rw-r--r--libpthread/nptl_db/td_symbol_list.c87
-rw-r--r--libpthread/nptl_db/td_ta_clear_event.c79
-rw-r--r--libpthread/nptl_db/td_ta_delete.c42
-rw-r--r--libpthread/nptl_db/td_ta_enable_stats.c35
-rw-r--r--libpthread/nptl_db/td_ta_event_addr.c61
-rw-r--r--libpthread/nptl_db/td_ta_event_getmsg.c105
-rw-r--r--libpthread/nptl_db/td_ta_get_nthreads.c42
-rw-r--r--libpthread/nptl_db/td_ta_get_ph.c36
-rw-r--r--libpthread/nptl_db/td_ta_get_stats.c35
-rw-r--r--libpthread/nptl_db/td_ta_map_id2thr.c38
-rw-r--r--libpthread/nptl_db/td_ta_map_lwp2thr.c178
-rw-r--r--libpthread/nptl_db/td_ta_new.c65
-rw-r--r--libpthread/nptl_db/td_ta_reset_stats.c35
-rw-r--r--libpthread/nptl_db/td_ta_set_event.c79
-rw-r--r--libpthread/nptl_db/td_ta_setconcurrency.c35
-rw-r--r--libpthread/nptl_db/td_ta_thr_iter.c148
-rw-r--r--libpthread/nptl_db/td_ta_tsd_iter.c81
-rw-r--r--libpthread/nptl_db/td_thr_clear_event.c77
-rw-r--r--libpthread/nptl_db/td_thr_dbresume.c30
-rw-r--r--libpthread/nptl_db/td_thr_dbsuspend.c30
-rw-r--r--libpthread/nptl_db/td_thr_event_enable.c34
-rw-r--r--libpthread/nptl_db/td_thr_event_getmsg.c119
-rw-r--r--libpthread/nptl_db/td_thr_get_info.c110
-rw-r--r--libpthread/nptl_db/td_thr_getfpregs.c53
-rw-r--r--libpthread/nptl_db/td_thr_getgregs.c53
-rw-r--r--libpthread/nptl_db/td_thr_getxregs.c30
-rw-r--r--libpthread/nptl_db/td_thr_getxregsize.c30
-rw-r--r--libpthread/nptl_db/td_thr_set_event.c77
-rw-r--r--libpthread/nptl_db/td_thr_setfpregs.c50
-rw-r--r--libpthread/nptl_db/td_thr_setgregs.c50
-rw-r--r--libpthread/nptl_db/td_thr_setprio.c30
-rw-r--r--libpthread/nptl_db/td_thr_setsigpending.c31
-rw-r--r--libpthread/nptl_db/td_thr_setxregs.c30
-rw-r--r--libpthread/nptl_db/td_thr_sigsetmask.c30
-rw-r--r--libpthread/nptl_db/td_thr_tls_get_addr.c43
-rw-r--r--libpthread/nptl_db/td_thr_tlsbase.c55
-rw-r--r--libpthread/nptl_db/td_thr_tsd.c96
-rw-r--r--libpthread/nptl_db/td_thr_validate.c91
-rw-r--r--libpthread/nptl_db/thread_db.h459
-rw-r--r--libpthread/nptl_db/thread_dbP.h258
49 files changed, 3964 insertions, 0 deletions
diff --git a/libpthread/nptl_db/ChangeLog b/libpthread/nptl_db/ChangeLog
new file mode 100644
index 000000000..52c849138
--- /dev/null
+++ b/libpthread/nptl_db/ChangeLog
@@ -0,0 +1,207 @@
+2004-09-09 Roland McGrath <roland@redhat.com>
+
+ * td_ta_map_lwp2thr.c (td_ta_map_lwp2thr): Don't abort if inferior's
+ descriptor is bogus.
+
+2004-05-27 Roland McGrath <roland@redhat.com>
+
+ * td_thr_validate.c: When we find no threads and the inferior appears
+ uninitialized, validate the main thread as a special case.
+
+2004-05-01 Jakub Jelinek <jakub@redhat.com>
+
+ * thread_dbP.h (LOG): Use write instead of __libc_write.
+
+2004-04-03 Ulrich Drepper <drepper@redhat.com>
+
+ * td_ta_set_event.c (td_ta_set_event): Initialize copy to avoid
+ warnings.
+
+ * td_ta_thr_iter.c (td_ta_thr_iter): Initialize list to avoid warning.
+ * td_ta_clear_event.c (td_ta_clear_event): Initialize eventmask to
+ avoid warning.
+ * td_ta_set_event.c (td_ta_set_event): Likewise.
+
+2004-03-24 Roland McGrath <roland@redhat.com>
+
+ * fetch-value.c (_td_locate_field): Cast DB_DESC_OFFSET to int32_t.
+ * thread_dbP.h (DB_DESC_OFFSET): Remove cast from definition.
+
+2004-03-13 Jakub Jelinek <jakub@redhat.com>
+
+ * db_info.c: Don't use TLS_TP_OFFSET in the #if, but
+ TLS_TCB_SIZE == 0 ?: in the DESC macro.
+
+2004-03-12 Roland McGrath <roland@redhat.com>
+
+ * db_info.c [TLS_DTV_AT_TP && TLS_TP_OFFSET > 0]
+ (_thread_db_pthread_dtvp): Define differently for this case (PowerPC).
+
+2003-12-11 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * db_info.c (REGISTER): Add bit size of thread register as second
+ parameter to REGISTER macro.
+
+2003-12-02 Roland McGrath <roland@redhat.com>
+
+ * thread_dbP.h (DB_FUNCTION): New macro.
+ * structs.def: Use it for __nptl_create_event and __nptl_death_event.
+ * db_info.c (DB_FUNCTION): New macro.
+ * td_symbol_list.c (DB_FUNCTION): New macro, prepend "." to symbol
+ name under [HAVE_ASM_GLOBAL_DOT_NAME].
+ (td_lookup) [HAVE_ASM_GLOBAL_DOT_NAME]: If lookup fails with PS_NOSYM
+ and name starts with a dot, try it without the dot.
+
+2003-09-08 Roland McGrath <roland@redhat.com>
+
+ * td_thr_get_info.c (td_thr_get_info): Cast th_unique to thread_t.
+
+2003-08-22 Roland McGrath <roland@redhat.com>
+
+ * fetch-value.c (_td_check_sizeof, _td_locate_field): Return
+ TD_NOCAPAB for PS_NOSYM, instead of vanilla TD_ERR.
+ * td_thr_tls_get_addr.c (td_thr_tls_get_addr): Return TD_NOAPLIC when
+ DB_GET_FIELD returns TD_NOCAPAB.
+
+ * thread_db.h (td_thr_tls_get_addr): Use psaddr_t in signature.
+ * structs.def [USE_TLS]: Add DB_STRUCT_FIELD (link_map, l_tls_modid).
+ * db_info.c (link_map): Typedef it.
+ * td_thr_tls_get_addr.c (td_thr_tls_get_addr): Rewritten.
+
+2003-08-14 Roland McGrath <roland@redhat.com>
+
+ * thread_dbP.h: Mostly rewritten with many new macros and decls.
+ * td_ta_new.c (td_ta_new): Don't cache a lot of symbol values.
+ * structs.def: New file.
+ * db_info.c: New file.
+ * td_symbol_list.c (symbol_list_arr): Define with structs.def macros.
+ * td_ta_clear_event.c: Rewritten.
+ * td_ta_event_addr.c: Rewritten.
+ * td_ta_event_getmsg.c: Rewritten.
+ * td_ta_get_nthreads.c: Rewritten.
+ * td_ta_map_lwp2thr.c: New file.
+ * td_ta_set_event.c: Rewritten.
+ * td_ta_thr_iter.c: Rewritten.
+ * td_ta_tsd_iter.c: Rewritten.
+ * td_thr_clear_event.c: Rewritten.
+ * td_thr_event_enable.c: Rewritten.
+ * td_thr_event_getmsg.c: Rewritten.
+ * td_thr_get_info.c: Rewritten.
+ * td_thr_getfpregs.c: Rewritten.
+ * td_thr_getgregs.c: Rewritten.
+ * td_thr_set_event.c: Rewritten.
+ * td_thr_setfpregs.c: Rewritten.
+ * td_thr_setgregs.c: Rewritten.
+ * td_thr_tlsbase.c: Rewritten.
+ * td_thr_tsd.c: Rewritten.
+ * td_thr_validate.c: Rewritten.
+ * Makefile (distribute): Add them.
+ * fetch-value.c: New file.
+ * Makefile (libthread_db-routines): Add it.
+
+ * thread_db.h (td_err_e): Comment fix.
+
+2003-08-05 Roland McGrath <roland@redhat.com>
+
+ * thread_dbP.h (td_lookup): Add attribute_hidden to decl.
+
+2003-08-04 Roland McGrath <roland@redhat.com>
+
+ * td_ta_clear_event.c (td_ta_clear_event): Fix sizes in ps_* calls.
+
+2003-06-23 Roland McGrath <roland@redhat.com>
+
+ * proc_service.h: Cosmetic and comment fixes.
+
+2003-06-19 Roland McGrath <roland@redhat.com>
+
+ * td_thr_event_enable.c (td_thr_event_enable): Use proper type `bool'
+ for value written into inferior's `report_events'.
+
+2003-03-18 Roland McGrath <roland@redhat.com>
+
+ * td_thr_event_getmsg.c (td_thr_event_getmsg): Splice the thread out
+ of the ->nextevent linkage.
+
+ * td_ta_event_getmsg.c (td_ta_event_getmsg): Runtime error instead of
+ assert for reading TD_EVENT_NONE. Clear the event buffer after
+ reading it. Add a sanity check for foo->nextevent = foo.
+
+2003-03-15 Roland McGrath <roland@redhat.com>
+
+ * thread_db.h (td_err_e): Add TD_NOTLS and TD_TLSDEFER.
+ (td_thr_tlsbase): Declare it.
+ * td_thr_tlsbase.c: New file.
+ * Makefile (libthread_db-routines): Add it.
+ * Versions (libthread_db: GLIBC_2.3.3): New set, add td_thr_tlsbase.
+ * td_thr_tls_get_addr.c (td_thr_tls_get_addr): Use td_thr_tlsbase.
+
+2003-03-14 Roland McGrath <roland@redhat.com>
+
+ * td_thr_tls_get_addr.c (td_thr_tls_get_addr): Use `header.' prefix.
+
+2003-03-10 Roland McGrath <roland@redhat.com>
+
+ * td_ta_thr_iter.c (iterate_thread_list): Don't use `header.data.'
+ prefix for `struct pthread' members.
+ * td_thr_validate.c (check_thread_list): Likewise.
+ * td_thr_tls_get_addr.c (td_thr_tls_get_addr): Likewise.
+
+2003-03-03 Roland McGrath <roland@redhat.com>
+
+ * td_thr_tls_get_addr.c (td_thr_tls_get_addr): Handle TLS_DTV_AT_TP.
+
+2003-02-15 Ulrich Drepper <drepper@redhat.com>
+
+ * td_symbol_list.c: New symbol name for SYM_PTHREAD_NTHREADS.
+
+2003-01-07 Jakub Jelinek <jakub@redhat.com>
+
+ * td_ta_event_getmsg.c: Include assert.h.
+
+-2003-01-05 Ulrich Drepper <drepper@redhat.com>
+
+ * Makefile (libthread_db.so-no-z-defs): Define.
+
+2003-01-03 Roland McGrath <roland@redhat.com>
+
+ * td_thr_setgregs.c (td_thr_setgregs): *_BIT -> *_BITMASK
+ * td_thr_setfpregs.c (td_thr_setfpregs): Likewise.
+ * td_thr_get_info.c (td_thr_get_info): Likewise.
+ * td_thr_getgregs.c (td_thr_getgregs): Likewise.
+ * td_thr_getfpregs.c (td_thr_getfpregs): Likewise.
+ * td_ta_thr_iter.c (iterate_thread_list): Likewise.
+
+2002-12-12 Roland McGrath <roland@redhat.com>
+
+ * td_ta_thr_iter.c (iterate_thread_list): Handle special case of
+ uninitialized __stack_user (zeros), hard-wire just the main thread.
+
+ * td_thr_get_info.c (td_thr_get_info): Fix ti_lid initialization.
+
+2002-12-06 Roland McGrath <roland@redhat.com>
+
+ * td_ta_event_getmsg.c (td_ta_event_getmsg): Write the NEXT pointer
+ into the inferior's __pthread_last_event variable, not a word from
+ an inferior address used in the parent. Pass the address of a
+ null word to ps_pdwrite, not a null pointer.
+
+2002-12-04 Roland McGrath <roland@redhat.com>
+
+ * td_thr_get_info.c (td_thr_get_info): ti_tid is pthread_t, not a PID.
+
+ * thread_db.h (td_thrinfo_t): Comment fix.
+
+ * td_ta_map_lwp2thr.c: Moved to ../nptl/sysdeps/i386/.
+
+2002-12-04 Ulrich Drepper <drepper@redhat.com>
+
+ * td_ta_thr_iter.c (iterate_thread_list): At end of iteration read
+ pointer to the next element from inferior.
+
+2002-12-02 Roland McGrath <roland@redhat.com>
+
+ * td_symbol_list.c (symbol_list_arr): pthread_keys -> __pthread_keys
+
+ * td_ta_map_lwp2thr.c (td_ta_map_lwp2thr): Fetch inferior registers to
+ see its %gs value, not our own.
diff --git a/libpthread/nptl_db/Makefile b/libpthread/nptl_db/Makefile
new file mode 100644
index 000000000..f9100219a
--- /dev/null
+++ b/libpthread/nptl_db/Makefile
@@ -0,0 +1,13 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+top_srcdir=../../
+top_builddir=../../
+include $(top_builddir)Rules.mak
+all: libs
+include Makefile.in
+include $(top_srcdir)Makerules
diff --git a/libpthread/nptl_db/Makefile.in b/libpthread/nptl_db/Makefile.in
new file mode 100644
index 000000000..3eaded59f
--- /dev/null
+++ b/libpthread/nptl_db/Makefile.in
@@ -0,0 +1,71 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+subdirs += libpthread/nptl/nptl_db
+
+# Get the thread include dependencies and shared object name
+CFLAGS-nptl_db := -DLIBPTHREAD_SO="\"libpthread.so.$(MAJOR_VERSION)\""
+CFLAGS-nptl_db += -I$(top_srcdir)libpthread/nptl -D_GNU_SOURCE
+CFLAGS-nptl_db += -DIS_IN_libthread_db=1 -std=gnu99 -I$(top_srcdir)ldso/include
+
+LDFLAGS-libthread_db.so := $(LDFLAGS_NOSTRIP) -s --warn-unresolved-symbols
+
+LIBS-libthread_db.so := $(LIBS)
+
+libthread_db_FULL_NAME := libthread_db-$(VERSION).so
+
+libthread_db_DIR := $(top_srcdir)libpthread/nptl_db
+libthread_db_OUT := $(top_builddir)libpthread/nptl_db
+
+libthread_db_SRC := $(wildcard $(libthread_db_DIR)/td_*.c) \
+ $(libthread_db_DIR)/fetch-value.c
+
+libthread_db_OBJ := $(patsubst $(libthread_db_DIR)/%.c,$(libthread_db_OUT)/%.o,$(libthread_db_SRC))
+
+libthread_db-so-y := $(libthread_db_OBJ:.o=.oS)
+ifeq ($(DOPIC),y)
+libthread_db-a-y := $(libthread_db-so-y)
+else
+libthread_db-a-y := $(libthread_db_OBJ)
+endif
+
+libthread_db-multi-y := $(libthread_db_SRC)
+
+lib-a-$(PTHREADS_DEBUG_SUPPORT) += $(top_builddir)lib/libthread_db.a
+lib-so-$(PTHREADS_DEBUG_SUPPORT) += $(top_builddir)lib/libthread_db.so
+objclean-y += libthread_db_clean
+headers-$(PTHREADS_DEBUG_SUPPORT) += $(nptl_db_headers)
+headers_clean-y += nptl_db_headers_clean
+
+ifeq ($(DOPIC),y)
+$(top_builddir)lib/libthread_db.so: $(top_builddir)lib/libthread_db.a $(libc)
+else
+$(top_builddir)lib/libthread_db.so: $(libthread_db_OUT)/libthread_db_so.a $(libc)
+endif
+ $(call link.so,$(libthread_db_FULL_NAME),1)
+
+$(libthread_db_OUT)/libthread_db_so.a: $(libthread_db-so-y)
+ $(Q)$(RM) $@
+ $(do_strip)
+ $(do_ar)
+
+$(top_builddir)lib/libthread_db.a: $(libthread_db-a-y)
+ $(Q)$(INSTALL) -d $(dir $@)
+ $(Q)$(RM) $@
+ $(do_strip)
+ $(do_ar)
+
+$(top_builddir)include/thread_db.h:
+ $(do_ln) $(call rel_srcdir)$(PTDIR)_db/$(@F) $@
+
+nptl_db_headers:= $(top_builddir)include/thread_db.h
+
+nptl_db_headers_clean:
+ $(do_rm) $(nptl_db_headers)
+
+libthread_db_clean:
+ $(do_rm) $(addprefix $(libthread_db_OUT)/*., o oS a)
diff --git a/libpthread/nptl_db/db_info.c b/libpthread/nptl_db/db_info.c
new file mode 100644
index 000000000..5aec152d5
--- /dev/null
+++ b/libpthread/nptl_db/db_info.c
@@ -0,0 +1,103 @@
+/* This file is included by pthread_create.c to define in libpthread
+ all the magic symbols required by libthread_db.
+
+ Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include "thread_dbP.h"
+#include <tls.h>
+
+typedef struct pthread pthread;
+typedef struct pthread_key_struct pthread_key_struct;
+typedef struct pthread_key_data pthread_key_data;
+typedef struct
+{
+ struct pthread_key_data data[PTHREAD_KEY_2NDLEVEL_SIZE];
+}
+pthread_key_data_level2;
+
+typedef struct
+{
+ union dtv dtv[UINT32_MAX / 2 / sizeof (union dtv)]; /* No constant bound. */
+} dtv;
+
+typedef struct link_map link_map;
+
+
+#define schedparam_sched_priority schedparam.sched_priority
+
+#define eventbuf_eventmask eventbuf.eventmask
+#define eventbuf_eventmask_event_bits eventbuf.eventmask.event_bits
+
+#define DESC(name, offset, obj) \
+ DB_DEFINE_DESC (name, 8 * sizeof (obj), 1, offset);
+#define ARRAY_DESC(name, offset, obj) \
+ DB_DEFINE_DESC (name, \
+ 8 * sizeof (obj)[0], sizeof (obj) / sizeof (obj)[0], \
+ offset);
+
+#if defined(TLS_TCB_AT_TP)
+# define dtvp header.dtv
+#elif defined(TLS_DTV_AT_TP)
+/* Special case hack. If TLS_TCB_SIZE == 0 (on PowerPC), there is no TCB
+ containing the DTV at the TP, but actually the TCB lies behind the TP,
+ i.e. at the very end of the area covered by TLS_PRE_TCB_SIZE. */
+DESC (_thread_db_pthread_dtvp,
+ TLS_PRE_TCB_SIZE + offsetof (tcbhead_t, dtv)
+ - (TLS_TCB_SIZE == 0 ? sizeof (tcbhead_t) : 0), union dtv)
+#endif
+
+
+#define DB_STRUCT(type) \
+ const uint32_t _thread_db_sizeof_##type = sizeof (type);
+#define DB_STRUCT_FIELD(type, field) \
+ DESC (_thread_db_##type##_##field, \
+ offsetof (type, field), ((type *) 0)->field)
+#define DB_STRUCT_ARRAY_FIELD(type, field) \
+ ARRAY_DESC (_thread_db_##type##_##field, \
+ offsetof (type, field), ((type *) 0)->field)
+#define DB_VARIABLE(name) DESC (_thread_db_##name, 0, name)
+#define DB_ARRAY_VARIABLE(name) ARRAY_DESC (_thread_db_##name, 0, name)
+#define DB_SYMBOL(name) /* Nothing. */
+#define DB_FUNCTION(name) /* Nothing. */
+#include "structs.def"
+#undef DB_STRUCT
+#undef DB_STRUCT_FIELD
+#undef DB_SYMBOL
+#undef DB_FUNCTION
+#undef DB_VARIABLE
+#undef DESC
+
+
+
+#ifdef DB_THREAD_SELF
+# ifdef DB_THREAD_SELF_INCLUDE
+# include DB_THREAD_SELF_INCLUDE
+# endif
+
+/* This macro is defined in the machine's tls.h using the three below. */
+# define CONST_THREAD_AREA(bits, value) \
+ const uint32_t _thread_db_const_thread_area = (value);
+# define REGISTER_THREAD_AREA(bits, regofs, scale) \
+ DB_DEFINE_DESC (_thread_db_register##bits##_thread_area, \
+ bits, (scale), (regofs));
+# define REGISTER(bits, size, regofs, bias) \
+ DB_DEFINE_DESC (_thread_db_register##bits, size, (uint32_t)(bias), (regofs));
+
+DB_THREAD_SELF
+#endif
diff --git a/libpthread/nptl_db/fetch-value.c b/libpthread/nptl_db/fetch-value.c
new file mode 100644
index 000000000..0d9bb0eb8
--- /dev/null
+++ b/libpthread/nptl_db/fetch-value.c
@@ -0,0 +1,284 @@
+/* Helper routines for libthread_db.
+ Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include "thread_dbP.h"
+#include <byteswap.h>
+#include <assert.h>
+
+td_err_e
+_td_check_sizeof (td_thragent_t *ta, uint32_t *sizep, int sizep_name)
+{
+ if (*sizep == 0)
+ {
+ psaddr_t descptr;
+ ps_err_e err = td_lookup (ta->ph, sizep_name, &descptr);
+ if (err == PS_NOSYM)
+ return TD_NOCAPAB;
+ if (err == PS_OK)
+ err = ps_pdread (ta->ph, descptr, sizep, sizeof *sizep);
+ if (err != PS_OK)
+ return TD_ERR;
+ if (*sizep & 0xff000000U)
+ *sizep = bswap_32 (*sizep);
+ }
+ return TD_OK;
+}
+
+td_err_e
+_td_locate_field (td_thragent_t *ta,
+ db_desc_t desc, int descriptor_name,
+ psaddr_t idx, psaddr_t *address)
+{
+ uint32_t elemsize;
+
+ if (DB_DESC_SIZE (desc) == 0)
+ {
+ /* Read the information about this field from the inferior. */
+ psaddr_t descptr;
+ ps_err_e err = td_lookup (ta->ph, descriptor_name, &descptr);
+ if (err == PS_NOSYM)
+ return TD_NOCAPAB;
+ if (err == PS_OK)
+ err = ps_pdread (ta->ph, descptr, desc, DB_SIZEOF_DESC);
+ if (err != PS_OK)
+ return TD_ERR;
+ if (DB_DESC_SIZE (desc) == 0)
+ return TD_DBERR;
+ if (DB_DESC_SIZE (desc) & 0xff000000U)
+ {
+ /* Byte-swap these words, though we leave the size word
+ in native order as the handy way to distinguish. */
+ DB_DESC_OFFSET (desc) = bswap_32 (DB_DESC_OFFSET (desc));
+ DB_DESC_NELEM (desc) = bswap_32 (DB_DESC_NELEM (desc));
+ }
+ }
+
+ if (idx != 0 && idx - (psaddr_t) 0 > DB_DESC_NELEM (desc))
+ /* This is an internal indicator to callers with nonzero IDX
+ that the IDX value is too big. */
+ return TD_NOAPLIC;
+
+ elemsize = DB_DESC_SIZE (desc);
+ if (elemsize & 0xff000000U)
+ elemsize = bswap_32 (elemsize);
+
+ *address += (int32_t) DB_DESC_OFFSET (desc);
+ *address += (elemsize / 8 * (idx - (psaddr_t) 0));
+ return TD_OK;
+}
+
+td_err_e
+_td_fetch_value (td_thragent_t *ta,
+ db_desc_t desc, int descriptor_name,
+ psaddr_t idx, psaddr_t address,
+ psaddr_t *result)
+{
+ ps_err_e err;
+ td_err_e terr = _td_locate_field (ta, desc, descriptor_name, idx, &address);
+ if (terr != TD_OK)
+ return terr;
+
+ if (DB_DESC_SIZE (desc) == 8 || DB_DESC_SIZE (desc) == bswap_32 (8))
+ {
+ uint8_t value;
+ err = ps_pdread (ta->ph, address, &value, sizeof value);
+ *result = (psaddr_t) 0 + value;
+ }
+ else if (DB_DESC_SIZE (desc) == 32)
+ {
+ uint32_t value;
+ err = ps_pdread (ta->ph, address, &value, sizeof value);
+ *result = (psaddr_t) 0 + value;
+ }
+ else if (DB_DESC_SIZE (desc) == 64)
+ {
+ uint64_t value;
+ if (sizeof (psaddr_t) < 8)
+ return TD_NOCAPAB;
+ err = ps_pdread (ta->ph, address, &value, sizeof value);
+ *result = (psaddr_t) 0 + value;
+ }
+ else if (DB_DESC_SIZE (desc) == bswap_32 (32))
+ {
+ uint32_t value;
+ err = ps_pdread (ta->ph, address, &value, sizeof value);
+ value = bswap_32 (value);
+ *result = (psaddr_t) 0 + value;
+ }
+ else if (DB_DESC_SIZE (desc) == bswap_32 (64))
+ {
+ uint64_t value;
+ if (sizeof (psaddr_t) < 8)
+ return TD_NOCAPAB;
+ err = ps_pdread (ta->ph, address, &value, sizeof value);
+ value = bswap_64 (value);
+ *result = (psaddr_t) 0 + value;
+ }
+ else
+ return TD_DBERR;
+
+ return err == PS_OK ? TD_OK : TD_ERR;
+}
+
+
+td_err_e
+_td_store_value (td_thragent_t *ta,
+ uint32_t desc[2], int descriptor_name, psaddr_t idx,
+ psaddr_t address, psaddr_t widened_value)
+{
+ ps_err_e err;
+ td_err_e terr = _td_locate_field (ta, desc, descriptor_name, idx, &address);
+ if (terr != TD_OK)
+ return terr;
+
+ if (DB_DESC_SIZE (desc) == 8 || DB_DESC_SIZE (desc) == bswap_32 (8))
+ {
+ uint8_t value = widened_value - (psaddr_t) 0;
+ err = ps_pdwrite (ta->ph, address, &value, sizeof value);
+ }
+ else if (DB_DESC_SIZE (desc) == 32)
+ {
+ uint32_t value = widened_value - (psaddr_t) 0;
+ err = ps_pdwrite (ta->ph, address, &value, sizeof value);
+ }
+ else if (DB_DESC_SIZE (desc) == 64)
+ {
+ uint64_t value = widened_value - (psaddr_t) 0;
+ if (sizeof (psaddr_t) < 8)
+ return TD_NOCAPAB;
+ err = ps_pdwrite (ta->ph, address, &value, sizeof value);
+ }
+ else if (DB_DESC_SIZE (desc) == bswap_32 (32))
+ {
+ uint32_t value = widened_value - (psaddr_t) 0;
+ value = bswap_32 (value);
+ err = ps_pdwrite (ta->ph, address, &value, sizeof value);
+ }
+ else if (DB_DESC_SIZE (desc) == bswap_32 (64))
+ {
+ uint64_t value = widened_value - (psaddr_t) 0;
+ if (sizeof (psaddr_t) < 8)
+ return TD_NOCAPAB;
+ value = bswap_64 (value);
+ err = ps_pdwrite (ta->ph, address, &value, sizeof value);
+ }
+ else
+ return TD_DBERR;
+
+ return err == PS_OK ? TD_OK : TD_ERR;
+}
+
+td_err_e
+_td_fetch_value_local (td_thragent_t *ta,
+ db_desc_t desc, int descriptor_name, psaddr_t idx,
+ void *address,
+ psaddr_t *result)
+{
+ td_err_e terr = _td_locate_field (ta, desc, descriptor_name, idx, &address);
+ if (terr != TD_OK)
+ return terr;
+
+ if (DB_DESC_SIZE (desc) == 8 || DB_DESC_SIZE (desc) == bswap_32 (8))
+ {
+ uint8_t value;
+ memcpy (&value, address, sizeof value);
+ *result = (psaddr_t) 0 + value;
+ }
+ else if (DB_DESC_SIZE (desc) == 32)
+ {
+ uint32_t value;
+ memcpy (&value, address, sizeof value);
+ *result = (psaddr_t) 0 + value;
+ }
+ else if (DB_DESC_SIZE (desc) == 64)
+ {
+ uint64_t value;
+ if (sizeof (psaddr_t) < 8)
+ return TD_NOCAPAB;
+ memcpy (&value, address, sizeof value);
+ *result = (psaddr_t) 0 + value;
+ }
+ else if (DB_DESC_SIZE (desc) == bswap_32 (32))
+ {
+ uint32_t value;
+ memcpy (&value, address, sizeof value);
+ value = bswap_32 (value);
+ *result = (psaddr_t) 0 + value;
+ }
+ else if (DB_DESC_SIZE (desc) == bswap_32 (64))
+ {
+ uint64_t value;
+ if (sizeof (psaddr_t) < 8)
+ return TD_NOCAPAB;
+ memcpy (&value, address, sizeof value);
+ value = bswap_64 (value);
+ *result = (psaddr_t) 0 + value;
+ }
+ else
+ return TD_DBERR;
+
+ return TD_OK;
+}
+
+
+td_err_e
+_td_store_value_local (td_thragent_t *ta,
+ uint32_t desc[2], int descriptor_name, psaddr_t idx,
+ void *address, psaddr_t widened_value)
+{
+ td_err_e terr = _td_locate_field (ta, desc, descriptor_name, idx, &address);
+ if (terr != TD_OK)
+ return terr;
+
+ if (DB_DESC_SIZE (desc) == 8 || DB_DESC_SIZE (desc) == bswap_32 (8))
+ {
+ uint8_t value = widened_value - (psaddr_t) 0;
+ memcpy (address, &value, sizeof value);
+ }
+ else if (DB_DESC_SIZE (desc) == 32)
+ {
+ uint32_t value = widened_value - (psaddr_t) 0;
+ memcpy (address, &value, sizeof value);
+ }
+ else if (DB_DESC_SIZE (desc) == 64)
+ {
+ uint64_t value = widened_value - (psaddr_t) 0;
+ if (sizeof (psaddr_t) < 8)
+ return TD_NOCAPAB;
+ memcpy (address, &value, sizeof value);
+ }
+ else if (DB_DESC_SIZE (desc) == bswap_32 (32))
+ {
+ uint32_t value = widened_value - (psaddr_t) 0;
+ value = bswap_32 (value);
+ memcpy (address, &value, sizeof value);
+ }
+ else if (DB_DESC_SIZE (desc) == bswap_32 (64))
+ {
+ uint64_t value = widened_value - (psaddr_t) 0;
+ if (sizeof (psaddr_t) < 8)
+ return TD_NOCAPAB;
+ value = bswap_64 (value);
+ memcpy (address, &value, sizeof value);
+ }
+ else
+ return TD_DBERR;
+
+ return TD_OK;
+}
diff --git a/libpthread/nptl_db/proc_service.h b/libpthread/nptl_db/proc_service.h
new file mode 100644
index 000000000..d49e87ab3
--- /dev/null
+++ b/libpthread/nptl_db/proc_service.h
@@ -0,0 +1,87 @@
+/* Callback interface for libthread_db, functions users must define.
+ Copyright (C) 1999,2002,2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/* The definitions in this file must correspond to those in the debugger. */
+#include <sys/procfs.h>
+
+/* Functions in this interface return one of these status codes. */
+typedef enum
+{
+ PS_OK, /* Generic "call succeeded". */
+ PS_ERR, /* Generic error. */
+ PS_BADPID, /* Bad process handle. */
+ PS_BADLID, /* Bad LWP identifier. */
+ PS_BADADDR, /* Bad address. */
+ PS_NOSYM, /* Could not find given symbol. */
+ PS_NOFREGS /* FPU register set not available for given LWP. */
+} ps_err_e;
+
+
+/* This type is opaque in this interface.
+ It's defined by the user of libthread_db. */
+struct ps_prochandle;
+
+
+/* Read or write process memory at the given address. */
+extern ps_err_e ps_pdread (struct ps_prochandle *,
+ psaddr_t, void *, size_t);
+extern ps_err_e ps_pdwrite (struct ps_prochandle *,
+ psaddr_t, const void *, size_t);
+extern ps_err_e ps_ptread (struct ps_prochandle *,
+ psaddr_t, void *, size_t);
+extern ps_err_e ps_ptwrite (struct ps_prochandle *,
+ psaddr_t, const void *, size_t);
+
+
+/* Get and set the given LWP's general or FPU register set. */
+extern ps_err_e ps_lgetregs (struct ps_prochandle *,
+ lwpid_t, prgregset_t);
+extern ps_err_e ps_lsetregs (struct ps_prochandle *,
+ lwpid_t, const prgregset_t);
+extern ps_err_e ps_lgetfpregs (struct ps_prochandle *,
+ lwpid_t, prfpregset_t *);
+extern ps_err_e ps_lsetfpregs (struct ps_prochandle *,
+ lwpid_t, const prfpregset_t *);
+
+/* Return the PID of the process. */
+extern pid_t ps_getpid (struct ps_prochandle *);
+
+/* Fetch the special per-thread address associated with the given LWP.
+ This call is only used on a few platforms (most use a normal register).
+ The meaning of the `int' parameter is machine-dependent. */
+extern ps_err_e ps_get_thread_area (const struct ps_prochandle *,
+ lwpid_t, int, psaddr_t *);
+
+
+/* Look up the named symbol in the named DSO in the symbol tables
+ associated with the process being debugged, filling in *SYM_ADDR
+ with the corresponding run-time address. */
+extern ps_err_e ps_pglobal_lookup (struct ps_prochandle *,
+ const char *object_name,
+ const char *sym_name,
+ psaddr_t *sym_addr);
+
+
+/* Stop or continue the entire process. */
+extern ps_err_e ps_pstop (const struct ps_prochandle *);
+extern ps_err_e ps_pcontinue (const struct ps_prochandle *);
+
+/* Stop or continue the given LWP alone. */
+extern ps_err_e ps_lstop (const struct ps_prochandle *, lwpid_t);
+extern ps_err_e ps_lcontinue (const struct ps_prochandle *, lwpid_t);
diff --git a/libpthread/nptl_db/structs.def b/libpthread/nptl_db/structs.def
new file mode 100644
index 000000000..823af5cba
--- /dev/null
+++ b/libpthread/nptl_db/structs.def
@@ -0,0 +1,88 @@
+/* List of types and symbols in libpthread examined by libthread_db.
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef DB_STRUCT_ARRAY_FIELD
+# define DB_STRUCT_ARRAY_FIELD(type, field) DB_STRUCT_FIELD (type, field)
+# define DB_ARRAY_VARIABLE(name) DB_VARIABLE (name)
+# define STRUCTS_DEF_DEFAULTS 1
+#endif
+
+DB_STRUCT (pthread)
+DB_STRUCT_FIELD (pthread, list)
+DB_STRUCT_FIELD (pthread, report_events)
+DB_STRUCT_FIELD (pthread, tid)
+DB_STRUCT_FIELD (pthread, start_routine)
+DB_STRUCT_FIELD (pthread, cancelhandling)
+DB_STRUCT_FIELD (pthread, schedpolicy)
+DB_STRUCT_FIELD (pthread, schedparam_sched_priority)
+DB_STRUCT_FIELD (pthread, specific)
+DB_STRUCT_FIELD (pthread, eventbuf)
+DB_STRUCT_FIELD (pthread, eventbuf_eventmask)
+DB_STRUCT_ARRAY_FIELD (pthread, eventbuf_eventmask_event_bits)
+DB_STRUCT_FIELD (pthread, nextevent)
+
+DB_STRUCT (list_t)
+DB_STRUCT_FIELD (list_t, next)
+DB_STRUCT_FIELD (list_t, prev)
+
+DB_STRUCT (td_thr_events_t)
+DB_STRUCT_ARRAY_FIELD (td_thr_events_t, event_bits)
+
+DB_STRUCT (td_eventbuf_t)
+DB_STRUCT_FIELD (td_eventbuf_t, eventnum)
+DB_STRUCT_FIELD (td_eventbuf_t, eventdata)
+
+DB_SYMBOL (stack_used)
+DB_SYMBOL (__stack_user)
+DB_SYMBOL (nptl_version)
+DB_FUNCTION (__nptl_create_event)
+DB_FUNCTION (__nptl_death_event)
+DB_SYMBOL (__nptl_threads_events)
+DB_VARIABLE (__nptl_nthreads)
+DB_VARIABLE (__nptl_last_event)
+
+DB_ARRAY_VARIABLE (__pthread_keys)
+DB_STRUCT (pthread_key_struct)
+DB_STRUCT_FIELD (pthread_key_struct, seq)
+DB_STRUCT_FIELD (pthread_key_struct, destr)
+
+DB_STRUCT (pthread_key_data)
+DB_STRUCT_FIELD (pthread_key_data, seq)
+DB_STRUCT_FIELD (pthread_key_data, data)
+DB_STRUCT (pthread_key_data_level2)
+DB_STRUCT_ARRAY_FIELD (pthread_key_data_level2, data)
+
+#if USE_TLS
+DB_STRUCT_FIELD (link_map, l_tls_modid)
+#endif
+
+#if !defined IS_IN_libpthread || USE_TLS
+DB_STRUCT_ARRAY_FIELD (dtv, dtv)
+# define pointer_val pointer.val /* Field of anonymous struct in dtv_t. */
+DB_STRUCT_FIELD (dtv_t, pointer_val)
+#endif
+#if !defined IS_IN_libpthread || TLS_TCB_AT_TP
+DB_STRUCT_FIELD (pthread, dtvp)
+#endif
+
+#ifdef STRUCTS_DEF_DEFAULTS
+# undef DB_STRUCT_ARRAY_FIELD
+# undef DB_ARRAY_VARIABLE
+# undef STRUCTS_DEF_DEFAULTS
+#endif
diff --git a/libpthread/nptl_db/td_init.c b/libpthread/nptl_db/td_init.c
new file mode 100644
index 000000000..946ff7244
--- /dev/null
+++ b/libpthread/nptl_db/td_init.c
@@ -0,0 +1,32 @@
+/* Initialization function of thread debugger support library.
+ Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include "thread_dbP.h"
+
+int __td_debug;
+
+
+td_err_e
+td_init (void)
+{
+ /* XXX We have to figure out what has to be done. */
+ LOG ("td_init");
+ return TD_OK;
+}
diff --git a/libpthread/nptl_db/td_log.c b/libpthread/nptl_db/td_log.c
new file mode 100644
index 000000000..52212a0e9
--- /dev/null
+++ b/libpthread/nptl_db/td_log.c
@@ -0,0 +1,32 @@
+/* Noop, left for historical reasons.
+ Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_log (void)
+{
+ /* This interface is deprecated in the Sun interface. We provide it
+ for compatibility but don't do anything ourself. We might in
+ future do some logging if this seems reasonable. */
+ LOG ("td_log");
+ return TD_OK;
+}
diff --git a/libpthread/nptl_db/td_symbol_list.c b/libpthread/nptl_db/td_symbol_list.c
new file mode 100644
index 000000000..04aed6787
--- /dev/null
+++ b/libpthread/nptl_db/td_symbol_list.c
@@ -0,0 +1,87 @@
+/* Return list of symbols the library can request.
+ Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <assert.h>
+#ifndef __UCLIBC__
+#include <gnu/lib-names.h>
+#endif
+#include "thread_dbP.h"
+
+
+#ifdef HAVE_ASM_GLOBAL_DOT_NAME
+# define DOT "." /* PPC64 requires . prefix on code symbols. */
+#else
+# define DOT /* No prefix. */
+#endif
+
+static const char *symbol_list_arr[] =
+{
+# define DB_STRUCT(type) \
+ [SYM_SIZEOF_##type] = "_thread_db_sizeof_" #type,
+# define DB_STRUCT_FIELD(type, field) \
+ [SYM_##type##_FIELD_##field] = "_thread_db_" #type "_" #field,
+# define DB_SYMBOL(name) \
+ [SYM_##name] = #name,
+# define DB_FUNCTION(name) \
+ [SYM_##name] = DOT #name,
+# define DB_VARIABLE(name) \
+ [SYM_##name] = #name, \
+ [SYM_DESC_##name] = "_thread_db_" #name,
+# include "structs.def"
+# undef DB_STRUCT
+# undef DB_FUNCTION
+# undef DB_SYMBOL
+# undef DB_VARIABLE
+
+ [SYM_TH_UNIQUE_CONST_THREAD_AREA] = "_thread_db_const_thread_area",
+ [SYM_TH_UNIQUE_REGISTER64] = "_thread_db_register64",
+ [SYM_TH_UNIQUE_REGISTER32] = "_thread_db_register32",
+ [SYM_TH_UNIQUE_REGISTER32_THREAD_AREA] = "_thread_db_register32_thread_area",
+ [SYM_TH_UNIQUE_REGISTER64_THREAD_AREA] = "_thread_db_register64_thread_area",
+
+ [SYM_NUM_MESSAGES] = NULL
+};
+
+
+const char **
+td_symbol_list (void)
+{
+ return symbol_list_arr;
+}
+
+
+ps_err_e
+td_lookup (struct ps_prochandle *ps, int idx, psaddr_t *sym_addr)
+{
+ ps_err_e result;
+ assert (idx >= 0 && idx < SYM_NUM_MESSAGES);
+ result = ps_pglobal_lookup (ps, LIBPTHREAD_SO, symbol_list_arr[idx],
+ sym_addr);
+
+#ifdef HAVE_ASM_GLOBAL_DOT_NAME
+ /* For PowerPC, 64-bit uses dot symbols but 32-bit does not.
+ We could be a 64-bit libthread_db debugging a 32-bit libpthread. */
+ if (result == PS_NOSYM && symbol_list_arr[idx][0] == '.')
+ result = ps_pglobal_lookup (ps, LIBPTHREAD_SO, &symbol_list_arr[idx][1],
+ sym_addr);
+#endif
+
+ return result;
+}
diff --git a/libpthread/nptl_db/td_ta_clear_event.c b/libpthread/nptl_db/td_ta_clear_event.c
new file mode 100644
index 000000000..7a2850c4e
--- /dev/null
+++ b/libpthread/nptl_db/td_ta_clear_event.c
@@ -0,0 +1,79 @@
+/* Globally disable events.
+ Copyright (C) 1999, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_ta_clear_event (ta_arg, event)
+ const td_thragent_t *ta_arg;
+ td_thr_events_t *event;
+{
+ td_thragent_t *const ta = (td_thragent_t *) ta_arg;
+ td_err_e err;
+ psaddr_t eventmask = 0;
+ void *copy = NULL;
+
+ LOG ("td_ta_clear_event");
+
+ /* Test whether the TA parameter is ok. */
+ if (! ta_ok (ta))
+ return TD_BADTA;
+
+ /* Fetch the old event mask from the inferior and modify it in place. */
+ err = DB_GET_SYMBOL (eventmask, ta, __nptl_threads_events);
+ if (err == TD_OK)
+ err = DB_GET_STRUCT (copy, ta, eventmask, td_thr_events_t);
+ if (err == TD_OK)
+ {
+ uint32_t idx;
+ for (idx = 0; idx < TD_EVENTSIZE; ++idx)
+ {
+ psaddr_t word;
+ uint32_t mask;
+ err = DB_GET_FIELD_LOCAL (word, ta, copy,
+ td_thr_events_t, event_bits, idx);
+ if (err != TD_OK)
+ break;
+ mask = (uintptr_t) word;
+ mask &= ~event->event_bits[idx];
+ word = (psaddr_t) (uintptr_t) mask;
+ err = DB_PUT_FIELD_LOCAL (ta, copy,
+ td_thr_events_t, event_bits, idx, word);
+ if (err != TD_OK)
+ break;
+ }
+ if (err == TD_NOAPLIC)
+ {
+ err = TD_OK;
+ while (idx < TD_EVENTSIZE)
+ if (event->event_bits[idx++] != 0)
+ {
+ err = TD_NOEVENT;
+ break;
+ }
+ }
+ if (err == TD_OK)
+ /* Now write it back to the inferior. */
+ err = DB_PUT_STRUCT (ta, eventmask, td_thr_events_t, copy);
+ }
+
+ return err;
+}
diff --git a/libpthread/nptl_db/td_ta_delete.c b/libpthread/nptl_db/td_ta_delete.c
new file mode 100644
index 000000000..57b90e57f
--- /dev/null
+++ b/libpthread/nptl_db/td_ta_delete.c
@@ -0,0 +1,42 @@
+/* Detach to target process.
+ Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <stdlib.h>
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_ta_delete (td_thragent_t *ta)
+{
+ LOG ("td_ta_delete");
+
+ /* Safety check. Note that the test will also fail for TA == NULL. */
+ if (!ta_ok (ta))
+ return TD_BADTA;
+
+ /* Remove the handle from the list. */
+ list_del (&ta->list);
+
+ /* The handle was allocated in `td_ta_new'. */
+ free (ta);
+
+ return TD_OK;
+}
diff --git a/libpthread/nptl_db/td_ta_enable_stats.c b/libpthread/nptl_db/td_ta_enable_stats.c
new file mode 100644
index 000000000..ec7014ad2
--- /dev/null
+++ b/libpthread/nptl_db/td_ta_enable_stats.c
@@ -0,0 +1,35 @@
+/* Enable collection of statistics for process.
+ Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_ta_enable_stats (const td_thragent_t *ta, int enable)
+{
+ /* XXX We have to figure out what has to be done. */
+ LOG ("td_ta_enable_stats");
+
+ /* Test whether the TA parameter is ok. */
+ if (! ta_ok (ta))
+ return TD_BADTA;
+
+ return TD_OK;
+}
diff --git a/libpthread/nptl_db/td_ta_event_addr.c b/libpthread/nptl_db/td_ta_event_addr.c
new file mode 100644
index 000000000..45c6b113d
--- /dev/null
+++ b/libpthread/nptl_db/td_ta_event_addr.c
@@ -0,0 +1,61 @@
+/* Get event address.
+ Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_ta_event_addr (const td_thragent_t *ta_arg,
+ td_event_e event, td_notify_t *addr)
+{
+ td_thragent_t *const ta = (td_thragent_t *) ta_arg;
+ td_err_e err;
+ psaddr_t taddr = NULL;
+
+ LOG ("td_ta_event_addr");
+
+ /* Test whether the TA parameter is ok. */
+ if (! ta_ok (ta))
+ return TD_BADTA;
+
+ switch (event)
+ {
+ case TD_CREATE:
+ err = DB_GET_SYMBOL (taddr, ta, __nptl_create_event);
+ break;
+
+ case TD_DEATH:
+ err = DB_GET_SYMBOL (taddr, ta, __nptl_death_event);
+ break;
+
+ default:
+ /* Event cannot be handled. */
+ return TD_NOEVENT;
+ }
+
+ if (err == TD_OK)
+ {
+ /* Success, we got the address. */
+ addr->type = NOTIFY_BPT;
+ addr->u.bptaddr = taddr;
+ }
+
+ return err;
+}
diff --git a/libpthread/nptl_db/td_ta_event_getmsg.c b/libpthread/nptl_db/td_ta_event_getmsg.c
new file mode 100644
index 000000000..d3b46bd56
--- /dev/null
+++ b/libpthread/nptl_db/td_ta_event_getmsg.c
@@ -0,0 +1,105 @@
+/* Retrieve event.
+ Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <stddef.h>
+#include <string.h>
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_ta_event_getmsg (const td_thragent_t *ta_arg, td_event_msg_t *msg)
+{
+ td_thragent_t *const ta = (td_thragent_t *) ta_arg;
+ td_err_e err;
+ psaddr_t eventbuf, eventnum, eventdata;
+ psaddr_t thp, next;
+ void *copy = NULL;
+
+ /* XXX I cannot think of another way but using a static variable. */
+ /* XXX Use at least __thread once it is possible. */
+ static td_thrhandle_t th;
+
+ LOG ("td_thr_event_getmsg");
+
+ /* Test whether the TA parameter is ok. */
+ if (! ta_ok (ta))
+ return TD_BADTA;
+
+ /* Get the pointer to the thread descriptor with the last event. */
+ err = DB_GET_VALUE (thp, ta, __nptl_last_event, 0);
+ if (err != TD_OK)
+ return err;
+
+ if (thp == 0)
+ /* Nothing waiting. */
+ return TD_NOMSG;
+
+ /* Copy the event message buffer in from the inferior. */
+ err = DB_GET_FIELD_ADDRESS (eventbuf, ta, thp, pthread, eventbuf, 0);
+ if (err == TD_OK)
+ err = DB_GET_STRUCT (copy, ta, eventbuf, td_eventbuf_t);
+ if (err != TD_OK)
+ return err;
+
+ /* Read the event details from the target thread. */
+ err = DB_GET_FIELD_LOCAL (eventnum, ta, copy, td_eventbuf_t, eventnum, 0);
+ if (err != TD_OK)
+ return err;
+ /* If the structure is on the list there better be an event recorded. */
+ if ((int) (uintptr_t) eventnum == TD_EVENT_NONE)
+ return TD_DBERR;
+
+ /* Fill the user's data structure. */
+ err = DB_GET_FIELD_LOCAL (eventdata, ta, copy, td_eventbuf_t, eventdata, 0);
+ if (err != TD_OK)
+ return err;
+
+ /* Generate the thread descriptor. */
+ th.th_ta_p = (td_thragent_t *) ta;
+ th.th_unique = thp;
+
+ /* Fill the user's data structure. */
+ msg->msg.data = (uintptr_t) eventdata;
+ msg->event = (uintptr_t) eventnum;
+ msg->th_p = &th;
+
+ /* And clear the event message in the target. */
+ memset (copy, 0, ta->ta_sizeof_td_eventbuf_t);
+ err = DB_PUT_STRUCT (ta, eventbuf, td_eventbuf_t, copy);
+ if (err != TD_OK)
+ return err;
+
+ /* Get the pointer to the next descriptor with an event. */
+ err = DB_GET_FIELD (next, ta, thp, pthread, nextevent, 0);
+ if (err != TD_OK)
+ return err;
+
+ /* Store the pointer in the list head variable. */
+ err = DB_PUT_VALUE (ta, __nptl_last_event, 0, next);
+ if (err != TD_OK)
+ return err;
+
+ if (next != 0)
+ /* Clear the next pointer in the current descriptor. */
+ err = DB_PUT_FIELD (ta, thp, pthread, nextevent, 0, 0);
+
+ return err;
+}
diff --git a/libpthread/nptl_db/td_ta_get_nthreads.c b/libpthread/nptl_db/td_ta_get_nthreads.c
new file mode 100644
index 000000000..ffe78bd57
--- /dev/null
+++ b/libpthread/nptl_db/td_ta_get_nthreads.c
@@ -0,0 +1,42 @@
+/* Get the number of threads in the process.
+ Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include "thread_dbP.h"
+
+td_err_e
+td_ta_get_nthreads (const td_thragent_t *ta_arg, int *np)
+{
+ td_thragent_t *const ta = (td_thragent_t *) ta_arg;
+ td_err_e err;
+ psaddr_t n;
+
+ LOG ("td_ta_get_nthreads");
+
+ /* Test whether the TA parameter is ok. */
+ if (! ta_ok (ta))
+ return TD_BADTA;
+
+ /* Access the variable in the inferior that tells us. */
+ err = DB_GET_VALUE (n, ta, __nptl_nthreads, 0);
+ if (err == TD_OK)
+ *np = (uintptr_t) n;
+
+ return err;
+}
diff --git a/libpthread/nptl_db/td_ta_get_ph.c b/libpthread/nptl_db/td_ta_get_ph.c
new file mode 100644
index 000000000..04e01fb73
--- /dev/null
+++ b/libpthread/nptl_db/td_ta_get_ph.c
@@ -0,0 +1,36 @@
+/* Get external process handle.
+ Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_ta_get_ph (const td_thragent_t *ta, struct ps_prochandle **ph)
+{
+ LOG ("td_ta_get_ph");
+
+ /* Test whether the TA parameter is ok. */
+ if (! ta_ok (ta))
+ return TD_BADTA;
+
+ *ph = ta->ph;
+
+ return TD_OK;
+}
diff --git a/libpthread/nptl_db/td_ta_get_stats.c b/libpthread/nptl_db/td_ta_get_stats.c
new file mode 100644
index 000000000..d5d879c3e
--- /dev/null
+++ b/libpthread/nptl_db/td_ta_get_stats.c
@@ -0,0 +1,35 @@
+/* Retrieve statistics for process.
+ Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_ta_get_stats (const td_thragent_t *ta, td_ta_stats_t *statsp)
+{
+ /* XXX We have to figure out what has to be done. */
+ LOG ("td_ta_get_stats");
+
+ /* Test whether the TA parameter is ok. */
+ if (! ta_ok (ta))
+ return TD_BADTA;
+
+ return TD_OK;
+}
diff --git a/libpthread/nptl_db/td_ta_map_id2thr.c b/libpthread/nptl_db/td_ta_map_id2thr.c
new file mode 100644
index 000000000..189a67171
--- /dev/null
+++ b/libpthread/nptl_db/td_ta_map_id2thr.c
@@ -0,0 +1,38 @@
+/* Map thread ID to thread handle.
+ Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_ta_map_id2thr (const td_thragent_t *ta, pthread_t pt, td_thrhandle_t *th)
+{
+ LOG ("td_ta_map_id2thr");
+
+ /* Test whether the TA parameter is ok. */
+ if (! ta_ok (ta))
+ return TD_BADTA;
+
+ /* Create the `td_thrhandle_t' object. */
+ th->th_ta_p = (td_thragent_t *) ta;
+ th->th_unique = (psaddr_t) pt;
+
+ return TD_OK;
+}
diff --git a/libpthread/nptl_db/td_ta_map_lwp2thr.c b/libpthread/nptl_db/td_ta_map_lwp2thr.c
new file mode 100644
index 000000000..1e93210b9
--- /dev/null
+++ b/libpthread/nptl_db/td_ta_map_lwp2thr.c
@@ -0,0 +1,178 @@
+/* Which thread is running on an LWP?
+ Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include "thread_dbP.h"
+#include <stdlib.h>
+#include <byteswap.h>
+#include <sys/procfs.h>
+
+
+td_err_e
+td_ta_map_lwp2thr (const td_thragent_t *ta_arg,
+ lwpid_t lwpid, td_thrhandle_t *th)
+{
+ td_thragent_t *const ta = (td_thragent_t *) ta_arg;
+ ps_err_e err;
+ td_err_e terr;
+ prgregset_t regs;
+ psaddr_t addr;
+
+ LOG ("td_ta_map_lwp2thr");
+
+ /* Test whether the TA parameter is ok. */
+ if (! ta_ok (ta))
+ return TD_BADTA;
+
+ if (ta->ta_howto == ta_howto_unknown)
+ {
+ /* We need to read in from the inferior the instructions what to do. */
+ psaddr_t howto;
+
+ err = td_lookup (ta->ph, SYM_TH_UNIQUE_CONST_THREAD_AREA, &howto);
+ if (err == PS_OK)
+ {
+ err = ps_pdread (ta->ph, howto,
+ &ta->ta_howto_data.const_thread_area,
+ sizeof ta->ta_howto_data.const_thread_area);
+ if (err != PS_OK)
+ return TD_ERR;
+ ta->ta_howto = ta_howto_const_thread_area;
+ if (ta->ta_howto_data.const_thread_area & 0xff000000U)
+ ta->ta_howto_data.const_thread_area
+ = bswap_32 (ta->ta_howto_data.const_thread_area);
+ }
+ else
+ {
+ switch (sizeof (regs[0]))
+ {
+ case 8:
+ err = td_lookup (ta->ph, SYM_TH_UNIQUE_REGISTER64, &howto);
+ if (err == PS_OK)
+ ta->ta_howto = ta_howto_reg;
+ else if (err == PS_NOSYM)
+ {
+ err = td_lookup (ta->ph,
+ SYM_TH_UNIQUE_REGISTER64_THREAD_AREA,
+ &howto);
+ if (err == PS_OK)
+ ta->ta_howto = ta_howto_reg_thread_area;
+ }
+ break;
+
+ case 4:
+ err = td_lookup (ta->ph, SYM_TH_UNIQUE_REGISTER32, &howto);
+ if (err == PS_OK)
+ ta->ta_howto = ta_howto_reg;
+ else if (err == PS_NOSYM)
+ {
+ err = td_lookup (ta->ph,
+ SYM_TH_UNIQUE_REGISTER32_THREAD_AREA,
+ &howto);
+ if (err == PS_OK)
+ ta->ta_howto = ta_howto_reg_thread_area;
+ }
+ break;
+
+ default:
+ abort ();
+ return TD_DBERR;
+ }
+
+ if (err != PS_OK)
+ return TD_DBERR;
+
+ /* For either of these methods we read in the same descriptor. */
+ err = ps_pdread (ta->ph, howto,
+ ta->ta_howto_data.reg, DB_SIZEOF_DESC);
+ if (err != PS_OK)
+ return TD_ERR;
+ if (DB_DESC_SIZE (ta->ta_howto_data.reg) == 0)
+ return TD_DBERR;
+ if (DB_DESC_SIZE (ta->ta_howto_data.reg) & 0xff000000U)
+ {
+ /* Byte-swap these words, though we leave the size word
+ in native order as the handy way to distinguish. */
+ DB_DESC_OFFSET (ta->ta_howto_data.reg)
+ = bswap_32 (DB_DESC_OFFSET (ta->ta_howto_data.reg));
+ DB_DESC_NELEM (ta->ta_howto_data.reg)
+ = bswap_32 (DB_DESC_NELEM (ta->ta_howto_data.reg));
+ }
+ }
+ }
+
+ switch (ta->ta_howto)
+ {
+ case ta_howto_unknown:
+ return TD_DBERR;
+
+ default:
+ return TD_DBERR;
+
+ case ta_howto_reg:
+ /* On most machines, we are just looking at a register. */
+ if (ps_lgetregs (ta->ph, lwpid, regs) != PS_OK)
+ return TD_ERR;
+ terr = _td_fetch_value_local (ta, ta->ta_howto_data.reg, -1,
+ 0, regs, &addr);
+ if (terr != TD_OK)
+ return terr;
+ /* In this descriptor the nelem word is overloaded as the bias. */
+ addr += (int32_t) DB_DESC_NELEM (ta->ta_howto_data.reg);
+ th->th_unique = addr;
+ break;
+
+ case ta_howto_const_thread_area:
+ /* Some hosts don't have this call and this case won't be used. */
+# pragma weak ps_get_thread_area
+ if (&ps_get_thread_area == NULL)
+ return TD_NOCAPAB;
+
+ /* A la x86-64, there is a constant magic index for get_thread_area. */
+ if (ps_get_thread_area (ta->ph, lwpid,
+ ta->ta_howto_data.const_thread_area,
+ &th->th_unique) != PS_OK)
+ return TD_ERR; /* XXX Other error value? */
+ break;
+
+ case ta_howto_reg_thread_area:
+ if (&ps_get_thread_area == NULL)
+ return TD_NOCAPAB;
+
+ /* A la i386, there is a register with an index for get_thread_area. */
+ if (ps_lgetregs (ta->ph, lwpid, regs) != PS_OK)
+ return TD_ERR;
+ terr = _td_fetch_value_local (ta, ta->ta_howto_data.reg_thread_area, -1,
+ 0, regs, &addr);
+ if (terr != TD_OK)
+ return terr;
+ /* In this descriptor the nelem word is overloaded as scale factor. */
+ if (ps_get_thread_area
+ (ta->ph, lwpid,
+ ((addr - (psaddr_t) 0)
+ >> DB_DESC_NELEM (ta->ta_howto_data.reg_thread_area)),
+ &th->th_unique) != PS_OK)
+ return TD_ERR; /* XXX Other error value? */
+ break;
+ }
+
+ /* Found it. Now complete the `td_thrhandle_t' object. */
+ th->th_ta_p = (td_thragent_t *) ta;
+
+ return TD_OK;
+}
diff --git a/libpthread/nptl_db/td_ta_new.c b/libpthread/nptl_db/td_ta_new.c
new file mode 100644
index 000000000..f84049af3
--- /dev/null
+++ b/libpthread/nptl_db/td_ta_new.c
@@ -0,0 +1,65 @@
+/* Attach to target process.
+ Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <version.h>
+
+#include "thread_dbP.h"
+
+
+/* Datatype for the list of known thread agents. Normally there will
+ be exactly one so we don't spend much though on making it fast. */
+LIST_HEAD (__td_agent_list);
+
+
+td_err_e
+td_ta_new (struct ps_prochandle *ps, td_thragent_t **ta)
+{
+ psaddr_t versaddr;
+ char versbuf[sizeof (VERSION)];
+
+ LOG ("td_ta_new");
+
+ /* Check whether the versions match. */
+ if (td_lookup (ps, SYM_nptl_version, &versaddr) != PS_OK)
+ return TD_NOLIBTHREAD;
+ if (ps_pdread (ps, versaddr, versbuf, sizeof (versbuf)) != PS_OK)
+ return TD_ERR;
+
+ if (memcmp (versbuf, VERSION, sizeof VERSION) != 0)
+ /* Not the right version. */
+ return TD_VERSION;
+
+ /* Fill in the appropriate information. */
+ *ta = (td_thragent_t *) calloc (1, sizeof (td_thragent_t));
+ if (*ta == NULL)
+ return TD_MALLOC;
+
+ /* Store the proc handle which we will pass to the callback functions
+ back into the debugger. */
+ (*ta)->ph = ps;
+
+ /* Now add the new agent descriptor to the list. */
+ list_add (&(*ta)->list, &__td_agent_list);
+
+ return TD_OK;
+}
diff --git a/libpthread/nptl_db/td_ta_reset_stats.c b/libpthread/nptl_db/td_ta_reset_stats.c
new file mode 100644
index 000000000..ea59d2cda
--- /dev/null
+++ b/libpthread/nptl_db/td_ta_reset_stats.c
@@ -0,0 +1,35 @@
+/* Reset statistics.
+ Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_ta_reset_stats (const td_thragent_t *ta)
+{
+ /* XXX We have to figure out what has to be done. */
+ LOG ("td_ta_reset_stats");
+
+ /* Test whether the TA parameter is ok. */
+ if (! ta_ok (ta))
+ return TD_BADTA;
+
+ return TD_OK;
+}
diff --git a/libpthread/nptl_db/td_ta_set_event.c b/libpthread/nptl_db/td_ta_set_event.c
new file mode 100644
index 000000000..29fc14bfb
--- /dev/null
+++ b/libpthread/nptl_db/td_ta_set_event.c
@@ -0,0 +1,79 @@
+/* Globally enable events.
+ Copyright (C) 1999,2001,2002,2003,2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_ta_set_event (ta_arg, event)
+ const td_thragent_t *ta_arg;
+ td_thr_events_t *event;
+{
+ td_thragent_t *const ta = (td_thragent_t *) ta_arg;
+ td_err_e err;
+ psaddr_t eventmask = 0;
+ void *copy = NULL;
+
+ LOG ("td_ta_set_event");
+
+ /* Test whether the TA parameter is ok. */
+ if (! ta_ok (ta))
+ return TD_BADTA;
+
+ /* Fetch the old event mask from the inferior and modify it in place. */
+ err = DB_GET_SYMBOL (eventmask, ta, __nptl_threads_events);
+ if (err == TD_OK)
+ err = DB_GET_STRUCT (copy, ta, eventmask, td_thr_events_t);
+ if (err == TD_OK)
+ {
+ uint32_t idx;
+ for (idx = 0; idx < TD_EVENTSIZE; ++idx)
+ {
+ psaddr_t word;
+ uint32_t mask;
+ err = DB_GET_FIELD_LOCAL (word, ta, copy,
+ td_thr_events_t, event_bits, idx);
+ if (err != TD_OK)
+ break;
+ mask = (uintptr_t) word;
+ mask |= event->event_bits[idx];
+ word = (psaddr_t) (uintptr_t) mask;
+ err = DB_PUT_FIELD_LOCAL (ta, copy,
+ td_thr_events_t, event_bits, idx, word);
+ if (err != TD_OK)
+ break;
+ }
+ if (err == TD_NOAPLIC)
+ {
+ err = TD_OK;
+ while (idx < TD_EVENTSIZE)
+ if (event->event_bits[idx++] != 0)
+ {
+ err = TD_NOEVENT;
+ break;
+ }
+ }
+ if (err == TD_OK)
+ /* Now write it back to the inferior. */
+ err = DB_PUT_STRUCT (ta, eventmask, td_thr_events_t, copy);
+ }
+
+ return err;
+}
diff --git a/libpthread/nptl_db/td_ta_setconcurrency.c b/libpthread/nptl_db/td_ta_setconcurrency.c
new file mode 100644
index 000000000..8552ffbe0
--- /dev/null
+++ b/libpthread/nptl_db/td_ta_setconcurrency.c
@@ -0,0 +1,35 @@
+/* Set suggested concurrency level for process.
+ Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_ta_setconcurrency (const td_thragent_t *ta, int level)
+{
+ /* This is something LinuxThreads does not need to support. */
+ LOG ("td_ta_setconcurrency");
+
+ /* Test whether the TA parameter is ok. */
+ if (! ta_ok (ta))
+ return TD_BADTA;
+
+ return TD_NOCAPAB;
+}
diff --git a/libpthread/nptl_db/td_ta_thr_iter.c b/libpthread/nptl_db/td_ta_thr_iter.c
new file mode 100644
index 000000000..66e437665
--- /dev/null
+++ b/libpthread/nptl_db/td_ta_thr_iter.c
@@ -0,0 +1,148 @@
+/* Iterate over a process's threads.
+ Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include "thread_dbP.h"
+
+
+static td_err_e
+iterate_thread_list (td_thragent_t *ta, td_thr_iter_f *callback,
+ void *cbdata_p, td_thr_state_e state, int ti_pri,
+ psaddr_t head, int fake_empty)
+{
+ td_err_e err;
+ psaddr_t next, ofs;
+ void *copy;
+
+ /* Test the state.
+ XXX This is incomplete. Normally this test should be in the loop. */
+ if (state != TD_THR_ANY_STATE)
+ return TD_OK;
+
+ err = DB_GET_FIELD (next, ta, head, list_t, next, 0);
+ if (err != TD_OK)
+ return err;
+
+ if (next == 0 && fake_empty)
+ {
+ /* __pthread_initialize_minimal has not run.
+ There is just the main thread to return. */
+ td_thrhandle_t th;
+ err = td_ta_map_lwp2thr (ta, ps_getpid (ta->ph), &th);
+ if (err == TD_OK)
+ err = callback (&th, cbdata_p) != 0 ? TD_DBERR : TD_OK;
+ return err;
+ }
+
+ /* Cache the offset from struct pthread to its list_t member. */
+ err = DB_GET_FIELD_ADDRESS (ofs, ta, 0, pthread, list, 0);
+ if (err != TD_OK)
+ return err;
+
+ if (ta->ta_sizeof_pthread == 0)
+ {
+ err = _td_check_sizeof (ta, &ta->ta_sizeof_pthread, SYM_SIZEOF_pthread);
+ if (err != TD_OK)
+ return err;
+ }
+ copy = __alloca (ta->ta_sizeof_pthread);
+
+ while (next != head)
+ {
+ psaddr_t addr, schedpolicy, schedprio;
+
+ addr = next - (ofs - (psaddr_t) 0);
+ if (next == 0 || addr == 0) /* Sanity check. */
+ return TD_DBERR;
+
+ /* Copy the whole descriptor in once so we can access the several
+ fields locally. Excess copying in one go is much better than
+ multiple ps_pdread calls. */
+ if (ps_pdread (ta->ph, addr, copy, ta->ta_sizeof_pthread) != PS_OK)
+ return TD_ERR;
+
+ err = DB_GET_FIELD_LOCAL (schedpolicy, ta, copy, pthread,
+ schedpolicy, 0);
+ if (err != TD_OK)
+ break;
+ err = DB_GET_FIELD_LOCAL (schedprio, ta, copy, pthread,
+ schedparam_sched_priority, 0);
+ if (err != TD_OK)
+ break;
+
+ /* Now test whether this thread matches the specified conditions. */
+
+ /* Only if the priority level is as high or higher. */
+ int descr_pri = ((uintptr_t) schedpolicy == SCHED_OTHER
+ ? 0 : (uintptr_t) schedprio);
+ if (descr_pri >= ti_pri)
+ {
+ /* Yep, it matches. Call the callback function. */
+ td_thrhandle_t th;
+ th.th_ta_p = (td_thragent_t *) ta;
+ th.th_unique = addr;
+ if (callback (&th, cbdata_p) != 0)
+ return TD_DBERR;
+ }
+
+ /* Get the pointer to the next element. */
+ err = DB_GET_FIELD_LOCAL (next, ta, copy + (ofs - (psaddr_t) 0), list_t,
+ next, 0);
+ if (err != TD_OK)
+ break;
+ }
+
+ return err;
+}
+
+
+td_err_e
+td_ta_thr_iter (const td_thragent_t *ta_arg, td_thr_iter_f *callback,
+ void *cbdata_p, td_thr_state_e state, int ti_pri,
+ sigset_t *ti_sigmask_p, unsigned int ti_user_flags)
+{
+ td_thragent_t *const ta = (td_thragent_t *) ta_arg;
+ td_err_e err;
+ psaddr_t list = 0;
+
+ LOG ("td_ta_thr_iter");
+
+ /* Test whether the TA parameter is ok. */
+ if (! ta_ok (ta))
+ return TD_BADTA;
+
+ /* The thread library keeps two lists for the running threads. One
+ list contains the thread which are using user-provided stacks
+ (this includes the main thread) and the other includes the
+ threads for which the thread library allocated the stacks. We
+ have to iterate over both lists separately. We start with the
+ list of threads with user-defined stacks. */
+
+ err = DB_GET_SYMBOL (list, ta, __stack_user);
+ if (err == TD_OK)
+ err = iterate_thread_list (ta, callback, cbdata_p, state, ti_pri, list, 1);
+
+ /* And the threads with stacks allocated by the implementation. */
+ if (err == TD_OK)
+ err = DB_GET_SYMBOL (list, ta, stack_used);
+ if (err == TD_OK)
+ err = iterate_thread_list (ta, callback, cbdata_p, state, ti_pri, list, 0);
+
+ return err;
+}
diff --git a/libpthread/nptl_db/td_ta_tsd_iter.c b/libpthread/nptl_db/td_ta_tsd_iter.c
new file mode 100644
index 000000000..9cfb1e8de
--- /dev/null
+++ b/libpthread/nptl_db/td_ta_tsd_iter.c
@@ -0,0 +1,81 @@
+/* Iterate over a process's thread-specific data.
+ Copyright (C) 1999,2000,2001,2002,2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include "thread_dbP.h"
+#include <alloca.h>
+
+td_err_e
+td_ta_tsd_iter (const td_thragent_t *ta_arg, td_key_iter_f *callback,
+ void *cbdata_p)
+{
+ td_thragent_t *const ta = (td_thragent_t *) ta_arg;
+ td_err_e err;
+ void *keys;
+ size_t keys_nb, keys_elemsize;
+ psaddr_t addr;
+ uint32_t idx;
+
+ LOG ("td_ta_tsd_iter");
+
+ /* Test whether the TA parameter is ok. */
+ if (! ta_ok (ta))
+ return TD_BADTA;
+
+ /* This makes sure we have the size information on hand. */
+ addr = 0;
+ err = _td_locate_field (ta,
+ ta->ta_var___pthread_keys, SYM_DESC___pthread_keys,
+ (psaddr_t) 0 + 1, &addr);
+ if (err != TD_OK)
+ return err;
+
+ /* Now copy in the entire array of key descriptors. */
+ keys_elemsize = (addr - (psaddr_t) 0) / 8;
+ keys_nb = keys_elemsize * DB_DESC_NELEM (ta->ta_var___pthread_keys);
+ keys = __alloca (keys_nb);
+ err = DB_GET_SYMBOL (addr, ta, __pthread_keys);
+ if (err != TD_OK)
+ return err;
+ if (ps_pdread (ta->ph, addr, keys, keys_nb) != PS_OK)
+ return TD_ERR;
+
+ /* Now get all descriptors, one after the other. */
+ for (idx = 0; idx < DB_DESC_NELEM (ta->ta_var___pthread_keys); ++idx)
+ {
+ psaddr_t seq, destr;
+ err = DB_GET_FIELD_LOCAL (seq, ta, keys, pthread_key_struct, seq, 0);
+ if (err != TD_OK)
+ return err;
+ if (((uintptr_t) seq) & 1)
+ {
+ err = DB_GET_FIELD_LOCAL (destr, ta, keys, pthread_key_struct,
+ destr, 0);
+ if (err != TD_OK)
+ return err;
+ /* Return with an error if the callback returns a nonzero value. */
+ if (callback ((thread_key_t) idx, destr, cbdata_p) != 0)
+ return TD_DBERR;
+ }
+ /* Advance to the next element in the copied array. */
+ keys += keys_elemsize;
+ }
+
+ return TD_OK;
+}
diff --git a/libpthread/nptl_db/td_thr_clear_event.c b/libpthread/nptl_db/td_thr_clear_event.c
new file mode 100644
index 000000000..c43c625a4
--- /dev/null
+++ b/libpthread/nptl_db/td_thr_clear_event.c
@@ -0,0 +1,77 @@
+/* Disable specific event for thread.
+ Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <stddef.h>
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_thr_clear_event (th, event)
+ const td_thrhandle_t *th;
+ td_thr_events_t *event;
+{
+ td_err_e err;
+ psaddr_t eventmask;
+ void *copy = NULL;
+
+ LOG ("td_thr_clear_event");
+
+ /* Fetch the old event mask from the inferior and modify it in place. */
+ err = DB_GET_FIELD_ADDRESS (eventmask, th->th_ta_p,
+ th->th_unique, pthread, eventbuf_eventmask, 0);
+ if (err == TD_OK)
+ err = DB_GET_STRUCT (copy, th->th_ta_p, eventmask, td_thr_events_t);
+ if (err == TD_OK)
+ {
+ uint32_t idx;
+ for (idx = 0; idx < TD_EVENTSIZE; ++idx)
+ {
+ psaddr_t word;
+ uint32_t mask;
+ err = DB_GET_FIELD_LOCAL (word, th->th_ta_p, copy,
+ td_thr_events_t, event_bits, idx);
+ if (err != TD_OK)
+ break;
+ mask = (uintptr_t) word;
+ mask &= ~event->event_bits[idx];
+ word = (psaddr_t) (uintptr_t) mask;
+ err = DB_PUT_FIELD_LOCAL (th->th_ta_p, copy,
+ td_thr_events_t, event_bits, idx, word);
+ if (err != TD_OK)
+ break;
+ }
+ if (err == TD_NOAPLIC)
+ {
+ err = TD_OK;
+ while (idx < TD_EVENTSIZE)
+ if (event->event_bits[idx++] != 0)
+ {
+ err = TD_NOEVENT;
+ break;
+ }
+ }
+ if (err == TD_OK)
+ /* Now write it back to the inferior. */
+ err = DB_PUT_STRUCT (th->th_ta_p, eventmask, td_thr_events_t, copy);
+ }
+
+ return err;
+}
diff --git a/libpthread/nptl_db/td_thr_dbresume.c b/libpthread/nptl_db/td_thr_dbresume.c
new file mode 100644
index 000000000..3fd794377
--- /dev/null
+++ b/libpthread/nptl_db/td_thr_dbresume.c
@@ -0,0 +1,30 @@
+/* Resume execution of given thread.
+ Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_thr_dbresume (const td_thrhandle_t *th)
+{
+ /* XXX We have to figure out what has to be done. */
+ LOG ("td_thr_dbresume");
+ return TD_NOCAPAB;
+}
diff --git a/libpthread/nptl_db/td_thr_dbsuspend.c b/libpthread/nptl_db/td_thr_dbsuspend.c
new file mode 100644
index 000000000..6ef82ad34
--- /dev/null
+++ b/libpthread/nptl_db/td_thr_dbsuspend.c
@@ -0,0 +1,30 @@
+/* Suspend execution of given thread.
+ Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_thr_dbsuspend (const td_thrhandle_t *th)
+{
+ /* XXX We have to figure out what has to be done. */
+ LOG ("td_thr_dbsuspend");
+ return TD_NOCAPAB;
+}
diff --git a/libpthread/nptl_db/td_thr_event_enable.c b/libpthread/nptl_db/td_thr_event_enable.c
new file mode 100644
index 000000000..a02be5da4
--- /dev/null
+++ b/libpthread/nptl_db/td_thr_event_enable.c
@@ -0,0 +1,34 @@
+/* Enable event process-wide.
+ Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_thr_event_enable (th, onoff)
+ const td_thrhandle_t *th;
+ int onoff;
+{
+ LOG ("td_thr_event_enable");
+
+ /* Write the new value into the thread data structure. */
+ return DB_PUT_FIELD (th->th_ta_p, th->th_unique, pthread, report_events, 0,
+ (psaddr_t) 0 + (onoff != 0));
+}
diff --git a/libpthread/nptl_db/td_thr_event_getmsg.c b/libpthread/nptl_db/td_thr_event_getmsg.c
new file mode 100644
index 000000000..b24fc25d7
--- /dev/null
+++ b/libpthread/nptl_db/td_thr_event_getmsg.c
@@ -0,0 +1,119 @@
+/* Retrieve event.
+ Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include "thread_dbP.h"
+#include <assert.h>
+
+
+td_err_e
+td_thr_event_getmsg (const td_thrhandle_t *th, td_event_msg_t *msg)
+{
+ td_err_e err;
+ psaddr_t eventbuf, eventnum, eventdata;
+ psaddr_t thp, prevp;
+ void *copy = NULL;
+
+ LOG ("td_thr_event_getmsg");
+
+ /* Copy the event message buffer in from the inferior. */
+ err = DB_GET_FIELD_ADDRESS (eventbuf, th->th_ta_p, th->th_unique, pthread,
+ eventbuf, 0);
+ if (err == TD_OK)
+ err = DB_GET_STRUCT (copy, th->th_ta_p, eventbuf, td_eventbuf_t);
+ if (err != TD_OK)
+ return err;
+
+ /* Check whether an event occurred. */
+ err = DB_GET_FIELD_LOCAL (eventnum, th->th_ta_p, copy,
+ td_eventbuf_t, eventnum, 0);
+ if (err != TD_OK)
+ return err;
+ if ((int) (uintptr_t) eventnum == TD_EVENT_NONE)
+ /* Nothing. */
+ return TD_NOMSG;
+
+ /* Fill the user's data structure. */
+ err = DB_GET_FIELD_LOCAL (eventdata, th->th_ta_p, copy,
+ td_eventbuf_t, eventdata, 0);
+ if (err != TD_OK)
+ return err;
+
+ msg->msg.data = (uintptr_t) eventdata;
+ msg->event = (uintptr_t) eventnum;
+ msg->th_p = th;
+
+ /* And clear the event message in the target. */
+ memset (copy, 0, th->th_ta_p->ta_sizeof_td_eventbuf_t);
+ err = DB_PUT_STRUCT (th->th_ta_p, eventbuf, td_eventbuf_t, copy);
+ if (err != TD_OK)
+ return err;
+
+ /* Get the pointer to the thread descriptor with the last event.
+ If it doesn't match TH, then walk down the list until we find it.
+ We must splice it out of the list so that there is no dangling
+ pointer to it later when it dies. */
+ err = DB_GET_SYMBOL (prevp, th->th_ta_p, __nptl_last_event);
+ if (err != TD_OK)
+ return err;
+ err = DB_GET_VALUE (thp, th->th_ta_p, __nptl_last_event, 0);
+ if (err != TD_OK)
+ return err;
+
+ while (thp != 0)
+ {
+ psaddr_t next;
+ err = DB_GET_FIELD (next, th->th_ta_p, th->th_unique, pthread,
+ nextevent, 0);
+ if (err != TD_OK)
+ return err;
+
+ if (next == thp)
+ return TD_DBERR;
+
+ if (thp == th->th_unique)
+ {
+ /* PREVP points at this thread, splice it out. */
+ psaddr_t next_nextp;
+ err = DB_GET_FIELD_ADDRESS (next_nextp, th->th_ta_p, next, pthread,
+ nextevent, 0);
+ assert (err == TD_OK); /* We used this field before. */
+ if (prevp == next_nextp)
+ return TD_DBERR;
+
+ err = _td_store_value (th->th_ta_p,
+ th->th_ta_p->ta_var___nptl_last_event, -1,
+ 0, prevp, next);
+ if (err != TD_OK)
+ return err;
+
+ /* Now clear this thread's own next pointer so it's not dangling
+ when the thread resumes and then chains on for its next event. */
+ return DB_PUT_FIELD (th->th_ta_p, thp, pthread, nextevent, 0, 0);
+ }
+
+ err = DB_GET_FIELD_ADDRESS (prevp, th->th_ta_p, thp, pthread,
+ nextevent, 0);
+ assert (err == TD_OK); /* We used this field before. */
+ thp = next;
+ }
+
+ /* Ack! This should not happen. */
+ return TD_DBERR;
+}
diff --git a/libpthread/nptl_db/td_thr_get_info.c b/libpthread/nptl_db/td_thr_get_info.c
new file mode 100644
index 000000000..bb1388804
--- /dev/null
+++ b/libpthread/nptl_db/td_thr_get_info.c
@@ -0,0 +1,110 @@
+/* Get thread information.
+ Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <stddef.h>
+#include <string.h>
+#include "thread_dbP.h"
+
+
+td_err_e
+td_thr_get_info (const td_thrhandle_t *th, td_thrinfo_t *infop)
+{
+ td_err_e err;
+ void *copy;
+ psaddr_t tls, schedpolicy, schedprio, cancelhandling, tid, report_events;
+
+ LOG ("td_thr_get_info");
+
+ /* Copy the whole descriptor in once so we can access the several
+ fields locally. Excess copying in one go is much better than
+ multiple ps_pdread calls. */
+ err = DB_GET_STRUCT (copy, th->th_ta_p, th->th_unique, pthread);
+ if (err != TD_OK)
+ return err;
+
+ err = DB_GET_FIELD_ADDRESS (tls, th->th_ta_p, th->th_unique,
+ pthread, specific, 0);
+ if (err != TD_OK)
+ return err;
+
+ err = DB_GET_FIELD_LOCAL (schedpolicy, th->th_ta_p, copy, pthread,
+ schedpolicy, 0);
+ if (err != TD_OK)
+ return err;
+ err = DB_GET_FIELD_LOCAL (schedprio, th->th_ta_p, copy, pthread,
+ schedparam_sched_priority, 0);
+ if (err != TD_OK)
+ return err;
+ err = DB_GET_FIELD_LOCAL (tid, th->th_ta_p, copy, pthread, tid, 0);
+ if (err != TD_OK)
+ return err;
+ err = DB_GET_FIELD_LOCAL (cancelhandling, th->th_ta_p, copy, pthread,
+ cancelhandling, 0);
+ if (err != TD_OK)
+ return err;
+ err = DB_GET_FIELD_LOCAL (report_events, th->th_ta_p, copy, pthread,
+ report_events, 0);
+ if (err != TD_OK)
+ return err;
+
+ /* Fill in information. Clear first to provide reproducable
+ results for the fields we do not fill in. */
+ memset (infop, '\0', sizeof (td_thrinfo_t));
+
+ infop->ti_tid = (thread_t) th->th_unique;
+ infop->ti_tls = (char *) tls;
+ infop->ti_pri = ((uintptr_t) schedpolicy == SCHED_OTHER
+ ? 0 : (uintptr_t) schedprio);
+ infop->ti_type = TD_THR_USER;
+
+ if ((((int) (uintptr_t) cancelhandling) & EXITING_BITMASK) == 0)
+ /* XXX For now there is no way to get more information. */
+ infop->ti_state = TD_THR_ACTIVE;
+ else if ((((int) (uintptr_t) cancelhandling) & TERMINATED_BITMASK) == 0)
+ infop->ti_state = TD_THR_ZOMBIE;
+ else
+ infop->ti_state = TD_THR_UNKNOWN;
+
+ /* Initialization which are the same in both cases. */
+ infop->ti_ta_p = th->th_ta_p;
+ infop->ti_lid = tid == 0 ? ps_getpid (th->th_ta_p->ph) : (uintptr_t) tid;
+ infop->ti_traceme = report_events != 0;
+
+ err = DB_GET_FIELD_LOCAL (infop->ti_startfunc, th->th_ta_p, copy, pthread,
+ start_routine, 0);
+ if (err == TD_OK)
+ {
+ uint32_t idx;
+ for (idx = 0; idx < TD_EVENTSIZE; ++idx)
+ {
+ psaddr_t word;
+ err = DB_GET_FIELD_LOCAL (word, th->th_ta_p, copy, pthread,
+ eventbuf_eventmask_event_bits, idx);
+ if (err != TD_OK)
+ break;
+ infop->ti_events.event_bits[idx] = (uintptr_t) word;
+ }
+ if (err == TD_NOAPLIC)
+ memset (&infop->ti_events.event_bits[idx], 0,
+ (TD_EVENTSIZE - idx) * sizeof infop->ti_events.event_bits[0]);
+ }
+
+ return err;
+}
diff --git a/libpthread/nptl_db/td_thr_getfpregs.c b/libpthread/nptl_db/td_thr_getfpregs.c
new file mode 100644
index 000000000..7760512eb
--- /dev/null
+++ b/libpthread/nptl_db/td_thr_getfpregs.c
@@ -0,0 +1,53 @@
+/* Get a thread's floating-point register set.
+ Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_thr_getfpregs (const td_thrhandle_t *th, prfpregset_t *regset)
+{
+ psaddr_t cancelhandling, tid;
+ td_err_e err;
+
+ LOG ("td_thr_getfpregs");
+
+ /* We have to get the state and the PID for this thread. */
+ err = DB_GET_FIELD (cancelhandling, th->th_ta_p, th->th_unique, pthread,
+ cancelhandling, 0);
+ if (err != TD_OK)
+ return err;
+
+ /* If the thread already terminated we return all zeroes. */
+ if (((int) (uintptr_t) cancelhandling) & TERMINATED_BITMASK)
+ memset (regset, '\0', sizeof (*regset));
+ /* Otherwise get the register content through the callback. */
+ else
+ {
+ err = DB_GET_FIELD (tid, th->th_ta_p, th->th_unique, pthread, tid, 0);
+ if (err != TD_OK)
+ return err;
+
+ if (ps_lgetfpregs (th->th_ta_p->ph, (uintptr_t) tid, regset) != PS_OK)
+ return TD_ERR;
+ }
+
+ return TD_OK;
+}
diff --git a/libpthread/nptl_db/td_thr_getgregs.c b/libpthread/nptl_db/td_thr_getgregs.c
new file mode 100644
index 000000000..4c2373ef6
--- /dev/null
+++ b/libpthread/nptl_db/td_thr_getgregs.c
@@ -0,0 +1,53 @@
+/* Get a thread's general register set.
+ Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_thr_getgregs (const td_thrhandle_t *th, prgregset_t regset)
+{
+ psaddr_t cancelhandling, tid;
+ td_err_e err;
+
+ LOG ("td_thr_getgregs");
+
+ /* We have to get the state and the PID for this thread. */
+ err = DB_GET_FIELD (cancelhandling, th->th_ta_p, th->th_unique, pthread,
+ cancelhandling, 0);
+ if (err != TD_OK)
+ return err;
+
+ /* If the thread already terminated we return all zeroes. */
+ if (((int) (uintptr_t) cancelhandling) & TERMINATED_BITMASK)
+ memset (regset, '\0', sizeof (*regset));
+ /* Otherwise get the register content through the callback. */
+ else
+ {
+ err = DB_GET_FIELD (tid, th->th_ta_p, th->th_unique, pthread, tid, 0);
+ if (err != TD_OK)
+ return err;
+
+ if (ps_lgetregs (th->th_ta_p->ph, (uintptr_t) tid, regset) != PS_OK)
+ return TD_ERR;
+ }
+
+ return TD_OK;
+}
diff --git a/libpthread/nptl_db/td_thr_getxregs.c b/libpthread/nptl_db/td_thr_getxregs.c
new file mode 100644
index 000000000..3c77ab6be
--- /dev/null
+++ b/libpthread/nptl_db/td_thr_getxregs.c
@@ -0,0 +1,30 @@
+/* Get a thread's extra state register set.
+ Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_thr_getxregs (const td_thrhandle_t *th, void *xregs)
+{
+ /* XXX This might be platform specific. */
+ LOG ("td_thr_getxregs");
+ return TD_NOXREGS;
+}
diff --git a/libpthread/nptl_db/td_thr_getxregsize.c b/libpthread/nptl_db/td_thr_getxregsize.c
new file mode 100644
index 000000000..1704e4b0a
--- /dev/null
+++ b/libpthread/nptl_db/td_thr_getxregsize.c
@@ -0,0 +1,30 @@
+/* Get the size of the extra state register set for this architecture.
+ Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_thr_getxregsize (const td_thrhandle_t *th, int *sizep)
+{
+ /* XXX This might be platform specific. */
+ LOG ("td_thr_getxregsize");
+ return TD_NOXREGS;
+}
diff --git a/libpthread/nptl_db/td_thr_set_event.c b/libpthread/nptl_db/td_thr_set_event.c
new file mode 100644
index 000000000..6617147a8
--- /dev/null
+++ b/libpthread/nptl_db/td_thr_set_event.c
@@ -0,0 +1,77 @@
+/* Enable specific event for thread.
+ Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <stddef.h>
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_thr_set_event (th, event)
+ const td_thrhandle_t *th;
+ td_thr_events_t *event;
+{
+ td_err_e err;
+ psaddr_t eventmask;
+ void *copy = NULL;
+
+ LOG ("td_thr_set_event");
+
+ /* Fetch the old event mask from the inferior and modify it in place. */
+ err = DB_GET_FIELD_ADDRESS (eventmask, th->th_ta_p,
+ th->th_unique, pthread, eventbuf_eventmask, 0);
+ if (err == TD_OK)
+ err = DB_GET_STRUCT (copy, th->th_ta_p, eventmask, td_thr_events_t);
+ if (err == TD_OK)
+ {
+ uint32_t idx;
+ for (idx = 0; idx < TD_EVENTSIZE; ++idx)
+ {
+ psaddr_t word;
+ uint32_t mask;
+ err = DB_GET_FIELD_LOCAL (word, th->th_ta_p, copy,
+ td_thr_events_t, event_bits, idx);
+ if (err != TD_OK)
+ break;
+ mask = (uintptr_t) word;
+ mask |= event->event_bits[idx];
+ word = (psaddr_t) (uintptr_t) mask;
+ err = DB_PUT_FIELD_LOCAL (th->th_ta_p, copy,
+ td_thr_events_t, event_bits, idx, word);
+ if (err != TD_OK)
+ break;
+ }
+ if (err == TD_NOAPLIC)
+ {
+ err = TD_OK;
+ while (idx < TD_EVENTSIZE)
+ if (event->event_bits[idx++] != 0)
+ {
+ err = TD_NOEVENT;
+ break;
+ }
+ }
+ if (err == TD_OK)
+ /* Now write it back to the inferior. */
+ err = DB_PUT_STRUCT (th->th_ta_p, eventmask, td_thr_events_t, copy);
+ }
+
+ return err;
+}
diff --git a/libpthread/nptl_db/td_thr_setfpregs.c b/libpthread/nptl_db/td_thr_setfpregs.c
new file mode 100644
index 000000000..01bdb5323
--- /dev/null
+++ b/libpthread/nptl_db/td_thr_setfpregs.c
@@ -0,0 +1,50 @@
+/* Set a thread's floating-point register set.
+ Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_thr_setfpregs (const td_thrhandle_t *th, const prfpregset_t *fpregs)
+{
+ psaddr_t cancelhandling, tid;
+ td_err_e err;
+
+ LOG ("td_thr_setfpregs");
+
+ /* We have to get the state and the PID for this thread. */
+ err = DB_GET_FIELD (cancelhandling, th->th_ta_p, th->th_unique, pthread,
+ cancelhandling, 0);
+ if (err != TD_OK)
+ return err;
+
+ /* Only set the registers if the thread hasn't yet terminated. */
+ if ((((int) (uintptr_t) cancelhandling) & TERMINATED_BITMASK) == 0)
+ {
+ err = DB_GET_FIELD (tid, th->th_ta_p, th->th_unique, pthread, tid, 0);
+ if (err != TD_OK)
+ return err;
+
+ if (ps_lsetfpregs (th->th_ta_p->ph, (uintptr_t) tid, fpregs) != PS_OK)
+ return TD_ERR;
+ }
+
+ return TD_OK;
+}
diff --git a/libpthread/nptl_db/td_thr_setgregs.c b/libpthread/nptl_db/td_thr_setgregs.c
new file mode 100644
index 000000000..2a9ce7e01
--- /dev/null
+++ b/libpthread/nptl_db/td_thr_setgregs.c
@@ -0,0 +1,50 @@
+/* Set a thread's general register set.
+ Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_thr_setgregs (const td_thrhandle_t *th, prgregset_t gregs)
+{
+ psaddr_t cancelhandling, tid;
+ td_err_e err;
+
+ LOG ("td_thr_setgregs");
+
+ /* We have to get the state and the PID for this thread. */
+ err = DB_GET_FIELD (cancelhandling, th->th_ta_p, th->th_unique, pthread,
+ cancelhandling, 0);
+ if (err != TD_OK)
+ return err;
+
+ /* Only set the registers if the thread hasn't yet terminated. */
+ if ((((int) (uintptr_t) cancelhandling) & TERMINATED_BITMASK) == 0)
+ {
+ err = DB_GET_FIELD (tid, th->th_ta_p, th->th_unique, pthread, tid, 0);
+ if (err != TD_OK)
+ return err;
+
+ if (ps_lsetregs (th->th_ta_p->ph, tid - (psaddr_t) 0, gregs) != PS_OK)
+ return TD_ERR;
+ }
+
+ return TD_OK;
+}
diff --git a/libpthread/nptl_db/td_thr_setprio.c b/libpthread/nptl_db/td_thr_setprio.c
new file mode 100644
index 000000000..6032b0ed4
--- /dev/null
+++ b/libpthread/nptl_db/td_thr_setprio.c
@@ -0,0 +1,30 @@
+/* Set a thread's priority.
+ Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_thr_setprio (const td_thrhandle_t *th, int prio)
+{
+ /* XXX We have to figure out what has to be done. */
+ LOG ("td_thr_setprio");
+ return TD_OK;
+}
diff --git a/libpthread/nptl_db/td_thr_setsigpending.c b/libpthread/nptl_db/td_thr_setsigpending.c
new file mode 100644
index 000000000..e2c9d7ad2
--- /dev/null
+++ b/libpthread/nptl_db/td_thr_setsigpending.c
@@ -0,0 +1,31 @@
+/* Raise a signal for a thread.
+ Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_thr_setsigpending (const td_thrhandle_t *th, unsigned char n,
+ const sigset_t *ss)
+{
+ /* XXX We have to figure out what has to be done. */
+ LOG ("td_thr_setsigpending");
+ return TD_OK;
+}
diff --git a/libpthread/nptl_db/td_thr_setxregs.c b/libpthread/nptl_db/td_thr_setxregs.c
new file mode 100644
index 000000000..f48877c78
--- /dev/null
+++ b/libpthread/nptl_db/td_thr_setxregs.c
@@ -0,0 +1,30 @@
+/* Set a thread's extra state register set.
+ Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_thr_setxregs (const td_thrhandle_t *ta, const void *addr)
+{
+ /* XXX This might have to be platform specific. */
+ LOG ("td_thr_setxregs");
+ return TD_NOXREGS;
+}
diff --git a/libpthread/nptl_db/td_thr_sigsetmask.c b/libpthread/nptl_db/td_thr_sigsetmask.c
new file mode 100644
index 000000000..3a68aecd3
--- /dev/null
+++ b/libpthread/nptl_db/td_thr_sigsetmask.c
@@ -0,0 +1,30 @@
+/* Set a thread's signal mask.
+ Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_thr_sigsetmask (const td_thrhandle_t *th, const sigset_t *ss)
+{
+ /* XXX We have to figure out what has to be done. */
+ LOG ("td_thr_sigsetmask");
+ return TD_OK;
+}
diff --git a/libpthread/nptl_db/td_thr_tls_get_addr.c b/libpthread/nptl_db/td_thr_tls_get_addr.c
new file mode 100644
index 000000000..e7d232272
--- /dev/null
+++ b/libpthread/nptl_db/td_thr_tls_get_addr.c
@@ -0,0 +1,43 @@
+/* Get address of thread local variable.
+ Copyright (C) 2002,2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 2002.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <link.h>
+#include "thread_dbP.h"
+
+td_err_e
+td_thr_tls_get_addr (const td_thrhandle_t *th,
+ psaddr_t map_address, size_t offset, psaddr_t *address)
+{
+ td_err_e err;
+ psaddr_t modid;
+
+ /* Get the TLS module ID from the `struct link_map' in the inferior. */
+ err = DB_GET_FIELD (modid, th->th_ta_p, map_address, link_map,
+ l_tls_modid, 0);
+ if (err == TD_NOCAPAB)
+ return TD_NOAPLIC;
+ if (err == TD_OK)
+ {
+ err = td_thr_tlsbase (th, (uintptr_t) modid, address);
+ if (err == TD_OK)
+ *address += offset;
+ }
+ return err;
+}
diff --git a/libpthread/nptl_db/td_thr_tlsbase.c b/libpthread/nptl_db/td_thr_tlsbase.c
new file mode 100644
index 000000000..aaeda6f3c
--- /dev/null
+++ b/libpthread/nptl_db/td_thr_tlsbase.c
@@ -0,0 +1,55 @@
+/* Locate TLS data for a thread.
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include "thread_dbP.h"
+
+td_err_e
+td_thr_tlsbase (const td_thrhandle_t *th,
+ unsigned long int modid,
+ psaddr_t *base)
+{
+ td_err_e err;
+ psaddr_t dtv, dtvslot, dtvptr;
+
+ if (modid < 1)
+ return TD_NOTLS;
+
+ /* Get the DTV pointer from the thread descriptor. */
+ err = DB_GET_FIELD (dtv, th->th_ta_p, th->th_unique, pthread, dtvp, 0);
+ if (err != TD_OK)
+ return err;
+
+ /* Find the corresponding entry in the DTV. */
+ err = DB_GET_FIELD_ADDRESS (dtvslot, th->th_ta_p, dtv, dtv, dtv, modid);
+ if (err != TD_OK)
+ return err;
+
+ /* Extract the TLS block address from that DTV slot. */
+ err = DB_GET_FIELD (dtvptr, th->th_ta_p, dtvslot, dtv_t, pointer_val, 0);
+ if (err != TD_OK)
+ return err;
+
+ /* It could be that the memory for this module is not allocated for
+ the given thread. */
+ if ((uintptr_t) dtvptr & 1)
+ return TD_TLSDEFER;
+
+ *base = dtvptr;
+ return TD_OK;
+}
diff --git a/libpthread/nptl_db/td_thr_tsd.c b/libpthread/nptl_db/td_thr_tsd.c
new file mode 100644
index 000000000..08f617b7d
--- /dev/null
+++ b/libpthread/nptl_db/td_thr_tsd.c
@@ -0,0 +1,96 @@
+/* Get a thread-specific data pointer for a thread.
+ Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_thr_tsd (const td_thrhandle_t *th, const thread_key_t tk, void **data)
+{
+ td_err_e err;
+ psaddr_t tk_seq, level1, level2, seq, value;
+ void *copy;
+ uint32_t pthread_key_2ndlevel_size, idx1st, idx2nd;
+
+ LOG ("td_thr_tsd");
+
+ /* Get the key entry. */
+ err = DB_GET_VALUE (tk_seq, th->th_ta_p, __pthread_keys, tk);
+ if (err == TD_NOAPLIC)
+ return TD_BADKEY;
+ if (err != TD_OK)
+ return err;
+
+ /* Fail if this key is not at all used. */
+ if (((uintptr_t) tk_seq & 1) == 0)
+ return TD_BADKEY;
+
+ /* This makes sure we have the size information on hand. */
+ err = DB_GET_FIELD_ADDRESS (level2, th->th_ta_p, 0, pthread_key_data_level2,
+ data, 1);
+ if (err != TD_OK)
+ return err;
+
+ /* Compute the indeces. */
+ pthread_key_2ndlevel_size
+ = DB_DESC_NELEM (th->th_ta_p->ta_field_pthread_key_data_level2_data);
+ idx1st = tk / pthread_key_2ndlevel_size;
+ idx2nd = tk % pthread_key_2ndlevel_size;
+
+ /* Now fetch the first level pointer. */
+ err = DB_GET_FIELD (level1, th->th_ta_p, th->th_unique, pthread,
+ specific, idx1st);
+ if (err == TD_NOAPLIC)
+ return TD_DBERR;
+ if (err != TD_OK)
+ return err;
+
+ /* Check the pointer to the second level array. */
+ if (level1 == 0)
+ return TD_NOTSD;
+
+ /* Locate the element within the second level array. */
+ err = DB_GET_FIELD_ADDRESS (level2, th->th_ta_p,
+ level1, pthread_key_data_level2, data, idx2nd);
+ if (err == TD_NOAPLIC)
+ return TD_DBERR;
+ if (err != TD_OK)
+ return err;
+
+ /* Now copy in that whole structure. */
+ err = DB_GET_STRUCT (copy, th->th_ta_p, level2, pthread_key_data);
+ if (err != TD_OK)
+ return err;
+
+ /* Check whether the data is valid. */
+ err = DB_GET_FIELD_LOCAL (seq, th->th_ta_p, copy, pthread_key_data, seq, 0);
+ if (err != TD_OK)
+ return err;
+ if (seq != tk_seq)
+ return TD_NOTSD;
+
+ /* Finally, fetch the value. */
+ err = DB_GET_FIELD_LOCAL (value, th->th_ta_p, copy, pthread_key_data,
+ data, 0);
+ if (err == TD_OK)
+ *data = value;
+
+ return err;
+}
diff --git a/libpthread/nptl_db/td_thr_validate.c b/libpthread/nptl_db/td_thr_validate.c
new file mode 100644
index 000000000..19ee940d6
--- /dev/null
+++ b/libpthread/nptl_db/td_thr_validate.c
@@ -0,0 +1,91 @@
+/* Validate a thread handle.
+ Copyright (C) 1999, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include "thread_dbP.h"
+#include <stdbool.h>
+
+static td_err_e
+check_thread_list (const td_thrhandle_t *th, psaddr_t head, bool *uninit)
+{
+ td_err_e err;
+ psaddr_t next, ofs;
+
+ err = DB_GET_FIELD (next, th->th_ta_p, head, list_t, next, 0);
+ if (err == TD_OK)
+ {
+ if (next == 0)
+ {
+ *uninit = true;
+ return TD_NOTHR;
+ }
+ err = DB_GET_FIELD_ADDRESS (ofs, th->th_ta_p, 0, pthread, list, 0);
+ }
+
+ while (err == TD_OK)
+ {
+ if (next == head)
+ return TD_NOTHR;
+
+ if (next - (ofs - (psaddr_t) 0) == th->th_unique)
+ return TD_OK;
+
+ err = DB_GET_FIELD (next, th->th_ta_p, next, list_t, next, 0);
+ }
+
+ return err;
+}
+
+
+td_err_e
+td_thr_validate (const td_thrhandle_t *th)
+{
+ td_err_e err;
+ psaddr_t list = NULL;
+
+ LOG ("td_thr_validate");
+
+ /* First check the list with threads using user allocated stacks. */
+ bool uninit = false;
+ err = DB_GET_SYMBOL (list, th->th_ta_p, __stack_user);
+ if (err == TD_OK)
+ err = check_thread_list (th, list, &uninit);
+
+ /* If our thread is not on this list search the list with stack
+ using implementation allocated stacks. */
+ if (err == TD_NOTHR)
+ {
+ err = DB_GET_SYMBOL (list, th->th_ta_p, stack_used);
+ if (err == TD_OK)
+ err = check_thread_list (th, list, &uninit);
+
+ if (err == TD_NOTHR && uninit)
+ {
+ /* __pthread_initialize_minimal has not run yet.
+ But the main thread still has a valid ID. */
+ td_thrhandle_t main_th;
+ err = td_ta_map_lwp2thr (th->th_ta_p,
+ ps_getpid (th->th_ta_p->ph), &main_th);
+ if (err == TD_OK && th->th_unique != main_th.th_unique)
+ err = TD_NOTHR;
+ }
+ }
+
+ return err;
+}
diff --git a/libpthread/nptl_db/thread_db.h b/libpthread/nptl_db/thread_db.h
new file mode 100644
index 000000000..433b54fd5
--- /dev/null
+++ b/libpthread/nptl_db/thread_db.h
@@ -0,0 +1,459 @@
+/* thread_db.h -- interface to libthread_db.so library for debugging -lpthread
+ Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _THREAD_DB_H
+#define _THREAD_DB_H 1
+
+/* This is the debugger interface for the NPTL library. It is
+ modelled closely after the interface with same names in Solaris
+ with the goal to share the same code in the debugger. */
+#include <pthread.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/procfs.h>
+
+
+/* Error codes of the library. */
+typedef enum
+{
+ TD_OK, /* No error. */
+ TD_ERR, /* No further specified error. */
+ TD_NOTHR, /* No matching thread found. */
+ TD_NOSV, /* No matching synchronization handle found. */
+ TD_NOLWP, /* No matching light-weighted process found. */
+ TD_BADPH, /* Invalid process handle. */
+ TD_BADTH, /* Invalid thread handle. */
+ TD_BADSH, /* Invalid synchronization handle. */
+ TD_BADTA, /* Invalid thread agent. */
+ TD_BADKEY, /* Invalid key. */
+ TD_NOMSG, /* No event available. */
+ TD_NOFPREGS, /* No floating-point register content available. */
+ TD_NOLIBTHREAD, /* Application not linked with thread library. */
+ TD_NOEVENT, /* Requested event is not supported. */
+ TD_NOCAPAB, /* Capability not available. */
+ TD_DBERR, /* Internal debug library error. */
+ TD_NOAPLIC, /* Operation is not applicable. */
+ TD_NOTSD, /* No thread-specific data available. */
+ TD_MALLOC, /* Out of memory. */
+ TD_PARTIALREG, /* Not entire register set was read or written. */
+ TD_NOXREGS, /* X register set not available for given thread. */
+ TD_TLSDEFER, /* Thread has not yet allocated TLS for given module. */
+ TD_NOTALLOC = TD_TLSDEFER,
+ TD_VERSION, /* Version if libpthread and libthread_db do not match. */
+ TD_NOTLS /* There is no TLS segment in the given module. */
+} td_err_e;
+
+
+/* Possible thread states. TD_THR_ANY_STATE is a pseudo-state used to
+ select threads regardless of state in td_ta_thr_iter(). */
+typedef enum
+{
+ TD_THR_ANY_STATE,
+ TD_THR_UNKNOWN,
+ TD_THR_STOPPED,
+ TD_THR_RUN,
+ TD_THR_ACTIVE,
+ TD_THR_ZOMBIE,
+ TD_THR_SLEEP,
+ TD_THR_STOPPED_ASLEEP
+} td_thr_state_e;
+
+/* Thread type: user or system. TD_THR_ANY_TYPE is a pseudo-type used
+ to select threads regardless of type in td_ta_thr_iter(). */
+typedef enum
+{
+ TD_THR_ANY_TYPE,
+ TD_THR_USER,
+ TD_THR_SYSTEM
+} td_thr_type_e;
+
+
+/* Types of the debugging library. */
+
+/* Handle for a process. This type is opaque. */
+typedef struct td_thragent td_thragent_t;
+
+/* The actual thread handle type. This is also opaque. */
+typedef struct td_thrhandle
+{
+ td_thragent_t *th_ta_p;
+ psaddr_t th_unique;
+} td_thrhandle_t;
+
+
+/* Forward declaration of a type defined by and for the dynamic linker. */
+struct link_map;
+
+
+/* Flags for `td_ta_thr_iter'. */
+#define TD_THR_ANY_USER_FLAGS 0xffffffff
+#define TD_THR_LOWEST_PRIORITY -20
+#define TD_SIGNO_MASK NULL
+
+
+#define TD_EVENTSIZE 2
+#define BT_UISHIFT 5 /* log base 2 of BT_NBIPUI, to extract word index */
+#define BT_NBIPUI (1 << BT_UISHIFT) /* n bits per uint */
+#define BT_UIMASK (BT_NBIPUI - 1) /* to extract bit index */
+
+/* Bitmask of enabled events. */
+typedef struct td_thr_events
+{
+ uint32_t event_bits[TD_EVENTSIZE];
+} td_thr_events_t;
+
+/* Event set manipulation macros. */
+#define __td_eventmask(n) \
+ (UINT32_C (1) << (((n) - 1) & BT_UIMASK))
+#define __td_eventword(n) \
+ ((UINT32_C ((n) - 1)) >> BT_UISHIFT)
+
+#define td_event_emptyset(setp) \
+ do { \
+ int __i; \
+ for (__i = TD_EVENTSIZE; __i > 0; --__i) \
+ (setp)->event_bits[__i - 1] = 0; \
+ } while (0)
+
+#define td_event_fillset(setp) \
+ do { \
+ int __i; \
+ for (__i = TD_EVENTSIZE; __i > 0; --__i) \
+ (setp)->event_bits[__i - 1] = UINT32_C (0xffffffff); \
+ } while (0)
+
+#define td_event_addset(setp, n) \
+ (((setp)->event_bits[__td_eventword (n)]) |= __td_eventmask (n))
+#define td_event_delset(setp, n) \
+ (((setp)->event_bits[__td_eventword (n)]) &= ~__td_eventmask (n))
+#define td_eventismember(setp, n) \
+ (__td_eventmask (n) & ((setp)->event_bits[__td_eventword (n)]))
+#if TD_EVENTSIZE == 2
+# define td_eventisempty(setp) \
+ (!((setp)->event_bits[0]) && !((setp)->event_bits[1]))
+#else
+# error "td_eventisempty must be changed to match TD_EVENTSIZE"
+#endif
+
+/* Events reportable by the thread implementation. */
+typedef enum
+{
+ TD_ALL_EVENTS, /* Pseudo-event number. */
+ TD_EVENT_NONE = TD_ALL_EVENTS, /* Depends on context. */
+ TD_READY, /* Is executable now. */
+ TD_SLEEP, /* Blocked in a synchronization obj. */
+ TD_SWITCHTO, /* Now assigned to a process. */
+ TD_SWITCHFROM, /* Not anymore assigned to a process. */
+ TD_LOCK_TRY, /* Trying to get an unavailable lock. */
+ TD_CATCHSIG, /* Signal posted to the thread. */
+ TD_IDLE, /* Process getting idle. */
+ TD_CREATE, /* New thread created. */
+ TD_DEATH, /* Thread terminated. */
+ TD_PREEMPT, /* Preempted. */
+ TD_PRI_INHERIT, /* Inherited elevated priority. */
+ TD_REAP, /* Reaped. */
+ TD_CONCURRENCY, /* Number of processes changing. */
+ TD_TIMEOUT, /* Conditional variable wait timed out. */
+ TD_MIN_EVENT_NUM = TD_READY,
+ TD_MAX_EVENT_NUM = TD_TIMEOUT,
+ TD_EVENTS_ENABLE = 31 /* Event reporting enabled. */
+} td_event_e;
+
+/* Values representing the different ways events are reported. */
+typedef enum
+{
+ NOTIFY_BPT, /* User must insert breakpoint at u.bptaddr. */
+ NOTIFY_AUTOBPT, /* Breakpoint at u.bptaddr is automatically
+ inserted. */
+ NOTIFY_SYSCALL /* System call u.syscallno will be invoked. */
+} td_notify_e;
+
+/* Description how event type is reported. */
+typedef struct td_notify
+{
+ td_notify_e type; /* Way the event is reported. */
+ union
+ {
+ psaddr_t bptaddr; /* Address of breakpoint. */
+ int syscallno; /* Number of system call used. */
+ } u;
+} td_notify_t;
+
+/* Structure used to report event. */
+typedef struct td_event_msg
+{
+ td_event_e event; /* Event type being reported. */
+ const td_thrhandle_t *th_p; /* Thread reporting the event. */
+ union
+ {
+# if 0
+ td_synchandle_t *sh; /* Handle of synchronization object. */
+#endif
+ uintptr_t data; /* Event specific data. */
+ } msg;
+} td_event_msg_t;
+
+/* Structure containing event data available in each thread structure. */
+typedef struct
+{
+ td_thr_events_t eventmask; /* Mask of enabled events. */
+ td_event_e eventnum; /* Number of last event. */
+ void *eventdata; /* Data associated with event. */
+} td_eventbuf_t;
+
+
+/* Gathered statistics about the process. */
+typedef struct td_ta_stats
+{
+ int nthreads; /* Total number of threads in use. */
+ int r_concurrency; /* Concurrency level requested by user. */
+ int nrunnable_num; /* Average runnable threads, numerator. */
+ int nrunnable_den; /* Average runnable threads, denominator. */
+ int a_concurrency_num; /* Achieved concurrency level, numerator. */
+ int a_concurrency_den; /* Achieved concurrency level, denominator. */
+ int nlwps_num; /* Average number of processes in use,
+ numerator. */
+ int nlwps_den; /* Average number of processes in use,
+ denominator. */
+ int nidle_num; /* Average number of idling processes,
+ numerator. */
+ int nidle_den; /* Average number of idling processes,
+ denominator. */
+} td_ta_stats_t;
+
+
+/* Since Sun's library is based on Solaris threads we have to define a few
+ types to map them to POSIX threads. */
+typedef pthread_t thread_t;
+typedef pthread_key_t thread_key_t;
+
+
+/* Callback for iteration over threads. */
+typedef int td_thr_iter_f (const td_thrhandle_t *, void *);
+
+/* Callback for iteration over thread local data. */
+typedef int td_key_iter_f (thread_key_t, void (*) (void *), void *);
+
+
+
+/* Forward declaration. This has to be defined by the user. */
+struct ps_prochandle;
+
+
+/* Information about the thread. */
+typedef struct td_thrinfo
+{
+ td_thragent_t *ti_ta_p; /* Process handle. */
+ unsigned int ti_user_flags; /* Unused. */
+ thread_t ti_tid; /* Thread ID returned by
+ pthread_create(). */
+ char *ti_tls; /* Pointer to thread-local data. */
+ psaddr_t ti_startfunc; /* Start function passed to
+ pthread_create(). */
+ psaddr_t ti_stkbase; /* Base of thread's stack. */
+ long int ti_stksize; /* Size of thread's stack. */
+ psaddr_t ti_ro_area; /* Unused. */
+ int ti_ro_size; /* Unused. */
+ td_thr_state_e ti_state; /* Thread state. */
+ unsigned char ti_db_suspended; /* Nonzero if suspended by debugger. */
+ td_thr_type_e ti_type; /* Type of the thread (system vs
+ user thread). */
+ intptr_t ti_pc; /* Unused. */
+ intptr_t ti_sp; /* Unused. */
+ short int ti_flags; /* Unused. */
+ int ti_pri; /* Thread priority. */
+ lwpid_t ti_lid; /* Kernel PID for this thread. */
+ sigset_t ti_sigmask; /* Signal mask. */
+ unsigned char ti_traceme; /* Nonzero if event reporting
+ enabled. */
+ unsigned char ti_preemptflag; /* Unused. */
+ unsigned char ti_pirecflag; /* Unused. */
+ sigset_t ti_pending; /* Set of pending signals. */
+ td_thr_events_t ti_events; /* Set of enabled events. */
+} td_thrinfo_t;
+
+
+
+/* Prototypes for exported library functions. */
+
+/* Initialize the thread debug support library. */
+extern td_err_e td_init (void);
+
+/* Historical relict. Should not be used anymore. */
+extern td_err_e td_log (void);
+
+/* Return list of symbols the library can request. */
+extern const char **td_symbol_list (void);
+
+/* Generate new thread debug library handle for process PS. */
+extern td_err_e td_ta_new (struct ps_prochandle *__ps, td_thragent_t **__ta);
+
+/* Free resources allocated for TA. */
+extern td_err_e td_ta_delete (td_thragent_t *__ta);
+
+/* Get number of currently running threads in process associated with TA. */
+extern td_err_e td_ta_get_nthreads (const td_thragent_t *__ta, int *__np);
+
+/* Return process handle passed in `td_ta_new' for process associated with
+ TA. */
+extern td_err_e td_ta_get_ph (const td_thragent_t *__ta,
+ struct ps_prochandle **__ph);
+
+/* Map thread library handle PT to thread debug library handle for process
+ associated with TA and store result in *TH. */
+extern td_err_e td_ta_map_id2thr (const td_thragent_t *__ta, pthread_t __pt,
+ td_thrhandle_t *__th);
+
+/* Map process ID LWPID to thread debug library handle for process
+ associated with TA and store result in *TH. */
+extern td_err_e td_ta_map_lwp2thr (const td_thragent_t *__ta, lwpid_t __lwpid,
+ td_thrhandle_t *__th);
+
+
+/* Call for each thread in a process associated with TA the callback function
+ CALLBACK. */
+extern td_err_e td_ta_thr_iter (const td_thragent_t *__ta,
+ td_thr_iter_f *__callback, void *__cbdata_p,
+ td_thr_state_e __state, int __ti_pri,
+ sigset_t *__ti_sigmask_p,
+ unsigned int __ti_user_flags);
+
+/* Call for each defined thread local data entry the callback function KI. */
+extern td_err_e td_ta_tsd_iter (const td_thragent_t *__ta, td_key_iter_f *__ki,
+ void *__p);
+
+
+/* Get event address for EVENT. */
+extern td_err_e td_ta_event_addr (const td_thragent_t *__ta,
+ td_event_e __event, td_notify_t *__ptr);
+
+/* Enable EVENT in global mask. */
+extern td_err_e td_ta_set_event (const td_thragent_t *__ta,
+ td_thr_events_t *__event);
+
+/* Disable EVENT in global mask. */
+extern td_err_e td_ta_clear_event (const td_thragent_t *__ta,
+ td_thr_events_t *__event);
+
+/* Return information about last event. */
+extern td_err_e td_ta_event_getmsg (const td_thragent_t *__ta,
+ td_event_msg_t *__msg);
+
+
+/* Set suggested concurrency level for process associated with TA. */
+extern td_err_e td_ta_setconcurrency (const td_thragent_t *__ta, int __level);
+
+
+/* Enable collecting statistics for process associated with TA. */
+extern td_err_e td_ta_enable_stats (const td_thragent_t *__ta, int __enable);
+
+/* Reset statistics. */
+extern td_err_e td_ta_reset_stats (const td_thragent_t *__ta);
+
+/* Retrieve statistics from process associated with TA. */
+extern td_err_e td_ta_get_stats (const td_thragent_t *__ta,
+ td_ta_stats_t *__statsp);
+
+
+/* Validate that TH is a thread handle. */
+extern td_err_e td_thr_validate (const td_thrhandle_t *__th);
+
+/* Return information about thread TH. */
+extern td_err_e td_thr_get_info (const td_thrhandle_t *__th,
+ td_thrinfo_t *__infop);
+
+/* Retrieve floating-point register contents of process running thread TH. */
+extern td_err_e td_thr_getfpregs (const td_thrhandle_t *__th,
+ prfpregset_t *__regset);
+
+/* Retrieve general register contents of process running thread TH. */
+extern td_err_e td_thr_getgregs (const td_thrhandle_t *__th,
+ prgregset_t __gregs);
+
+/* Retrieve extended register contents of process running thread TH. */
+extern td_err_e td_thr_getxregs (const td_thrhandle_t *__th, void *__xregs);
+
+/* Get size of extended register set of process running thread TH. */
+extern td_err_e td_thr_getxregsize (const td_thrhandle_t *__th, int *__sizep);
+
+/* Set floating-point register contents of process running thread TH. */
+extern td_err_e td_thr_setfpregs (const td_thrhandle_t *__th,
+ const prfpregset_t *__fpregs);
+
+/* Set general register contents of process running thread TH. */
+extern td_err_e td_thr_setgregs (const td_thrhandle_t *__th,
+ prgregset_t __gregs);
+
+/* Set extended register contents of process running thread TH. */
+extern td_err_e td_thr_setxregs (const td_thrhandle_t *__th,
+ const void *__addr);
+
+
+/* Get address of the given module's TLS storage area for the given thread. */
+extern td_err_e td_thr_tlsbase (const td_thrhandle_t *__th,
+ unsigned long int __modid,
+ psaddr_t *__base);
+
+/* Get address of thread local variable. */
+extern td_err_e td_thr_tls_get_addr (const td_thrhandle_t *__th,
+ psaddr_t __map_address, size_t __offset,
+ psaddr_t *__address);
+
+
+/* Enable reporting for EVENT for thread TH. */
+extern td_err_e td_thr_event_enable (const td_thrhandle_t *__th, int __event);
+
+/* Enable EVENT for thread TH. */
+extern td_err_e td_thr_set_event (const td_thrhandle_t *__th,
+ td_thr_events_t *__event);
+
+/* Disable EVENT for thread TH. */
+extern td_err_e td_thr_clear_event (const td_thrhandle_t *__th,
+ td_thr_events_t *__event);
+
+/* Get event message for thread TH. */
+extern td_err_e td_thr_event_getmsg (const td_thrhandle_t *__th,
+ td_event_msg_t *__msg);
+
+
+/* Set priority of thread TH. */
+extern td_err_e td_thr_setprio (const td_thrhandle_t *__th, int __prio);
+
+
+/* Set pending signals for thread TH. */
+extern td_err_e td_thr_setsigpending (const td_thrhandle_t *__th,
+ unsigned char __n, const sigset_t *__ss);
+
+/* Set signal mask for thread TH. */
+extern td_err_e td_thr_sigsetmask (const td_thrhandle_t *__th,
+ const sigset_t *__ss);
+
+
+/* Return thread local data associated with key TK in thread TH. */
+extern td_err_e td_thr_tsd (const td_thrhandle_t *__th,
+ const thread_key_t __tk, void **__data);
+
+
+/* Suspend execution of thread TH. */
+extern td_err_e td_thr_dbsuspend (const td_thrhandle_t *__th);
+
+/* Resume execution of thread TH. */
+extern td_err_e td_thr_dbresume (const td_thrhandle_t *__th);
+
+#endif /* thread_db.h */
diff --git a/libpthread/nptl_db/thread_dbP.h b/libpthread/nptl_db/thread_dbP.h
new file mode 100644
index 000000000..c3d263b0c
--- /dev/null
+++ b/libpthread/nptl_db/thread_dbP.h
@@ -0,0 +1,258 @@
+/* Private header for thread debug library
+ Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _THREAD_DBP_H
+#define _THREAD_DBP_H 1
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <assert.h>
+#include "proc_service.h"
+#include "thread_db.h"
+#include "../nptl/pthreadP.h" /* This is for *_BITMASK only. */
+
+#ifdef __UCLIBC__
+#define __alloca alloca
+#endif
+
+/* Indeces for the symbol names. */
+enum
+ {
+# define DB_STRUCT(type) SYM_SIZEOF_##type,
+# define DB_STRUCT_FIELD(type, field) SYM_##type##_FIELD_##field,
+# define DB_SYMBOL(name) SYM_##name,
+# define DB_FUNCTION(name) SYM_##name,
+# define DB_VARIABLE(name) SYM_##name, SYM_DESC_##name,
+# include "structs.def"
+# undef DB_STRUCT
+# undef DB_STRUCT_FIELD
+# undef DB_SYMBOL
+# undef DB_FUNCTION
+# undef DB_VARIABLE
+
+ SYM_TH_UNIQUE_CONST_THREAD_AREA,
+ SYM_TH_UNIQUE_REGISTER64,
+ SYM_TH_UNIQUE_REGISTER32,
+ SYM_TH_UNIQUE_REGISTER64_THREAD_AREA,
+ SYM_TH_UNIQUE_REGISTER32_THREAD_AREA,
+
+ SYM_NUM_MESSAGES
+ };
+
+
+/* Comment out the following for less verbose output. */
+#ifndef NDEBUG
+# define LOG(c) if (__td_debug) write (2, c "\n", strlen (c "\n"))
+extern int __td_debug attribute_hidden;
+#else
+# define LOG(c)
+#endif
+
+
+#define DB_DESC_SIZE(desc) ((desc)[0])
+#define DB_DESC_NELEM(desc) ((desc)[1])
+#define DB_DESC_OFFSET(desc) ((desc)[2])
+#define DB_SIZEOF_DESC (3 * sizeof (uint32_t))
+#define DB_DEFINE_DESC(name, size, nelem, offset) \
+ const uint32_t name[3] = { (size), (nelem), (offset) }
+typedef uint32_t db_desc_t[3];
+
+
+/* Handle for a process. This type is opaque. */
+struct td_thragent
+{
+ /* Chain on the list of all agent structures. */
+ list_t list;
+
+ /* Delivered by the debugger and we have to pass it back in the
+ proc callbacks. */
+ struct ps_prochandle *ph;
+
+ /* Cached values read from the inferior. */
+# define DB_STRUCT(type) \
+ uint32_t ta_sizeof_##type;
+# define DB_STRUCT_FIELD(type, field) \
+ db_desc_t ta_field_##type##_##field;
+# define DB_SYMBOL(name) \
+ psaddr_t ta_addr_##name;
+# define DB_FUNCTION(name) \
+ psaddr_t ta_addr_##name;
+# define DB_VARIABLE(name) \
+ psaddr_t ta_addr_##name; \
+ db_desc_t ta_var_##name;
+# include "structs.def"
+# undef DB_STRUCT
+# undef DB_STRUCT_FIELD
+# undef DB_FUNCTION
+# undef DB_SYMBOL
+# undef DB_VARIABLE
+
+ /* The method of locating a thread's th_unique value. */
+ enum
+ {
+ ta_howto_unknown,
+ ta_howto_reg,
+ ta_howto_reg_thread_area,
+ ta_howto_const_thread_area
+ } ta_howto;
+ union
+ {
+ uint32_t const_thread_area; /* Constant argument to ps_get_thread_area. */
+ /* These are as if the descriptor of the field in prregset_t,
+ but DB_DESC_NELEM is overloaded as follows: */
+ db_desc_t reg; /* Signed bias applied to register value. */
+ db_desc_t reg_thread_area; /* Bits to scale down register value. */
+ } ta_howto_data;
+};
+
+
+/* List of all known descriptors. */
+extern list_t __td_agent_list attribute_hidden;
+
+
+/* Function used to test for correct thread agent pointer. */
+static inline bool
+ta_ok (const td_thragent_t *ta)
+{
+ list_t *runp;
+
+ list_for_each (runp, &__td_agent_list)
+ if (list_entry (runp, td_thragent_t, list) == ta)
+ return true;
+
+ return false;
+}
+
+
+/* Internal wrapper around ps_pglobal_lookup. */
+extern ps_err_e td_lookup (struct ps_prochandle *ps,
+ int idx, psaddr_t *sym_addr) attribute_hidden;
+
+
+
+
+/* Store in psaddr_t VAR the address of inferior's symbol NAME. */
+#define DB_GET_SYMBOL(var, ta, name) \
+ (((ta)->ta_addr_##name == 0 \
+ && td_lookup ((ta)->ph, SYM_##name, &(ta)->ta_addr_##name) != PS_OK) \
+ ? TD_ERR : ((var) = (ta)->ta_addr_##name, TD_OK))
+
+/* Store in psaddr_t VAR the value of ((TYPE) PTR)->FIELD[IDX] in the inferior.
+ A target field smaller than psaddr_t is zero-extended. */
+#define DB_GET_FIELD(var, ta, ptr, type, field, idx) \
+ _td_fetch_value ((ta), (ta)->ta_field_##type##_##field, \
+ SYM_##type##_FIELD_##field, \
+ (psaddr_t) 0 + (idx), (ptr), &(var))
+
+#define DB_GET_FIELD_ADDRESS(var, ta, ptr, type, field, idx) \
+ ((var) = (ptr), _td_locate_field ((ta), (ta)->ta_field_##type##_##field, \
+ SYM_##type##_FIELD_##field, \
+ (psaddr_t) 0 + (idx), &(var)))
+
+extern td_err_e _td_locate_field (td_thragent_t *ta,
+ db_desc_t desc, int descriptor_name,
+ psaddr_t idx,
+ psaddr_t *address) attribute_hidden;
+
+
+/* Like DB_GET_FIELD, but PTR is a local pointer to a structure that
+ has already been copied in from the inferior. */
+#define DB_GET_FIELD_LOCAL(var, ta, ptr, type, field, idx) \
+ _td_fetch_value_local ((ta), (ta)->ta_field_##type##_##field, \
+ SYM_##type##_FIELD_##field, \
+ (psaddr_t) 0 + (idx), (ptr), &(var))
+
+/* Store in psaddr_t VAR the value of variable NAME[IDX] in the inferior.
+ A target value smaller than psaddr_t is zero-extended. */
+#define DB_GET_VALUE(var, ta, name, idx) \
+ (((ta)->ta_addr_##name == 0 \
+ && td_lookup ((ta)->ph, SYM_##name, &(ta)->ta_addr_##name) != PS_OK) \
+ ? TD_ERR \
+ : _td_fetch_value ((ta), (ta)->ta_var_##name, SYM_DESC_##name, \
+ (psaddr_t) 0 + (idx), (ta)->ta_addr_##name, &(var)))
+
+/* Helper functions for those. */
+extern td_err_e _td_fetch_value (td_thragent_t *ta,
+ db_desc_t field, int descriptor_name,
+ psaddr_t idx, psaddr_t address,
+ psaddr_t *result) attribute_hidden;
+extern td_err_e _td_fetch_value_local (td_thragent_t *ta,
+ db_desc_t field,
+ int descriptor_name,
+ psaddr_t idx, void *address,
+ psaddr_t *result) attribute_hidden;
+
+/* Store psaddr_t VALUE in ((TYPE) PTR)->FIELD[IDX] in the inferior.
+ A target field smaller than psaddr_t is zero-extended. */
+#define DB_PUT_FIELD(ta, ptr, type, field, idx, value) \
+ _td_store_value ((ta), (ta)->ta_field_##type##_##field, \
+ SYM_##type##_FIELD_##field, \
+ (psaddr_t) 0 + (idx), (ptr), (value))
+
+#define DB_PUT_FIELD_LOCAL(ta, ptr, type, field, idx, value) \
+ _td_store_value_local ((ta), (ta)->ta_field_##type##_##field, \
+ SYM_##type##_FIELD_##field, \
+ (psaddr_t) 0 + (idx), (ptr), (value))
+
+/* Store psaddr_t VALUE in variable NAME[IDX] in the inferior.
+ A target field smaller than psaddr_t is zero-extended. */
+#define DB_PUT_VALUE(ta, name, idx, value) \
+ (((ta)->ta_addr_##name == 0 \
+ && td_lookup ((ta)->ph, SYM_##name, &(ta)->ta_addr_##name) != PS_OK) \
+ ? TD_ERR \
+ : _td_store_value ((ta), (ta)->ta_var_##name, SYM_DESC_##name, \
+ (psaddr_t) 0 + (idx), (ta)->ta_addr_##name, (value)))
+
+/* Helper functions for those. */
+extern td_err_e _td_store_value (td_thragent_t *ta,
+ db_desc_t field, int descriptor_name,
+ psaddr_t idx, psaddr_t address,
+ psaddr_t value) attribute_hidden;
+extern td_err_e _td_store_value_local (td_thragent_t *ta,
+ db_desc_t field, int descriptor_name,
+ psaddr_t idx, void *address,
+ psaddr_t value) attribute_hidden;
+
+#define DB_GET_STRUCT(var, ta, ptr, type) \
+ ({ td_err_e _err = TD_OK; \
+ if ((ta)->ta_sizeof_##type == 0) \
+ _err = _td_check_sizeof ((ta), &(ta)->ta_sizeof_##type, \
+ SYM_SIZEOF_##type); \
+ if (_err == TD_OK) \
+ _err = ps_pdread ((ta)->ph, (ptr), \
+ (var) = __alloca ((ta)->ta_sizeof_##type), \
+ (ta)->ta_sizeof_##type) \
+ == PS_OK ? TD_OK : TD_ERR; \
+ else \
+ (var) = NULL; \
+ _err; \
+ })
+#define DB_PUT_STRUCT(ta, ptr, type, copy) \
+ ({ assert ((ta)->ta_sizeof_##type != 0); \
+ ps_pdwrite ((ta)->ph, (ptr), (copy), (ta)->ta_sizeof_##type) \
+ == PS_OK ? TD_OK : TD_ERR; \
+ })
+
+extern td_err_e _td_check_sizeof (td_thragent_t *ta, uint32_t *sizep,
+ int sizep_name) attribute_hidden;
+
+#endif /* thread_dbP.h */