/* libthread_db assisted debugging support, generic parts.
- Copyright (C) 1999-2021 Free Software Foundation, Inc.
+ Copyright (C) 1999-2022 Free Software Foundation, Inc.
This file is part of GDB.
CORE_ADDR load_module_addr,
CORE_ADDR offset) override;
const char *extra_thread_info (struct thread_info *) override;
- ptid_t get_ada_task_ptid (long lwp, long thread) override;
+ ptid_t get_ada_task_ptid (long lwp, ULONGEST thread) override;
thread_info *thread_handle_to_thread_info (const gdb_byte *thread_handle,
int handle_len,
gdb::byte_vector thread_info_to_thread_handle (struct thread_info *) override;
};
-static char *libthread_db_search_path;
+static std::string libthread_db_search_path = LIBTHREAD_DB_SEARCH_PATH;
/* Set to true if thread_db auto-loading is enabled
by the "set auto-load libthread-db" command. */
set_libthread_db_search_path (const char *ignored, int from_tty,
struct cmd_list_element *c)
{
- if (*libthread_db_search_path == '\0')
- {
- xfree (libthread_db_search_path);
- libthread_db_search_path = xstrdup (LIBTHREAD_DB_SEARCH_PATH);
- }
+ if (libthread_db_search_path.empty ())
+ libthread_db_search_path = LIBTHREAD_DB_SEARCH_PATH;
}
/* If non-zero, print details of libthread_db processing. */
calls are made, we just assume they were; future changes
to how GDB accesses TLS could result in this passing
without exercising the calls it's supposed to. */
- ptid_t ptid = ptid_t (tdb_testinfo->info->pid, ti.ti_lid, 0);
+ ptid_t ptid = ptid_t (tdb_testinfo->info->pid, ti.ti_lid);
thread_info *thread_info = find_thread_ptid (linux_target, ptid);
if (thread_info != NULL && thread_info->priv != NULL)
{
return test_passed;
}
+/* Predicate which tests whether objfile OBJ refers to the library
+ containing pthread related symbols. Historically, this library has
+ been named in such a way that looking for "libpthread" in the name
+ was sufficient to identify it. As of glibc-2.34, the C library
+ (libc) contains the thread library symbols. Therefore we check
+ that the name matches a possible thread library, but we also check
+ that it contains at least one of the symbols (pthread_create) that
+ we'd expect to find in the thread library. */
+
+static bool
+libpthread_objfile_p (objfile *obj)
+{
+ return (libpthread_name_p (objfile_name (obj))
+ && lookup_minimal_symbol ("pthread_create",
+ NULL,
+ obj).minsym != NULL);
+}
+
/* Attempt to initialize dlopen()ed libthread_db, described by INFO.
Return true on success.
Failure could happen if libthread_db does not have symbols we expect,
if (info->td_ta_thr_iter_p == NULL)
{
- struct lwp_info *lp;
int pid = inferior_ptid.pid ();
thread_info *curr_thread = inferior_thread ();
linux_stop_and_wait_all_lwps ();
- ALL_LWPS (lp)
+ for (const lwp_info *lp : all_lwps ())
if (lp->ptid.pid () == pid)
thread_from_lwp (curr_thread, lp->ptid);
printf_unfiltered (_("[Thread debugging using libthread_db enabled]\n"));
- if (*libthread_db_search_path || libthread_db_debug)
+ if (!libthread_db_search_path.empty () || libthread_db_debug)
{
struct ui_file *file;
const char *library;
disabled, still print it to gdb_stdout if debug output is
enabled. User visible output should not depend on debug
settings. */
- file = *libthread_db_search_path != '\0' ? gdb_stdout : gdb_stdlog;
+ file = !libthread_db_search_path.empty () ? gdb_stdout : gdb_stdlog;
fprintf_unfiltered (file,
_("Using host libthread_db library \"%ps\".\n"),
styled_string (file_name_style.style (), library));
if (strchr (library, '/') != NULL)
info->filename = gdb_realpath (library).release ();
- if (try_thread_db_load_1 (info))
- return true;
+ try
+ {
+ if (try_thread_db_load_1 (info))
+ return true;
+ }
+ catch (const gdb_exception_error &except)
+ {
+ if (libthread_db_debug)
+ exception_fprintf (gdb_stdlog, except,
+ "Warning: While trying to load libthread_db: ");
+ }
/* This library "refused" to work on current inferior. */
delete_thread_db_info (current_inferior ()->process_target (),
return false;
for (objfile *obj : current_program_space->objfiles ())
- if (libpthread_name_p (objfile_name (obj)))
+ if (libpthread_objfile_p (obj))
{
if (try_thread_db_load_from_pdir_1 (obj, subdir))
return true;
bool rc = false;
std::vector<gdb::unique_xmalloc_ptr<char>> dir_vec
- = dirnames_to_char_ptr_vec (libthread_db_search_path);
+ = dirnames_to_char_ptr_vec (libthread_db_search_path.c_str ());
for (const gdb::unique_xmalloc_ptr<char> &this_dir_up : dir_vec)
{
has_libpthread (void)
{
for (objfile *obj : current_program_space->objfiles ())
- if (libpthread_name_p (objfile_name (obj)))
+ if (libpthread_objfile_p (obj))
return true;
return false;
static bool
thread_db_load (void)
{
- struct thread_db_info *info;
+ inferior *inf = current_inferior ();
- info = get_thread_db_info (current_inferior ()->process_target (),
- inferior_ptid.pid ());
+ /* When attaching / handling fork child, don't try loading libthread_db
+ until we know about all shared libraries. */
+ if (inf->in_initial_library_scan)
+ return false;
+
+ thread_db_info *info = get_thread_db_info (inf->process_target (),
+ inferior_ptid.pid ());
if (info != NULL)
return true;
an inferior is created (or otherwise acquired, e.g. attached to)
and when new shared libraries are loaded into a running process. */
-void
+static void
check_for_thread_db (void)
{
/* Do nothing if we couldn't load libthread_db.so.1. */
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 (objfile))))
+ || libpthread_objfile_p (objfile)))
check_for_thread_db ();
}
ptid = beneath->wait (ptid, ourstatus, options);
- switch (ourstatus->kind)
+ switch (ourstatus->kind ())
{
case TARGET_WAITKIND_IGNORE:
case TARGET_WAITKIND_EXITED:
continue;
thread_info *thread = any_live_thread_of_inferior (inf);
- if (thread == NULL || thread->executing)
+ if (thread == NULL || thread->executing ())
continue;
/* It's best to avoid td_ta_thr_iter if possible. That walks
/* Implement the to_get_ada_task_ptid target method for this target. */
ptid_t
-thread_db_target::get_ada_task_ptid (long lwp, long thread)
+thread_db_target::get_ada_task_ptid (long lwp, ULONGEST thread)
{
/* NPTL uses a 1:1 model, so the LWP id suffices. */
- return ptid_t (inferior_ptid.pid (), lwp, 0);
+ return ptid_t (inferior_ptid.pid (), lwp);
}
void
i++;
}
- uiout->field_string ("pids", pids.c_str ());
+ uiout->field_string ("pids", pids);
uiout->text ("\n");
}
and until there is a running inferior, we can't tell which
libthread_db is the correct one to load. */
- libthread_db_search_path = xstrdup (LIBTHREAD_DB_SEARCH_PATH);
-
add_setshow_optional_filename_cmd ("libthread-db-search-path",
class_support,
&libthread_db_search_path, _("\