OSDN Git Service

libpthread/nptl_db: debugging support for nptl
authorAustin Foxley <austinf@cetoncorp.com>
Sat, 17 Oct 2009 19:32:38 +0000 (12:32 -0700)
committerAustin Foxley <austinf@cetoncorp.com>
Sat, 17 Oct 2009 19:32:38 +0000 (12:32 -0700)
Signed-off-by: Austin Foxley <austinf@cetoncorp.com>
49 files changed:
libpthread/nptl_db/ChangeLog [new file with mode: 0644]
libpthread/nptl_db/Makefile [new file with mode: 0644]
libpthread/nptl_db/Makefile.in [new file with mode: 0644]
libpthread/nptl_db/db_info.c [new file with mode: 0644]
libpthread/nptl_db/fetch-value.c [new file with mode: 0644]
libpthread/nptl_db/proc_service.h [new file with mode: 0644]
libpthread/nptl_db/structs.def [new file with mode: 0644]
libpthread/nptl_db/td_init.c [new file with mode: 0644]
libpthread/nptl_db/td_log.c [new file with mode: 0644]
libpthread/nptl_db/td_symbol_list.c [new file with mode: 0644]
libpthread/nptl_db/td_ta_clear_event.c [new file with mode: 0644]
libpthread/nptl_db/td_ta_delete.c [new file with mode: 0644]
libpthread/nptl_db/td_ta_enable_stats.c [new file with mode: 0644]
libpthread/nptl_db/td_ta_event_addr.c [new file with mode: 0644]
libpthread/nptl_db/td_ta_event_getmsg.c [new file with mode: 0644]
libpthread/nptl_db/td_ta_get_nthreads.c [new file with mode: 0644]
libpthread/nptl_db/td_ta_get_ph.c [new file with mode: 0644]
libpthread/nptl_db/td_ta_get_stats.c [new file with mode: 0644]
libpthread/nptl_db/td_ta_map_id2thr.c [new file with mode: 0644]
libpthread/nptl_db/td_ta_map_lwp2thr.c [new file with mode: 0644]
libpthread/nptl_db/td_ta_new.c [new file with mode: 0644]
libpthread/nptl_db/td_ta_reset_stats.c [new file with mode: 0644]
libpthread/nptl_db/td_ta_set_event.c [new file with mode: 0644]
libpthread/nptl_db/td_ta_setconcurrency.c [new file with mode: 0644]
libpthread/nptl_db/td_ta_thr_iter.c [new file with mode: 0644]
libpthread/nptl_db/td_ta_tsd_iter.c [new file with mode: 0644]
libpthread/nptl_db/td_thr_clear_event.c [new file with mode: 0644]
libpthread/nptl_db/td_thr_dbresume.c [new file with mode: 0644]
libpthread/nptl_db/td_thr_dbsuspend.c [new file with mode: 0644]
libpthread/nptl_db/td_thr_event_enable.c [new file with mode: 0644]
libpthread/nptl_db/td_thr_event_getmsg.c [new file with mode: 0644]
libpthread/nptl_db/td_thr_get_info.c [new file with mode: 0644]
libpthread/nptl_db/td_thr_getfpregs.c [new file with mode: 0644]
libpthread/nptl_db/td_thr_getgregs.c [new file with mode: 0644]
libpthread/nptl_db/td_thr_getxregs.c [new file with mode: 0644]
libpthread/nptl_db/td_thr_getxregsize.c [new file with mode: 0644]
libpthread/nptl_db/td_thr_set_event.c [new file with mode: 0644]
libpthread/nptl_db/td_thr_setfpregs.c [new file with mode: 0644]
libpthread/nptl_db/td_thr_setgregs.c [new file with mode: 0644]
libpthread/nptl_db/td_thr_setprio.c [new file with mode: 0644]
libpthread/nptl_db/td_thr_setsigpending.c [new file with mode: 0644]
libpthread/nptl_db/td_thr_setxregs.c [new file with mode: 0644]
libpthread/nptl_db/td_thr_sigsetmask.c [new file with mode: 0644]
libpthread/nptl_db/td_thr_tls_get_addr.c [new file with mode: 0644]
libpthread/nptl_db/td_thr_tlsbase.c [new file with mode: 0644]
libpthread/nptl_db/td_thr_tsd.c [new file with mode: 0644]
libpthread/nptl_db/td_thr_validate.c [new file with mode: 0644]
libpthread/nptl_db/thread_db.h [new file with mode: 0644]
libpthread/nptl_db/thread_dbP.h [new file with mode: 0644]

diff --git a/libpthread/nptl_db/ChangeLog b/libpthread/nptl_db/ChangeLog
new file mode 100644 (file)
index 0000000..52c8491
--- /dev/null
@@ -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 (file)
index 0000000..f910021
--- /dev/null
@@ -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 (file)
index 0000000..3eaded5
--- /dev/null
@@ -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 (file)
index 0000000..5aec152
--- /dev/null
@@ -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 (file)
index 0000000..0d9bb0e
--- /dev/null
@@ -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 (file)
index 0000000..d49e87a
--- /dev/null
@@ -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 (file)
index 0000000..823af5c
--- /dev/null
@@ -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 (file)
index 0000000..946ff72
--- /dev/null
@@ -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 (file)
index 0000000..52212a0
--- /dev/null
@@ -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 (file)
index 0000000..04aed67
--- /dev/null
@@ -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 (file)
index 0000000..7a2850c
--- /dev/null
@@ -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 (file)
index 0000000..57b90e5
--- /dev/null
@@ -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 (file)
index 0000000..ec7014a
--- /dev/null
@@ -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 (file)
index 0000000..45c6b11
--- /dev/null
@@ -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 (file)
index 0000000..d3b46bd
--- /dev/null
@@ -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 (file)
index 0000000..ffe78bd
--- /dev/null
@@ -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 (file)
index 0000000..04e01fb
--- /dev/null
@@ -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 (file)
index 0000000..d5d879c
--- /dev/null
@@ -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 (file)
index 0000000..189a671
--- /dev/null
@@ -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 (file)
index 0000000..1e93210
--- /dev/null
@@ -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 (file)
index 0000000..f84049a
--- /dev/null
@@ -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 (file)
index 0000000..ea59d2c
--- /dev/null
@@ -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 (file)
index 0000000..29fc14b
--- /dev/null
@@ -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 (file)
index 0000000..8552ffb
--- /dev/null
@@ -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 (file)
index 0000000..66e4376
--- /dev/null
@@ -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 (file)
index 0000000..9cfb1e8
--- /dev/null
@@ -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 (file)
index 0000000..c43c625
--- /dev/null
@@ -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 (file)
index 0000000..3fd7943
--- /dev/null
@@ -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 (file)
index 0000000..6ef82ad
--- /dev/null
@@ -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 (file)
index 0000000..a02be5d
--- /dev/null
@@ -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 (file)
index 0000000..b24fc25
--- /dev/null
@@ -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 (file)
index 0000000..bb13888
--- /dev/null
@@ -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 (file)
index 0000000..7760512
--- /dev/null
@@ -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 (file)
index 0000000..4c2373e
--- /dev/null
@@ -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 (file)
index 0000000..3c77ab6
--- /dev/null
@@ -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 (file)
index 0000000..1704e4b
--- /dev/null
@@ -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 (file)
index 0000000..6617147
--- /dev/null
@@ -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 (file)
index 0000000..01bdb53
--- /dev/null
@@ -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 (file)
index 0000000..2a9ce7e
--- /dev/null
@@ -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 (file)
index 0000000..6032b0e
--- /dev/null
@@ -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 (file)
index 0000000..e2c9d7a
--- /dev/null
@@ -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 (file)
index 0000000..f48877c
--- /dev/null
@@ -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 (file)
index 0000000..3a68aec
--- /dev/null
@@ -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 (file)
index 0000000..e7d2322
--- /dev/null
@@ -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 (file)
index 0000000..aaeda6f
--- /dev/null
@@ -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 (file)
index 0000000..08f617b
--- /dev/null
@@ -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 (file)
index 0000000..19ee940
--- /dev/null
@@ -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 (file)
index 0000000..433b54f
--- /dev/null
@@ -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 (file)
index 0000000..c3d263b
--- /dev/null
@@ -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 */