+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
--- /dev/null
+ld {
+ GLIBC_PRIVATE {
+ # These are used by libthread_db, so must be visible somehow.
+ _thread_db_*;
+ }
+}
--- /dev/null
+/* 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
+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
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.
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
# 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;
/* 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
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)
{
/* 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)
--- /dev/null
+/* 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
/* 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
# 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)
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)
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.
/* 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.
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)
/* 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.
if (! ta_ok (ta))
return TD_BADTA;
+ err = _td_ta_check_nptl (ta);
+ if (err != TD_OK)
+ return err;
+
switch (event)
{
case TD_CREATE:
/* 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.
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)
/* 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.
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)
/* 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,
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;
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;
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)
{
/* 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.
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;
/* 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;
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;
+}
/* 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.
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)
/* 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.
#include "thread_dbP.h"
+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,
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);
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
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);
/* 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.
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,
/* 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.
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)
/* 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.
{
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. */
/* 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.
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)
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
{
/* 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.
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)
/* 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.
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)
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)
/* 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
/* 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.
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)))
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)))
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 */