summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland McGrath <roland@redhat.com>2009-11-22 20:42:53 -0800
committerRoland McGrath <roland@redhat.com>2009-12-09 01:01:28 -0800
commit6f1672172c9c9e5eb5afdcf521e3528b38b2e2dd (patch)
treef1ca70b5d1c32d593b0c2e825f10c56b49d14c06
parentee1a7fabb4e0abd3e73e828ce326dcb5fd38b874 (diff)
downloadglibc-roland/nptl_db.tar.gz
Make libthread_db work without libpthread, just enough for TLS decoding.roland/nptl_db
-rw-r--r--nptl/ChangeLog5
-rw-r--r--nptl/sysdeps/pthread/Versions6
-rw-r--r--nptl/sysdeps/pthread/dl-sysdep.c38
-rw-r--r--nptl_db/ChangeLog47
-rw-r--r--nptl_db/Makefile10
-rw-r--r--nptl_db/db-symbols.awk4
-rw-r--r--nptl_db/fetch-value.c6
-rw-r--r--nptl_db/rtld-db-symbols.awk5
-rw-r--r--nptl_db/structs.def10
-rw-r--r--nptl_db/td_symbol_list.c6
-rw-r--r--nptl_db/td_ta_clear_event.c7
-rw-r--r--nptl_db/td_ta_event_addr.c6
-rw-r--r--nptl_db/td_ta_event_getmsg.c6
-rw-r--r--nptl_db/td_ta_get_nthreads.c6
-rw-r--r--nptl_db/td_ta_map_lwp2thr.c29
-rw-r--r--nptl_db/td_ta_new.c58
-rw-r--r--nptl_db/td_ta_set_event.c7
-rw-r--r--nptl_db/td_ta_thr_iter.c31
-rw-r--r--nptl_db/td_ta_tsd_iter.c6
-rw-r--r--nptl_db/td_thr_clear_event.c9
-rw-r--r--nptl_db/td_thr_event_enable.c6
-rw-r--r--nptl_db/td_thr_event_getmsg.c9
-rw-r--r--nptl_db/td_thr_get_info.c10
-rw-r--r--nptl_db/td_thr_set_event.c9
-rw-r--r--nptl_db/td_thr_tsd.c7
-rw-r--r--nptl_db/td_thr_validate.c34
-rw-r--r--nptl_db/thread_dbP.h18
27 files changed, 310 insertions, 85 deletions
diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index 494b5904fb..d8dee1c0e9 100644
--- a/nptl/ChangeLog
+++ b/nptl/ChangeLog
@@ -1,3 +1,8 @@
+2009-11-23 Roland McGrath <roland@redhat.com>
+
+ * sysdeps/pthread/dl-sysdep.c: New file.
+ * sysdeps/pthread/Versions: New file.
+
2009-11-27 Thomas Schwinge <thomas@codesourcery.com>
* sysdeps/unix/sysv/linux/sh/pt-initfini.c (_init): Don't call
diff --git a/nptl/sysdeps/pthread/Versions b/nptl/sysdeps/pthread/Versions
new file mode 100644
index 0000000000..ab6aec0fe0
--- /dev/null
+++ b/nptl/sysdeps/pthread/Versions
@@ -0,0 +1,6 @@
+ld {
+ GLIBC_PRIVATE {
+ # These are used by libthread_db, so must be visible somehow.
+ _thread_db_*;
+ }
+}
diff --git a/nptl/sysdeps/pthread/dl-sysdep.c b/nptl/sysdeps/pthread/dl-sysdep.c
new file mode 100644
index 0000000000..3dbeebc4fa
--- /dev/null
+++ b/nptl/sysdeps/pthread/dl-sysdep.c
@@ -0,0 +1,38 @@
+/* libthread_db hooks in the dynamic linker.
+ Copyright (C) 2009 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. */
+
+/* This cpp magic lets us use #include_next in the #else branch. */
+#ifndef IS_IN_dl_sysdep
+# define IS_IN_dl_sysdep 1
+# include <dl-sysdep.c>
+#else
+
+# include_next <dl-sysdep.c>
+
+/* A dynamic linker with TLS support needs to make some information
+ available to libthread_db so debuggers can figure out TLS lookups
+ even when libpthread is not loaded. */
+
+# include <version.h>
+
+const char _thread_db_dl_nptl_version[] __attribute_used__ = VERSION;
+
+# include <../nptl_db/db_info.c>
+
+#endif
diff --git a/nptl_db/ChangeLog b/nptl_db/ChangeLog
index f79fc18e4b..55948b5d94 100644
--- a/nptl_db/ChangeLog
+++ b/nptl_db/ChangeLog
@@ -1,3 +1,50 @@
+2009-11-23 Roland McGrath <roland@redhat.com>
+
+ * rtld-db-symbols.awk: New file.
+ * Makefile (distribute): Add it.
+ ($(objpfx)rtld-db-symbols.v.i): New target.
+ ($(objpfx)rtld-db-symbols.out): New target.
+ (tests): Depend on that.
+
+ * td_ta_map_lwp2thr.c (td_ta_map_lwp2thr): Handle TD_NOLIBTHREAD case
+ like pre-initialization case.
+ * td_thr_validate.c (td_thr_validate): Likewise.
+ * td_ta_thr_iter.c (td_ta_thr_iter): Likewise.
+
+ * td_ta_clear_event.c: Call _td_ta_check_nptl first and punt on failure.
+ * td_ta_event_addr.c: Likewise.
+ * td_ta_event_getmsg.c: Likewise.
+ * td_ta_get_nthreads.c: Likewise.
+ * td_ta_set_event.c: Likewise.
+ * td_ta_tsd_iter.c: Likewise.
+ * td_thr_clear_event.c: Likewise.
+ * td_thr_event_enable.c: Likewise.
+ * td_thr_event_getmsg.c: Likewise.
+ * td_thr_set_event.c: Likewise.
+ * td_thr_tsd.c: Likewise.
+
+ * td_ta_new.c (check_version): New function, broken out of ...
+ (td_ta_new): ... here. Call it. Cache version symbol addresses
+ in *TA. Accept _thread_db_dl_nptl_version from rtld if libpthread
+ lookup fails.
+ (_td_ta_check_nptl): New function.
+ * thread_dbP.h: Declare it.
+
+ * td_symbol_list.c (td_lookup): Renamed to ...
+ (td_lookup_1): ... this. Take RTLD flag to choose DSO name.
+ * thread_dbP.h (td_lookup_1): Declare it.
+ (td_lookup): Define as macro using that,
+ now take td_thragent pointer as first argument.
+ (DB_GET_SYMBOL, DB_GET_VALUE, DB_PUT_VALUE): Update callers.
+ * fetch-value.c (_td_locate_field, _td_check_sizeof): Likewise.
+ * td_ta_map_lwp2thr.c: Likewise.
+
+ * structs.def [IS_IN_libpthread || defined IS_IN_libthread_db]:
+ Put most fields under this condition, only TLS ones outside it.
+ [! IS_IN_libpthread]: Add _thread_db_dl_nptl_version symbol.
+ * db-symbols.awk [! IS_IN_rtld]: %define IS_IN_libpthread before
+ %include "db-symbols.h".
+
2009-08-23 Roland McGrath <roland@redhat.com>
* td_ta_map_lwp2thr.c (__td_ta_lookup_th_unique): Move ta_ok check
diff --git a/nptl_db/Makefile b/nptl_db/Makefile
index af542dcac9..8d53779246 100644
--- a/nptl_db/Makefile
+++ b/nptl_db/Makefile
@@ -51,7 +51,8 @@ libthread_db-inhibit-o = $(filter-out .os,$(object-suffixes))
libthread_db.so-no-z-defs = yes
distribute = thread_dbP.h shlib-versions proc_service.h \
- db_info.c structs.def db-symbols.h db-symbols.awk
+ db_info.c structs.def db-symbols.h \
+ db-symbols.awk rtld-db-symbols.awk
include ../Rules
# Depend on libc.so so a DT_NEEDED is generated in the shared objects.
@@ -66,3 +67,10 @@ $(objpfx)db-symbols.out: $(objpfx)db-symbols.v.i \
readelf -W -s $(filter %.so,$^) | $(AWK) -f $< > $@
$(objpfx)db-symbols.v.i: db-symbols.awk
+
+tests: $(objpfx)rtld-db-symbols.out
+$(objpfx)rtld-db-symbols.out: $(objpfx)rtld-db-symbols.v.i \
+ $(common-objpfx)elf/ld.so
+ readelf -W -s $(filter %.so,$^) | $(AWK) -f $< > $@
+
+$(objpfx)rtld-db-symbols.v.i: rtld-db-symbols.awk db-symbols.awk
diff --git a/nptl_db/db-symbols.awk b/nptl_db/db-symbols.awk
index f9a91b93bf..ce8701c806 100644
--- a/nptl_db/db-symbols.awk
+++ b/nptl_db/db-symbols.awk
@@ -1,6 +1,10 @@
# This script processes the output of 'readelf -W -s' on the libpthread.so
# we've just built. It checks for all the symbols used in td_symbol_list.
+%ifndef IS_IN_rtld
+%define IS_IN_libpthread
+%endif
+
BEGIN {
%define DB_LOOKUP_NAME(idx, name) required[STRINGIFY (name)] = 1;
%define DB_LOOKUP_NAME_TH_UNIQUE(idx, name) th_unique[STRINGIFY (name)] = 1;
diff --git a/nptl_db/fetch-value.c b/nptl_db/fetch-value.c
index 0d9bb0eb80..5c97502e20 100644
--- a/nptl_db/fetch-value.c
+++ b/nptl_db/fetch-value.c
@@ -1,5 +1,5 @@
/* Helper routines for libthread_db.
- Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2009 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
@@ -27,7 +27,7 @@ _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);
+ ps_err_e err = td_lookup (ta, sizep_name, &descptr);
if (err == PS_NOSYM)
return TD_NOCAPAB;
if (err == PS_OK)
@@ -51,7 +51,7 @@ _td_locate_field (td_thragent_t *ta,
{
/* Read the information about this field from the inferior. */
psaddr_t descptr;
- ps_err_e err = td_lookup (ta->ph, descriptor_name, &descptr);
+ ps_err_e err = td_lookup (ta, descriptor_name, &descptr);
if (err == PS_NOSYM)
return TD_NOCAPAB;
if (err == PS_OK)
diff --git a/nptl_db/rtld-db-symbols.awk b/nptl_db/rtld-db-symbols.awk
new file mode 100644
index 0000000000..a916eba718
--- /dev/null
+++ b/nptl_db/rtld-db-symbols.awk
@@ -0,0 +1,5 @@
+/* This file precedes db-symbols.awk before preprocessing when making
+ rtld-db-symbols.v.i for the test. We just set this macro here so
+ that we get the list of ld.so symbols instead of libpthread ones. */
+
+%define IS_IN_rtld
diff --git a/nptl_db/structs.def b/nptl_db/structs.def
index 75da95a36e..fbb36538fa 100644
--- a/nptl_db/structs.def
+++ b/nptl_db/structs.def
@@ -1,5 +1,5 @@
/* List of types and symbols in libpthread examined by libthread_db.
- Copyright (C) 2003, 2006, 2007, 2008 Free Software Foundation, Inc.
+ Copyright (C) 2003,2006,2007,2008,2009 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
@@ -23,6 +23,8 @@
# define STRUCTS_DEF_DEFAULTS 1
#endif
+#if defined IS_IN_libpthread || defined IS_IN_libthread_db
+
DB_STRUCT (pthread)
DB_STRUCT_FIELD (pthread, list)
DB_STRUCT_FIELD (pthread, report_events)
@@ -70,6 +72,12 @@ DB_STRUCT_FIELD (pthread_key_data, data)
DB_STRUCT (pthread_key_data_level2)
DB_STRUCT_ARRAY_FIELD (pthread_key_data_level2, data)
+#endif /* IS_IN_libpthread || IS_IN_libthread_db */
+
+#ifndef IS_IN_libpthread
+DB_SYMBOL (_thread_db_dl_nptl_version)
+#endif
+
DB_STRUCT_FIELD (link_map, l_tls_modid)
DB_STRUCT_ARRAY_FIELD (dtv, dtv)
diff --git a/nptl_db/td_symbol_list.c b/nptl_db/td_symbol_list.c
index 474251d627..bf2dbc1809 100644
--- a/nptl_db/td_symbol_list.c
+++ b/nptl_db/td_symbol_list.c
@@ -42,12 +42,12 @@ td_symbol_list (void)
ps_err_e
-td_lookup (struct ps_prochandle *ps, int idx, psaddr_t *sym_addr)
+td_lookup_1 (struct ps_prochandle *ps, int idx, psaddr_t *sym_addr, bool rtld)
{
ps_err_e result;
assert (idx >= 0 && idx < SYM_NUM_MESSAGES);
- result = ps_pglobal_lookup (ps, LIBPTHREAD_SO, symbol_list_arr[idx],
- sym_addr);
+ result = ps_pglobal_lookup (ps, rtld ? LD_SO : 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.
diff --git a/nptl_db/td_ta_clear_event.c b/nptl_db/td_ta_clear_event.c
index 7a2850c4ea..d3ec1b3409 100644
--- a/nptl_db/td_ta_clear_event.c
+++ b/nptl_db/td_ta_clear_event.c
@@ -1,5 +1,5 @@
/* Globally disable events.
- Copyright (C) 1999, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1999,2001,2002,2003,2004,2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
@@ -37,8 +37,11 @@ td_ta_clear_event (ta_arg, event)
if (! ta_ok (ta))
return TD_BADTA;
+ err = _td_ta_check_nptl (ta);
+
/* 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_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)
diff --git a/nptl_db/td_ta_event_addr.c b/nptl_db/td_ta_event_addr.c
index 37196e643f..1484bae3ca 100644
--- a/nptl_db/td_ta_event_addr.c
+++ b/nptl_db/td_ta_event_addr.c
@@ -1,5 +1,5 @@
/* Get event address.
- Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc.
+ Copyright (C) 1999,2001,2002,2003,2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
@@ -35,6 +35,10 @@ td_ta_event_addr (const td_thragent_t *ta_arg,
if (! ta_ok (ta))
return TD_BADTA;
+ err = _td_ta_check_nptl (ta);
+ if (err != TD_OK)
+ return err;
+
switch (event)
{
case TD_CREATE:
diff --git a/nptl_db/td_ta_event_getmsg.c b/nptl_db/td_ta_event_getmsg.c
index 6e68ff4ff2..258b4fba14 100644
--- a/nptl_db/td_ta_event_getmsg.c
+++ b/nptl_db/td_ta_event_getmsg.c
@@ -1,5 +1,5 @@
/* Retrieve event.
- Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1999,2001,2002,2003,2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
@@ -43,6 +43,10 @@ td_ta_event_getmsg (const td_thragent_t *ta_arg, td_event_msg_t *msg)
if (! ta_ok (ta))
return TD_BADTA;
+ err = _td_ta_check_nptl (ta);
+ if (err != TD_OK)
+ return err;
+
/* 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)
diff --git a/nptl_db/td_ta_get_nthreads.c b/nptl_db/td_ta_get_nthreads.c
index ffe78bd57e..a0480d1964 100644
--- a/nptl_db/td_ta_get_nthreads.c
+++ b/nptl_db/td_ta_get_nthreads.c
@@ -1,5 +1,5 @@
/* Get the number of threads in the process.
- Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc.
+ Copyright (C) 1999,2001,2002,2003,2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
@@ -33,6 +33,10 @@ td_ta_get_nthreads (const td_thragent_t *ta_arg, int *np)
if (! ta_ok (ta))
return TD_BADTA;
+ err = _td_ta_check_nptl (ta);
+ if (err != TD_OK)
+ return err;
+
/* Access the variable in the inferior that tells us. */
err = DB_GET_VALUE (n, ta, __nptl_nthreads, 0);
if (err == TD_OK)
diff --git a/nptl_db/td_ta_map_lwp2thr.c b/nptl_db/td_ta_map_lwp2thr.c
index 4835f31f94..d140358b5e 100644
--- a/nptl_db/td_ta_map_lwp2thr.c
+++ b/nptl_db/td_ta_map_lwp2thr.c
@@ -38,7 +38,7 @@ __td_ta_lookup_th_unique (const td_thragent_t *ta_arg,
/* 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);
+ err = td_lookup (ta, SYM_TH_UNIQUE_CONST_THREAD_AREA, &howto);
if (err == PS_OK)
{
err = ps_pdread (ta->ph, howto,
@@ -56,13 +56,12 @@ __td_ta_lookup_th_unique (const td_thragent_t *ta_arg,
switch (sizeof (regs[0]))
{
case 8:
- err = td_lookup (ta->ph, SYM_TH_UNIQUE_REGISTER64, &howto);
+ err = td_lookup (ta, 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,
+ err = td_lookup (ta, SYM_TH_UNIQUE_REGISTER64_THREAD_AREA,
&howto);
if (err == PS_OK)
ta->ta_howto = ta_howto_reg_thread_area;
@@ -70,13 +69,12 @@ __td_ta_lookup_th_unique (const td_thragent_t *ta_arg,
break;
case 4:
- err = td_lookup (ta->ph, SYM_TH_UNIQUE_REGISTER32, &howto);
+ err = td_lookup (ta, 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,
+ err = td_lookup (ta, SYM_TH_UNIQUE_REGISTER32_THREAD_AREA,
&howto);
if (err == PS_OK)
ta->ta_howto = ta_howto_reg_thread_area;
@@ -187,14 +185,19 @@ td_ta_map_lwp2thr (const td_thragent_t *ta_arg,
at exec. So if it looks like initialization is incomplete, we only
fake a special descriptor for the initial thread. */
- psaddr_t list;
- td_err_e err = DB_GET_SYMBOL (list, ta, __stack_user);
- if (err != TD_OK)
- return err;
+ psaddr_t list = 0;
- err = DB_GET_FIELD (list, ta, list, list_t, next, 0);
- if (err != TD_OK)
+ td_err_e err = _td_ta_check_nptl (ta);
+ if (err == TD_NOLIBTHREAD)
+ list = 0;
+ else if (err != TD_OK)
return err;
+ else
+ {
+ err = DB_GET_SYMBOL (list, ta, __stack_user);
+ if (err == TD_OK)
+ err = DB_GET_FIELD (list, ta, list, list_t, next, 0);
+ }
if (list == 0)
{
diff --git a/nptl_db/td_ta_new.c b/nptl_db/td_ta_new.c
index f84049af34..bbb4234f68 100644
--- a/nptl_db/td_ta_new.c
+++ b/nptl_db/td_ta_new.c
@@ -1,5 +1,5 @@
/* Attach to target process.
- Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc.
+ Copyright (C) 1999,2001,2002,2003,2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
@@ -30,18 +30,14 @@
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)
+static td_err_e
+check_version (struct ps_prochandle *ps, psaddr_t versaddr)
{
- 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)
+ if (versaddr == 0)
return TD_NOLIBTHREAD;
+
if (ps_pdread (ps, versaddr, versbuf, sizeof (versbuf)) != PS_OK)
return TD_ERR;
@@ -49,11 +45,35 @@ td_ta_new (struct ps_prochandle *ps, td_thragent_t **ta)
/* Not the right version. */
return TD_VERSION;
+ return TD_OK;
+}
+
+td_err_e
+td_ta_new (struct ps_prochandle *ps, td_thragent_t **ta)
+{
+ psaddr_t versaddr = 0;
+ psaddr_t dl_versaddr = 0;
+
+ LOG ("td_ta_new");
+
+ /* Check whether the versions match. */
+ if (td_lookup_1 (ps, SYM_nptl_version, &versaddr, false) != PS_OK
+ && td_lookup_1 (ps, SYM__thread_db_dl_nptl_version,
+ &dl_versaddr, true) != PS_OK)
+ return TD_NOLIBTHREAD;
+
+ td_err_e result = check_version (ps, versaddr ?: dl_versaddr);
+ if (result != TD_OK)
+ return result;
+
/* Fill in the appropriate information. */
*ta = (td_thragent_t *) calloc (1, sizeof (td_thragent_t));
if (*ta == NULL)
return TD_MALLOC;
+ (*ta)->ta_addr_nptl_version = versaddr;
+ (*ta)->ta_addr__thread_db_dl_nptl_version = dl_versaddr;
+
/* Store the proc handle which we will pass to the callback functions
back into the debugger. */
(*ta)->ph = ps;
@@ -63,3 +83,23 @@ td_ta_new (struct ps_prochandle *ps, td_thragent_t **ta)
return TD_OK;
}
+
+td_err_e
+_td_ta_check_nptl (td_thragent_t *ta)
+{
+ if (ta->ta_addr_nptl_version != 0)
+ return TD_OK;
+
+ if (ta->ta_addr__thread_db_dl_nptl_version == 0)
+ return TD_BADTA;
+
+ psaddr_t versaddr = 0;
+ if (td_lookup_1 (ta->ph, SYM_nptl_version, &versaddr, false) != PS_OK)
+ return TD_NOLIBTHREAD;
+
+ td_err_e result = check_version (ta->ph, versaddr);
+ if (result == TD_OK)
+ ta->ta_addr_nptl_version = versaddr;
+
+ return result;
+}
diff --git a/nptl_db/td_ta_set_event.c b/nptl_db/td_ta_set_event.c
index 29fc14bfb3..438800a626 100644
--- a/nptl_db/td_ta_set_event.c
+++ b/nptl_db/td_ta_set_event.c
@@ -1,5 +1,5 @@
/* Globally enable events.
- Copyright (C) 1999,2001,2002,2003,2004 Free Software Foundation, Inc.
+ Copyright (C) 1999,2001,2002,2003,2004,2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
@@ -37,8 +37,11 @@ td_ta_set_event (ta_arg, event)
if (! ta_ok (ta))
return TD_BADTA;
+ err = _td_ta_check_nptl (ta);
+
/* 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_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)
diff --git a/nptl_db/td_ta_thr_iter.c b/nptl_db/td_ta_thr_iter.c
index 9a594ed1d8..b5e71433a0 100644
--- a/nptl_db/td_ta_thr_iter.c
+++ b/nptl_db/td_ta_thr_iter.c
@@ -1,5 +1,5 @@
/* Iterate over a process's threads.
- Copyright (C) 1999,2000,2001,2002,2003,2004,2007,2008
+ Copyright (C) 1999,2000,2001,2002,2003,2004,2007,2008,2009
Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
@@ -23,6 +23,18 @@
static td_err_e
+fake_initial_thread (td_thragent_t *ta, td_thr_iter_f *callback, void *cbdata_p)
+{
+ /* __pthread_initialize_minimal has not run. There is just the main
+ thread to return. We cannot rely on its thread register. They
+ sometimes contain garbage that would confuse us, left by the
+ kernel at exec. So if it looks like initialization is incomplete,
+ we only fake a special descriptor for the initial thread. */
+ td_thrhandle_t th = { ta, 0 };
+ return (*callback) (&th, cbdata_p) != 0 ? TD_DBERR : TD_OK;
+}
+
+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, bool fake_empty, pid_t match_pid)
@@ -41,15 +53,7 @@ iterate_thread_list (td_thragent_t *ta, td_thr_iter_f *callback,
return err;
if (next == 0 && fake_empty)
- {
- /* __pthread_initialize_minimal has not run. There is just the main
- thread to return. We cannot rely on its thread register. They
- sometimes contain garbage that would confuse us, left by the
- kernel at exec. So if it looks like initialization is incomplete,
- we only fake a special descriptor for the initial thread. */
- td_thrhandle_t th = { ta, 0 };
- return callback (&th, cbdata_p) != 0 ? TD_DBERR : TD_OK;
- }
+ return fake_initial_thread (ta, callback, cbdata_p);
/* Cache the offset from struct pthread to its list_t member. */
err = DB_GET_FIELD_ADDRESS (ofs, ta, 0, pthread, list, 0);
@@ -148,6 +152,10 @@ td_ta_thr_iter (const td_thragent_t *ta_arg, td_thr_iter_f *callback,
if (! ta_ok (ta))
return TD_BADTA;
+ err = _td_ta_check_nptl (ta);
+ if (err == TD_NOLIBTHREAD)
+ return fake_initial_thread (ta, callback, cbdata_p);
+
/* 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
@@ -156,7 +164,8 @@ td_ta_thr_iter (const td_thragent_t *ta_arg, td_thr_iter_f *callback,
list of threads with user-defined stacks. */
pid_t pid = ps_getpid (ta->ph);
- err = DB_GET_SYMBOL (list, ta, __stack_user);
+ if (err == TD_OK)
+ err = DB_GET_SYMBOL (list, ta, __stack_user);
if (err == TD_OK)
err = iterate_thread_list (ta, callback, cbdata_p, state, ti_pri,
list, true, pid);
diff --git a/nptl_db/td_ta_tsd_iter.c b/nptl_db/td_ta_tsd_iter.c
index 9cfb1e8de0..cf5d919f86 100644
--- a/nptl_db/td_ta_tsd_iter.c
+++ b/nptl_db/td_ta_tsd_iter.c
@@ -1,5 +1,5 @@
/* Iterate over a process's thread-specific data.
- Copyright (C) 1999,2000,2001,2002,2003 Free Software Foundation, Inc.
+ Copyright (C) 1999,2000,2001,2002,2003,2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
@@ -38,6 +38,10 @@ td_ta_tsd_iter (const td_thragent_t *ta_arg, td_key_iter_f *callback,
if (! ta_ok (ta))
return TD_BADTA;
+ err = _td_ta_check_nptl (ta);
+ if (err != TD_OK)
+ return err;
+
/* This makes sure we have the size information on hand. */
addr = 0;
err = _td_locate_field (ta,
diff --git a/nptl_db/td_thr_clear_event.c b/nptl_db/td_thr_clear_event.c
index fc999df9c2..6e7b33481e 100644
--- a/nptl_db/td_thr_clear_event.c
+++ b/nptl_db/td_thr_clear_event.c
@@ -1,5 +1,5 @@
/* Disable specific event for thread.
- Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc.
+ Copyright (C) 1999,2001,2002,2003,2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
@@ -34,9 +34,12 @@ td_thr_clear_event (th, event)
LOG ("td_thr_clear_event");
+ err = _td_ta_check_nptl (th->th_ta_p);
+
/* 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_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)
diff --git a/nptl_db/td_thr_event_enable.c b/nptl_db/td_thr_event_enable.c
index c8b2cd463d..c6b1e794b7 100644
--- a/nptl_db/td_thr_event_enable.c
+++ b/nptl_db/td_thr_event_enable.c
@@ -1,5 +1,5 @@
/* Enable event process-wide.
- Copyright (C) 1999, 2001, 2002, 2003, 2007 Free Software Foundation, Inc.
+ Copyright (C) 1999,2001,2002,2003,2007,2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
@@ -28,6 +28,10 @@ td_thr_event_enable (th, onoff)
{
LOG ("td_thr_event_enable");
+ td_err_e err = _td_ta_check_nptl (th->th_ta_p);
+ if (err != TD_OK)
+ return err;
+
if (th->th_unique != 0)
{
/* Write the new value into the thread data structure. */
diff --git a/nptl_db/td_thr_event_getmsg.c b/nptl_db/td_thr_event_getmsg.c
index 70ea6953ed..f10bb5ff01 100644
--- a/nptl_db/td_thr_event_getmsg.c
+++ b/nptl_db/td_thr_event_getmsg.c
@@ -1,5 +1,5 @@
/* Retrieve event.
- Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1999,2001,2002,2003,2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
@@ -32,9 +32,12 @@ td_thr_event_getmsg (const td_thrhandle_t *th, td_event_msg_t *msg)
LOG ("td_thr_event_getmsg");
+ err = _td_ta_check_nptl (th->th_ta_p);
+
/* 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_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)
diff --git a/nptl_db/td_thr_get_info.c b/nptl_db/td_thr_get_info.c
index 52985603bf..80513ea767 100644
--- a/nptl_db/td_thr_get_info.c
+++ b/nptl_db/td_thr_get_info.c
@@ -41,8 +41,14 @@ td_thr_get_info (const td_thrhandle_t *th, td_thrinfo_t *infop)
schedpolicy = SCHED_OTHER;
schedprio = 0;
tid = 0;
- err = DB_GET_VALUE (report_events, th->th_ta_p,
- __nptl_initial_report_events, 0);
+ if (th->th_ta_p->ta_addr_nptl_version == 0)
+ {
+ report_events = 0;
+ err = TD_OK;
+ }
+ else
+ err = DB_GET_VALUE (report_events, th->th_ta_p,
+ __nptl_initial_report_events, 0);
}
else
{
diff --git a/nptl_db/td_thr_set_event.c b/nptl_db/td_thr_set_event.c
index 2bb0b9d1f8..772a25fd5e 100644
--- a/nptl_db/td_thr_set_event.c
+++ b/nptl_db/td_thr_set_event.c
@@ -1,5 +1,5 @@
/* Enable specific event for thread.
- Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc.
+ Copyright (C) 1999,2001,2002,2003,2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
@@ -34,9 +34,12 @@ td_thr_set_event (th, event)
LOG ("td_thr_set_event");
+ err = _td_ta_check_nptl (th->th_ta_p);
+
/* 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_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)
diff --git a/nptl_db/td_thr_tsd.c b/nptl_db/td_thr_tsd.c
index 08f617b7d2..9082ce3101 100644
--- a/nptl_db/td_thr_tsd.c
+++ b/nptl_db/td_thr_tsd.c
@@ -1,5 +1,5 @@
/* Get a thread-specific data pointer for a thread.
- Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc.
+ Copyright (C) 1999,2001,2002,2003,2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
@@ -31,8 +31,11 @@ td_thr_tsd (const td_thrhandle_t *th, const thread_key_t tk, void **data)
LOG ("td_thr_tsd");
+ err = _td_ta_check_nptl (th->th_ta_p);
+
/* Get the key entry. */
- err = DB_GET_VALUE (tk_seq, th->th_ta_p, __pthread_keys, tk);
+ if (err == TD_OK)
+ err = DB_GET_VALUE (tk_seq, th->th_ta_p, __pthread_keys, tk);
if (err == TD_NOAPLIC)
return TD_BADKEY;
if (err != TD_OK)
diff --git a/nptl_db/td_thr_validate.c b/nptl_db/td_thr_validate.c
index adcde3c87e..45d8546dd8 100644
--- a/nptl_db/td_thr_validate.c
+++ b/nptl_db/td_thr_validate.c
@@ -62,24 +62,30 @@ td_thr_validate (const td_thrhandle_t *th)
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 = _td_ta_check_nptl (th->th_ta_p);
+ if (err == TD_NOLIBTHREAD && th->th_unique == 0)
+ err = TD_OK;
+ else if (err == TD_OK)
{
- err = DB_GET_SYMBOL (list, th->th_ta_p, stack_used);
+ /* 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 (err == TD_NOTHR && uninit && th->th_unique == 0)
- /* __pthread_initialize_minimal has not run yet.
- There is only the special case thread handle. */
- err = TD_OK;
+ /* 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 && th->th_unique == 0)
+ /* __pthread_initialize_minimal has not run yet.
+ There is only the special case thread handle. */
+ err = TD_OK;
+ }
}
if (err == TD_OK)
diff --git a/nptl_db/thread_dbP.h b/nptl_db/thread_dbP.h
index e5db9bf94b..6d0e91dea3 100644
--- a/nptl_db/thread_dbP.h
+++ b/nptl_db/thread_dbP.h
@@ -1,5 +1,5 @@
/* Private header for thread debug library
- Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2003,2004,2007,2009 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
@@ -140,16 +140,16 @@ ta_ok (const td_thragent_t *ta)
/* Internal wrapper around ps_pglobal_lookup. */
-extern ps_err_e td_lookup (struct ps_prochandle *ps,
- int idx, psaddr_t *sym_addr) attribute_hidden;
-
-
+extern ps_err_e td_lookup_1 (struct ps_prochandle *ps, int idx,
+ psaddr_t *sym_addr, bool rtld) attribute_hidden;
+#define td_lookup(ta, idx, sym_addr) \
+ td_lookup_1 ((ta)->ph, idx, sym_addr, (ta)->ta_addr_nptl_version == 0)
/* 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_lookup ((ta), 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.
@@ -181,7 +181,7 @@ extern td_err_e _td_locate_field (td_thragent_t *ta,
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_lookup ((ta), 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)))
@@ -213,7 +213,7 @@ extern td_err_e _td_fetch_value_local (td_thragent_t *ta,
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_lookup ((ta), 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)))
@@ -254,4 +254,6 @@ extern td_err_e _td_check_sizeof (td_thragent_t *ta, uint32_t *sizep,
extern td_err_e __td_ta_lookup_th_unique (const td_thragent_t *ta,
lwpid_t lwpid, td_thrhandle_t *th);
+extern td_err_e _td_ta_check_nptl (td_thragent_t *ta) attribute_hidden;
+
#endif /* thread_dbP.h */