/* libthread_db assisted debugging support, generic parts.
- Copyright (C) 1999-2020 Free Software Foundation, Inc.
+ Copyright (C) 1999-2021 Free Software Foundation, Inc.
This file is part of GDB.
strata stratum () const override { return thread_stratum; }
void detach (inferior *, int) override;
- ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
+ ptid_t wait (ptid_t, struct target_waitstatus *, target_wait_flags) override;
void resume (ptid_t, int, enum gdb_signal) override;
void mourn_inferior () override;
+ void follow_exec (inferior *, ptid_t, const char *) override;
void update_thread_list () override;
std::string pid_to_str (ptid_t) override;
CORE_ADDR get_thread_local_address (ptid_t ptid,
/* Non-zero if we have determined the signals used by the threads
library. */
static int thread_signals;
-static sigset_t thread_stop_set;
-static sigset_t thread_print_set;
struct thread_db_info
{
/* List of known processes using thread_db, and the required
bookkeeping. */
-struct thread_db_info *thread_db_list;
+static thread_db_info *thread_db_list;
static void thread_db_find_new_threads_1 (thread_info *stopped);
static void thread_db_find_new_threads_2 (thread_info *stopped,
/* The workaround works by reading from /proc/pid/status, so it is
disabled for core files. */
- if (target_has_execution)
+ if (target_has_execution ())
info->need_stale_parent_threads_check = 1;
info->next = thread_db_list;
{
struct bound_minimal_symbol version_msym;
CORE_ADDR version_addr;
- gdb::unique_xmalloc_ptr<char> version;
- int err, got, retval = 0;
+ int 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.get (), 0, got) == version.get () + got - 1)
+ gdb::unique_xmalloc_ptr<char> version
+ = target_read_string (version_addr, 32, &got);
+ if (version != nullptr
+ && memchr (version.get (), 0, got) == version.get () + got - 1)
{
int major, minor;
corrupted. For core files it does not apply, no 'later enumeration'
is possible. */
- if (!target_has_execution || !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 "
memset (&th2, 23, sizeof (td_thrhandle_t));
CALL_UNCHECKED (td_ta_map_lwp2thr, th->th_ta_p, ti.ti_lid, &th2);
- if (tdb_testinfo->last_result == TD_ERR && !target_has_execution)
+ if (tdb_testinfo->last_result == TD_ERR && !target_has_execution ())
{
/* Some platforms require execution for td_ta_map_lwp2thr. */
LOG (_("; can't map_lwp2thr"));
fprintf_unfiltered (gdb_stdlog, _("td_ta_new failed: %s\n"),
thread_db_err_str (err));
else
- switch (err)
- {
- case TD_NOLIBTHREAD:
+ switch (err)
+ {
+ case TD_NOLIBTHREAD:
#ifdef THREAD_DB_HAS_TD_VERSION
- case TD_VERSION:
+ case TD_VERSION:
#endif
- /* The errors above are not unexpected and silently ignored:
- they just mean we haven't found correct version of
- libthread_db yet. */
- break;
- default:
- warning (_("td_ta_new failed: %s"), thread_db_err_str (err));
- }
+ /* The errors above are not unexpected and silently ignored:
+ they just mean we haven't found correct version of
+ libthread_db yet. */
+ break;
+ default:
+ warning (_("td_ta_new failed: %s"), thread_db_err_str (err));
+ }
return false;
}
td_ta_map_lwp2thr uses ps_get_thread_area, but we can't use that
currently on core targets, as it uses ptrace directly. */
- if (target_has_execution
+ if (target_has_execution ()
&& linux_proc_task_list_dir_exists (inferior_ptid.pid ()))
info->td_ta_thr_iter_p = NULL;
else
else if (thread_db_find_new_threads_silently (inferior_thread ()) != 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. */
+ corrupted, we'd not manage to list any threads. Better reject this
+ thread_db, and fall back to at least listing LWPs. */
return false;
}
/* The thread library was detected. Activate the thread_db target
for this process. */
- push_target (&the_thread_db_target);
+ current_inferior ()->push_target (&the_thread_db_target);
return true;
}
return false;
}
- if (!file_is_auto_load_safe (library, _("auto-load: Loading libthread-db "
- "library \"%s\" from explicit "
- "directory.\n"),
- library))
+ auto_load_debug_printf
+ ("Loading libthread-db library \"%s\" from explicit directory.",
+ library);
+
+ if (!file_is_auto_load_safe (library))
return false;
}
td_init = dlsym (handle, "td_init");
if (td_init != NULL)
- {
- const char *const libpath = dladdr_to_soname (td_init);
+ {
+ const char *const libpath = dladdr_to_soname (td_init);
- if (libpath != NULL)
- fprintf_unfiltered (gdb_stdlog, _("Host %s resolved to: %s.\n"),
- library, libpath);
- }
+ if (libpath != NULL)
+ fprintf_unfiltered (gdb_stdlog, _("Host %s resolved to: %s.\n"),
+ library, libpath);
+ }
}
info = add_thread_db_info (handle);
/* Don't attempt to use thread_db on executables not running
yet. */
- if (!target_has_registers)
+ if (!target_has_registers ())
return false;
/* Don't attempt to use thread_db for remote targets. */
{
if (!thread_signals)
{
- sigset_t mask;
int i;
- lin_thread_get_thread_signals (&mask);
- sigemptyset (&thread_stop_set);
- sigemptyset (&thread_print_set);
-
- for (i = 1; i < NSIG; i++)
+ for (i = 0; i < lin_thread_get_thread_signal_num (); i++)
{
- if (sigismember (&mask, i))
- {
- if (signal_stop_update (gdb_signal_from_host (i), 0))
- sigaddset (&thread_stop_set, i);
- if (signal_print_update (gdb_signal_from_host (i), 0))
- sigaddset (&thread_print_set, i);
- thread_signals = 1;
- }
+ int sig = lin_thread_get_thread_signal (i);
+ signal_stop_update (gdb_signal_from_host (sig), 0);
+ signal_print_update (gdb_signal_from_host (sig), 0);
+ thread_signals = 1;
}
}
}
}
static void
-check_pid_namespace_match (void)
+check_pid_namespace_match (inferior *inf)
{
/* Check is only relevant for local targets targets. */
if (target_can_run ())
child's thread list, we'll mistakenly think it has no threads
since the thread PID fields won't match the PID we give to
libthread_db. */
- if (!linux_ns_same (inferior_ptid.pid (), LINUX_NS_PID))
+ if (!linux_ns_same (inf->pid, LINUX_NS_PID))
{
warning (_ ("Target and debugger are in different PID "
"namespaces; thread lists and other data are "
This handles the case of debugging statically linked executables. */
static void
-thread_db_inferior_created (struct target_ops *target, int from_tty)
+thread_db_inferior_created (inferior *inf)
{
- check_pid_namespace_match ();
+ check_pid_namespace_match (inf);
check_for_thread_db ();
}
else
tp->priv.reset (priv);
- if (target_has_execution)
+ if (target_has_execution ())
check_thread_signals ();
return tp;
/* NOTE: From this point on, inferior_ptid is null_ptid. */
/* Detach the thread_db target from this inferior. */
- unpush_target (this);
+ inf->unpush_target (this);
}
ptid_t
thread_db_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
- int options)
+ target_wait_flags options)
{
struct thread_db_info *info;
case TARGET_WAITKIND_EXITED:
case TARGET_WAITKIND_THREAD_EXITED:
case TARGET_WAITKIND_SIGNALLED:
+ case TARGET_WAITKIND_EXECD:
return ptid;
}
if (info == NULL)
return ptid;
- if (ourstatus->kind == TARGET_WAITKIND_EXECD)
- {
- /* New image, it may or may not end up using thread_db. Assume
- not unless we find otherwise. */
- delete_thread_db_info (beneath, ptid.pid ());
- unpush_target (this);
-
- return ptid;
- }
-
/* Fill in the thread's user-level thread id and status. */
thread_from_lwp (find_thread_ptid (beneath, ptid), ptid);
target_beneath->mourn_inferior ();
/* Detach the thread_db target from this inferior. */
- unpush_target (this);
+ current_inferior ()->unpush_target (this);
+}
+
+void
+thread_db_target::follow_exec (inferior *follow_inf, ptid_t ptid,
+ const char *execd_pathname)
+{
+ process_stratum_target *beneath
+ = as_process_stratum_target (this->beneath ());
+
+ delete_thread_db_info (beneath, ptid.pid ());
+
+ current_inferior ()->unpush_target (this);
+ beneath->follow_exec (follow_inf, ptid, execd_pathname);
}
struct callback_data
thread_db_thread_info *priv = get_thread_db_thread_info (tp);
if (priv != NULL && handle_tid == priv->tid)
- return tp;
+ return tp;
}
return NULL;
/* Now, if libthread_db provided the initialization image's
address, we *could* try to build a non-lvalue value from
the initialization image. */
- throw_error (TLS_NOT_ALLOCATED_YET_ERROR,
- _("TLS not allocated yet"));
+ throw_error (TLS_NOT_ALLOCATED_YET_ERROR,
+ _("TLS not allocated yet"));
#endif
/* Something else went wrong. */
if (err != TD_OK)
- throw_error (TLS_GENERIC_ERROR,
- (("%s")), thread_db_err_str (err));
+ throw_error (TLS_GENERIC_ERROR,
+ (("%s")), thread_db_err_str (err));
/* Cast assuming host == target. Joy. */
/* Do proper sign extension for the target. */
- gdb_assert (exec_bfd);
- return (bfd_get_sign_extend_vma (exec_bfd) > 0
+ gdb_assert (current_program_space->exec_bfd ());
+ return (bfd_get_sign_extend_vma (current_program_space->exec_bfd ()) > 0
? (CORE_ADDR) (intptr_t) address
: (CORE_ADDR) (uintptr_t) address);
}
i++;
}
- uiout->field_string ("pids", pids.c_str ());
+ uiout->field_string ("pids", pids);
uiout->text ("\n");
}
check_thread_db (info, true);
}
+void _initialize_thread_db ();
void
-_initialize_thread_db (void)
+_initialize_thread_db ()
{
/* Defer loading of libthread_db.so until inferior is running.
This allows gdb to load correct libthread_db for a given
&maintenance_show_cmdlist);
/* Add ourselves to objfile event chain. */
- gdb::observers::new_objfile.attach (thread_db_new_objfile);
+ gdb::observers::new_objfile.attach (thread_db_new_objfile, "linux-thread-db");
/* Add ourselves to inferior_created event chain.
This is needed to handle debugging statically linked programs where
the new_objfile observer won't get called for libpthread. */
- gdb::observers::inferior_created.attach (thread_db_inferior_created);
+ gdb::observers::inferior_created.attach (thread_db_inferior_created,
+ "linux-thread-db");
}