X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gdb%2Flinux-thread-db.c;h=ff5f2cc7629ee2c75dbf5aa437f9dbbbeecbd6b5;hb=e609377629a12f6518eaf100c1983e23c80fecc1;hp=f78f662d4359cae58229290fa4aa8b9af8912087;hpb=4dc84fd1097fab1fb14a6c77a6b77003296d27eb;p=platform%2Fupstream%2Fbinutils.git diff --git a/gdb/linux-thread-db.c b/gdb/linux-thread-db.c index f78f662..ff5f2cc 100644 --- a/gdb/linux-thread-db.c +++ b/gdb/linux-thread-db.c @@ -1,6 +1,6 @@ /* libthread_db assisted debugging support, generic parts. - Copyright (C) 1999-2001, 2003-2012 Free Software Foundation, Inc. + Copyright (C) 1999-2014 Free Software Foundation, Inc. This file is part of GDB. @@ -18,18 +18,16 @@ along with this program. If not, see . */ #include "defs.h" - -#include "gdb_assert.h" #include #include "gdb_proc_service.h" -#include "gdb_thread_db.h" - +#include "nat/gdb_thread_db.h" +#include "gdb_vecs.h" #include "bfd.h" #include "command.h" -#include "exceptions.h" #include "gdbcmd.h" #include "gdbthread.h" #include "inferior.h" +#include "infrun.h" #include "symfile.h" #include "objfiles.h" #include "target.h" @@ -39,17 +37,14 @@ #include "gdbcore.h" #include "observer.h" #include "linux-nat.h" -#include "linux-procfs.h" -#include "linux-osdata.h" +#include "nat/linux-procfs.h" +#include "nat/linux-osdata.h" #include "auto-load.h" +#include "cli/cli-utils.h" #include #include -#ifdef HAVE_GNU_LIBC_VERSION_H -#include -#endif - /* GNU/Linux libthread_db support. libthread_db is a library, provided along with libpthread.so, which @@ -106,7 +101,7 @@ set_libthread_db_search_path (char *ignored, int from_tty, /* If non-zero, print details of libthread_db processing. */ -static int libthread_db_debug; +static unsigned int libthread_db_debug; static void show_libthread_db_debug (struct ui_file *file, int from_tty, @@ -199,6 +194,9 @@ struct thread_db_info td_err_e (*td_thr_tls_get_addr_p) (const td_thrhandle_t *th, psaddr_t map_address, size_t offset, psaddr_t *address); + td_err_e (*td_thr_tlsbase_p) (const td_thrhandle_t *th, + unsigned long int modid, + psaddr_t *base); }; /* List of known processes using thread_db, and the required @@ -426,11 +424,6 @@ thread_get_info_callback (const td_thrhandle_t *thp, void *argp) thread_ptid = ptid_build (info->pid, ti.ti_lid, 0); inout->thread_info = find_thread_ptid (thread_ptid); - /* In the case of a zombie thread, don't continue. We don't want to - attach to it thinking it is a new thread. */ - if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE) - return TD_THR_ZOMBIE; - if (inout->thread_info == NULL) { /* New thread. Attach to it now (why wait?). */ @@ -445,9 +438,9 @@ thread_get_info_callback (const td_thrhandle_t *thp, void *argp) return 0; } -/* Convert between user-level thread ids and LWP ids. */ +/* Fetch the user-level thread id of PTID. */ -static ptid_t +static void thread_from_lwp (ptid_t ptid) { td_thrhandle_t th; @@ -460,33 +453,22 @@ thread_from_lwp (ptid_t ptid) /* This ptid comes from linux-nat.c, which should always fill in the LWP. */ - gdb_assert (GET_LWP (ptid) != 0); + gdb_assert (ptid_get_lwp (ptid) != 0); - info = get_thread_db_info (GET_PID (ptid)); + info = get_thread_db_info (ptid_get_pid (ptid)); /* Access an lwp we know is stopped. */ info->proc_handle.ptid = ptid; - err = info->td_ta_map_lwp2thr_p (info->thread_agent, GET_LWP (ptid), &th); + err = info->td_ta_map_lwp2thr_p (info->thread_agent, ptid_get_lwp (ptid), + &th); if (err != TD_OK) error (_("Cannot find user-level thread for LWP %ld: %s"), - GET_LWP (ptid), thread_db_err_str (err)); - - /* Fetch the thread info. If we get back TD_THR_ZOMBIE, then the - event thread has already died. If another gdb interface has called - thread_alive() previously, the thread won't be found on the thread list - anymore. In that case, we don't want to process this ptid anymore - to avoid the possibility of later treating it as a newly - discovered thread id that we should add to the list. Thus, - we return a -1 ptid which is also how the thread list marks a - dead thread. */ + ptid_get_lwp (ptid), thread_db_err_str (err)); + + /* Long-winded way of fetching the thread info. */ io.thread_db_info = info; io.thread_info = NULL; - if (thread_get_info_callback (&th, &io) == TD_THR_ZOMBIE - && io.thread_info == NULL) - return minus_one_ptid; - - gdb_assert (ptid_get_tid (ptid) == 0); - return ptid; + thread_get_info_callback (&th, &io); } @@ -501,14 +483,14 @@ thread_db_attach_lwp (ptid_t ptid) td_err_e err; struct thread_db_info *info; - info = get_thread_db_info (GET_PID (ptid)); + info = get_thread_db_info (ptid_get_pid (ptid)); if (info == NULL) return 0; /* This ptid comes from linux-nat.c, which should always fill in the LWP. */ - gdb_assert (GET_LWP (ptid) != 0); + gdb_assert (ptid_get_lwp (ptid) != 0); /* Access an lwp we know is stopped. */ info->proc_handle.ptid = ptid; @@ -519,7 +501,8 @@ thread_db_attach_lwp (ptid_t ptid) if (!have_threads (ptid)) thread_db_find_new_threads_1 (ptid); - err = info->td_ta_map_lwp2thr_p (info->thread_agent, GET_LWP (ptid), &th); + err = info->td_ta_map_lwp2thr_p (info->thread_agent, ptid_get_lwp (ptid), + &th); if (err != TD_OK) /* Cannot find user-level thread. */ return 0; @@ -552,7 +535,7 @@ enable_thread_event (int event, CORE_ADDR *bp) td_err_e err; struct thread_db_info *info; - info = get_thread_db_info (GET_PID (inferior_ptid)); + info = get_thread_db_info (ptid_get_pid (inferior_ptid)); /* Access an lwp we know is stopped. */ info->proc_handle.ptid = inferior_ptid; @@ -565,29 +548,56 @@ enable_thread_event (int event, CORE_ADDR *bp) /* Set up the breakpoint. */ gdb_assert (exec_bfd); (*bp) = (gdbarch_convert_from_func_ptr_addr - (target_gdbarch, + (target_gdbarch (), /* Do proper sign extension for the target. */ (bfd_get_sign_extend_vma (exec_bfd) > 0 ? (CORE_ADDR) (intptr_t) notify.u.bptaddr : (CORE_ADDR) (uintptr_t) notify.u.bptaddr), ¤t_target)); - create_thread_event_breakpoint (target_gdbarch, *bp); + create_thread_event_breakpoint (target_gdbarch (), *bp); return TD_OK; } +/* Verify inferior's '\0'-terminated symbol VER_SYMBOL starts with "%d.%d" and + return 1 if this version is lower (and not equal) to + VER_MAJOR_MIN.VER_MINOR_MIN. Return 0 in all other cases. */ + +static int +inferior_has_bug (const char *ver_symbol, int ver_major_min, int ver_minor_min) +{ + struct bound_minimal_symbol version_msym; + CORE_ADDR version_addr; + char *version; + int err, got, retval = 0; + + version_msym = lookup_minimal_symbol (ver_symbol, NULL, NULL); + if (version_msym.minsym == NULL) + return 0; + + version_addr = BMSYMBOL_VALUE_ADDRESS (version_msym); + got = target_read_string (version_addr, &version, 32, &err); + if (err == 0 && memchr (version, 0, got) == &version[got -1]) + { + int major, minor; + + retval = (sscanf (version, "%d.%d", &major, &minor) == 2 + && (major < ver_major_min + || (major == ver_major_min && minor < ver_minor_min))); + } + xfree (version); + + return retval; +} + static void enable_thread_event_reporting (void) { td_thr_events_t events; td_err_e err; -#ifdef HAVE_GNU_LIBC_VERSION_H - const char *libc_version; - int libc_major, libc_minor; -#endif struct thread_db_info *info; - info = get_thread_db_info (GET_PID (inferior_ptid)); + info = get_thread_db_info (ptid_get_pid (inferior_ptid)); /* We cannot use the thread event reporting facility if these functions aren't available. */ @@ -601,14 +611,13 @@ enable_thread_event_reporting (void) td_event_emptyset (&events); td_event_addset (&events, TD_CREATE); -#ifdef HAVE_GNU_LIBC_VERSION_H - /* The event reporting facility is broken for TD_DEATH events in - glibc 2.1.3, so don't enable it if we have glibc but a lower - version. */ - libc_version = gnu_get_libc_version (); - if (sscanf (libc_version, "%d.%d", &libc_major, &libc_minor) == 2 - && (libc_major > 2 || (libc_major == 2 && libc_minor > 1))) -#endif + /* There is a bug fixed between linuxthreads 2.1.3 and 2.2 by + commit 2e4581e4fba917f1779cd0a010a45698586c190a + * manager.c (pthread_exited): Correctly report event as TD_REAP + instead of TD_DEATH. Fix comments. + where event reporting facility is broken for TD_DEATH events, + so don't enable it if we have glibc but a lower version. */ + if (!inferior_has_bug ("__linuxthreads_version", 2, 2)) td_event_addset (&events, TD_DEATH); err = info->td_ta_set_event_p (info->thread_agent, &events); @@ -643,9 +652,13 @@ enable_thread_event_reporting (void) } } -/* Same as thread_db_find_new_threads_1, but silently ignore errors. */ +/* Similar as thread_db_find_new_threads_1, but try to silently ignore errors + if appropriate. -static void + Return 1 if the caller should abort libthread_db initialization. Return 0 + otherwise. */ + +static int thread_db_find_new_threads_silently (ptid_t ptid) { volatile struct gdb_exception except; @@ -655,11 +668,37 @@ thread_db_find_new_threads_silently (ptid_t ptid) thread_db_find_new_threads_2 (ptid, 1); } - if (except.reason < 0 && libthread_db_debug) + if (except.reason < 0) { - exception_fprintf (gdb_stderr, except, - "Warning: thread_db_find_new_threads_silently: "); + if (libthread_db_debug) + exception_fprintf (gdb_stderr, except, + "Warning: thread_db_find_new_threads_silently: "); + + /* There is a bug fixed between nptl 2.6.1 and 2.7 by + commit 7d9d8bd18906fdd17364f372b160d7ab896ce909 + where calls to td_thr_get_info fail with TD_ERR for statically linked + executables if td_thr_get_info is called before glibc has initialized + itself. + + If the nptl bug is NOT present in the inferior and still thread_db + reports an error return 1. It means the inferior has corrupted thread + list and GDB should fall back only to LWPs. + + If the nptl bug is present in the inferior return 0 to silently ignore + such errors, and let gdb enumerate threads again later. In such case + GDB cannot properly display LWPs if the inferior thread list is + corrupted. For core files it does not apply, no 'later enumeration' + is possible. */ + + if (!target_has_execution || !inferior_has_bug ("nptl_version", 2, 7)) + { + exception_fprintf (gdb_stderr, except, + _("Warning: couldn't activate thread debugging " + "using libthread_db: ")); + return 1; + } } + return 0; } /* Lookup a library in which given symbol resides. @@ -761,6 +800,15 @@ try_thread_db_load_1 (struct thread_db_info *info) info->td_ta_event_getmsg_p = dlsym (info->handle, "td_ta_event_getmsg"); info->td_thr_event_enable_p = dlsym (info->handle, "td_thr_event_enable"); info->td_thr_tls_get_addr_p = dlsym (info->handle, "td_thr_tls_get_addr"); + info->td_thr_tlsbase_p = dlsym (info->handle, "td_thr_tlsbase"); + + if (thread_db_find_new_threads_silently (inferior_ptid) != 0) + { + /* Even if libthread_db initializes, if the thread list is + corrupted, we'd not manage to list any threads. Better reject this + thread_db, and fall back to at least listing LWPs. */ + return 0; + } printf_unfiltered (_("[Thread debugging using libthread_db enabled]\n")); @@ -785,12 +833,6 @@ try_thread_db_load_1 (struct thread_db_info *info) if (target_has_execution) enable_thread_event_reporting (); - /* There appears to be a bug in glibc-2.3.6: calls to td_thr_get_info fail - with TD_ERR for statically linked executables if td_thr_get_info is - called before glibc has initialized itself. Silently ignore such - errors, and let gdb enumerate threads again later. */ - thread_db_find_new_threads_silently (inferior_ptid); - return 1; } @@ -798,7 +840,7 @@ try_thread_db_load_1 (struct thread_db_info *info) relative, or just LIBTHREAD_DB. */ static int -try_thread_db_load (const char *library) +try_thread_db_load (const char *library, int check_auto_load_safe) { void *handle; struct thread_db_info *info; @@ -806,6 +848,25 @@ try_thread_db_load (const char *library) if (libthread_db_debug) printf_unfiltered (_("Trying host libthread_db library: %s.\n"), library); + + if (check_auto_load_safe) + { + if (access (library, R_OK) != 0) + { + /* Do not print warnings by file_is_auto_load_safe if the library does + not exist at this place. */ + if (libthread_db_debug) + printf_unfiltered (_("open failed: %s.\n"), safe_strerror (errno)); + return 0; + } + + if (!file_is_auto_load_safe (library, _("auto-load: Loading libthread-db " + "library \"%s\" from explicit " + "directory.\n"), + library)) + return 0; + } + handle = dlopen (library, RTLD_NOW); if (handle == NULL) { @@ -839,54 +900,59 @@ try_thread_db_load (const char *library) return 1; /* This library "refused" to work on current inferior. */ - delete_thread_db_info (GET_PID (inferior_ptid)); + delete_thread_db_info (ptid_get_pid (inferior_ptid)); return 0; } /* Subroutine of try_thread_db_load_from_pdir to simplify it. - Try loading libthread_db from the same directory as OBJ. + Try loading libthread_db in directory(OBJ)/SUBDIR. + SUBDIR may be NULL. It may also be something like "../lib64". The result is true for success. */ static int -try_thread_db_load_from_pdir_1 (struct objfile *obj) +try_thread_db_load_from_pdir_1 (struct objfile *obj, const char *subdir) { struct cleanup *cleanup; char *path, *cp; int result; + const char *obj_name = objfile_name (obj); - if (obj->name[0] != '/') + if (obj_name[0] != '/') { warning (_("Expected absolute pathname for libpthread in the" - " inferior, but got %s."), obj->name); + " inferior, but got %s."), obj_name); return 0; } - path = xmalloc (strlen (obj->name) + 1 + strlen (LIBTHREAD_DB_SO) + 1); + path = xmalloc (strlen (obj_name) + (subdir ? strlen (subdir) + 1 : 0) + + 1 + strlen (LIBTHREAD_DB_SO) + 1); cleanup = make_cleanup (xfree, path); - strcpy (path, obj->name); + strcpy (path, obj_name); cp = strrchr (path, '/'); /* This should at minimum hit the first character. */ gdb_assert (cp != NULL); - strcpy (cp + 1, LIBTHREAD_DB_SO); + cp[1] = '\0'; + if (subdir != NULL) + { + strcat (cp, subdir); + strcat (cp, "/"); + } + strcat (cp, LIBTHREAD_DB_SO); - if (!file_is_auto_load_safe (path, _("auto-load: Loading libthread-db " - "library \"%s\" from $pdir.\n"), - path)) - result = 0; - else - result = try_thread_db_load (path); + result = try_thread_db_load (path, 1); do_cleanups (cleanup); return result; } /* Handle $pdir in libthread-db-search-path. - Look for libthread_db in the directory of libpthread. + Look for libthread_db in directory(libpthread)/SUBDIR. + SUBDIR may be NULL. It may also be something like "../lib64". The result is true for success. */ static int -try_thread_db_load_from_pdir (void) +try_thread_db_load_from_pdir (const char *subdir) { struct objfile *obj; @@ -894,16 +960,17 @@ try_thread_db_load_from_pdir (void) return 0; ALL_OBJFILES (obj) - if (libpthread_name_p (obj->name)) + if (libpthread_name_p (objfile_name (obj))) { - if (try_thread_db_load_from_pdir_1 (obj)) + if (try_thread_db_load_from_pdir_1 (obj, subdir)) return 1; /* We may have found the separate-debug-info version of libpthread, and it may live in a directory without a matching libthread_db. */ if (obj->separate_debug_objfile_backlink != NULL) - return try_thread_db_load_from_pdir_1 (obj->separate_debug_objfile_backlink); + return try_thread_db_load_from_pdir_1 (obj->separate_debug_objfile_backlink, + subdir); return 0; } @@ -919,7 +986,7 @@ try_thread_db_load_from_pdir (void) static int try_thread_db_load_from_sdir (void) { - return try_thread_db_load (LIBTHREAD_DB_SO); + return try_thread_db_load (LIBTHREAD_DB_SO, 0); } /* Try to load libthread_db from directory DIR of length DIR_LEN. @@ -942,13 +1009,7 @@ try_thread_db_load_from_dir (const char *dir, size_t dir_len) path[dir_len] = '/'; strcpy (path + dir_len + 1, LIBTHREAD_DB_SO); - if (!file_is_auto_load_safe (path, _("auto-load: Loading libthread-db " - "library \"%s\" from explicit " - "directory.\n"), - path)) - result = 0; - else - result = try_thread_db_load (path); + result = try_thread_db_load (path, 1); do_cleanups (cleanup); return result; @@ -961,37 +1022,41 @@ try_thread_db_load_from_dir (const char *dir, size_t dir_len) static int thread_db_load_search (void) { - const char *search_path = libthread_db_search_path; - int rc = 0; + VEC (char_ptr) *dir_vec; + struct cleanup *cleanups; + char *this_dir; + int i, rc = 0; + + dir_vec = dirnames_to_char_ptr_vec (libthread_db_search_path); + cleanups = make_cleanup_free_char_ptr_vec (dir_vec); - while (*search_path) + for (i = 0; VEC_iterate (char_ptr, dir_vec, i, this_dir); ++i) { - const char *end = strchr (search_path, ':'); - const char *this_dir = search_path; + const int pdir_len = sizeof ("$pdir") - 1; size_t this_dir_len; - if (end) - { - this_dir_len = end - search_path; - search_path += this_dir_len + 1; - } - else - { - this_dir_len = strlen (this_dir); - search_path += this_dir_len; - } + this_dir_len = strlen (this_dir); - if (this_dir_len == sizeof ("$pdir") - 1 - && strncmp (this_dir, "$pdir", this_dir_len) == 0) + if (strncmp (this_dir, "$pdir", pdir_len) == 0 + && (this_dir[pdir_len] == '\0' + || this_dir[pdir_len] == '/')) { - if (try_thread_db_load_from_pdir ()) + char *subdir = NULL; + struct cleanup *free_subdir_cleanup + = make_cleanup (null_cleanup, NULL); + + if (this_dir[pdir_len] == '/') { - rc = 1; - break; + subdir = xmalloc (strlen (this_dir)); + make_cleanup (xfree, subdir); + strcpy (subdir, this_dir + pdir_len + 1); } + rc = try_thread_db_load_from_pdir (subdir); + do_cleanups (free_subdir_cleanup); + if (rc) + break; } - else if (this_dir_len == sizeof ("$sdir") - 1 - && strncmp (this_dir, "$sdir", this_dir_len) == 0) + else if (strcmp (this_dir, "$sdir") == 0) { if (try_thread_db_load_from_sdir ()) { @@ -1009,6 +1074,7 @@ thread_db_load_search (void) } } + do_cleanups (cleanups); if (libthread_db_debug) printf_unfiltered (_("thread_db_load_search returning %d\n"), rc); return rc; @@ -1022,7 +1088,7 @@ has_libpthread (void) struct objfile *obj; ALL_OBJFILES (obj) - if (libpthread_name_p (obj->name)) + if (libpthread_name_p (objfile_name (obj))) return 1; return 0; @@ -1036,7 +1102,7 @@ thread_db_load (void) { struct thread_db_info *info; - info = get_thread_db_info (GET_PID (inferior_ptid)); + info = get_thread_db_info (ptid_get_pid (inferior_ptid)); if (info != NULL) return 1; @@ -1101,9 +1167,9 @@ check_thread_signals (void) { if (sigismember (&mask, i)) { - if (signal_stop_update (target_signal_from_host (i), 0)) + if (signal_stop_update (gdb_signal_from_host (i), 0)) sigaddset (&thread_stop_set, i); - if (signal_print_update (target_signal_from_host (i), 0)) + if (signal_print_update (gdb_signal_from_host (i), 0)) sigaddset (&thread_print_set, i); thread_signals = 1; } @@ -1132,6 +1198,12 @@ thread_db_new_objfile (struct objfile *objfile) correctly. */ if (objfile != NULL + /* libpthread with separate debug info has its debug info file already + loaded (and notified without successful thread_db initialization) + the time observer_notify_new_objfile is called for the library itself. + Static executables have their separate debug info loaded already + before the inferior has started. */ + && objfile->separate_debug_objfile_backlink == NULL /* Only check for thread_db if we loaded libpthread, or if this is the main symbol file. We need to check OBJF_MAINLINE to handle the case of debugging @@ -1141,7 +1213,7 @@ thread_db_new_objfile (struct objfile *objfile) of the list of shared libraries to load, and in an app of several thousand shared libraries, this can otherwise be painful. */ && ((objfile->flags & OBJF_MAINLINE) != 0 - || libpthread_name_p (objfile->name))) + || libpthread_name_p (objfile_name (objfile)))) check_for_thread_db (); } @@ -1200,16 +1272,14 @@ attach_thread (ptid_t ptid, const td_thrhandle_t *th_p, if (target_has_execution) check_thread_signals (); - if (ti_p->ti_state == TD_THR_UNKNOWN || ti_p->ti_state == TD_THR_ZOMBIE) - return 0; /* A zombie thread -- do not attach. */ - /* Under GNU/Linux, we have to attach to each and every thread. */ if (target_has_execution && tp == NULL) { int res; - res = lin_lwp_attach_lwp (BUILD_LWP (ti_p->ti_lid, GET_PID (ptid))); + res = lin_lwp_attach_lwp (ptid_build (ptid_get_pid (ptid), + ti_p->ti_lid, 0)); if (res < 0) { /* Error, stop iterating. */ @@ -1237,6 +1307,8 @@ attach_thread (ptid_t ptid, const td_thrhandle_t *th_p, gdb_assert (ti_p->ti_tid != 0); private->th = *th_p; private->tid = ti_p->ti_tid; + if (ti_p->ti_state == TD_THR_UNKNOWN || ti_p->ti_state == TD_THR_ZOMBIE) + private->dying = 1; /* Add the thread to GDB's thread list. */ if (tp == NULL) @@ -1244,7 +1316,7 @@ attach_thread (ptid_t ptid, const td_thrhandle_t *th_p, else tp->private = private; - info = get_thread_db_info (GET_PID (ptid)); + info = get_thread_db_info (ptid_get_pid (ptid)); /* Enable thread event reporting for this thread, except when debugging a core file. */ @@ -1278,12 +1350,12 @@ detach_thread (ptid_t ptid) } static void -thread_db_detach (struct target_ops *ops, char *args, int from_tty) +thread_db_detach (struct target_ops *ops, const char *args, int from_tty) { struct target_ops *target_beneath = find_target_beneath (ops); struct thread_db_info *info; - info = get_thread_db_info (GET_PID (inferior_ptid)); + info = get_thread_db_info (ptid_get_pid (inferior_ptid)); if (info) { @@ -1299,7 +1371,7 @@ thread_db_detach (struct target_ops *ops, char *args, int from_tty) remove_thread_event_breakpoints (); } - delete_thread_db_info (GET_PID (inferior_ptid)); + delete_thread_db_info (ptid_get_pid (inferior_ptid)); } target_beneath->to_detach (target_beneath, args, from_tty); @@ -1328,11 +1400,11 @@ check_event (ptid_t ptid) int loop = 0; struct thread_db_info *info; - info = get_thread_db_info (GET_PID (ptid)); + info = get_thread_db_info (ptid_get_pid (ptid)); /* Bail out early if we're not at a thread event breakpoint. */ stop_pc = regcache_read_pc (regcache) - - gdbarch_decr_pc_after_break (gdbarch); + - target_decr_pc_after_break (gdbarch); if (stop_pc != info->td_create_bp_addr && stop_pc != info->td_death_bp_addr) return; @@ -1378,7 +1450,7 @@ check_event (ptid_t ptid) if (err != TD_OK) error (_("Cannot get thread info: %s"), thread_db_err_str (err)); - ptid = ptid_build (GET_PID (ptid), ti.ti_lid, 0); + ptid = ptid_build (ptid_get_pid (ptid), ti.ti_lid, 0); switch (msg.event) { @@ -1422,7 +1494,7 @@ thread_db_wait (struct target_ops *ops, || ourstatus->kind == TARGET_WAITKIND_SIGNALLED) return ptid; - info = get_thread_db_info (GET_PID (ptid)); + info = get_thread_db_info (ptid_get_pid (ptid)); /* If this process isn't using thread_db, we're done. */ if (info == NULL) @@ -1432,7 +1504,7 @@ thread_db_wait (struct target_ops *ops, { /* New image, it may or may not end up using thread_db. Assume not unless we find otherwise. */ - delete_thread_db_info (GET_PID (ptid)); + delete_thread_db_info (ptid_get_pid (ptid)); if (!thread_db_list) unpush_target (&thread_db_ops); @@ -1448,21 +1520,14 @@ thread_db_wait (struct target_ops *ops, thread_db_find_new_threads_1 (ptid); if (ourstatus->kind == TARGET_WAITKIND_STOPPED - && ourstatus->value.sig == TARGET_SIGNAL_TRAP) + && ourstatus->value.sig == GDB_SIGNAL_TRAP) /* Check for a thread event. */ check_event (ptid); if (have_threads (ptid)) { - /* Change ptids back into the higher level PID + TID format. If - the thread is dead and no longer on the thread list, we will - get back a dead ptid. This can occur if the thread death - event gets postponed by other simultaneous events. In such a - case, we want to just ignore the event and continue on. */ - - ptid = thread_from_lwp (ptid); - if (GET_PID (ptid) == -1) - ourstatus->kind = TARGET_WAITKIND_SPURIOUS; + /* Fill in the thread's user-level thread id. */ + thread_from_lwp (ptid); } return ptid; @@ -1473,7 +1538,7 @@ thread_db_mourn_inferior (struct target_ops *ops) { struct target_ops *target_beneath = find_target_beneath (ops); - delete_thread_db_info (GET_PID (inferior_ptid)); + delete_thread_db_info (ptid_get_pid (inferior_ptid)); target_beneath->to_mourn_inferior (target_beneath); @@ -1507,9 +1572,6 @@ find_new_threads_callback (const td_thrhandle_t *th_p, void *data) error (_("find_new_threads_callback: cannot get thread info: %s"), thread_db_err_str (err)); - if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE) - return 0; /* A zombie -- ignore. */ - if (ti.ti_tid == 0) { /* A thread ID of zero means that this is the main thread, but @@ -1612,12 +1674,11 @@ find_new_threads_once (struct thread_db_info *info, int iteration, static void thread_db_find_new_threads_2 (ptid_t ptid, int until_no_new) { - td_err_e err; + td_err_e err = TD_OK; struct thread_db_info *info; - int pid = ptid_get_pid (ptid); int i, loop; - info = get_thread_db_info (GET_PID (ptid)); + info = get_thread_db_info (ptid_get_pid (ptid)); /* Access an lwp we know is stopped. */ info->proc_handle.ptid = ptid; @@ -1628,17 +1689,18 @@ thread_db_find_new_threads_2 (ptid_t ptid, int until_no_new) The 4 is a heuristic: there is an inherent race here, and I have seen that 2 iterations in a row are not always sufficient to "capture" all threads. */ - for (i = 0, loop = 0; loop < 4; ++i, ++loop) - if (find_new_threads_once (info, i, NULL) != 0) - /* Found some new threads. Restart the loop from beginning. */ - loop = -1; + for (i = 0, loop = 0; loop < 4 && err == TD_OK; ++i, ++loop) + if (find_new_threads_once (info, i, &err) != 0) + { + /* Found some new threads. Restart the loop from beginning. */ + loop = -1; + } } else - { - find_new_threads_once (info, 0, &err); - if (err != TD_OK) - error (_("Cannot find new threads: %s"), thread_db_err_str (err)); - } + find_new_threads_once (info, 0, &err); + + if (err != TD_OK) + error (_("Cannot find new threads: %s"), thread_db_err_str (err)); } static void @@ -1696,23 +1758,21 @@ thread_db_pid_to_str (struct target_ops *ops, ptid_t ptid) tid = thread_info->private->tid; snprintf (buf, sizeof (buf), "Thread 0x%lx (LWP %ld)", - tid, GET_LWP (ptid)); + tid, ptid_get_lwp (ptid)); return buf; } beneath = find_target_beneath (ops); - if (beneath->to_pid_to_str (beneath, ptid)) - return beneath->to_pid_to_str (beneath, ptid); - - return normal_pid_to_str (ptid); + return beneath->to_pid_to_str (beneath, ptid); } /* Return a string describing the state of the thread specified by INFO. */ static char * -thread_db_extra_thread_info (struct thread_info *info) +thread_db_extra_thread_info (struct target_ops *self, + struct thread_info *info) { if (info->private == NULL) return NULL; @@ -1748,23 +1808,41 @@ thread_db_get_thread_local_address (struct target_ops *ops, psaddr_t address; struct thread_db_info *info; - info = get_thread_db_info (GET_PID (ptid)); - - /* glibc doesn't provide the needed interface. */ - if (!info->td_thr_tls_get_addr_p) - throw_error (TLS_NO_LIBRARY_SUPPORT_ERROR, - _("No TLS library support")); - - /* Caller should have verified that lm != 0. */ - gdb_assert (lm != 0); + info = get_thread_db_info (ptid_get_pid (ptid)); /* Finally, get the address of the variable. */ - /* Note the cast through uintptr_t: this interface only works if - a target address fits in a psaddr_t, which is a host pointer. - So a 32-bit debugger can not access 64-bit TLS through this. */ - err = info->td_thr_tls_get_addr_p (&thread_info->private->th, - (psaddr_t)(uintptr_t) lm, - offset, &address); + if (lm != 0) + { + /* glibc doesn't provide the needed interface. */ + if (!info->td_thr_tls_get_addr_p) + throw_error (TLS_NO_LIBRARY_SUPPORT_ERROR, + _("No TLS library support")); + + /* Note the cast through uintptr_t: this interface only works if + a target address fits in a psaddr_t, which is a host pointer. + So a 32-bit debugger can not access 64-bit TLS through this. */ + err = info->td_thr_tls_get_addr_p (&thread_info->private->th, + (psaddr_t)(uintptr_t) lm, + offset, &address); + } + else + { + /* If glibc doesn't provide the needed interface throw an error + that LM is zero - normally cases it should not be. */ + if (!info->td_thr_tlsbase_p) + throw_error (TLS_LOAD_MODULE_NOT_FOUND_ERROR, + _("TLS load module not found")); + + /* This code path handles the case of -static -pthread executables: + https://sourceware.org/ml/libc-help/2014-03/msg00024.html + For older GNU libc r_debug.r_map is NULL. For GNU libc after + PR libc/16831 due to GDB PR threads/16954 LOAD_MODULE is also NULL. + The constant number 1 depends on GNU __libc_setup_tls + initialization of l_tls_modid to 1. */ + err = info->td_thr_tlsbase_p (&thread_info->private->th, + 1, &address); + address = (char *) address + offset; + } #ifdef THREAD_DB_HAS_TD_NOTALLOC /* The memory hasn't been allocated, yet. */ @@ -1790,11 +1868,7 @@ thread_db_get_thread_local_address (struct target_ops *ops, } beneath = find_target_beneath (ops); - if (beneath->to_get_thread_local_address) - return beneath->to_get_thread_local_address (beneath, ptid, lm, offset); - else - throw_error (TLS_GENERIC_ERROR, - _("TLS not supported on this target")); + return beneath->to_get_thread_local_address (beneath, ptid, lm, offset); } /* Callback routine used to find a thread based on the TID part of @@ -1814,7 +1888,7 @@ thread_db_find_thread_from_tid (struct thread_info *thread, void *data) /* Implement the to_get_ada_task_ptid target method for this target. */ static ptid_t -thread_db_get_ada_task_ptid (long lwp, long thread) +thread_db_get_ada_task_ptid (struct target_ops *self, long lwp, long thread) { struct thread_info *thread_info; @@ -1828,15 +1902,15 @@ thread_db_get_ada_task_ptid (long lwp, long thread) static void thread_db_resume (struct target_ops *ops, - ptid_t ptid, int step, enum target_signal signo) + ptid_t ptid, int step, enum gdb_signal signo) { struct target_ops *beneath = find_target_beneath (ops); struct thread_db_info *info; if (ptid_equal (ptid, minus_one_ptid)) - info = get_thread_db_info (GET_PID (inferior_ptid)); + info = get_thread_db_info (ptid_get_pid (inferior_ptid)); else - info = get_thread_db_info (GET_PID (ptid)); + info = get_thread_db_info (ptid_get_pid (ptid)); /* This workaround is only needed for child fork lwps stopped in a PTRACE_O_TRACEFORK event. When the inferior is resumed, the @@ -1879,8 +1953,7 @@ info_auto_load_libthread_db (char *args, int from_tty) char *pids; int i; - while (isspace (*cs)) - cs++; + cs = skip_spaces_const (cs); if (*cs) error (_("'info auto-load libthread-db' does not accept any parameters")); @@ -2010,6 +2083,8 @@ init_thread_db_ops (void) thread_db_ops.to_extra_thread_info = thread_db_extra_thread_info; thread_db_ops.to_get_ada_task_ptid = thread_db_get_ada_task_ptid; thread_db_ops.to_magic = OPS_MAGIC; + + complete_target_initialization (&thread_db_ops); } /* Provide a prototype to silence -Wmissing-prototypes. */ @@ -2019,7 +2094,6 @@ void _initialize_thread_db (void) { init_thread_db_ops (); - add_target (&thread_db_ops); /* Defer loading of libthread_db.so until inferior is running. This allows gdb to load correct libthread_db for a given @@ -2043,14 +2117,14 @@ Setting the search path to an empty list resets it to its default value."), NULL, &setlist, &showlist); - add_setshow_zinteger_cmd ("libthread-db", class_maintenance, - &libthread_db_debug, _("\ + add_setshow_zuinteger_cmd ("libthread-db", class_maintenance, + &libthread_db_debug, _("\ Set libthread-db debugging."), _("\ Show libthread-db debugging."), _("\ When non-zero, libthread-db debugging is enabled."), - NULL, - show_libthread_db_debug, - &setdebuglist, &showdebuglist); + NULL, + show_libthread_db_debug, + &setdebuglist, &showdebuglist); add_setshow_boolean_cmd ("libthread-db", class_support, &auto_load_thread_db, _("\