From 6f1672172c9c9e5eb5afdcf521e3528b38b2e2dd Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Sun, 22 Nov 2009 20:42:53 -0800 Subject: Make libthread_db work without libpthread, just enough for TLS decoding. --- nptl/ChangeLog | 5 ++++ nptl/sysdeps/pthread/Versions | 6 +++++ nptl/sysdeps/pthread/dl-sysdep.c | 38 ++++++++++++++++++++++++++ nptl_db/ChangeLog | 47 ++++++++++++++++++++++++++++++++ nptl_db/Makefile | 10 ++++++- nptl_db/db-symbols.awk | 4 +++ nptl_db/fetch-value.c | 6 ++--- nptl_db/rtld-db-symbols.awk | 5 ++++ nptl_db/structs.def | 10 ++++++- nptl_db/td_symbol_list.c | 6 ++--- nptl_db/td_ta_clear_event.c | 7 +++-- nptl_db/td_ta_event_addr.c | 6 ++++- nptl_db/td_ta_event_getmsg.c | 6 ++++- nptl_db/td_ta_get_nthreads.c | 6 ++++- nptl_db/td_ta_map_lwp2thr.c | 29 +++++++++++--------- nptl_db/td_ta_new.c | 58 +++++++++++++++++++++++++++++++++------- nptl_db/td_ta_set_event.c | 7 +++-- nptl_db/td_ta_thr_iter.c | 31 +++++++++++++-------- nptl_db/td_ta_tsd_iter.c | 6 ++++- nptl_db/td_thr_clear_event.c | 9 ++++--- nptl_db/td_thr_event_enable.c | 6 ++++- nptl_db/td_thr_event_getmsg.c | 9 ++++--- nptl_db/td_thr_get_info.c | 10 +++++-- nptl_db/td_thr_set_event.c | 9 ++++--- nptl_db/td_thr_tsd.c | 7 +++-- nptl_db/td_thr_validate.c | 34 +++++++++++++---------- nptl_db/thread_dbP.h | 18 +++++++------ 27 files changed, 310 insertions(+), 85 deletions(-) create mode 100644 nptl/sysdeps/pthread/Versions create mode 100644 nptl/sysdeps/pthread/dl-sysdep.c create mode 100644 nptl_db/rtld-db-symbols.awk 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 + + * sysdeps/pthread/dl-sysdep.c: New file. + * sysdeps/pthread/Versions: New file. + 2009-11-27 Thomas Schwinge * 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 +#else + +# include_next + +/* 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 + +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 + + * 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 * 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 , 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 , 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 , 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 , 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 , 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 , 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 , 1999. @@ -22,6 +22,18 @@ #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, @@ -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 , 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 , 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 , 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 , 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 , 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 , 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 */ -- cgit 1.4.1