patches/gdb/6.3/710-debian_thread-db-multiple-libraries.patch
author "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
Thu May 17 16:22:51 2007 +0000 (2007-05-17)
changeset 96 aa1a9fbd6eb8
permissions -rw-r--r--
Debug facilities:
- add a framework to easily add new ones
- add gdb as a first debug facility
- add patches for gdb
After the kernel checked its installed headers, clean up the mess of .checked.* files.
Reorder scripts/crosstool.sh:
- dump the configuration early
- renice early
- get info about build system early, when setting up the environment
- when in cross or native, the host tools are those of the build system, and only in this case
- elapsed time calculations moved to scripts/functions
Remove handling of the color: it's gone once and for all.
Update tools/addToolVersion.sh:
- handle debug facilities
- commonalise some code
- remove dead tools (cygwin, tcc)
Point to my address for bug reports.
     1 Support loading two libthread_db DSOs.  In this case, the LinuxThreads
     2 and NPTL ones.
     3 
     4 Index: gdb-6.3/gdb/thread-db.c
     5 ===================================================================
     6 --- gdb-6.3.orig/gdb/thread-db.c	2004-11-10 10:46:24.000000000 -0500
     7 +++ gdb-6.3/gdb/thread-db.c	2004-11-10 11:22:34.858812426 -0500
     8 @@ -79,53 +79,63 @@ static td_thragent_t *thread_agent;
     9  
    10  /* Pointers to the libthread_db functions.  */
    11  
    12 -static td_err_e (*td_init_p) (void);
    13 +struct thread_db_pointers
    14 +{
    15 +  const char *filename;
    16 +
    17 +  td_err_e (*td_init_p) (void);
    18  
    19 -static td_err_e (*td_ta_new_p) (struct ps_prochandle * ps,
    20 -				td_thragent_t **ta);
    21 -static td_err_e (*td_ta_map_id2thr_p) (const td_thragent_t *ta, thread_t pt,
    22 -				       td_thrhandle_t *__th);
    23 -static td_err_e (*td_ta_map_lwp2thr_p) (const td_thragent_t *ta,
    24 -					lwpid_t lwpid, td_thrhandle_t *th);
    25 -static td_err_e (*td_ta_thr_iter_p) (const td_thragent_t *ta,
    26 -				     td_thr_iter_f *callback, void *cbdata_p,
    27 -				     td_thr_state_e state, int ti_pri,
    28 -				     sigset_t *ti_sigmask_p,
    29 -				     unsigned int ti_user_flags);
    30 -static td_err_e (*td_ta_event_addr_p) (const td_thragent_t *ta,
    31 -				       td_event_e event, td_notify_t *ptr);
    32 -static td_err_e (*td_ta_set_event_p) (const td_thragent_t *ta,
    33 -				      td_thr_events_t *event);
    34 -static td_err_e (*td_ta_event_getmsg_p) (const td_thragent_t *ta,
    35 -					 td_event_msg_t *msg);
    36 -
    37 -static td_err_e (*td_thr_validate_p) (const td_thrhandle_t *th);
    38 -static td_err_e (*td_thr_get_info_p) (const td_thrhandle_t *th,
    39 -				      td_thrinfo_t *infop);
    40 -static td_err_e (*td_thr_getfpregs_p) (const td_thrhandle_t *th,
    41 -				       gdb_prfpregset_t *regset);
    42 -static td_err_e (*td_thr_getgregs_p) (const td_thrhandle_t *th,
    43 -				      prgregset_t gregs);
    44 -static td_err_e (*td_thr_setfpregs_p) (const td_thrhandle_t *th,
    45 -				       const gdb_prfpregset_t *fpregs);
    46 -static td_err_e (*td_thr_setgregs_p) (const td_thrhandle_t *th,
    47 -				      prgregset_t gregs);
    48 -static td_err_e (*td_thr_event_enable_p) (const td_thrhandle_t *th,
    49 -					  int event);
    50 -
    51 -static td_err_e (*td_thr_tls_get_addr_p) (const td_thrhandle_t *th,
    52 -					  void *map_address,
    53 -					  size_t offset, void **address);
    54 +  td_err_e (*td_ta_new_p) (struct ps_prochandle * ps,
    55 +			   td_thragent_t **ta);
    56 +  td_err_e (*td_ta_map_id2thr_p) (const td_thragent_t *ta, thread_t pt,
    57 +				  td_thrhandle_t *__th);
    58 +  td_err_e (*td_ta_map_lwp2thr_p) (const td_thragent_t *ta,
    59 +				   lwpid_t lwpid, td_thrhandle_t *th);
    60 +
    61 +  td_err_e (*td_ta_thr_iter_p) (const td_thragent_t *ta,
    62 +				td_thr_iter_f *callback, void *cbdata_p,
    63 +				td_thr_state_e state, int ti_pri,
    64 +				sigset_t *ti_sigmask_p,
    65 +				unsigned int ti_user_flags);
    66 +  td_err_e (*td_ta_event_addr_p) (const td_thragent_t *ta,
    67 +				  td_event_e event, td_notify_t *ptr);
    68 +  td_err_e (*td_ta_set_event_p) (const td_thragent_t *ta,
    69 +				 td_thr_events_t *event);
    70 +  td_err_e (*td_ta_event_getmsg_p) (const td_thragent_t *ta,
    71 +				    td_event_msg_t *msg);
    72 +
    73 +  td_err_e (*td_thr_validate_p) (const td_thrhandle_t *th);
    74 +  td_err_e (*td_thr_get_info_p) (const td_thrhandle_t *th,
    75 +				 td_thrinfo_t *infop);
    76 +  td_err_e (*td_thr_getfpregs_p) (const td_thrhandle_t *th,
    77 +				  gdb_prfpregset_t *regset);
    78 +  td_err_e (*td_thr_getgregs_p) (const td_thrhandle_t *th,
    79 +				 prgregset_t gregs);
    80 +  td_err_e (*td_thr_setfpregs_p) (const td_thrhandle_t *th,
    81 +				  const gdb_prfpregset_t *fpregs);
    82 +  td_err_e (*td_thr_setgregs_p) (const td_thrhandle_t *th,
    83 +				 prgregset_t gregs);
    84 +  td_err_e (*td_thr_event_enable_p) (const td_thrhandle_t *th,
    85 +				     int event);
    86 +
    87 +  td_err_e (*td_thr_tls_get_addr_p) (const td_thrhandle_t *th,
    88 +				     void *map_address,
    89 +				     size_t offset, void **address);
    90 +
    91 +  struct thread_db_pointers *next;
    92 +};
    93  
    94  /* Location of the thread creation event breakpoint.  The code at this
    95     location in the child process will be called by the pthread library
    96     whenever a new thread is created.  By setting a special breakpoint
    97     at this location, GDB can detect when a new thread is created.  We
    98     obtain this location via the td_ta_event_addr call.  */
    99 -static CORE_ADDR td_create_bp_addr;
   100 +CORE_ADDR td_create_bp_addr;
   101  
   102  /* Location of the thread death event breakpoint.  */
   103 -static CORE_ADDR td_death_bp_addr;
   104 +CORE_ADDR td_death_bp_addr;
   105 +
   106 +static struct thread_db_pointers *current_pointers, *all_pointers;
   107  
   108  /* Prototypes for local functions.  */
   109  static void thread_db_find_new_threads (void);
   110 @@ -262,7 +272,7 @@ thread_get_info_callback (const td_thrha
   111    struct thread_info *thread_info;
   112    ptid_t thread_ptid;
   113  
   114 -  err = td_thr_get_info_p (thp, &ti);
   115 +  err = current_pointers->td_thr_get_info_p (thp, &ti);
   116    if (err != TD_OK)
   117      error ("thread_get_info_callback: cannot get thread info: %s",
   118  	   thread_db_err_str (err));
   119 @@ -316,8 +326,9 @@ thread_db_map_id2thr (struct thread_info
   120    if (thread_info->private->th_valid)
   121      return;
   122  
   123 -  err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (thread_info->ptid),
   124 -			    &thread_info->private->th);
   125 +  err = current_pointers->td_ta_map_id2thr_p (thread_agent,
   126 +					      GET_THREAD (thread_info->ptid),
   127 +					      &thread_info->private->th);
   128    if (err != TD_OK)
   129      {
   130        if (fatal)
   131 @@ -340,8 +351,8 @@ thread_db_get_info (struct thread_info *
   132    if (!thread_info->private->th_valid)
   133      thread_db_map_id2thr (thread_info, 1);
   134  
   135 -  err =
   136 -    td_thr_get_info_p (&thread_info->private->th, &thread_info->private->ti);
   137 +  err = current_pointers->td_thr_get_info_p (&thread_info->private->th,
   138 +					     &thread_info->private->ti);
   139    if (err != TD_OK)
   140      error ("thread_db_get_info: cannot get thread info: %s",
   141  	   thread_db_err_str (err));
   142 @@ -365,7 +376,8 @@ thread_from_lwp (ptid_t ptid)
   143  
   144    gdb_assert (is_lwp (ptid));
   145  
   146 -  err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), &th);
   147 +  err = current_pointers->td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid),
   148 +					       &th);
   149    if (err != TD_OK)
   150      error ("Cannot find user-level thread for LWP %ld: %s",
   151  	   GET_LWP (ptid), thread_db_err_str (err));
   152 @@ -420,85 +432,102 @@ verbose_dlsym (void *handle, const char 
   153    return sym;
   154  }
   155  
   156 -static int
   157 -thread_db_load (void)
   158 +static struct thread_db_pointers *
   159 +thread_db_load (const char *name)
   160  {
   161 +  struct thread_db_pointers *ptrs;
   162 +  Dl_info info;
   163    void *handle;
   164    td_err_e err;
   165  
   166 -  handle = dlopen (LIBTHREAD_DB_SO, RTLD_NOW);
   167 +  ptrs = xcalloc (1, sizeof (struct thread_db_pointers));
   168 +
   169 +  handle = dlopen (name, RTLD_NOW);
   170    if (handle == NULL)
   171      {
   172 -      fprintf_filtered (gdb_stderr, "\n\ndlopen failed on '%s' - %s\n",
   173 -			LIBTHREAD_DB_SO, dlerror ());
   174 -      fprintf_filtered (gdb_stderr,
   175 -			"GDB will not be able to debug pthreads.\n\n");
   176 +      if (all_pointers == NULL)
   177 +	{
   178 +	  fprintf_filtered (gdb_stderr, "\n\ndlopen failed on '%s' - %s\n",
   179 +			    name, dlerror ());
   180 +	  fprintf_filtered (gdb_stderr,
   181 +			    "GDB will not be able to debug pthreads.\n\n");
   182 +	}
   183        return 0;
   184      }
   185  
   186    /* Initialize pointers to the dynamic library functions we will use.
   187       Essential functions first.  */
   188  
   189 -  td_init_p = verbose_dlsym (handle, "td_init");
   190 -  if (td_init_p == NULL)
   191 +  ptrs->td_init_p = verbose_dlsym (handle, "td_init");
   192 +  if (ptrs->td_init_p == NULL)
   193      return 0;
   194  
   195 -  td_ta_new_p = verbose_dlsym (handle, "td_ta_new");
   196 -  if (td_ta_new_p == NULL)
   197 +  ptrs->td_ta_new_p = verbose_dlsym (handle, "td_ta_new");
   198 +  if (ptrs->td_ta_new_p == NULL)
   199      return 0;
   200  
   201 -  td_ta_map_id2thr_p = verbose_dlsym (handle, "td_ta_map_id2thr");
   202 -  if (td_ta_map_id2thr_p == NULL)
   203 +  ptrs->td_ta_map_id2thr_p = verbose_dlsym (handle, "td_ta_map_id2thr");
   204 +  if (ptrs->td_ta_map_id2thr_p == NULL)
   205      return 0;
   206  
   207 -  td_ta_map_lwp2thr_p = verbose_dlsym (handle, "td_ta_map_lwp2thr");
   208 -  if (td_ta_map_lwp2thr_p == NULL)
   209 +  ptrs->td_ta_map_lwp2thr_p = verbose_dlsym (handle, "td_ta_map_lwp2thr");
   210 +  if (ptrs->td_ta_map_lwp2thr_p == NULL)
   211      return 0;
   212  
   213 -  td_ta_thr_iter_p = verbose_dlsym (handle, "td_ta_thr_iter");
   214 -  if (td_ta_thr_iter_p == NULL)
   215 +  ptrs->td_ta_thr_iter_p = verbose_dlsym (handle, "td_ta_thr_iter");
   216 +  if (ptrs->td_ta_thr_iter_p == NULL)
   217      return 0;
   218  
   219 -  td_thr_validate_p = verbose_dlsym (handle, "td_thr_validate");
   220 -  if (td_thr_validate_p == NULL)
   221 +  ptrs->td_thr_validate_p = verbose_dlsym (handle, "td_thr_validate");
   222 +  if (ptrs->td_thr_validate_p == NULL)
   223      return 0;
   224  
   225 -  td_thr_get_info_p = verbose_dlsym (handle, "td_thr_get_info");
   226 -  if (td_thr_get_info_p == NULL)
   227 +  ptrs->td_thr_get_info_p = verbose_dlsym (handle, "td_thr_get_info");
   228 +  if (ptrs->td_thr_get_info_p == NULL)
   229      return 0;
   230  
   231 -  td_thr_getfpregs_p = verbose_dlsym (handle, "td_thr_getfpregs");
   232 -  if (td_thr_getfpregs_p == NULL)
   233 +  ptrs->td_thr_getfpregs_p = verbose_dlsym (handle, "td_thr_getfpregs");
   234 +  if (ptrs->td_thr_getfpregs_p == NULL)
   235      return 0;
   236  
   237 -  td_thr_getgregs_p = verbose_dlsym (handle, "td_thr_getgregs");
   238 -  if (td_thr_getgregs_p == NULL)
   239 +  ptrs->td_thr_getgregs_p = verbose_dlsym (handle, "td_thr_getgregs");
   240 +  if (ptrs->td_thr_getgregs_p == NULL)
   241      return 0;
   242  
   243 -  td_thr_setfpregs_p = verbose_dlsym (handle, "td_thr_setfpregs");
   244 -  if (td_thr_setfpregs_p == NULL)
   245 +  ptrs->td_thr_setfpregs_p = verbose_dlsym (handle, "td_thr_setfpregs");
   246 +  if (ptrs->td_thr_setfpregs_p == NULL)
   247      return 0;
   248  
   249 -  td_thr_setgregs_p = verbose_dlsym (handle, "td_thr_setgregs");
   250 -  if (td_thr_setgregs_p == NULL)
   251 +  ptrs->td_thr_setgregs_p = verbose_dlsym (handle, "td_thr_setgregs");
   252 +  if (ptrs->td_thr_setgregs_p == NULL)
   253      return 0;
   254  
   255    /* Initialize the library.  */
   256 -  err = td_init_p ();
   257 +  err = ptrs->td_init_p ();
   258    if (err != TD_OK)
   259      {
   260        warning ("Cannot initialize libthread_db: %s", thread_db_err_str (err));
   261 +      xfree (ptrs);
   262        return 0;
   263      }
   264  
   265    /* These are not essential.  */
   266 -  td_ta_event_addr_p = dlsym (handle, "td_ta_event_addr");
   267 -  td_ta_set_event_p = dlsym (handle, "td_ta_set_event");
   268 -  td_ta_event_getmsg_p = dlsym (handle, "td_ta_event_getmsg");
   269 -  td_thr_event_enable_p = dlsym (handle, "td_thr_event_enable");
   270 -  td_thr_tls_get_addr_p = dlsym (handle, "td_thr_tls_get_addr");
   271 +  ptrs->td_ta_event_addr_p = dlsym (handle, "td_ta_event_addr");
   272 +  ptrs->td_ta_set_event_p = dlsym (handle, "td_ta_set_event");
   273 +  ptrs->td_ta_event_getmsg_p = dlsym (handle, "td_ta_event_getmsg");
   274 +  ptrs->td_thr_event_enable_p = dlsym (handle, "td_thr_event_enable");
   275 +  ptrs->td_thr_tls_get_addr_p = dlsym (handle, "td_thr_tls_get_addr");
   276 +
   277 +  if (dladdr (ptrs->td_ta_new_p, &info) != 0)
   278 +    ptrs->filename = info.dli_fname;
   279 +
   280 +  /* Try dlinfo?  */
   281 +
   282 +  if (ptrs->filename == NULL)
   283 +    /* Paranoid - don't let a NULL path slip through.  */
   284 +    ptrs->filename = name;
   285  
   286 -  return 1;
   287 +  return ptrs;
   288  }
   289  
   290  static td_err_e
   291 @@ -508,7 +537,7 @@ enable_thread_event (td_thragent_t *thre
   292    td_err_e err;
   293  
   294    /* Get the breakpoint address for thread EVENT.  */
   295 -  err = td_ta_event_addr_p (thread_agent, event, &notify);
   296 +  err = current_pointers->td_ta_event_addr_p (thread_agent, event, &notify);
   297    if (err != TD_OK)
   298      return err;
   299  
   300 @@ -534,8 +563,10 @@ enable_thread_event_reporting (void)
   301  
   302    /* We cannot use the thread event reporting facility if these
   303       functions aren't available.  */
   304 -  if (td_ta_event_addr_p == NULL || td_ta_set_event_p == NULL
   305 -      || td_ta_event_getmsg_p == NULL || td_thr_event_enable_p == NULL)
   306 +  if (current_pointers->td_ta_event_addr_p == NULL
   307 +      || current_pointers->td_ta_set_event_p == NULL
   308 +      || current_pointers->td_ta_event_getmsg_p == NULL
   309 +      || current_pointers->td_thr_event_enable_p == NULL)
   310      return;
   311  
   312    /* Set the process wide mask saying which events we're interested in.  */
   313 @@ -552,7 +583,7 @@ enable_thread_event_reporting (void)
   314  #endif
   315      td_event_addset (&events, TD_DEATH);
   316  
   317 -  err = td_ta_set_event_p (thread_agent, &events);
   318 +  err = current_pointers->td_ta_set_event_p (thread_agent, &events);
   319    if (err != TD_OK)
   320      {
   321        warning ("Unable to set global thread event mask: %s",
   322 @@ -592,7 +623,7 @@ disable_thread_event_reporting (void)
   323    /* Set the process wide mask saying we aren't interested in any
   324       events anymore.  */
   325    td_event_emptyset (&events);
   326 -  td_ta_set_event_p (thread_agent, &events);
   327 +  current_pointers->td_ta_set_event_p (thread_agent, &events);
   328  
   329    /* Delete thread event breakpoints, if any.  */
   330    remove_thread_event_breakpoints ();
   331 @@ -635,7 +666,6 @@ check_thread_signals (void)
   332  static void
   333  check_for_thread_db (void)
   334  {
   335 -  td_err_e err;
   336    static int already_loaded;
   337  
   338    /* First time through, report that libthread_db was successfuly
   339 @@ -644,19 +674,8 @@ check_for_thread_db (void)
   340  
   341    if (!already_loaded)
   342      {
   343 -      Dl_info info;
   344 -      const char *library = NULL;
   345 -      if (dladdr ((*td_ta_new_p), &info) != 0)
   346 -	library = info.dli_fname;
   347 -
   348 -      /* Try dlinfo?  */
   349 -
   350 -      if (library == NULL)
   351 -	/* Paranoid - don't let a NULL path slip through.  */
   352 -	library = LIBTHREAD_DB_SO;
   353 -
   354        printf_unfiltered ("Using host libthread_db library \"%s\".\n",
   355 -			 library);
   356 +			 all_pointers->filename);
   357        already_loaded = 1;
   358      }
   359  
   360 @@ -674,28 +693,34 @@ check_for_thread_db (void)
   361    proc_handle.pid = GET_PID (inferior_ptid);
   362  
   363    /* Now attempt to open a connection to the thread library.  */
   364 -  err = td_ta_new_p (&proc_handle, &thread_agent);
   365 -  switch (err)
   366 +  for (current_pointers = all_pointers;
   367 +       current_pointers != NULL;
   368 +       current_pointers = current_pointers->next)
   369      {
   370 -    case TD_NOLIBTHREAD:
   371 -      /* No thread library was detected.  */
   372 -      break;
   373 -
   374 -    case TD_OK:
   375 -      printf_unfiltered ("[Thread debugging using libthread_db enabled]\n");
   376 +      td_err_e err;
   377 +      err = current_pointers->td_ta_new_p (&proc_handle, &thread_agent);
   378 +      switch (err)
   379 +	{
   380 +	case TD_NOLIBTHREAD:
   381 +	  /* No thread library was detected.  */
   382 +	  break;
   383  
   384 -      /* The thread library was detected.  Activate the thread_db target.  */
   385 -      push_target (&thread_db_ops);
   386 -      using_thread_db = 1;
   387 +	case TD_OK:
   388 +	  printf_unfiltered ("[Thread debugging using libthread_db enabled]\n");
   389  
   390 -      enable_thread_event_reporting ();
   391 -      thread_db_find_new_threads ();
   392 -      break;
   393 +	  /* The thread library was detected.  Activate the thread_db target.  */
   394 +	  push_target (&thread_db_ops);
   395 +	  using_thread_db = 1;
   396 +
   397 +	  enable_thread_event_reporting ();
   398 +	  thread_db_find_new_threads ();
   399 +	  return;
   400  
   401 -    default:
   402 -      warning ("Cannot initialize thread debugging library: %s",
   403 -	       thread_db_err_str (err));
   404 -      break;
   405 +	default:
   406 +	  warning ("Cannot initialize thread debugging library: %s",
   407 +		   thread_db_err_str (err));
   408 +	  break;
   409 +	}
   410      }
   411  }
   412  
   413 @@ -766,7 +791,7 @@ attach_thread (ptid_t ptid, const td_thr
   414  #endif
   415  
   416    /* Enable thread event reporting for this thread.  */
   417 -  err = td_thr_event_enable_p (th_p, 1);
   418 +  err = current_pointers->td_thr_event_enable_p (th_p, 1);
   419    if (err != TD_OK)
   420      error ("Cannot enable thread event reporting for %s: %s",
   421  	   target_pid_to_str (ptid), thread_db_err_str (err));
   422 @@ -892,7 +917,7 @@ check_event (ptid_t ptid)
   423  
   424    do
   425      {
   426 -      err = td_ta_event_getmsg_p (thread_agent, &msg);
   427 +      err = current_pointers->td_ta_event_getmsg_p (thread_agent, &msg);
   428        if (err != TD_OK)
   429  	{
   430  	  if (err == TD_NOMSG)
   431 @@ -902,7 +927,7 @@ check_event (ptid_t ptid)
   432  		 thread_db_err_str (err));
   433  	}
   434  
   435 -      err = td_thr_get_info_p (msg.th_p, &ti);
   436 +      err = current_pointers->td_thr_get_info_p (msg.th_p, &ti);
   437        if (err != TD_OK)
   438  	error ("Cannot get thread info: %s", thread_db_err_str (err));
   439  
   440 @@ -1015,12 +1040,14 @@ thread_db_fetch_registers (int regno)
   441    thread_info = find_thread_pid (inferior_ptid);
   442    thread_db_map_id2thr (thread_info, 1);
   443  
   444 -  err = td_thr_getgregs_p (&thread_info->private->th, gregset);
   445 +  err = current_pointers->td_thr_getgregs_p (&thread_info->private->th,
   446 +					     gregset);
   447    if (err != TD_OK)
   448      error ("Cannot fetch general-purpose registers for thread %ld: %s",
   449  	   (long) GET_THREAD (inferior_ptid), thread_db_err_str (err));
   450  
   451 -  err = td_thr_getfpregs_p (&thread_info->private->th, &fpregset);
   452 +  err = current_pointers->td_thr_getfpregs_p (&thread_info->private->th,
   453 +					      &fpregset);
   454    if (err != TD_OK)
   455      error ("Cannot get floating-point registers for thread %ld: %s",
   456  	   (long) GET_THREAD (inferior_ptid), thread_db_err_str (err));
   457 @@ -1062,11 +1089,13 @@ thread_db_store_registers (int regno)
   458    fill_gregset ((gdb_gregset_t *) gregset, -1);
   459    fill_fpregset (&fpregset, -1);
   460  
   461 -  err = td_thr_setgregs_p (&thread_info->private->th, gregset);
   462 +  err = current_pointers->td_thr_setgregs_p (&thread_info->private->th,
   463 +					     gregset);
   464    if (err != TD_OK)
   465      error ("Cannot store general-purpose registers for thread %ld: %s",
   466  	   (long) GET_THREAD (inferior_ptid), thread_db_err_str (err));
   467 -  err = td_thr_setfpregs_p (&thread_info->private->th, &fpregset);
   468 +  err = current_pointers->td_thr_setfpregs_p (&thread_info->private->th,
   469 +					      &fpregset);
   470    if (err != TD_OK)
   471      error ("Cannot store floating-point registers  for thread %ld: %s",
   472  	   (long) GET_THREAD (inferior_ptid), thread_db_err_str (err));
   473 @@ -1136,15 +1165,14 @@ thread_db_thread_alive (ptid_t ptid)
   474        if (!thread_info->private->th_valid)
   475  	return 0;
   476  
   477 -      err = td_thr_validate_p (&thread_info->private->th);
   478 +      err = current_pointers->td_thr_validate_p (&thread_info->private->th);
   479        if (err != TD_OK)
   480  	return 0;
   481  
   482        if (!thread_info->private->ti_valid)
   483  	{
   484 -	  err =
   485 -	    td_thr_get_info_p (&thread_info->private->th,
   486 -			       &thread_info->private->ti);
   487 +	  err = current_pointers->td_thr_get_info_p
   488 +	    (&thread_info->private->th, &thread_info->private->ti);
   489  	  if (err != TD_OK)
   490  	    return 0;
   491  	  thread_info->private->ti_valid = 1;
   492 @@ -1170,7 +1198,7 @@ find_new_threads_callback (const td_thrh
   493    td_err_e err;
   494    ptid_t ptid;
   495  
   496 -  err = td_thr_get_info_p (th_p, &ti);
   497 +  err = current_pointers->td_thr_get_info_p (th_p, &ti);
   498    if (err != TD_OK)
   499      error ("find_new_threads_callback: cannot get thread info: %s",
   500  	   thread_db_err_str (err));
   501 @@ -1192,9 +1220,10 @@ thread_db_find_new_threads (void)
   502    td_err_e err;
   503  
   504    /* Iterate over all user-space threads to discover new threads.  */
   505 -  err = td_ta_thr_iter_p (thread_agent, find_new_threads_callback, NULL,
   506 -			  TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
   507 -			  TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
   508 +  err = current_pointers->td_ta_thr_iter_p
   509 +    (thread_agent, find_new_threads_callback, NULL,
   510 +     TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
   511 +     TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
   512    if (err != TD_OK)
   513      error ("Cannot find new threads: %s", thread_db_err_str (err));
   514  }
   515 @@ -1257,7 +1286,7 @@ thread_db_get_thread_local_address (ptid
   516        struct thread_info *thread_info;
   517  
   518        /* glibc doesn't provide the needed interface.  */
   519 -      if (!td_thr_tls_get_addr_p)
   520 +      if (!current_pointers->td_thr_tls_get_addr_p)
   521  	error ("Cannot find thread-local variables in this thread library.");
   522  
   523        /* Get the address of the link map for this objfile.  */
   524 @@ -1279,8 +1308,8 @@ thread_db_get_thread_local_address (ptid
   525        thread_db_map_id2thr (thread_info, 1);
   526  
   527        /* Finally, get the address of the variable.  */
   528 -      err = td_thr_tls_get_addr_p (&thread_info->private->th, (void *) lm,
   529 -				   offset, &address);
   530 +      err = current_pointers->td_thr_tls_get_addr_p
   531 +	(&thread_info->private->th, (void *) lm, offset, &address);
   532  
   533  #ifdef THREAD_DB_HAS_TD_NOTALLOC
   534        /* The memory hasn't been allocated, yet.  */
   535 @@ -1360,17 +1389,49 @@ init_thread_db_ops (void)
   536  void
   537  _initialize_thread_db (void)
   538  {
   539 +  struct thread_db_pointers *ptrs;
   540 +  const char *p;
   541 +
   542    /* Only initialize the module if we can load libthread_db.  */
   543 -  if (thread_db_load ())
   544 -    {
   545 -      init_thread_db_ops ();
   546 -      add_target (&thread_db_ops);
   547 +  ptrs = thread_db_load (LIBTHREAD_DB_SO);
   548 +  if (ptrs == NULL)
   549 +    return;
   550 +
   551 +  all_pointers = ptrs;
   552  
   553 -      /* Add ourselves to objfile event chain.  */
   554 -      target_new_objfile_chain = deprecated_target_new_objfile_hook;
   555 -      deprecated_target_new_objfile_hook = thread_db_new_objfile;
   556 +  /* Some GNU/Linux systems have more than one binary-compatible copy
   557 +     of libthread_db.  If we can find a second one, load that too.
   558 +     The inferior may force the use of a different threading package
   559 +     than we expect.  Our guess for the location is somewhat hokey:
   560 +     strip out anything between /lib (or /lib64) and LIBTHREAD_DB_SO.
   561 +     If we loaded the NPTL libthread_db by default, this may find us
   562 +     the LinuxThreads copy.  */
   563 +  p = strrchr (ptrs->filename, '/');
   564 +  while (p != NULL && p > ptrs->filename)
   565 +    {
   566 +      const char *component;
   567  
   568 -      /* Register ourselves for the new inferior observer.  */
   569 -      observer_attach_inferior_created (check_for_thread_db_observer);
   570 +      component = memrchr (ptrs->filename, '/', p - ptrs->filename);
   571 +      if (component != NULL && strncmp (component, "/lib", 4) == 0)
   572 +	{
   573 +	  char *new_name = xmalloc (p - ptrs->filename + 2
   574 +				    + strlen (LIBTHREAD_DB_SO));
   575 +	  memcpy (new_name, ptrs->filename, p - ptrs->filename + 1);
   576 +	  strcpy (new_name + (p - ptrs->filename) + 1, LIBTHREAD_DB_SO);
   577 +	  ptrs->next = thread_db_load (new_name);
   578 +	  xfree (new_name);
   579 +	  break;
   580 +	}
   581 +      p = component;
   582      }
   583 +
   584 +  init_thread_db_ops ();
   585 +  add_target (&thread_db_ops);
   586 +
   587 +  /* Add ourselves to objfile event chain.  */
   588 +  target_new_objfile_chain = deprecated_target_new_objfile_hook;
   589 +  deprecated_target_new_objfile_hook = thread_db_new_objfile;
   590 +
   591 +  /* Register ourselves for the new inferior observer.  */
   592 +  observer_attach_inferior_created (check_for_thread_db_observer);
   593  }