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, ¬ify);
|
yann@96
|
296 |
+ err = current_pointers->td_ta_event_addr_p (thread_agent, event, ¬ify);
|
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 |
}
|