patches/gdb/6.3/710-debian_thread-db-multiple-libraries.patch
changeset 96 aa1a9fbd6eb8
     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 May 17 16:22:51 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, &notify);
   1.299 ++  err = current_pointers->td_ta_event_addr_p (thread_agent, event, &notify);
   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 + }