/* libthread_db assisted debugging support, generic parts.
- Copyright (C) 1999-2018 Free Software Foundation, Inc.
+ Copyright (C) 1999-2019 Free Software Foundation, Inc.
This file is part of GDB.
#include <dlfcn.h>
#include "gdb_proc_service.h"
#include "nat/gdb_thread_db.h"
-#include "gdb_vecs.h"
+#include "common/gdb_vecs.h"
#include "bfd.h"
#include "command.h"
#include "gdbcmd.h"
class thread_db_target final : public target_ops
{
public:
- thread_db_target ();
-
const target_info &info () const override
{ return thread_db_target_info; }
+ strata stratum () const override { return thread_stratum; }
+
void detach (inferior *, int) override;
ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
void resume (ptid_t, int, enum gdb_signal) override;
void mourn_inferior () override;
void update_thread_list () override;
- const char *pid_to_str (ptid_t) override;
+ std::string pid_to_str (ptid_t) override;
CORE_ADDR get_thread_local_address (ptid_t ptid,
CORE_ADDR load_module_addr,
CORE_ADDR offset) override;
inferior *inf) override;
};
-thread_db_target::thread_db_target ()
-{
- this->to_stratum = thread_stratum;
-}
-
static char *libthread_db_search_path;
/* Set to non-zero if thread_db auto-loading is enabled
td_init_ftype *td_init_p;
td_ta_new_ftype *td_ta_new_p;
+ td_ta_delete_ftype *td_ta_delete_p;
td_ta_map_lwp2thr_ftype *td_ta_map_lwp2thr_p;
td_ta_thr_iter_ftype *td_ta_thr_iter_p;
td_thr_get_info_ftype *td_thr_get_info_p;
return NULL;
}
+static const char *thread_db_err_str (td_err_e err);
+
/* When PID has exited or has been detached, we no longer want to keep
track of it as using libpthread. Call this function to discard
thread_db related info related to PID. Note that this closes
if (info == NULL)
return;
+ if (info->thread_agent != NULL && info->td_ta_delete_p != NULL)
+ {
+ td_err_e err = info->td_ta_delete_p (info->thread_agent);
+
+ if (err != TD_OK)
+ warning (_("Cannot deregister process %d from libthread_db: %s"),
+ pid, thread_db_err_str (err));
+ info->thread_agent = NULL;
+ }
+
if (info->handle != NULL)
dlclose (info->handle);
/* This ptid comes from linux-nat.c, which should always fill in the
LWP. */
- gdb_assert (ptid_get_lwp (ptid) != 0);
+ gdb_assert (ptid.lwp () != 0);
info = get_thread_db_info (ptid.pid ());
/* Access an lwp we know is stopped. */
info->proc_handle.thread = stopped;
- err = info->td_ta_map_lwp2thr_p (info->thread_agent, ptid_get_lwp (ptid),
+ err = info->td_ta_map_lwp2thr_p (info->thread_agent, ptid.lwp (),
&th);
if (err != TD_OK)
error (_("Cannot find user-level thread for LWP %ld: %s"),
- ptid_get_lwp (ptid), thread_db_err_str (err));
+ ptid.lwp (), thread_db_err_str (err));
err = info->td_thr_get_info_p (&th, &ti);
if (err != TD_OK)
/* These are not essential. */
TDB_DLSYM (info, td_thr_tls_get_addr);
TDB_DLSYM (info, td_thr_tlsbase);
+ TDB_DLSYM (info, td_ta_delete);
/* It's best to avoid td_ta_thr_iter if possible. That walks data
structures in the inferior's address space that may be corrupted,
static int
try_thread_db_load_from_pdir (const char *subdir)
{
- struct objfile *obj;
-
if (!auto_load_thread_db)
return 0;
- ALL_OBJFILES (obj)
+ for (objfile *obj : current_program_space->objfiles ())
if (libpthread_name_p (objfile_name (obj)))
{
if (try_thread_db_load_from_pdir_1 (obj, subdir))
static int
has_libpthread (void)
{
- struct objfile *obj;
-
- ALL_OBJFILES (obj)
+ for (objfile *obj : current_program_space->objfiles ())
if (libpthread_name_p (objfile_name (obj)))
return 1;
thread_db_target::update_thread_list ()
{
struct thread_db_info *info;
- struct inferior *inf;
prune_threads ();
- ALL_INFERIORS (inf)
+ for (inferior *inf : all_inferiors ())
{
struct thread_info *thread;
this->beneath ()->update_thread_list ();
}
-const char *
+std::string
thread_db_target::pid_to_str (ptid_t ptid)
{
struct thread_info *thread_info = find_thread_ptid (ptid);
if (thread_info != NULL && thread_info->priv != NULL)
{
- static char buf[64];
thread_db_thread_info *priv = get_thread_db_thread_info (thread_info);
- snprintf (buf, sizeof (buf), "Thread 0x%lx (LWP %ld)",
- (unsigned long) priv->tid, ptid_get_lwp (ptid));
-
- return buf;
+ return string_printf ("Thread 0x%lx (LWP %ld)",
+ (unsigned long) priv->tid, ptid.lwp ());
}
return beneath ()->pid_to_str (ptid);
int handle_len,
inferior *inf)
{
- struct thread_info *tp;
thread_t handle_tid;
/* Thread handle sizes must match in order to proceed. We don't use an
handle_tid = * (const thread_t *) thread_handle;
- ALL_NON_EXITED_THREADS (tp)
+ for (thread_info *tp : inf->non_exited_threads ())
{
thread_db_thread_info *priv = get_thread_db_thread_info (tp);
- if (tp->inf == inf && priv != NULL && handle_tid == priv->tid)
+ if (priv != NULL && handle_tid == priv->tid)
return tp;
}
{
struct thread_db_info *info;
- if (ptid_equal (ptid, minus_one_ptid))
+ if (ptid == minus_one_ptid)
info = get_thread_db_info (inferior_ptid.pid ());
else
info = get_thread_db_info (ptid.pid ());
If enabled, libthread_db will be searched in 'set libthread-db-search-path'\n\
locations to load libthread_db compatible with the inferior.\n\
Standard system libthread_db still gets loaded even with this option off.\n\
-This options has security implications for untrusted inferiors."),
+This option has security implications for untrusted inferiors."),
NULL, show_auto_load_thread_db,
auto_load_set_cmdlist_get (),
auto_load_show_cmdlist_get ());