yann@96: Support loading two libthread_db DSOs. In this case, the LinuxThreads yann@96: and NPTL ones. yann@96: yann@96: Index: gdb-6.3/gdb/thread-db.c yann@96: =================================================================== yann@96: --- gdb-6.3.orig/gdb/thread-db.c 2004-11-10 10:46:24.000000000 -0500 yann@96: +++ gdb-6.3/gdb/thread-db.c 2004-11-10 11:22:34.858812426 -0500 yann@96: @@ -79,53 +79,63 @@ static td_thragent_t *thread_agent; yann@96: yann@96: /* Pointers to the libthread_db functions. */ yann@96: yann@96: -static td_err_e (*td_init_p) (void); yann@96: +struct thread_db_pointers yann@96: +{ yann@96: + const char *filename; yann@96: + yann@96: + td_err_e (*td_init_p) (void); yann@96: yann@96: -static td_err_e (*td_ta_new_p) (struct ps_prochandle * ps, yann@96: - td_thragent_t **ta); yann@96: -static td_err_e (*td_ta_map_id2thr_p) (const td_thragent_t *ta, thread_t pt, yann@96: - td_thrhandle_t *__th); yann@96: -static td_err_e (*td_ta_map_lwp2thr_p) (const td_thragent_t *ta, yann@96: - lwpid_t lwpid, td_thrhandle_t *th); yann@96: -static td_err_e (*td_ta_thr_iter_p) (const td_thragent_t *ta, yann@96: - td_thr_iter_f *callback, void *cbdata_p, yann@96: - td_thr_state_e state, int ti_pri, yann@96: - sigset_t *ti_sigmask_p, yann@96: - unsigned int ti_user_flags); yann@96: -static td_err_e (*td_ta_event_addr_p) (const td_thragent_t *ta, yann@96: - td_event_e event, td_notify_t *ptr); yann@96: -static td_err_e (*td_ta_set_event_p) (const td_thragent_t *ta, yann@96: - td_thr_events_t *event); yann@96: -static td_err_e (*td_ta_event_getmsg_p) (const td_thragent_t *ta, yann@96: - td_event_msg_t *msg); yann@96: - yann@96: -static td_err_e (*td_thr_validate_p) (const td_thrhandle_t *th); yann@96: -static td_err_e (*td_thr_get_info_p) (const td_thrhandle_t *th, yann@96: - td_thrinfo_t *infop); yann@96: -static td_err_e (*td_thr_getfpregs_p) (const td_thrhandle_t *th, yann@96: - gdb_prfpregset_t *regset); yann@96: -static td_err_e (*td_thr_getgregs_p) (const td_thrhandle_t *th, yann@96: - prgregset_t gregs); yann@96: -static td_err_e (*td_thr_setfpregs_p) (const td_thrhandle_t *th, yann@96: - const gdb_prfpregset_t *fpregs); yann@96: -static td_err_e (*td_thr_setgregs_p) (const td_thrhandle_t *th, yann@96: - prgregset_t gregs); yann@96: -static td_err_e (*td_thr_event_enable_p) (const td_thrhandle_t *th, yann@96: - int event); yann@96: - yann@96: -static td_err_e (*td_thr_tls_get_addr_p) (const td_thrhandle_t *th, yann@96: - void *map_address, yann@96: - size_t offset, void **address); yann@96: + td_err_e (*td_ta_new_p) (struct ps_prochandle * ps, yann@96: + td_thragent_t **ta); yann@96: + td_err_e (*td_ta_map_id2thr_p) (const td_thragent_t *ta, thread_t pt, yann@96: + td_thrhandle_t *__th); yann@96: + td_err_e (*td_ta_map_lwp2thr_p) (const td_thragent_t *ta, yann@96: + lwpid_t lwpid, td_thrhandle_t *th); yann@96: + yann@96: + td_err_e (*td_ta_thr_iter_p) (const td_thragent_t *ta, yann@96: + td_thr_iter_f *callback, void *cbdata_p, yann@96: + td_thr_state_e state, int ti_pri, yann@96: + sigset_t *ti_sigmask_p, yann@96: + unsigned int ti_user_flags); yann@96: + td_err_e (*td_ta_event_addr_p) (const td_thragent_t *ta, yann@96: + td_event_e event, td_notify_t *ptr); yann@96: + td_err_e (*td_ta_set_event_p) (const td_thragent_t *ta, yann@96: + td_thr_events_t *event); yann@96: + td_err_e (*td_ta_event_getmsg_p) (const td_thragent_t *ta, yann@96: + td_event_msg_t *msg); yann@96: + yann@96: + td_err_e (*td_thr_validate_p) (const td_thrhandle_t *th); yann@96: + td_err_e (*td_thr_get_info_p) (const td_thrhandle_t *th, yann@96: + td_thrinfo_t *infop); yann@96: + td_err_e (*td_thr_getfpregs_p) (const td_thrhandle_t *th, yann@96: + gdb_prfpregset_t *regset); yann@96: + td_err_e (*td_thr_getgregs_p) (const td_thrhandle_t *th, yann@96: + prgregset_t gregs); yann@96: + td_err_e (*td_thr_setfpregs_p) (const td_thrhandle_t *th, yann@96: + const gdb_prfpregset_t *fpregs); yann@96: + td_err_e (*td_thr_setgregs_p) (const td_thrhandle_t *th, yann@96: + prgregset_t gregs); yann@96: + td_err_e (*td_thr_event_enable_p) (const td_thrhandle_t *th, yann@96: + int event); yann@96: + yann@96: + td_err_e (*td_thr_tls_get_addr_p) (const td_thrhandle_t *th, yann@96: + void *map_address, yann@96: + size_t offset, void **address); yann@96: + yann@96: + struct thread_db_pointers *next; yann@96: +}; yann@96: yann@96: /* Location of the thread creation event breakpoint. The code at this yann@96: location in the child process will be called by the pthread library yann@96: whenever a new thread is created. By setting a special breakpoint yann@96: at this location, GDB can detect when a new thread is created. We yann@96: obtain this location via the td_ta_event_addr call. */ yann@96: -static CORE_ADDR td_create_bp_addr; yann@96: +CORE_ADDR td_create_bp_addr; yann@96: yann@96: /* Location of the thread death event breakpoint. */ yann@96: -static CORE_ADDR td_death_bp_addr; yann@96: +CORE_ADDR td_death_bp_addr; yann@96: + yann@96: +static struct thread_db_pointers *current_pointers, *all_pointers; yann@96: yann@96: /* Prototypes for local functions. */ yann@96: static void thread_db_find_new_threads (void); yann@96: @@ -262,7 +272,7 @@ thread_get_info_callback (const td_thrha yann@96: struct thread_info *thread_info; yann@96: ptid_t thread_ptid; yann@96: yann@96: - err = td_thr_get_info_p (thp, &ti); yann@96: + err = current_pointers->td_thr_get_info_p (thp, &ti); yann@96: if (err != TD_OK) yann@96: error ("thread_get_info_callback: cannot get thread info: %s", yann@96: thread_db_err_str (err)); yann@96: @@ -316,8 +326,9 @@ thread_db_map_id2thr (struct thread_info yann@96: if (thread_info->private->th_valid) yann@96: return; yann@96: yann@96: - err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (thread_info->ptid), yann@96: - &thread_info->private->th); yann@96: + err = current_pointers->td_ta_map_id2thr_p (thread_agent, yann@96: + GET_THREAD (thread_info->ptid), yann@96: + &thread_info->private->th); yann@96: if (err != TD_OK) yann@96: { yann@96: if (fatal) yann@96: @@ -340,8 +351,8 @@ thread_db_get_info (struct thread_info * yann@96: if (!thread_info->private->th_valid) yann@96: thread_db_map_id2thr (thread_info, 1); yann@96: yann@96: - err = yann@96: - td_thr_get_info_p (&thread_info->private->th, &thread_info->private->ti); yann@96: + err = current_pointers->td_thr_get_info_p (&thread_info->private->th, yann@96: + &thread_info->private->ti); yann@96: if (err != TD_OK) yann@96: error ("thread_db_get_info: cannot get thread info: %s", yann@96: thread_db_err_str (err)); yann@96: @@ -365,7 +376,8 @@ thread_from_lwp (ptid_t ptid) yann@96: yann@96: gdb_assert (is_lwp (ptid)); yann@96: yann@96: - err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), &th); yann@96: + err = current_pointers->td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), yann@96: + &th); yann@96: if (err != TD_OK) yann@96: error ("Cannot find user-level thread for LWP %ld: %s", yann@96: GET_LWP (ptid), thread_db_err_str (err)); yann@96: @@ -420,85 +432,102 @@ verbose_dlsym (void *handle, const char yann@96: return sym; yann@96: } yann@96: yann@96: -static int yann@96: -thread_db_load (void) yann@96: +static struct thread_db_pointers * yann@96: +thread_db_load (const char *name) yann@96: { yann@96: + struct thread_db_pointers *ptrs; yann@96: + Dl_info info; yann@96: void *handle; yann@96: td_err_e err; yann@96: yann@96: - handle = dlopen (LIBTHREAD_DB_SO, RTLD_NOW); yann@96: + ptrs = xcalloc (1, sizeof (struct thread_db_pointers)); yann@96: + yann@96: + handle = dlopen (name, RTLD_NOW); yann@96: if (handle == NULL) yann@96: { yann@96: - fprintf_filtered (gdb_stderr, "\n\ndlopen failed on '%s' - %s\n", yann@96: - LIBTHREAD_DB_SO, dlerror ()); yann@96: - fprintf_filtered (gdb_stderr, yann@96: - "GDB will not be able to debug pthreads.\n\n"); yann@96: + if (all_pointers == NULL) yann@96: + { yann@96: + fprintf_filtered (gdb_stderr, "\n\ndlopen failed on '%s' - %s\n", yann@96: + name, dlerror ()); yann@96: + fprintf_filtered (gdb_stderr, yann@96: + "GDB will not be able to debug pthreads.\n\n"); yann@96: + } yann@96: return 0; yann@96: } yann@96: yann@96: /* Initialize pointers to the dynamic library functions we will use. yann@96: Essential functions first. */ yann@96: yann@96: - td_init_p = verbose_dlsym (handle, "td_init"); yann@96: - if (td_init_p == NULL) yann@96: + ptrs->td_init_p = verbose_dlsym (handle, "td_init"); yann@96: + if (ptrs->td_init_p == NULL) yann@96: return 0; yann@96: yann@96: - td_ta_new_p = verbose_dlsym (handle, "td_ta_new"); yann@96: - if (td_ta_new_p == NULL) yann@96: + ptrs->td_ta_new_p = verbose_dlsym (handle, "td_ta_new"); yann@96: + if (ptrs->td_ta_new_p == NULL) yann@96: return 0; yann@96: yann@96: - td_ta_map_id2thr_p = verbose_dlsym (handle, "td_ta_map_id2thr"); yann@96: - if (td_ta_map_id2thr_p == NULL) yann@96: + ptrs->td_ta_map_id2thr_p = verbose_dlsym (handle, "td_ta_map_id2thr"); yann@96: + if (ptrs->td_ta_map_id2thr_p == NULL) yann@96: return 0; yann@96: yann@96: - td_ta_map_lwp2thr_p = verbose_dlsym (handle, "td_ta_map_lwp2thr"); yann@96: - if (td_ta_map_lwp2thr_p == NULL) yann@96: + ptrs->td_ta_map_lwp2thr_p = verbose_dlsym (handle, "td_ta_map_lwp2thr"); yann@96: + if (ptrs->td_ta_map_lwp2thr_p == NULL) yann@96: return 0; yann@96: yann@96: - td_ta_thr_iter_p = verbose_dlsym (handle, "td_ta_thr_iter"); yann@96: - if (td_ta_thr_iter_p == NULL) yann@96: + ptrs->td_ta_thr_iter_p = verbose_dlsym (handle, "td_ta_thr_iter"); yann@96: + if (ptrs->td_ta_thr_iter_p == NULL) yann@96: return 0; yann@96: yann@96: - td_thr_validate_p = verbose_dlsym (handle, "td_thr_validate"); yann@96: - if (td_thr_validate_p == NULL) yann@96: + ptrs->td_thr_validate_p = verbose_dlsym (handle, "td_thr_validate"); yann@96: + if (ptrs->td_thr_validate_p == NULL) yann@96: return 0; yann@96: yann@96: - td_thr_get_info_p = verbose_dlsym (handle, "td_thr_get_info"); yann@96: - if (td_thr_get_info_p == NULL) yann@96: + ptrs->td_thr_get_info_p = verbose_dlsym (handle, "td_thr_get_info"); yann@96: + if (ptrs->td_thr_get_info_p == NULL) yann@96: return 0; yann@96: yann@96: - td_thr_getfpregs_p = verbose_dlsym (handle, "td_thr_getfpregs"); yann@96: - if (td_thr_getfpregs_p == NULL) yann@96: + ptrs->td_thr_getfpregs_p = verbose_dlsym (handle, "td_thr_getfpregs"); yann@96: + if (ptrs->td_thr_getfpregs_p == NULL) yann@96: return 0; yann@96: yann@96: - td_thr_getgregs_p = verbose_dlsym (handle, "td_thr_getgregs"); yann@96: - if (td_thr_getgregs_p == NULL) yann@96: + ptrs->td_thr_getgregs_p = verbose_dlsym (handle, "td_thr_getgregs"); yann@96: + if (ptrs->td_thr_getgregs_p == NULL) yann@96: return 0; yann@96: yann@96: - td_thr_setfpregs_p = verbose_dlsym (handle, "td_thr_setfpregs"); yann@96: - if (td_thr_setfpregs_p == NULL) yann@96: + ptrs->td_thr_setfpregs_p = verbose_dlsym (handle, "td_thr_setfpregs"); yann@96: + if (ptrs->td_thr_setfpregs_p == NULL) yann@96: return 0; yann@96: yann@96: - td_thr_setgregs_p = verbose_dlsym (handle, "td_thr_setgregs"); yann@96: - if (td_thr_setgregs_p == NULL) yann@96: + ptrs->td_thr_setgregs_p = verbose_dlsym (handle, "td_thr_setgregs"); yann@96: + if (ptrs->td_thr_setgregs_p == NULL) yann@96: return 0; yann@96: yann@96: /* Initialize the library. */ yann@96: - err = td_init_p (); yann@96: + err = ptrs->td_init_p (); yann@96: if (err != TD_OK) yann@96: { yann@96: warning ("Cannot initialize libthread_db: %s", thread_db_err_str (err)); yann@96: + xfree (ptrs); yann@96: return 0; yann@96: } yann@96: yann@96: /* These are not essential. */ yann@96: - td_ta_event_addr_p = dlsym (handle, "td_ta_event_addr"); yann@96: - td_ta_set_event_p = dlsym (handle, "td_ta_set_event"); yann@96: - td_ta_event_getmsg_p = dlsym (handle, "td_ta_event_getmsg"); yann@96: - td_thr_event_enable_p = dlsym (handle, "td_thr_event_enable"); yann@96: - td_thr_tls_get_addr_p = dlsym (handle, "td_thr_tls_get_addr"); yann@96: + ptrs->td_ta_event_addr_p = dlsym (handle, "td_ta_event_addr"); yann@96: + ptrs->td_ta_set_event_p = dlsym (handle, "td_ta_set_event"); yann@96: + ptrs->td_ta_event_getmsg_p = dlsym (handle, "td_ta_event_getmsg"); yann@96: + ptrs->td_thr_event_enable_p = dlsym (handle, "td_thr_event_enable"); yann@96: + ptrs->td_thr_tls_get_addr_p = dlsym (handle, "td_thr_tls_get_addr"); yann@96: + yann@96: + if (dladdr (ptrs->td_ta_new_p, &info) != 0) yann@96: + ptrs->filename = info.dli_fname; yann@96: + yann@96: + /* Try dlinfo? */ yann@96: + yann@96: + if (ptrs->filename == NULL) yann@96: + /* Paranoid - don't let a NULL path slip through. */ yann@96: + ptrs->filename = name; yann@96: yann@96: - return 1; yann@96: + return ptrs; yann@96: } yann@96: yann@96: static td_err_e yann@96: @@ -508,7 +537,7 @@ enable_thread_event (td_thragent_t *thre yann@96: td_err_e err; yann@96: yann@96: /* Get the breakpoint address for thread EVENT. */ yann@96: - err = td_ta_event_addr_p (thread_agent, event, ¬ify); yann@96: + err = current_pointers->td_ta_event_addr_p (thread_agent, event, ¬ify); yann@96: if (err != TD_OK) yann@96: return err; yann@96: yann@96: @@ -534,8 +563,10 @@ enable_thread_event_reporting (void) yann@96: yann@96: /* We cannot use the thread event reporting facility if these yann@96: functions aren't available. */ yann@96: - if (td_ta_event_addr_p == NULL || td_ta_set_event_p == NULL yann@96: - || td_ta_event_getmsg_p == NULL || td_thr_event_enable_p == NULL) yann@96: + if (current_pointers->td_ta_event_addr_p == NULL yann@96: + || current_pointers->td_ta_set_event_p == NULL yann@96: + || current_pointers->td_ta_event_getmsg_p == NULL yann@96: + || current_pointers->td_thr_event_enable_p == NULL) yann@96: return; yann@96: yann@96: /* Set the process wide mask saying which events we're interested in. */ yann@96: @@ -552,7 +583,7 @@ enable_thread_event_reporting (void) yann@96: #endif yann@96: td_event_addset (&events, TD_DEATH); yann@96: yann@96: - err = td_ta_set_event_p (thread_agent, &events); yann@96: + err = current_pointers->td_ta_set_event_p (thread_agent, &events); yann@96: if (err != TD_OK) yann@96: { yann@96: warning ("Unable to set global thread event mask: %s", yann@96: @@ -592,7 +623,7 @@ disable_thread_event_reporting (void) yann@96: /* Set the process wide mask saying we aren't interested in any yann@96: events anymore. */ yann@96: td_event_emptyset (&events); yann@96: - td_ta_set_event_p (thread_agent, &events); yann@96: + current_pointers->td_ta_set_event_p (thread_agent, &events); yann@96: yann@96: /* Delete thread event breakpoints, if any. */ yann@96: remove_thread_event_breakpoints (); yann@96: @@ -635,7 +666,6 @@ check_thread_signals (void) yann@96: static void yann@96: check_for_thread_db (void) yann@96: { yann@96: - td_err_e err; yann@96: static int already_loaded; yann@96: yann@96: /* First time through, report that libthread_db was successfuly yann@96: @@ -644,19 +674,8 @@ check_for_thread_db (void) yann@96: yann@96: if (!already_loaded) yann@96: { yann@96: - Dl_info info; yann@96: - const char *library = NULL; yann@96: - if (dladdr ((*td_ta_new_p), &info) != 0) yann@96: - library = info.dli_fname; yann@96: - yann@96: - /* Try dlinfo? */ yann@96: - yann@96: - if (library == NULL) yann@96: - /* Paranoid - don't let a NULL path slip through. */ yann@96: - library = LIBTHREAD_DB_SO; yann@96: - yann@96: printf_unfiltered ("Using host libthread_db library \"%s\".\n", yann@96: - library); yann@96: + all_pointers->filename); yann@96: already_loaded = 1; yann@96: } yann@96: yann@96: @@ -674,28 +693,34 @@ check_for_thread_db (void) yann@96: proc_handle.pid = GET_PID (inferior_ptid); yann@96: yann@96: /* Now attempt to open a connection to the thread library. */ yann@96: - err = td_ta_new_p (&proc_handle, &thread_agent); yann@96: - switch (err) yann@96: + for (current_pointers = all_pointers; yann@96: + current_pointers != NULL; yann@96: + current_pointers = current_pointers->next) yann@96: { yann@96: - case TD_NOLIBTHREAD: yann@96: - /* No thread library was detected. */ yann@96: - break; yann@96: - yann@96: - case TD_OK: yann@96: - printf_unfiltered ("[Thread debugging using libthread_db enabled]\n"); yann@96: + td_err_e err; yann@96: + err = current_pointers->td_ta_new_p (&proc_handle, &thread_agent); yann@96: + switch (err) yann@96: + { yann@96: + case TD_NOLIBTHREAD: yann@96: + /* No thread library was detected. */ yann@96: + break; yann@96: yann@96: - /* The thread library was detected. Activate the thread_db target. */ yann@96: - push_target (&thread_db_ops); yann@96: - using_thread_db = 1; yann@96: + case TD_OK: yann@96: + printf_unfiltered ("[Thread debugging using libthread_db enabled]\n"); yann@96: yann@96: - enable_thread_event_reporting (); yann@96: - thread_db_find_new_threads (); yann@96: - break; yann@96: + /* The thread library was detected. Activate the thread_db target. */ yann@96: + push_target (&thread_db_ops); yann@96: + using_thread_db = 1; yann@96: + yann@96: + enable_thread_event_reporting (); yann@96: + thread_db_find_new_threads (); yann@96: + return; yann@96: yann@96: - default: yann@96: - warning ("Cannot initialize thread debugging library: %s", yann@96: - thread_db_err_str (err)); yann@96: - break; yann@96: + default: yann@96: + warning ("Cannot initialize thread debugging library: %s", yann@96: + thread_db_err_str (err)); yann@96: + break; yann@96: + } yann@96: } yann@96: } yann@96: yann@96: @@ -766,7 +791,7 @@ attach_thread (ptid_t ptid, const td_thr yann@96: #endif yann@96: yann@96: /* Enable thread event reporting for this thread. */ yann@96: - err = td_thr_event_enable_p (th_p, 1); yann@96: + err = current_pointers->td_thr_event_enable_p (th_p, 1); yann@96: if (err != TD_OK) yann@96: error ("Cannot enable thread event reporting for %s: %s", yann@96: target_pid_to_str (ptid), thread_db_err_str (err)); yann@96: @@ -892,7 +917,7 @@ check_event (ptid_t ptid) yann@96: yann@96: do yann@96: { yann@96: - err = td_ta_event_getmsg_p (thread_agent, &msg); yann@96: + err = current_pointers->td_ta_event_getmsg_p (thread_agent, &msg); yann@96: if (err != TD_OK) yann@96: { yann@96: if (err == TD_NOMSG) yann@96: @@ -902,7 +927,7 @@ check_event (ptid_t ptid) yann@96: thread_db_err_str (err)); yann@96: } yann@96: yann@96: - err = td_thr_get_info_p (msg.th_p, &ti); yann@96: + err = current_pointers->td_thr_get_info_p (msg.th_p, &ti); yann@96: if (err != TD_OK) yann@96: error ("Cannot get thread info: %s", thread_db_err_str (err)); yann@96: yann@96: @@ -1015,12 +1040,14 @@ thread_db_fetch_registers (int regno) yann@96: thread_info = find_thread_pid (inferior_ptid); yann@96: thread_db_map_id2thr (thread_info, 1); yann@96: yann@96: - err = td_thr_getgregs_p (&thread_info->private->th, gregset); yann@96: + err = current_pointers->td_thr_getgregs_p (&thread_info->private->th, yann@96: + gregset); yann@96: if (err != TD_OK) yann@96: error ("Cannot fetch general-purpose registers for thread %ld: %s", yann@96: (long) GET_THREAD (inferior_ptid), thread_db_err_str (err)); yann@96: yann@96: - err = td_thr_getfpregs_p (&thread_info->private->th, &fpregset); yann@96: + err = current_pointers->td_thr_getfpregs_p (&thread_info->private->th, yann@96: + &fpregset); yann@96: if (err != TD_OK) yann@96: error ("Cannot get floating-point registers for thread %ld: %s", yann@96: (long) GET_THREAD (inferior_ptid), thread_db_err_str (err)); yann@96: @@ -1062,11 +1089,13 @@ thread_db_store_registers (int regno) yann@96: fill_gregset ((gdb_gregset_t *) gregset, -1); yann@96: fill_fpregset (&fpregset, -1); yann@96: yann@96: - err = td_thr_setgregs_p (&thread_info->private->th, gregset); yann@96: + err = current_pointers->td_thr_setgregs_p (&thread_info->private->th, yann@96: + gregset); yann@96: if (err != TD_OK) yann@96: error ("Cannot store general-purpose registers for thread %ld: %s", yann@96: (long) GET_THREAD (inferior_ptid), thread_db_err_str (err)); yann@96: - err = td_thr_setfpregs_p (&thread_info->private->th, &fpregset); yann@96: + err = current_pointers->td_thr_setfpregs_p (&thread_info->private->th, yann@96: + &fpregset); yann@96: if (err != TD_OK) yann@96: error ("Cannot store floating-point registers for thread %ld: %s", yann@96: (long) GET_THREAD (inferior_ptid), thread_db_err_str (err)); yann@96: @@ -1136,15 +1165,14 @@ thread_db_thread_alive (ptid_t ptid) yann@96: if (!thread_info->private->th_valid) yann@96: return 0; yann@96: yann@96: - err = td_thr_validate_p (&thread_info->private->th); yann@96: + err = current_pointers->td_thr_validate_p (&thread_info->private->th); yann@96: if (err != TD_OK) yann@96: return 0; yann@96: yann@96: if (!thread_info->private->ti_valid) yann@96: { yann@96: - err = yann@96: - td_thr_get_info_p (&thread_info->private->th, yann@96: - &thread_info->private->ti); yann@96: + err = current_pointers->td_thr_get_info_p yann@96: + (&thread_info->private->th, &thread_info->private->ti); yann@96: if (err != TD_OK) yann@96: return 0; yann@96: thread_info->private->ti_valid = 1; yann@96: @@ -1170,7 +1198,7 @@ find_new_threads_callback (const td_thrh yann@96: td_err_e err; yann@96: ptid_t ptid; yann@96: yann@96: - err = td_thr_get_info_p (th_p, &ti); yann@96: + err = current_pointers->td_thr_get_info_p (th_p, &ti); yann@96: if (err != TD_OK) yann@96: error ("find_new_threads_callback: cannot get thread info: %s", yann@96: thread_db_err_str (err)); yann@96: @@ -1192,9 +1220,10 @@ thread_db_find_new_threads (void) yann@96: td_err_e err; yann@96: yann@96: /* Iterate over all user-space threads to discover new threads. */ yann@96: - err = td_ta_thr_iter_p (thread_agent, find_new_threads_callback, NULL, yann@96: - TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, yann@96: - TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS); yann@96: + err = current_pointers->td_ta_thr_iter_p yann@96: + (thread_agent, find_new_threads_callback, NULL, yann@96: + TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, yann@96: + TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS); yann@96: if (err != TD_OK) yann@96: error ("Cannot find new threads: %s", thread_db_err_str (err)); yann@96: } yann@96: @@ -1257,7 +1286,7 @@ thread_db_get_thread_local_address (ptid yann@96: struct thread_info *thread_info; yann@96: yann@96: /* glibc doesn't provide the needed interface. */ yann@96: - if (!td_thr_tls_get_addr_p) yann@96: + if (!current_pointers->td_thr_tls_get_addr_p) yann@96: error ("Cannot find thread-local variables in this thread library."); yann@96: yann@96: /* Get the address of the link map for this objfile. */ yann@96: @@ -1279,8 +1308,8 @@ thread_db_get_thread_local_address (ptid yann@96: thread_db_map_id2thr (thread_info, 1); yann@96: yann@96: /* Finally, get the address of the variable. */ yann@96: - err = td_thr_tls_get_addr_p (&thread_info->private->th, (void *) lm, yann@96: - offset, &address); yann@96: + err = current_pointers->td_thr_tls_get_addr_p yann@96: + (&thread_info->private->th, (void *) lm, offset, &address); yann@96: yann@96: #ifdef THREAD_DB_HAS_TD_NOTALLOC yann@96: /* The memory hasn't been allocated, yet. */ yann@96: @@ -1360,17 +1389,49 @@ init_thread_db_ops (void) yann@96: void yann@96: _initialize_thread_db (void) yann@96: { yann@96: + struct thread_db_pointers *ptrs; yann@96: + const char *p; yann@96: + yann@96: /* Only initialize the module if we can load libthread_db. */ yann@96: - if (thread_db_load ()) yann@96: - { yann@96: - init_thread_db_ops (); yann@96: - add_target (&thread_db_ops); yann@96: + ptrs = thread_db_load (LIBTHREAD_DB_SO); yann@96: + if (ptrs == NULL) yann@96: + return; yann@96: + yann@96: + all_pointers = ptrs; yann@96: yann@96: - /* Add ourselves to objfile event chain. */ yann@96: - target_new_objfile_chain = deprecated_target_new_objfile_hook; yann@96: - deprecated_target_new_objfile_hook = thread_db_new_objfile; yann@96: + /* Some GNU/Linux systems have more than one binary-compatible copy yann@96: + of libthread_db. If we can find a second one, load that too. yann@96: + The inferior may force the use of a different threading package yann@96: + than we expect. Our guess for the location is somewhat hokey: yann@96: + strip out anything between /lib (or /lib64) and LIBTHREAD_DB_SO. yann@96: + If we loaded the NPTL libthread_db by default, this may find us yann@96: + the LinuxThreads copy. */ yann@96: + p = strrchr (ptrs->filename, '/'); yann@96: + while (p != NULL && p > ptrs->filename) yann@96: + { yann@96: + const char *component; yann@96: yann@96: - /* Register ourselves for the new inferior observer. */ yann@96: - observer_attach_inferior_created (check_for_thread_db_observer); yann@96: + component = memrchr (ptrs->filename, '/', p - ptrs->filename); yann@96: + if (component != NULL && strncmp (component, "/lib", 4) == 0) yann@96: + { yann@96: + char *new_name = xmalloc (p - ptrs->filename + 2 yann@96: + + strlen (LIBTHREAD_DB_SO)); yann@96: + memcpy (new_name, ptrs->filename, p - ptrs->filename + 1); yann@96: + strcpy (new_name + (p - ptrs->filename) + 1, LIBTHREAD_DB_SO); yann@96: + ptrs->next = thread_db_load (new_name); yann@96: + xfree (new_name); yann@96: + break; yann@96: + } yann@96: + p = component; yann@96: } yann@96: + yann@96: + init_thread_db_ops (); yann@96: + add_target (&thread_db_ops); yann@96: + yann@96: + /* Add ourselves to objfile event chain. */ yann@96: + target_new_objfile_chain = deprecated_target_new_objfile_hook; yann@96: + deprecated_target_new_objfile_hook = thread_db_new_objfile; yann@96: + yann@96: + /* Register ourselves for the new inferior observer. */ yann@96: + observer_attach_inferior_created (check_for_thread_db_observer); yann@96: }