1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/patches/gdb/6.3/710-debian_thread-db-multiple-libraries.patch Thu Jul 12 13:22:26 2007 +0000
1.3 @@ -0,0 +1,593 @@
1.4 +Support loading two libthread_db DSOs. In this case, the LinuxThreads
1.5 +and NPTL ones.
1.6 +
1.7 +Index: gdb-6.3/gdb/thread-db.c
1.8 +===================================================================
1.9 +--- gdb-6.3.orig/gdb/thread-db.c 2004-11-10 10:46:24.000000000 -0500
1.10 ++++ gdb-6.3/gdb/thread-db.c 2004-11-10 11:22:34.858812426 -0500
1.11 +@@ -79,53 +79,63 @@ static td_thragent_t *thread_agent;
1.12 +
1.13 + /* Pointers to the libthread_db functions. */
1.14 +
1.15 +-static td_err_e (*td_init_p) (void);
1.16 ++struct thread_db_pointers
1.17 ++{
1.18 ++ const char *filename;
1.19 ++
1.20 ++ td_err_e (*td_init_p) (void);
1.21 +
1.22 +-static td_err_e (*td_ta_new_p) (struct ps_prochandle * ps,
1.23 +- td_thragent_t **ta);
1.24 +-static td_err_e (*td_ta_map_id2thr_p) (const td_thragent_t *ta, thread_t pt,
1.25 +- td_thrhandle_t *__th);
1.26 +-static td_err_e (*td_ta_map_lwp2thr_p) (const td_thragent_t *ta,
1.27 +- lwpid_t lwpid, td_thrhandle_t *th);
1.28 +-static td_err_e (*td_ta_thr_iter_p) (const td_thragent_t *ta,
1.29 +- td_thr_iter_f *callback, void *cbdata_p,
1.30 +- td_thr_state_e state, int ti_pri,
1.31 +- sigset_t *ti_sigmask_p,
1.32 +- unsigned int ti_user_flags);
1.33 +-static td_err_e (*td_ta_event_addr_p) (const td_thragent_t *ta,
1.34 +- td_event_e event, td_notify_t *ptr);
1.35 +-static td_err_e (*td_ta_set_event_p) (const td_thragent_t *ta,
1.36 +- td_thr_events_t *event);
1.37 +-static td_err_e (*td_ta_event_getmsg_p) (const td_thragent_t *ta,
1.38 +- td_event_msg_t *msg);
1.39 +-
1.40 +-static td_err_e (*td_thr_validate_p) (const td_thrhandle_t *th);
1.41 +-static td_err_e (*td_thr_get_info_p) (const td_thrhandle_t *th,
1.42 +- td_thrinfo_t *infop);
1.43 +-static td_err_e (*td_thr_getfpregs_p) (const td_thrhandle_t *th,
1.44 +- gdb_prfpregset_t *regset);
1.45 +-static td_err_e (*td_thr_getgregs_p) (const td_thrhandle_t *th,
1.46 +- prgregset_t gregs);
1.47 +-static td_err_e (*td_thr_setfpregs_p) (const td_thrhandle_t *th,
1.48 +- const gdb_prfpregset_t *fpregs);
1.49 +-static td_err_e (*td_thr_setgregs_p) (const td_thrhandle_t *th,
1.50 +- prgregset_t gregs);
1.51 +-static td_err_e (*td_thr_event_enable_p) (const td_thrhandle_t *th,
1.52 +- int event);
1.53 +-
1.54 +-static td_err_e (*td_thr_tls_get_addr_p) (const td_thrhandle_t *th,
1.55 +- void *map_address,
1.56 +- size_t offset, void **address);
1.57 ++ td_err_e (*td_ta_new_p) (struct ps_prochandle * ps,
1.58 ++ td_thragent_t **ta);
1.59 ++ td_err_e (*td_ta_map_id2thr_p) (const td_thragent_t *ta, thread_t pt,
1.60 ++ td_thrhandle_t *__th);
1.61 ++ td_err_e (*td_ta_map_lwp2thr_p) (const td_thragent_t *ta,
1.62 ++ lwpid_t lwpid, td_thrhandle_t *th);
1.63 ++
1.64 ++ td_err_e (*td_ta_thr_iter_p) (const td_thragent_t *ta,
1.65 ++ td_thr_iter_f *callback, void *cbdata_p,
1.66 ++ td_thr_state_e state, int ti_pri,
1.67 ++ sigset_t *ti_sigmask_p,
1.68 ++ unsigned int ti_user_flags);
1.69 ++ td_err_e (*td_ta_event_addr_p) (const td_thragent_t *ta,
1.70 ++ td_event_e event, td_notify_t *ptr);
1.71 ++ td_err_e (*td_ta_set_event_p) (const td_thragent_t *ta,
1.72 ++ td_thr_events_t *event);
1.73 ++ td_err_e (*td_ta_event_getmsg_p) (const td_thragent_t *ta,
1.74 ++ td_event_msg_t *msg);
1.75 ++
1.76 ++ td_err_e (*td_thr_validate_p) (const td_thrhandle_t *th);
1.77 ++ td_err_e (*td_thr_get_info_p) (const td_thrhandle_t *th,
1.78 ++ td_thrinfo_t *infop);
1.79 ++ td_err_e (*td_thr_getfpregs_p) (const td_thrhandle_t *th,
1.80 ++ gdb_prfpregset_t *regset);
1.81 ++ td_err_e (*td_thr_getgregs_p) (const td_thrhandle_t *th,
1.82 ++ prgregset_t gregs);
1.83 ++ td_err_e (*td_thr_setfpregs_p) (const td_thrhandle_t *th,
1.84 ++ const gdb_prfpregset_t *fpregs);
1.85 ++ td_err_e (*td_thr_setgregs_p) (const td_thrhandle_t *th,
1.86 ++ prgregset_t gregs);
1.87 ++ td_err_e (*td_thr_event_enable_p) (const td_thrhandle_t *th,
1.88 ++ int event);
1.89 ++
1.90 ++ td_err_e (*td_thr_tls_get_addr_p) (const td_thrhandle_t *th,
1.91 ++ void *map_address,
1.92 ++ size_t offset, void **address);
1.93 ++
1.94 ++ struct thread_db_pointers *next;
1.95 ++};
1.96 +
1.97 + /* Location of the thread creation event breakpoint. The code at this
1.98 + location in the child process will be called by the pthread library
1.99 + whenever a new thread is created. By setting a special breakpoint
1.100 + at this location, GDB can detect when a new thread is created. We
1.101 + obtain this location via the td_ta_event_addr call. */
1.102 +-static CORE_ADDR td_create_bp_addr;
1.103 ++CORE_ADDR td_create_bp_addr;
1.104 +
1.105 + /* Location of the thread death event breakpoint. */
1.106 +-static CORE_ADDR td_death_bp_addr;
1.107 ++CORE_ADDR td_death_bp_addr;
1.108 ++
1.109 ++static struct thread_db_pointers *current_pointers, *all_pointers;
1.110 +
1.111 + /* Prototypes for local functions. */
1.112 + static void thread_db_find_new_threads (void);
1.113 +@@ -262,7 +272,7 @@ thread_get_info_callback (const td_thrha
1.114 + struct thread_info *thread_info;
1.115 + ptid_t thread_ptid;
1.116 +
1.117 +- err = td_thr_get_info_p (thp, &ti);
1.118 ++ err = current_pointers->td_thr_get_info_p (thp, &ti);
1.119 + if (err != TD_OK)
1.120 + error ("thread_get_info_callback: cannot get thread info: %s",
1.121 + thread_db_err_str (err));
1.122 +@@ -316,8 +326,9 @@ thread_db_map_id2thr (struct thread_info
1.123 + if (thread_info->private->th_valid)
1.124 + return;
1.125 +
1.126 +- err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (thread_info->ptid),
1.127 +- &thread_info->private->th);
1.128 ++ err = current_pointers->td_ta_map_id2thr_p (thread_agent,
1.129 ++ GET_THREAD (thread_info->ptid),
1.130 ++ &thread_info->private->th);
1.131 + if (err != TD_OK)
1.132 + {
1.133 + if (fatal)
1.134 +@@ -340,8 +351,8 @@ thread_db_get_info (struct thread_info *
1.135 + if (!thread_info->private->th_valid)
1.136 + thread_db_map_id2thr (thread_info, 1);
1.137 +
1.138 +- err =
1.139 +- td_thr_get_info_p (&thread_info->private->th, &thread_info->private->ti);
1.140 ++ err = current_pointers->td_thr_get_info_p (&thread_info->private->th,
1.141 ++ &thread_info->private->ti);
1.142 + if (err != TD_OK)
1.143 + error ("thread_db_get_info: cannot get thread info: %s",
1.144 + thread_db_err_str (err));
1.145 +@@ -365,7 +376,8 @@ thread_from_lwp (ptid_t ptid)
1.146 +
1.147 + gdb_assert (is_lwp (ptid));
1.148 +
1.149 +- err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), &th);
1.150 ++ err = current_pointers->td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid),
1.151 ++ &th);
1.152 + if (err != TD_OK)
1.153 + error ("Cannot find user-level thread for LWP %ld: %s",
1.154 + GET_LWP (ptid), thread_db_err_str (err));
1.155 +@@ -420,85 +432,102 @@ verbose_dlsym (void *handle, const char
1.156 + return sym;
1.157 + }
1.158 +
1.159 +-static int
1.160 +-thread_db_load (void)
1.161 ++static struct thread_db_pointers *
1.162 ++thread_db_load (const char *name)
1.163 + {
1.164 ++ struct thread_db_pointers *ptrs;
1.165 ++ Dl_info info;
1.166 + void *handle;
1.167 + td_err_e err;
1.168 +
1.169 +- handle = dlopen (LIBTHREAD_DB_SO, RTLD_NOW);
1.170 ++ ptrs = xcalloc (1, sizeof (struct thread_db_pointers));
1.171 ++
1.172 ++ handle = dlopen (name, RTLD_NOW);
1.173 + if (handle == NULL)
1.174 + {
1.175 +- fprintf_filtered (gdb_stderr, "\n\ndlopen failed on '%s' - %s\n",
1.176 +- LIBTHREAD_DB_SO, dlerror ());
1.177 +- fprintf_filtered (gdb_stderr,
1.178 +- "GDB will not be able to debug pthreads.\n\n");
1.179 ++ if (all_pointers == NULL)
1.180 ++ {
1.181 ++ fprintf_filtered (gdb_stderr, "\n\ndlopen failed on '%s' - %s\n",
1.182 ++ name, dlerror ());
1.183 ++ fprintf_filtered (gdb_stderr,
1.184 ++ "GDB will not be able to debug pthreads.\n\n");
1.185 ++ }
1.186 + return 0;
1.187 + }
1.188 +
1.189 + /* Initialize pointers to the dynamic library functions we will use.
1.190 + Essential functions first. */
1.191 +
1.192 +- td_init_p = verbose_dlsym (handle, "td_init");
1.193 +- if (td_init_p == NULL)
1.194 ++ ptrs->td_init_p = verbose_dlsym (handle, "td_init");
1.195 ++ if (ptrs->td_init_p == NULL)
1.196 + return 0;
1.197 +
1.198 +- td_ta_new_p = verbose_dlsym (handle, "td_ta_new");
1.199 +- if (td_ta_new_p == NULL)
1.200 ++ ptrs->td_ta_new_p = verbose_dlsym (handle, "td_ta_new");
1.201 ++ if (ptrs->td_ta_new_p == NULL)
1.202 + return 0;
1.203 +
1.204 +- td_ta_map_id2thr_p = verbose_dlsym (handle, "td_ta_map_id2thr");
1.205 +- if (td_ta_map_id2thr_p == NULL)
1.206 ++ ptrs->td_ta_map_id2thr_p = verbose_dlsym (handle, "td_ta_map_id2thr");
1.207 ++ if (ptrs->td_ta_map_id2thr_p == NULL)
1.208 + return 0;
1.209 +
1.210 +- td_ta_map_lwp2thr_p = verbose_dlsym (handle, "td_ta_map_lwp2thr");
1.211 +- if (td_ta_map_lwp2thr_p == NULL)
1.212 ++ ptrs->td_ta_map_lwp2thr_p = verbose_dlsym (handle, "td_ta_map_lwp2thr");
1.213 ++ if (ptrs->td_ta_map_lwp2thr_p == NULL)
1.214 + return 0;
1.215 +
1.216 +- td_ta_thr_iter_p = verbose_dlsym (handle, "td_ta_thr_iter");
1.217 +- if (td_ta_thr_iter_p == NULL)
1.218 ++ ptrs->td_ta_thr_iter_p = verbose_dlsym (handle, "td_ta_thr_iter");
1.219 ++ if (ptrs->td_ta_thr_iter_p == NULL)
1.220 + return 0;
1.221 +
1.222 +- td_thr_validate_p = verbose_dlsym (handle, "td_thr_validate");
1.223 +- if (td_thr_validate_p == NULL)
1.224 ++ ptrs->td_thr_validate_p = verbose_dlsym (handle, "td_thr_validate");
1.225 ++ if (ptrs->td_thr_validate_p == NULL)
1.226 + return 0;
1.227 +
1.228 +- td_thr_get_info_p = verbose_dlsym (handle, "td_thr_get_info");
1.229 +- if (td_thr_get_info_p == NULL)
1.230 ++ ptrs->td_thr_get_info_p = verbose_dlsym (handle, "td_thr_get_info");
1.231 ++ if (ptrs->td_thr_get_info_p == NULL)
1.232 + return 0;
1.233 +
1.234 +- td_thr_getfpregs_p = verbose_dlsym (handle, "td_thr_getfpregs");
1.235 +- if (td_thr_getfpregs_p == NULL)
1.236 ++ ptrs->td_thr_getfpregs_p = verbose_dlsym (handle, "td_thr_getfpregs");
1.237 ++ if (ptrs->td_thr_getfpregs_p == NULL)
1.238 + return 0;
1.239 +
1.240 +- td_thr_getgregs_p = verbose_dlsym (handle, "td_thr_getgregs");
1.241 +- if (td_thr_getgregs_p == NULL)
1.242 ++ ptrs->td_thr_getgregs_p = verbose_dlsym (handle, "td_thr_getgregs");
1.243 ++ if (ptrs->td_thr_getgregs_p == NULL)
1.244 + return 0;
1.245 +
1.246 +- td_thr_setfpregs_p = verbose_dlsym (handle, "td_thr_setfpregs");
1.247 +- if (td_thr_setfpregs_p == NULL)
1.248 ++ ptrs->td_thr_setfpregs_p = verbose_dlsym (handle, "td_thr_setfpregs");
1.249 ++ if (ptrs->td_thr_setfpregs_p == NULL)
1.250 + return 0;
1.251 +
1.252 +- td_thr_setgregs_p = verbose_dlsym (handle, "td_thr_setgregs");
1.253 +- if (td_thr_setgregs_p == NULL)
1.254 ++ ptrs->td_thr_setgregs_p = verbose_dlsym (handle, "td_thr_setgregs");
1.255 ++ if (ptrs->td_thr_setgregs_p == NULL)
1.256 + return 0;
1.257 +
1.258 + /* Initialize the library. */
1.259 +- err = td_init_p ();
1.260 ++ err = ptrs->td_init_p ();
1.261 + if (err != TD_OK)
1.262 + {
1.263 + warning ("Cannot initialize libthread_db: %s", thread_db_err_str (err));
1.264 ++ xfree (ptrs);
1.265 + return 0;
1.266 + }
1.267 +
1.268 + /* These are not essential. */
1.269 +- td_ta_event_addr_p = dlsym (handle, "td_ta_event_addr");
1.270 +- td_ta_set_event_p = dlsym (handle, "td_ta_set_event");
1.271 +- td_ta_event_getmsg_p = dlsym (handle, "td_ta_event_getmsg");
1.272 +- td_thr_event_enable_p = dlsym (handle, "td_thr_event_enable");
1.273 +- td_thr_tls_get_addr_p = dlsym (handle, "td_thr_tls_get_addr");
1.274 ++ ptrs->td_ta_event_addr_p = dlsym (handle, "td_ta_event_addr");
1.275 ++ ptrs->td_ta_set_event_p = dlsym (handle, "td_ta_set_event");
1.276 ++ ptrs->td_ta_event_getmsg_p = dlsym (handle, "td_ta_event_getmsg");
1.277 ++ ptrs->td_thr_event_enable_p = dlsym (handle, "td_thr_event_enable");
1.278 ++ ptrs->td_thr_tls_get_addr_p = dlsym (handle, "td_thr_tls_get_addr");
1.279 ++
1.280 ++ if (dladdr (ptrs->td_ta_new_p, &info) != 0)
1.281 ++ ptrs->filename = info.dli_fname;
1.282 ++
1.283 ++ /* Try dlinfo? */
1.284 ++
1.285 ++ if (ptrs->filename == NULL)
1.286 ++ /* Paranoid - don't let a NULL path slip through. */
1.287 ++ ptrs->filename = name;
1.288 +
1.289 +- return 1;
1.290 ++ return ptrs;
1.291 + }
1.292 +
1.293 + static td_err_e
1.294 +@@ -508,7 +537,7 @@ enable_thread_event (td_thragent_t *thre
1.295 + td_err_e err;
1.296 +
1.297 + /* Get the breakpoint address for thread EVENT. */
1.298 +- err = td_ta_event_addr_p (thread_agent, event, ¬ify);
1.299 ++ err = current_pointers->td_ta_event_addr_p (thread_agent, event, ¬ify);
1.300 + if (err != TD_OK)
1.301 + return err;
1.302 +
1.303 +@@ -534,8 +563,10 @@ enable_thread_event_reporting (void)
1.304 +
1.305 + /* We cannot use the thread event reporting facility if these
1.306 + functions aren't available. */
1.307 +- if (td_ta_event_addr_p == NULL || td_ta_set_event_p == NULL
1.308 +- || td_ta_event_getmsg_p == NULL || td_thr_event_enable_p == NULL)
1.309 ++ if (current_pointers->td_ta_event_addr_p == NULL
1.310 ++ || current_pointers->td_ta_set_event_p == NULL
1.311 ++ || current_pointers->td_ta_event_getmsg_p == NULL
1.312 ++ || current_pointers->td_thr_event_enable_p == NULL)
1.313 + return;
1.314 +
1.315 + /* Set the process wide mask saying which events we're interested in. */
1.316 +@@ -552,7 +583,7 @@ enable_thread_event_reporting (void)
1.317 + #endif
1.318 + td_event_addset (&events, TD_DEATH);
1.319 +
1.320 +- err = td_ta_set_event_p (thread_agent, &events);
1.321 ++ err = current_pointers->td_ta_set_event_p (thread_agent, &events);
1.322 + if (err != TD_OK)
1.323 + {
1.324 + warning ("Unable to set global thread event mask: %s",
1.325 +@@ -592,7 +623,7 @@ disable_thread_event_reporting (void)
1.326 + /* Set the process wide mask saying we aren't interested in any
1.327 + events anymore. */
1.328 + td_event_emptyset (&events);
1.329 +- td_ta_set_event_p (thread_agent, &events);
1.330 ++ current_pointers->td_ta_set_event_p (thread_agent, &events);
1.331 +
1.332 + /* Delete thread event breakpoints, if any. */
1.333 + remove_thread_event_breakpoints ();
1.334 +@@ -635,7 +666,6 @@ check_thread_signals (void)
1.335 + static void
1.336 + check_for_thread_db (void)
1.337 + {
1.338 +- td_err_e err;
1.339 + static int already_loaded;
1.340 +
1.341 + /* First time through, report that libthread_db was successfuly
1.342 +@@ -644,19 +674,8 @@ check_for_thread_db (void)
1.343 +
1.344 + if (!already_loaded)
1.345 + {
1.346 +- Dl_info info;
1.347 +- const char *library = NULL;
1.348 +- if (dladdr ((*td_ta_new_p), &info) != 0)
1.349 +- library = info.dli_fname;
1.350 +-
1.351 +- /* Try dlinfo? */
1.352 +-
1.353 +- if (library == NULL)
1.354 +- /* Paranoid - don't let a NULL path slip through. */
1.355 +- library = LIBTHREAD_DB_SO;
1.356 +-
1.357 + printf_unfiltered ("Using host libthread_db library \"%s\".\n",
1.358 +- library);
1.359 ++ all_pointers->filename);
1.360 + already_loaded = 1;
1.361 + }
1.362 +
1.363 +@@ -674,28 +693,34 @@ check_for_thread_db (void)
1.364 + proc_handle.pid = GET_PID (inferior_ptid);
1.365 +
1.366 + /* Now attempt to open a connection to the thread library. */
1.367 +- err = td_ta_new_p (&proc_handle, &thread_agent);
1.368 +- switch (err)
1.369 ++ for (current_pointers = all_pointers;
1.370 ++ current_pointers != NULL;
1.371 ++ current_pointers = current_pointers->next)
1.372 + {
1.373 +- case TD_NOLIBTHREAD:
1.374 +- /* No thread library was detected. */
1.375 +- break;
1.376 +-
1.377 +- case TD_OK:
1.378 +- printf_unfiltered ("[Thread debugging using libthread_db enabled]\n");
1.379 ++ td_err_e err;
1.380 ++ err = current_pointers->td_ta_new_p (&proc_handle, &thread_agent);
1.381 ++ switch (err)
1.382 ++ {
1.383 ++ case TD_NOLIBTHREAD:
1.384 ++ /* No thread library was detected. */
1.385 ++ break;
1.386 +
1.387 +- /* The thread library was detected. Activate the thread_db target. */
1.388 +- push_target (&thread_db_ops);
1.389 +- using_thread_db = 1;
1.390 ++ case TD_OK:
1.391 ++ printf_unfiltered ("[Thread debugging using libthread_db enabled]\n");
1.392 +
1.393 +- enable_thread_event_reporting ();
1.394 +- thread_db_find_new_threads ();
1.395 +- break;
1.396 ++ /* The thread library was detected. Activate the thread_db target. */
1.397 ++ push_target (&thread_db_ops);
1.398 ++ using_thread_db = 1;
1.399 ++
1.400 ++ enable_thread_event_reporting ();
1.401 ++ thread_db_find_new_threads ();
1.402 ++ return;
1.403 +
1.404 +- default:
1.405 +- warning ("Cannot initialize thread debugging library: %s",
1.406 +- thread_db_err_str (err));
1.407 +- break;
1.408 ++ default:
1.409 ++ warning ("Cannot initialize thread debugging library: %s",
1.410 ++ thread_db_err_str (err));
1.411 ++ break;
1.412 ++ }
1.413 + }
1.414 + }
1.415 +
1.416 +@@ -766,7 +791,7 @@ attach_thread (ptid_t ptid, const td_thr
1.417 + #endif
1.418 +
1.419 + /* Enable thread event reporting for this thread. */
1.420 +- err = td_thr_event_enable_p (th_p, 1);
1.421 ++ err = current_pointers->td_thr_event_enable_p (th_p, 1);
1.422 + if (err != TD_OK)
1.423 + error ("Cannot enable thread event reporting for %s: %s",
1.424 + target_pid_to_str (ptid), thread_db_err_str (err));
1.425 +@@ -892,7 +917,7 @@ check_event (ptid_t ptid)
1.426 +
1.427 + do
1.428 + {
1.429 +- err = td_ta_event_getmsg_p (thread_agent, &msg);
1.430 ++ err = current_pointers->td_ta_event_getmsg_p (thread_agent, &msg);
1.431 + if (err != TD_OK)
1.432 + {
1.433 + if (err == TD_NOMSG)
1.434 +@@ -902,7 +927,7 @@ check_event (ptid_t ptid)
1.435 + thread_db_err_str (err));
1.436 + }
1.437 +
1.438 +- err = td_thr_get_info_p (msg.th_p, &ti);
1.439 ++ err = current_pointers->td_thr_get_info_p (msg.th_p, &ti);
1.440 + if (err != TD_OK)
1.441 + error ("Cannot get thread info: %s", thread_db_err_str (err));
1.442 +
1.443 +@@ -1015,12 +1040,14 @@ thread_db_fetch_registers (int regno)
1.444 + thread_info = find_thread_pid (inferior_ptid);
1.445 + thread_db_map_id2thr (thread_info, 1);
1.446 +
1.447 +- err = td_thr_getgregs_p (&thread_info->private->th, gregset);
1.448 ++ err = current_pointers->td_thr_getgregs_p (&thread_info->private->th,
1.449 ++ gregset);
1.450 + if (err != TD_OK)
1.451 + error ("Cannot fetch general-purpose registers for thread %ld: %s",
1.452 + (long) GET_THREAD (inferior_ptid), thread_db_err_str (err));
1.453 +
1.454 +- err = td_thr_getfpregs_p (&thread_info->private->th, &fpregset);
1.455 ++ err = current_pointers->td_thr_getfpregs_p (&thread_info->private->th,
1.456 ++ &fpregset);
1.457 + if (err != TD_OK)
1.458 + error ("Cannot get floating-point registers for thread %ld: %s",
1.459 + (long) GET_THREAD (inferior_ptid), thread_db_err_str (err));
1.460 +@@ -1062,11 +1089,13 @@ thread_db_store_registers (int regno)
1.461 + fill_gregset ((gdb_gregset_t *) gregset, -1);
1.462 + fill_fpregset (&fpregset, -1);
1.463 +
1.464 +- err = td_thr_setgregs_p (&thread_info->private->th, gregset);
1.465 ++ err = current_pointers->td_thr_setgregs_p (&thread_info->private->th,
1.466 ++ gregset);
1.467 + if (err != TD_OK)
1.468 + error ("Cannot store general-purpose registers for thread %ld: %s",
1.469 + (long) GET_THREAD (inferior_ptid), thread_db_err_str (err));
1.470 +- err = td_thr_setfpregs_p (&thread_info->private->th, &fpregset);
1.471 ++ err = current_pointers->td_thr_setfpregs_p (&thread_info->private->th,
1.472 ++ &fpregset);
1.473 + if (err != TD_OK)
1.474 + error ("Cannot store floating-point registers for thread %ld: %s",
1.475 + (long) GET_THREAD (inferior_ptid), thread_db_err_str (err));
1.476 +@@ -1136,15 +1165,14 @@ thread_db_thread_alive (ptid_t ptid)
1.477 + if (!thread_info->private->th_valid)
1.478 + return 0;
1.479 +
1.480 +- err = td_thr_validate_p (&thread_info->private->th);
1.481 ++ err = current_pointers->td_thr_validate_p (&thread_info->private->th);
1.482 + if (err != TD_OK)
1.483 + return 0;
1.484 +
1.485 + if (!thread_info->private->ti_valid)
1.486 + {
1.487 +- err =
1.488 +- td_thr_get_info_p (&thread_info->private->th,
1.489 +- &thread_info->private->ti);
1.490 ++ err = current_pointers->td_thr_get_info_p
1.491 ++ (&thread_info->private->th, &thread_info->private->ti);
1.492 + if (err != TD_OK)
1.493 + return 0;
1.494 + thread_info->private->ti_valid = 1;
1.495 +@@ -1170,7 +1198,7 @@ find_new_threads_callback (const td_thrh
1.496 + td_err_e err;
1.497 + ptid_t ptid;
1.498 +
1.499 +- err = td_thr_get_info_p (th_p, &ti);
1.500 ++ err = current_pointers->td_thr_get_info_p (th_p, &ti);
1.501 + if (err != TD_OK)
1.502 + error ("find_new_threads_callback: cannot get thread info: %s",
1.503 + thread_db_err_str (err));
1.504 +@@ -1192,9 +1220,10 @@ thread_db_find_new_threads (void)
1.505 + td_err_e err;
1.506 +
1.507 + /* Iterate over all user-space threads to discover new threads. */
1.508 +- err = td_ta_thr_iter_p (thread_agent, find_new_threads_callback, NULL,
1.509 +- TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
1.510 +- TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
1.511 ++ err = current_pointers->td_ta_thr_iter_p
1.512 ++ (thread_agent, find_new_threads_callback, NULL,
1.513 ++ TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
1.514 ++ TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
1.515 + if (err != TD_OK)
1.516 + error ("Cannot find new threads: %s", thread_db_err_str (err));
1.517 + }
1.518 +@@ -1257,7 +1286,7 @@ thread_db_get_thread_local_address (ptid
1.519 + struct thread_info *thread_info;
1.520 +
1.521 + /* glibc doesn't provide the needed interface. */
1.522 +- if (!td_thr_tls_get_addr_p)
1.523 ++ if (!current_pointers->td_thr_tls_get_addr_p)
1.524 + error ("Cannot find thread-local variables in this thread library.");
1.525 +
1.526 + /* Get the address of the link map for this objfile. */
1.527 +@@ -1279,8 +1308,8 @@ thread_db_get_thread_local_address (ptid
1.528 + thread_db_map_id2thr (thread_info, 1);
1.529 +
1.530 + /* Finally, get the address of the variable. */
1.531 +- err = td_thr_tls_get_addr_p (&thread_info->private->th, (void *) lm,
1.532 +- offset, &address);
1.533 ++ err = current_pointers->td_thr_tls_get_addr_p
1.534 ++ (&thread_info->private->th, (void *) lm, offset, &address);
1.535 +
1.536 + #ifdef THREAD_DB_HAS_TD_NOTALLOC
1.537 + /* The memory hasn't been allocated, yet. */
1.538 +@@ -1360,17 +1389,49 @@ init_thread_db_ops (void)
1.539 + void
1.540 + _initialize_thread_db (void)
1.541 + {
1.542 ++ struct thread_db_pointers *ptrs;
1.543 ++ const char *p;
1.544 ++
1.545 + /* Only initialize the module if we can load libthread_db. */
1.546 +- if (thread_db_load ())
1.547 +- {
1.548 +- init_thread_db_ops ();
1.549 +- add_target (&thread_db_ops);
1.550 ++ ptrs = thread_db_load (LIBTHREAD_DB_SO);
1.551 ++ if (ptrs == NULL)
1.552 ++ return;
1.553 ++
1.554 ++ all_pointers = ptrs;
1.555 +
1.556 +- /* Add ourselves to objfile event chain. */
1.557 +- target_new_objfile_chain = deprecated_target_new_objfile_hook;
1.558 +- deprecated_target_new_objfile_hook = thread_db_new_objfile;
1.559 ++ /* Some GNU/Linux systems have more than one binary-compatible copy
1.560 ++ of libthread_db. If we can find a second one, load that too.
1.561 ++ The inferior may force the use of a different threading package
1.562 ++ than we expect. Our guess for the location is somewhat hokey:
1.563 ++ strip out anything between /lib (or /lib64) and LIBTHREAD_DB_SO.
1.564 ++ If we loaded the NPTL libthread_db by default, this may find us
1.565 ++ the LinuxThreads copy. */
1.566 ++ p = strrchr (ptrs->filename, '/');
1.567 ++ while (p != NULL && p > ptrs->filename)
1.568 ++ {
1.569 ++ const char *component;
1.570 +
1.571 +- /* Register ourselves for the new inferior observer. */
1.572 +- observer_attach_inferior_created (check_for_thread_db_observer);
1.573 ++ component = memrchr (ptrs->filename, '/', p - ptrs->filename);
1.574 ++ if (component != NULL && strncmp (component, "/lib", 4) == 0)
1.575 ++ {
1.576 ++ char *new_name = xmalloc (p - ptrs->filename + 2
1.577 ++ + strlen (LIBTHREAD_DB_SO));
1.578 ++ memcpy (new_name, ptrs->filename, p - ptrs->filename + 1);
1.579 ++ strcpy (new_name + (p - ptrs->filename) + 1, LIBTHREAD_DB_SO);
1.580 ++ ptrs->next = thread_db_load (new_name);
1.581 ++ xfree (new_name);
1.582 ++ break;
1.583 ++ }
1.584 ++ p = component;
1.585 + }
1.586 ++
1.587 ++ init_thread_db_ops ();
1.588 ++ add_target (&thread_db_ops);
1.589 ++
1.590 ++ /* Add ourselves to objfile event chain. */
1.591 ++ target_new_objfile_chain = deprecated_target_new_objfile_hook;
1.592 ++ deprecated_target_new_objfile_hook = thread_db_new_objfile;
1.593 ++
1.594 ++ /* Register ourselves for the new inferior observer. */
1.595 ++ observer_attach_inferior_created (check_for_thread_db_observer);
1.596 + }