X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Flinux-thread-db.c;h=593fc29b54e5c0d4361982e7d2f8ec4e94c98056;hb=62574b938f80a485874b85a770d03bf0f21eece5;hp=dff8fc2598ce2473ffc64d86836d18b0fde8a50c;hpb=fcb4437118d0bbc82cf56f76d00c44c0220c0005;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/linux-thread-db.c b/gdb/linux-thread-db.c index dff8fc2598..593fc29b54 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-2013 Free Software Foundation, Inc. This file is part of GDB. @@ -23,7 +23,7 @@ #include #include "gdb_proc_service.h" #include "gdb_thread_db.h" - +#include "gdb_vecs.h" #include "bfd.h" #include "command.h" #include "exceptions.h" @@ -42,14 +42,11 @@ #include "linux-procfs.h" #include "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 +103,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, @@ -426,11 +423,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 +437,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 +452,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 +482,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 +500,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 +534,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,13 +547,13 @@ 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; } @@ -612,13 +594,9 @@ 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. */ @@ -632,14 +610,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); @@ -709,9 +686,10 @@ thread_db_find_new_threads_silently (ptid_t ptid) 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. */ + corrupted. For core files it does not apply, no 'later enumeration' + is possible. */ - if (!inferior_has_bug ("nptl_version", 2, 7)) + if (!target_has_execution || !inferior_has_bug ("nptl_version", 2, 7)) { exception_fprintf (gdb_stderr, except, _("Warning: couldn't activate thread debugging " @@ -901,36 +879,45 @@ 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"), @@ -944,11 +931,12 @@ try_thread_db_load_from_pdir_1 (struct objfile *obj) } /* 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; @@ -956,16 +944,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; } @@ -1023,37 +1012,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 ()) { @@ -1071,6 +1064,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; @@ -1084,7 +1078,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; @@ -1098,7 +1092,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; @@ -1195,7 +1189,7 @@ thread_db_new_objfile (struct objfile *objfile) if (objfile != NULL /* libpthread with separate debug info has its debug info file already - loaded (and notified without successfult thread_db initialization)) + 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. */ @@ -1209,7 +1203,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 (); } @@ -1268,16 +1262,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. */ @@ -1305,6 +1297,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) @@ -1312,7 +1306,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. */ @@ -1351,7 +1345,7 @@ thread_db_detach (struct target_ops *ops, 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) { @@ -1367,7 +1361,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); @@ -1396,7 +1390,7 @@ 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) @@ -1446,7 +1440,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) { @@ -1490,7 +1484,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) @@ -1500,7 +1494,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); @@ -1522,15 +1516,8 @@ thread_db_wait (struct target_ops *ops, 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; @@ -1541,7 +1528,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); @@ -1575,9 +1562,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 @@ -1682,10 +1666,9 @@ thread_db_find_new_threads_2 (ptid_t ptid, int until_no_new) { 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; @@ -1765,7 +1748,7 @@ 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; } @@ -1817,7 +1800,7 @@ 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)); + info = get_thread_db_info (ptid_get_pid (ptid)); /* glibc doesn't provide the needed interface. */ if (!info->td_thr_tls_get_addr_p) @@ -1903,9 +1886,9 @@ thread_db_resume (struct target_ops *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 @@ -1948,8 +1931,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")); @@ -2079,6 +2061,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. */ @@ -2088,7 +2072,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 @@ -2112,14 +2095,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, _("\