From 77e31bd04a937264436ddaa63ebceeb9a6c9b906 Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Wed, 13 Sep 2017 23:58:03 +0100 Subject: [PATCH] Allow loading libthread_db.so with non-threaded processes --- elf/dl-tls.c | 13 +++++++++++++ nptl_db/structs.def | 6 ++++-- nptl_db/td_ta_map_lwp2thr.c | 27 +++++++++++++++++++-------- nptl_db/td_thr_get_info.c | 12 ++++++++++-- 4 files changed, 46 insertions(+), 12 deletions(-) diff --git a/elf/dl-tls.c b/elf/dl-tls.c index 5aba33b..8d43e38 100644 --- a/elf/dl-tls.c +++ b/elf/dl-tls.c @@ -951,3 +951,16 @@ cannot create TLS data structures")); listp->slotinfo[idx].map = l; listp->slotinfo[idx].gen = GL(dl_tls_generation) + 1; } + +/* Information for libthread_db. */ + +#include +#include + +/* Version of the library, used in libthread_db to detect mismatches. */ +static const char nptl_version[] __attribute_used__ = VERSION; + +/* Likely could have better #if checks in structs.def instead. */ +#define DB_RTLD_SYMS 1 +#include "../nptl_db/db_info.c" + diff --git a/nptl_db/structs.def b/nptl_db/structs.def index 8a65afd..f9f9ab7 100644 --- a/nptl_db/structs.def +++ b/nptl_db/structs.def @@ -31,7 +31,7 @@ #endif #ifndef DB_RTLD_GLOBAL_FIELD -# if !IS_IN (libpthread) +# if !IS_IN (libpthread) && !defined DB_RTLD_SYMS # define DB_RTLD_GLOBAL_FIELD(field) \ DB_STRUCT_FIELD (rtld_global, _##field) \ DB_MAIN_VARIABLE (_##field) @@ -76,8 +76,10 @@ DB_FUNCTION (__nptl_create_event) DB_FUNCTION (__nptl_death_event) DB_SYMBOL (__nptl_threads_events) DB_VARIABLE (__nptl_nthreads) +#if !defined DB_RTLD_SYMS DB_VARIABLE (__nptl_last_event) DB_VARIABLE (__nptl_initial_report_events) +#endif DB_ARRAY_VARIABLE (__pthread_keys) DB_STRUCT (pthread_key_struct) @@ -101,7 +103,7 @@ DB_STRUCT_FIELD (dtv_t, counter) DB_STRUCT_FIELD (pthread, dtvp) #endif -#if !(IS_IN (libpthread) && !defined SHARED) +#if !(IS_IN (libpthread) && !defined SHARED) && !defined DB_RTLD_SYMS DB_STRUCT (rtld_global) DB_RTLD_VARIABLE (_rtld_global) #endif diff --git a/nptl_db/td_ta_map_lwp2thr.c b/nptl_db/td_ta_map_lwp2thr.c index d34711d..798c6e9 100644 --- a/nptl_db/td_ta_map_lwp2thr.c +++ b/nptl_db/td_ta_map_lwp2thr.c @@ -168,6 +168,20 @@ __td_ta_lookup_th_unique (const td_thragent_t *ta_arg, return TD_OK; } +/* If LWPID is the thread group leader, return the fake special + descriptor for the initial thread. Otherwise, return error. */ + +static td_err_e +initial_thread_desc (td_thragent_t *const ta, + lwpid_t lwpid, td_thrhandle_t *th) +{ + if (ps_getpid (ta->ph) != lwpid) + return TD_ERR; + th->th_ta_p = ta; + th->th_unique = 0; + return TD_OK; +} + td_err_e td_ta_map_lwp2thr (const td_thragent_t *ta_arg, lwpid_t lwpid, td_thrhandle_t *th) @@ -189,20 +203,17 @@ td_ta_map_lwp2thr (const td_thragent_t *ta_arg, psaddr_t list; td_err_e err = DB_GET_SYMBOL (list, ta, __stack_user); if (err != TD_OK) - return err; + { + /* Looks like this is a non-threaded program. */ + return initial_thread_desc (ta, lwpid, th); + } err = DB_GET_FIELD (list, ta, list, list_t, next, 0); if (err != TD_OK) return err; if (list == 0) - { - if (ps_getpid (ta->ph) != lwpid) - return TD_ERR; - th->th_ta_p = ta; - th->th_unique = 0; - return TD_OK; - } + return initial_thread_desc (ta, lwpid, th); return __td_ta_lookup_th_unique (ta_arg, lwpid, th); } diff --git a/nptl_db/td_thr_get_info.c b/nptl_db/td_thr_get_info.c index 48979b8..e92bd1f 100644 --- a/nptl_db/td_thr_get_info.c +++ b/nptl_db/td_thr_get_info.c @@ -43,6 +43,14 @@ td_thr_get_info (const td_thrhandle_t *th, td_thrinfo_t *infop) tid = 0; err = DB_GET_VALUE (report_events, th->th_ta_p, __nptl_initial_report_events, 0); + if (err != TD_OK) + { + /* If the program is non-threaded, + __nptl_initial_report_events is nowhere to be found (it + only exists in libpthread.so). */ + report_events = 0; + err = TD_OK; + } } else { @@ -75,9 +83,9 @@ td_thr_get_info (const td_thrhandle_t *th, td_thrinfo_t *infop) return err; err = DB_GET_FIELD_LOCAL (report_events, th->th_ta_p, copy, pthread, report_events, 0); + if (err != TD_OK) + return err; } - if (err != TD_OK) - return err; /* Fill in information. Clear first to provide reproducable results for the fields we do not fill in. */ -- 2.5.5