/* libthread_db assisted debugging support, generic parts.
- Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009
- Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+ 2010 Free Software Foundation, Inc.
This file is part of GDB.
td_event_e event, td_notify_t *ptr);
td_err_e (*td_ta_set_event_p) (const td_thragent_t *ta,
td_thr_events_t *event);
+ td_err_e (*td_ta_clear_event_p) (const td_thragent_t *ta,
+ td_thr_events_t *event);
td_err_e (*td_ta_event_getmsg_p) (const td_thragent_t *ta,
td_event_msg_t *msg);
int event);
td_err_e (*td_thr_tls_get_addr_p) (const td_thrhandle_t *th,
- void *map_address,
- size_t offset, void **address);
+ psaddr_t map_address,
+ size_t offset, psaddr_t *address);
};
/* List of known processes using thread_db, and the required
static struct thread_db_info *
add_thread_db_info (void *handle)
{
- int pid;
struct thread_db_info *info;
info = xcalloc (1, sizeof (*info));
have_threads_callback (struct thread_info *thread, void *args)
{
int pid = * (int *) args;
+
if (ptid_get_pid (thread->ptid) != pid)
return 0;
{
td_thrhandle_t th;
td_err_e err;
- ptid_t thread_ptid;
struct thread_db_info *info;
struct thread_get_info_inout io = {0};
enable_thread_event_reporting (void)
{
td_thr_events_t events;
- td_notify_t notify;
td_err_e err;
#ifdef HAVE_GNU_LIBC_VERSION_H
const char *libc_version;
}
if (except.reason < 0 && info_verbose)
- {
- exception_fprintf (gdb_stderr, except,
- "Warning: thread_db_find_new_threads_silently: ");
- }
+ {
+ exception_fprintf (gdb_stderr, except,
+ "Warning: thread_db_find_new_threads_silently: ");
+ }
}
/* Lookup a library in which given symbol resides.
/* These are not essential. */
info->td_ta_event_addr_p = dlsym (info->handle, "td_ta_event_addr");
info->td_ta_set_event_p = dlsym (info->handle, "td_ta_set_event");
+ info->td_ta_clear_event_p = dlsym (info->handle, "td_ta_clear_event");
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");
while (*search_path)
{
const char *end = strchr (search_path, ':');
+
if (end)
{
size_t len = end - search_path;
+
if (len + 1 + strlen (LIBTHREAD_DB_SO) + 1 > sizeof (path))
{
char *cp = xmalloc (len + 1);
+
memcpy (cp, search_path, len);
cp[len] = '\0';
warning (_("libthread_db_search_path component too long,"
}
static void
-disable_thread_event_reporting (void)
+disable_thread_event_reporting (struct thread_db_info *info)
{
- td_thr_events_t events;
- struct thread_db_info *info;
-
- info = get_thread_db_info (GET_PID (inferior_ptid));
+ if (info->td_ta_clear_event_p != NULL)
+ {
+ td_thr_events_t events;
- /* Set the process wide mask saying we aren't interested in any
- events anymore. */
- td_event_emptyset (&events);
- info->td_ta_set_event_p (info->thread_agent, &events);
+ /* Set the process wide mask saying we aren't interested in any
+ events anymore. */
+ td_event_fillset (&events);
+ info->td_ta_clear_event_p (info->thread_agent, &events);
+ }
- /* Delete thread event breakpoints, if any. */
- remove_thread_event_breakpoints ();
info->td_create_bp_addr = 0;
info->td_death_bp_addr = 0;
}
void
check_for_thread_db (void)
{
- td_err_e err;
- static void *last_loaded;
-
/* Do nothing if we couldn't load libthread_db.so.1. */
if (!thread_db_load ())
return;
if (info)
{
- disable_thread_event_reporting ();
+ disable_thread_event_reporting (info);
/* Delete the old thread event breakpoints. Note that unlike
when mourning, we can remove them here because there's still
if (info->need_stale_parent_threads_check)
{
int tgid = linux_proc_get_tgid (ti.ti_lid);
+
if (tgid != -1 && tgid != info->pid)
return 0;
}
static int
find_new_threads_once (struct thread_db_info *info, int iteration,
- int *errp)
+ td_err_e *errp)
{
volatile struct gdb_exception except;
struct callback_data data;
- int err = TD_ERR;
+ td_err_e err = TD_ERR;
data.info = info;
data.new_threads = 0;
}
else
{
- int err;
-
find_new_threads_once (info, 0, &err);
if (err != TD_OK)
error (_("Cannot find new threads: %s"), thread_db_err_str (err));
thread_db_find_new_threads_2 (ptid, 0);
}
+static int
+update_thread_core (struct lwp_info *info, void *closure)
+{
+ info->core = linux_nat_core_of_thread_1 (info->ptid);
+ return 0;
+}
static void
thread_db_find_new_threads (struct target_ops *ops)
return;
thread_db_find_new_threads_1 (inferior_ptid);
+
+ iterate_over_lwps (minus_one_ptid /* iterate over all */,
+ update_thread_core, NULL);
}
static char *
if (thread_info != NULL && thread_info->private != NULL)
{
td_err_e err;
- void *address;
+ psaddr_t address;
struct thread_db_info *info;
info = get_thread_db_info (GET_PID (ptid));
gdb_assert (lm != 0);
/* 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,
- (void *)(size_t) lm,
+ (psaddr_t)(uintptr_t) lm,
offset, &address);
#ifdef THREAD_DB_HAS_TD_NOTALLOC