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