Removed
Link Here
|
1 |
/* $FreeBSD$ */ |
2 |
/* FreeBSD libthread_db assisted debugging support. |
3 |
Copyright 1999, 2000, 2001 Free Software Foundation, Inc. |
4 |
|
5 |
This file is part of GDB. |
6 |
|
7 |
This program is free software; you can redistribute it and/or modify |
8 |
it under the terms of the GNU General Public License as published by |
9 |
the Free Software Foundation; either version 2 of the License, or |
10 |
(at your option) any later version. |
11 |
|
12 |
This program is distributed in the hope that it will be useful, |
13 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 |
GNU General Public License for more details. |
16 |
|
17 |
You should have received a copy of the GNU General Public License |
18 |
along with this program; if not, write to the Free Software |
19 |
Foundation, Inc., 59 Temple Place - Suite 330, |
20 |
Boston, MA 02111-1307, USA. */ |
21 |
#include <sys/param.h> |
22 |
#include <sys/sysctl.h> |
23 |
#include <sys/user.h> |
24 |
#include <libutil.h> |
25 |
|
26 |
#include <dlfcn.h> |
27 |
#include <sys/types.h> |
28 |
#include <sys/ptrace.h> |
29 |
#include <signal.h> |
30 |
|
31 |
#include "proc_service.h" |
32 |
#include "thread_db.h" |
33 |
|
34 |
#include "defs.h" |
35 |
#include "bfd.h" |
36 |
#include "elf-bfd.h" |
37 |
#include "gdb_assert.h" |
38 |
#include "gdbcore.h" |
39 |
#include "gdbthread.h" |
40 |
#include "inferior.h" |
41 |
#include "objfiles.h" |
42 |
#include "regcache.h" |
43 |
#include "symfile.h" |
44 |
#include "symtab.h" |
45 |
#include "target.h" |
46 |
#include "observer.h" |
47 |
#include "gdbcmd.h" |
48 |
#include "gregset.h" |
49 |
#ifdef PT_GETXMMREGS |
50 |
#include "i387-tdep.h" |
51 |
#endif |
52 |
|
53 |
#define LIBTHREAD_DB_SO "libthread_db.so" |
54 |
|
55 |
struct private_thread_info |
56 |
{ |
57 |
char *lwp_name; |
58 |
}; |
59 |
|
60 |
struct ps_prochandle |
61 |
{ |
62 |
pid_t pid; |
63 |
}; |
64 |
|
65 |
/* Defining the prototype of _initialize_thread_db to remove warning */ |
66 |
extern initialize_file_ftype _initialize_thread_db; |
67 |
|
68 |
/* This module's target vectors. */ |
69 |
static struct target_ops fbsd_thread_ops; |
70 |
|
71 |
/* Non-zero if there is a thread module */ |
72 |
static int fbsd_thread_present; |
73 |
|
74 |
/* Non-zero if we're using this module's target vector. */ |
75 |
static int fbsd_thread_active; |
76 |
|
77 |
/* Non-zero if we have to keep this module's target vector active |
78 |
across re-runs. */ |
79 |
static int keep_thread_db; |
80 |
|
81 |
/* Structure that identifies the child process for the |
82 |
<proc_service.h> interface. */ |
83 |
static struct ps_prochandle proc_handle; |
84 |
|
85 |
/* Connection to the libthread_db library. */ |
86 |
static td_thragent_t *thread_agent; |
87 |
|
88 |
/* The last thread we are single stepping */ |
89 |
static ptid_t last_single_step_thread; |
90 |
|
91 |
|
92 |
/* Pointers to the libthread_db functions. */ |
93 |
static td_err_e (*td_init_p) (void); |
94 |
|
95 |
static td_err_e (*td_ta_new_p) (struct ps_prochandle *ps, td_thragent_t **ta); |
96 |
static td_err_e (*td_ta_delete_p) (td_thragent_t *); |
97 |
static td_err_e (*td_ta_map_id2thr_p) (const td_thragent_t *ta, thread_t pt, |
98 |
td_thrhandle_t *__th); |
99 |
static td_err_e (*td_ta_map_lwp2thr_p) (const td_thragent_t *ta, lwpid_t lwpid, |
100 |
td_thrhandle_t *th); |
101 |
static td_err_e (*td_ta_thr_iter_p) (const td_thragent_t *ta, |
102 |
td_thr_iter_f *callback, |
103 |
void *cbdata_p, td_thr_state_e state, |
104 |
int ti_pri, sigset_t *ti_sigmask_p, |
105 |
unsigned int ti_user_flags); |
106 |
static td_err_e (*td_ta_event_addr_p) (const td_thragent_t *ta, |
107 |
td_event_e event, td_notify_t *ptr); |
108 |
static td_err_e (*td_ta_set_event_p) (const td_thragent_t *ta, |
109 |
td_thr_events_t *event); |
110 |
static td_err_e (*td_ta_event_getmsg_p) (const td_thragent_t *ta, |
111 |
td_event_msg_t *msg); |
112 |
static td_err_e (*td_thr_get_info_p) (const td_thrhandle_t *th, |
113 |
td_thrinfo_t *infop); |
114 |
#ifdef PT_GETXMMREGS |
115 |
static td_err_e (*td_thr_getxmmregs_p) (const td_thrhandle_t *th, |
116 |
char *regset); |
117 |
#endif |
118 |
static td_err_e (*td_thr_getfpregs_p) (const td_thrhandle_t *th, |
119 |
prfpregset_t *regset); |
120 |
static td_err_e (*td_thr_getgregs_p) (const td_thrhandle_t *th, |
121 |
prgregset_t gregs); |
122 |
#ifdef PT_GETXMMREGS |
123 |
static td_err_e (*td_thr_setxmmregs_p) (const td_thrhandle_t *th, |
124 |
const char *fpregs); |
125 |
#endif |
126 |
static td_err_e (*td_thr_setfpregs_p) (const td_thrhandle_t *th, |
127 |
const prfpregset_t *fpregs); |
128 |
static td_err_e (*td_thr_setgregs_p) (const td_thrhandle_t *th, |
129 |
prgregset_t gregs); |
130 |
static td_err_e (*td_thr_event_enable_p) (const td_thrhandle_t *th, int event); |
131 |
|
132 |
static td_err_e (*td_thr_sstep_p) (td_thrhandle_t *th, int step); |
133 |
|
134 |
static td_err_e (*td_ta_tsd_iter_p) (const td_thragent_t *ta, |
135 |
td_key_iter_f *func, void *data); |
136 |
static td_err_e (*td_thr_tls_get_addr_p) (const td_thrhandle_t *th, |
137 |
void *map_address, |
138 |
size_t offset, void **address); |
139 |
static td_err_e (*td_thr_dbsuspend_p) (const td_thrhandle_t *); |
140 |
static td_err_e (*td_thr_dbresume_p) (const td_thrhandle_t *); |
141 |
|
142 |
static CORE_ADDR td_create_bp_addr; |
143 |
|
144 |
/* Location of the thread death event breakpoint. */ |
145 |
static CORE_ADDR td_death_bp_addr; |
146 |
|
147 |
/* Prototypes for local functions. */ |
148 |
static void fbsd_find_lwp_name(long lwpid, struct private_thread_info *info); |
149 |
static void fbsd_thread_update_thread_list (struct target_ops *ops); |
150 |
static int fbsd_thread_alive (struct target_ops *ops, ptid_t ptid); |
151 |
static void attach_thread (ptid_t ptid, const td_thrhandle_t *th_p, |
152 |
const td_thrinfo_t *ti_p, int verbose); |
153 |
static void fbsd_thread_detach (struct target_ops *ops, const char *args, |
154 |
int from_tty); |
155 |
|
156 |
CORE_ADDR fbsd_thread_get_local_address(struct target_ops *ops, |
157 |
ptid_t ptid, CORE_ADDR lm, CORE_ADDR offset); |
158 |
|
159 |
/* Building process ids. */ |
160 |
|
161 |
#define GET_PID(ptid) ptid_get_pid (ptid) |
162 |
#define GET_LWP(ptid) ptid_get_lwp (ptid) |
163 |
#define GET_THREAD(ptid) ptid_get_tid (ptid) |
164 |
|
165 |
#define IS_LWP(ptid) (GET_LWP (ptid) != 0) |
166 |
#define IS_THREAD(ptid) (GET_THREAD (ptid) != 0) |
167 |
|
168 |
#define BUILD_LWP(lwp, pid) ptid_build (pid, lwp, 0) |
169 |
#define BUILD_THREAD(tid, pid) ptid_build (pid, 0, tid) |
170 |
|
171 |
static void |
172 |
free_private_thread_info(struct private_thread_info *info) |
173 |
{ |
174 |
xfree(info->lwp_name); |
175 |
xfree(info); |
176 |
} |
177 |
|
178 |
static char * |
179 |
thread_db_err_str (td_err_e err) |
180 |
{ |
181 |
static char buf[64]; |
182 |
|
183 |
switch (err) |
184 |
{ |
185 |
case TD_OK: |
186 |
return "generic 'call succeeded'"; |
187 |
case TD_ERR: |
188 |
return "generic error"; |
189 |
case TD_NOTHR: |
190 |
return "no thread to satisfy query"; |
191 |
case TD_NOSV: |
192 |
return "no sync handle to satisfy query"; |
193 |
case TD_NOLWP: |
194 |
return "no LWP to satisfy query"; |
195 |
case TD_BADPH: |
196 |
return "invalid process handle"; |
197 |
case TD_BADTH: |
198 |
return "invalid thread handle"; |
199 |
case TD_BADSH: |
200 |
return "invalid synchronization handle"; |
201 |
case TD_BADTA: |
202 |
return "invalid thread agent"; |
203 |
case TD_BADKEY: |
204 |
return "invalid key"; |
205 |
case TD_NOMSG: |
206 |
return "no event message for getmsg"; |
207 |
case TD_NOFPREGS: |
208 |
return "FPU register set not available"; |
209 |
case TD_NOLIBTHREAD: |
210 |
return "application not linked with libthread"; |
211 |
case TD_NOEVENT: |
212 |
return "requested event is not supported"; |
213 |
case TD_NOCAPAB: |
214 |
return "capability not available"; |
215 |
case TD_DBERR: |
216 |
return "debugger service failed"; |
217 |
case TD_NOAPLIC: |
218 |
return "operation not applicable to"; |
219 |
case TD_NOTSD: |
220 |
return "no thread-specific data for this thread"; |
221 |
case TD_MALLOC: |
222 |
return "malloc failed"; |
223 |
case TD_PARTIALREG: |
224 |
return "only part of register set was written/read"; |
225 |
case TD_NOXREGS: |
226 |
return "X register set not available for this thread"; |
227 |
default: |
228 |
snprintf (buf, sizeof (buf), "unknown thread_db error '%d'", err); |
229 |
return buf; |
230 |
} |
231 |
} |
232 |
|
233 |
static char * |
234 |
thread_db_state_str (td_thr_state_e state) |
235 |
{ |
236 |
static char buf[64]; |
237 |
|
238 |
switch (state) |
239 |
{ |
240 |
case TD_THR_STOPPED: |
241 |
return "stopped by debugger"; |
242 |
case TD_THR_RUN: |
243 |
return "runnable"; |
244 |
case TD_THR_ACTIVE: |
245 |
return "active"; |
246 |
case TD_THR_ZOMBIE: |
247 |
return "zombie"; |
248 |
case TD_THR_SLEEP: |
249 |
return "sleeping"; |
250 |
case TD_THR_STOPPED_ASLEEP: |
251 |
return "stopped by debugger AND blocked"; |
252 |
default: |
253 |
snprintf (buf, sizeof (buf), "unknown thread_db state %d", state); |
254 |
return buf; |
255 |
} |
256 |
} |
257 |
|
258 |
/* Convert LWP to user-level thread id. */ |
259 |
static ptid_t |
260 |
thread_from_lwp (ptid_t ptid, td_thrhandle_t *th, td_thrinfo_t *ti) |
261 |
{ |
262 |
td_err_e err; |
263 |
|
264 |
gdb_assert (IS_LWP (ptid)); |
265 |
|
266 |
if (fbsd_thread_active) |
267 |
{ |
268 |
err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), th); |
269 |
if (err == TD_OK) |
270 |
{ |
271 |
err = td_thr_get_info_p (th, ti); |
272 |
if (err != TD_OK) |
273 |
error ("Cannot get thread info: %s", thread_db_err_str (err)); |
274 |
return BUILD_THREAD (ti->ti_tid, GET_PID (ptid)); |
275 |
} |
276 |
} |
277 |
|
278 |
/* the LWP is not mapped to user thread */ |
279 |
return BUILD_LWP (GET_LWP (ptid), GET_PID (ptid)); |
280 |
} |
281 |
|
282 |
static void |
283 |
fbsd_core_get_first_lwp (bfd *abfd, asection *asect, void *obj) |
284 |
{ |
285 |
if (strncmp (bfd_section_name (abfd, asect), ".reg/", 5) != 0) |
286 |
return; |
287 |
|
288 |
if (*(lwpid_t *)obj != 0) |
289 |
return; |
290 |
|
291 |
*(lwpid_t *)obj = atoi (bfd_section_name (abfd, asect) + 5); |
292 |
} |
293 |
|
294 |
static long |
295 |
get_current_lwp (int pid) |
296 |
{ |
297 |
struct ptrace_lwpinfo pl; |
298 |
lwpid_t lwpid; |
299 |
|
300 |
if (!target_has_execution) |
301 |
{ |
302 |
lwpid = 0; |
303 |
bfd_map_over_sections (core_bfd, fbsd_core_get_first_lwp, &lwpid); |
304 |
return lwpid; |
305 |
} |
306 |
if (ptrace (PT_LWPINFO, pid, (caddr_t)&pl, sizeof(pl))) |
307 |
perror_with_name("PT_LWPINFO"); |
308 |
|
309 |
return (long)pl.pl_lwpid; |
310 |
} |
311 |
|
312 |
static void |
313 |
get_current_thread (void) |
314 |
{ |
315 |
td_thrhandle_t th; |
316 |
td_thrinfo_t ti; |
317 |
long lwp; |
318 |
ptid_t tmp, ptid; |
319 |
|
320 |
lwp = get_current_lwp (proc_handle.pid); |
321 |
tmp = BUILD_LWP (lwp, proc_handle.pid); |
322 |
ptid = thread_from_lwp (tmp, &th, &ti); |
323 |
if (in_thread_list (inferior_ptid) ) |
324 |
{ |
325 |
struct thread_info * ti_inf = inferior_thread(); |
326 |
ti_inf->ptid = ptid; |
327 |
} |
328 |
if (!in_thread_list (ptid)) |
329 |
{ |
330 |
attach_thread (ptid, &th, &ti, 1); |
331 |
} |
332 |
inferior_ptid = ptid; |
333 |
} |
334 |
|
335 |
static CORE_ADDR |
336 |
extract_func_ptr(void *value) |
337 |
{ |
338 |
|
339 |
return (extract_typed_address |
340 |
((gdb_byte *)value, |
341 |
builtin_type (target_gdbarch ())->builtin_func_ptr)); |
342 |
} |
343 |
|
344 |
static CORE_ADDR |
345 |
extract_data_ptr(void *value) |
346 |
{ |
347 |
|
348 |
return (extract_typed_address |
349 |
((gdb_byte *)value, |
350 |
builtin_type (target_gdbarch ())->builtin_data_ptr)); |
351 |
} |
352 |
|
353 |
static td_err_e |
354 |
enable_thread_event (td_thragent_t *thread_agent, int event, CORE_ADDR *bp) |
355 |
{ |
356 |
td_notify_t notify; |
357 |
td_err_e err; |
358 |
|
359 |
/* Get the breakpoint address for thread EVENT. */ |
360 |
err = td_ta_event_addr_p (thread_agent, event, ¬ify); |
361 |
if (err != TD_OK) |
362 |
return err; |
363 |
|
364 |
/* Set up the breakpoint. */ |
365 |
(*bp) = (gdbarch_convert_from_func_ptr_addr |
366 |
(target_gdbarch (), |
367 |
extract_func_ptr(¬ify.u.bptaddr), |
368 |
¤t_target)); |
369 |
create_thread_event_breakpoint (target_gdbarch (), (*bp)); |
370 |
|
371 |
return TD_OK; |
372 |
} |
373 |
|
374 |
static void |
375 |
enable_thread_event_reporting (void) |
376 |
{ |
377 |
td_thr_events_t events; |
378 |
td_notify_t notify; |
379 |
td_err_e err; |
380 |
|
381 |
/* We cannot use the thread event reporting facility if these |
382 |
functions aren't available. */ |
383 |
if (td_ta_event_addr_p == NULL || td_ta_set_event_p == NULL |
384 |
|| td_ta_event_getmsg_p == NULL || td_thr_event_enable_p == NULL) |
385 |
return; |
386 |
|
387 |
/* Set the process wide mask saying which events we're interested in. */ |
388 |
td_event_emptyset (&events); |
389 |
td_event_addset (&events, TD_CREATE); |
390 |
td_event_addset (&events, TD_DEATH); |
391 |
|
392 |
err = td_ta_set_event_p (thread_agent, &events); |
393 |
if (err != TD_OK) |
394 |
{ |
395 |
warning ("Unable to set global thread event mask: %s", |
396 |
thread_db_err_str (err)); |
397 |
return; |
398 |
} |
399 |
|
400 |
/* Delete previous thread event breakpoints, if any. */ |
401 |
remove_thread_event_breakpoints (); |
402 |
td_create_bp_addr = 0; |
403 |
td_death_bp_addr = 0; |
404 |
|
405 |
/* Set up the thread creation event. */ |
406 |
err = enable_thread_event (thread_agent, TD_CREATE, &td_create_bp_addr); |
407 |
if (err != TD_OK) |
408 |
{ |
409 |
warning ("Unable to get location for thread creation breakpoint: %s", |
410 |
thread_db_err_str (err)); |
411 |
return; |
412 |
} |
413 |
|
414 |
/* Set up the thread death event. */ |
415 |
err = enable_thread_event (thread_agent, TD_DEATH, &td_death_bp_addr); |
416 |
if (err != TD_OK) |
417 |
{ |
418 |
warning ("Unable to get location for thread death breakpoint: %s", |
419 |
thread_db_err_str (err)); |
420 |
return; |
421 |
} |
422 |
} |
423 |
|
424 |
static void |
425 |
disable_thread_event_reporting (void) |
426 |
{ |
427 |
td_thr_events_t events; |
428 |
|
429 |
/* Set the process wide mask saying we aren't interested in any |
430 |
events anymore. */ |
431 |
td_event_emptyset (&events); |
432 |
td_ta_set_event_p (thread_agent, &events); |
433 |
|
434 |
td_create_bp_addr = 0; |
435 |
td_death_bp_addr = 0; |
436 |
} |
437 |
|
438 |
static void |
439 |
fbsd_thread_activate (void) |
440 |
{ |
441 |
fbsd_thread_active = 1; |
442 |
if (target_has_execution) |
443 |
enable_thread_event_reporting (); |
444 |
else |
445 |
init_thread_list (); |
446 |
fbsd_thread_update_thread_list (NULL); |
447 |
get_current_thread (); |
448 |
} |
449 |
|
450 |
static void |
451 |
fbsd_thread_deactivate (void) |
452 |
{ |
453 |
if (target_has_execution) |
454 |
disable_thread_event_reporting(); |
455 |
td_ta_delete_p (thread_agent); |
456 |
|
457 |
inferior_ptid = pid_to_ptid (proc_handle.pid); |
458 |
proc_handle.pid = 0; |
459 |
fbsd_thread_active = 0; |
460 |
fbsd_thread_present = 0; |
461 |
} |
462 |
|
463 |
static void |
464 |
check_for_thread_db (void) |
465 |
{ |
466 |
td_err_e err; |
467 |
|
468 |
if (td_ta_new_p == NULL) |
469 |
return; |
470 |
|
471 |
/* Don't try to attach to a dead target if there is no core file. */ |
472 |
if (!target_has_execution && core_bfd == NULL) |
473 |
return; |
474 |
|
475 |
/* Nothing to do. The thread library was already detected and the |
476 |
target vector was already activated. */ |
477 |
if (fbsd_thread_active) |
478 |
return; |
479 |
|
480 |
/* Now, initialize libthread_db. This needs to be done after the |
481 |
shared libraries are located because it needs information from |
482 |
the user's thread library. */ |
483 |
|
484 |
err = td_init_p (); |
485 |
if (err != TD_OK) |
486 |
{ |
487 |
warning ("Cannot initialize libthread_db: %s", thread_db_err_str (err)); |
488 |
return; |
489 |
} |
490 |
|
491 |
/* Initialize the structure that identifies the child process. Note |
492 |
that at this point there is no guarantee that we actually have a |
493 |
child process. */ |
494 |
proc_handle.pid = GET_PID (inferior_ptid); |
495 |
|
496 |
/* Now attempt to open a connection to the thread library. */ |
497 |
err = td_ta_new_p (&proc_handle, &thread_agent); |
498 |
switch (err) |
499 |
{ |
500 |
case TD_NOLIBTHREAD: |
501 |
/* No thread library was detected. */ |
502 |
break; |
503 |
|
504 |
case TD_OK: |
505 |
/* The thread library was detected. Activate the thread_db target. */ |
506 |
push_target(&fbsd_thread_ops); |
507 |
fbsd_thread_present = 1; |
508 |
fbsd_thread_activate(); |
509 |
|
510 |
break; |
511 |
|
512 |
default: |
513 |
warning ("Cannot initialize thread debugging library: %s", |
514 |
thread_db_err_str (err)); |
515 |
break; |
516 |
} |
517 |
} |
518 |
|
519 |
static void |
520 |
fbsd_thread_new_objfile (struct objfile *objfile) |
521 |
{ |
522 |
if (objfile != NULL) |
523 |
check_for_thread_db (); |
524 |
} |
525 |
|
526 |
static void |
527 |
fbsd_thread_detach (struct target_ops *ops, const char *args, int from_tty) |
528 |
{ |
529 |
struct target_ops *beneath = find_target_beneath (ops); |
530 |
|
531 |
fbsd_thread_deactivate (); |
532 |
|
533 |
/* Delete thread event breakpoints, if any. */ |
534 |
remove_thread_event_breakpoints (); |
535 |
|
536 |
unpush_target (&fbsd_thread_ops); |
537 |
|
538 |
beneath->to_detach (beneath, args, from_tty); |
539 |
} |
540 |
|
541 |
static int |
542 |
suspend_thread_callback (const td_thrhandle_t *th_p, void *data) |
543 |
{ |
544 |
int err = td_thr_dbsuspend_p (th_p); |
545 |
if (err != 0) |
546 |
fprintf_filtered(gdb_stderr, "%s %s\n", __func__, thread_db_err_str (err)); |
547 |
return (err); |
548 |
} |
549 |
|
550 |
static int |
551 |
resume_thread_callback (const td_thrhandle_t *th_p, void *data) |
552 |
{ |
553 |
int err = td_thr_dbresume_p (th_p); |
554 |
if (err != 0) |
555 |
fprintf_filtered(gdb_stderr, "%s %s\n", __func__, thread_db_err_str (err)); |
556 |
return (err); |
557 |
} |
558 |
|
559 |
static void |
560 |
fbsd_thread_resume (struct target_ops *ops, |
561 |
ptid_t ptid, int step, enum gdb_signal signo) |
562 |
{ |
563 |
struct target_ops *beneath = find_target_beneath (ops); |
564 |
td_thrhandle_t th; |
565 |
td_thrinfo_t ti; |
566 |
ptid_t work_ptid; |
567 |
int resume_all, ret; |
568 |
long lwp, thvalid = 0; |
569 |
|
570 |
if (!fbsd_thread_active) |
571 |
{ |
572 |
// XXX: I don't think this can happen |
573 |
printf_unfiltered ("%s: called without active threads\n", __func__); |
574 |
beneath->to_resume (beneath, ptid, step, signo); |
575 |
return; |
576 |
} |
577 |
|
578 |
if (GET_PID(ptid) != -1 && step != 0) |
579 |
{ |
580 |
resume_all = 0; |
581 |
work_ptid = ptid; |
582 |
} |
583 |
else |
584 |
{ |
585 |
resume_all = 1; |
586 |
work_ptid = inferior_ptid; |
587 |
} |
588 |
|
589 |
lwp = GET_LWP (work_ptid); |
590 |
if (lwp == 0) |
591 |
{ |
592 |
/* check user thread */ |
593 |
ret = td_ta_map_id2thr_p (thread_agent, GET_THREAD(work_ptid), &th); |
594 |
if (ret) |
595 |
error ("%s: %s", __func__, thread_db_err_str (ret)); |
596 |
|
597 |
/* For M:N thread, we need to tell UTS to set/unset single step |
598 |
flag at context switch time, the flag will be written into |
599 |
thread mailbox. This becauses some architecture may not have |
600 |
machine single step flag in ucontext, so we put the flag in mailbox, |
601 |
when the thread switches back, kse_switchin restores the single step |
602 |
state. */ |
603 |
ret = td_thr_sstep_p (&th, step); |
604 |
if (ret) |
605 |
error ("%s: %s", __func__, thread_db_err_str (ret)); |
606 |
ret = td_thr_get_info_p (&th, &ti); |
607 |
if (ret) |
608 |
error ("%s: %s", __func__, thread_db_err_str (ret)); |
609 |
thvalid = 1; |
610 |
lwp = ti.ti_lid; |
611 |
} |
612 |
|
613 |
if (lwp) |
614 |
{ |
615 |
int req = step ? PT_SETSTEP : PT_CLEARSTEP; |
616 |
if (ptrace (req, (pid_t) lwp, (caddr_t) 1, gdb_signal_to_host(signo))) |
617 |
perror_with_name ("PT_SETSTEP/PT_CLEARSTEP"); |
618 |
} |
619 |
|
620 |
if (!ptid_equal (last_single_step_thread, null_ptid)) |
621 |
{ |
622 |
ret = td_ta_thr_iter_p (thread_agent, resume_thread_callback, NULL, |
623 |
TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, |
624 |
TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS); |
625 |
if (ret != TD_OK) |
626 |
error ("resume error: %s", thread_db_err_str (ret)); |
627 |
} |
628 |
|
629 |
if (!resume_all) |
630 |
{ |
631 |
ret = td_ta_thr_iter_p (thread_agent, suspend_thread_callback, NULL, |
632 |
TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, |
633 |
TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS); |
634 |
if (ret != TD_OK) |
635 |
error ("suspend error: %s", thread_db_err_str (ret)); |
636 |
last_single_step_thread = work_ptid; |
637 |
} |
638 |
else |
639 |
last_single_step_thread = null_ptid; |
640 |
|
641 |
if (thvalid) |
642 |
{ |
643 |
ret = td_thr_dbresume_p (&th); |
644 |
if (ret != TD_OK) |
645 |
error ("resume error: %s", thread_db_err_str (ret)); |
646 |
} |
647 |
else |
648 |
{ |
649 |
/* it is not necessary, put it here for completness */ |
650 |
ret = ptrace(PT_RESUME, lwp, 0, 0); |
651 |
} |
652 |
|
653 |
/* now continue the process, suspended thread wont run */ |
654 |
if (ptrace (PT_CONTINUE, proc_handle.pid , (caddr_t)1, |
655 |
gdb_signal_to_host(signo))) |
656 |
perror_with_name ("PT_CONTINUE"); |
657 |
} |
658 |
|
659 |
static void |
660 |
attach_thread (ptid_t ptid, const td_thrhandle_t *th_p, |
661 |
const td_thrinfo_t *ti_p, int verbose) |
662 |
{ |
663 |
struct private_thread_info *private; |
664 |
struct thread_info *tp = NULL; |
665 |
char *lwpstr = NULL; |
666 |
td_err_e err; |
667 |
|
668 |
/* Add the thread to GDB's thread list. */ |
669 |
if (!in_thread_list (ptid)) |
670 |
{ |
671 |
/* Add thread with info */ |
672 |
private = xmalloc(sizeof(struct private_thread_info)); |
673 |
gdb_assert(private != NULL); |
674 |
// Thread name is assigned when printed |
675 |
memset(private, 0, sizeof(struct private_thread_info)); |
676 |
|
677 |
tp = add_thread_with_info(ptid, private); |
678 |
tp->priv = private; |
679 |
tp->private_dtor = free_private_thread_info; |
680 |
} |
681 |
|
682 |
if (ti_p->ti_state == TD_THR_UNKNOWN || ti_p->ti_state == TD_THR_ZOMBIE) |
683 |
return; /* A zombie thread -- do not attach. */ |
684 |
|
685 |
if (! IS_THREAD(ptid)) |
686 |
return; |
687 |
if (!target_has_execution) |
688 |
return; |
689 |
/* Enable thread event reporting for this thread. */ |
690 |
err = td_thr_event_enable_p (th_p, 1); |
691 |
if (err != TD_OK) |
692 |
error ("Cannot enable thread event reporting for %s: %s", |
693 |
target_pid_to_str (ptid), thread_db_err_str (err)); |
694 |
} |
695 |
|
696 |
static void |
697 |
detach_thread (ptid_t ptid, int verbose) |
698 |
{ |
699 |
if (verbose) |
700 |
printf_unfiltered ("[%s exited]\n", target_pid_to_str (ptid)); |
701 |
} |
702 |
|
703 |
static void |
704 |
check_event (ptid_t ptid) |
705 |
{ |
706 |
struct regcache *regcache = get_thread_regcache (ptid); |
707 |
struct gdbarch *gdbarch = get_regcache_arch (regcache); |
708 |
td_event_msg_t msg; |
709 |
td_thrinfo_t ti; |
710 |
td_err_e err; |
711 |
CORE_ADDR stop_pc; |
712 |
int loop = 0; |
713 |
|
714 |
/* Bail out early if we're not at a thread event breakpoint. */ |
715 |
stop_pc = regcache_read_pc (regcache) |
716 |
- gdbarch_decr_pc_after_break (gdbarch); |
717 |
if (stop_pc != td_create_bp_addr && stop_pc != td_death_bp_addr) |
718 |
return; |
719 |
loop = 1; |
720 |
|
721 |
do |
722 |
{ |
723 |
err = td_ta_event_getmsg_p (thread_agent, &msg); |
724 |
if (err != TD_OK) |
725 |
{ |
726 |
if (err == TD_NOMSG) |
727 |
return; |
728 |
error ("Cannot get thread event message: %s", |
729 |
thread_db_err_str (err)); |
730 |
} |
731 |
err = td_thr_get_info_p ((void *)(uintptr_t)msg.th_p, &ti); |
732 |
if (err != TD_OK) |
733 |
error ("Cannot get thread info: %s", thread_db_err_str (err)); |
734 |
ptid = BUILD_THREAD (ti.ti_tid, GET_PID (ptid)); |
735 |
switch (msg.event) |
736 |
{ |
737 |
case TD_CREATE: |
738 |
/* We may already know about this thread, for instance when the |
739 |
user has issued the `info threads' command before the SIGTRAP |
740 |
for hitting the thread creation breakpoint was reported. */ |
741 |
attach_thread (ptid, (void *)(uintptr_t)msg.th_p, &ti, 1); |
742 |
break; |
743 |
case TD_DEATH: |
744 |
if (!in_thread_list (ptid)) |
745 |
error ("Spurious thread death event."); |
746 |
detach_thread (ptid, 1); |
747 |
break; |
748 |
default: |
749 |
error ("Spurious thread event."); |
750 |
} |
751 |
} |
752 |
while (loop); |
753 |
} |
754 |
|
755 |
static ptid_t |
756 |
fbsd_thread_wait (struct target_ops *ops, |
757 |
ptid_t ptid, struct target_waitstatus *ourstatus, int options) |
758 |
{ |
759 |
struct target_ops *beneath = find_target_beneath (ops); |
760 |
ptid_t ret; |
761 |
long lwp; |
762 |
CORE_ADDR stop_pc; |
763 |
td_thrhandle_t th; |
764 |
td_thrinfo_t ti; |
765 |
|
766 |
ret = beneath->to_wait (beneath, ptid, ourstatus, options); |
767 |
if (GET_PID(ret) >= 0 && |
768 |
( ourstatus->kind == TARGET_WAITKIND_STOPPED || |
769 |
ourstatus->kind == TARGET_WAITKIND_VFORKED || |
770 |
ourstatus->kind == TARGET_WAITKIND_FORKED ) ) |
771 |
{ |
772 |
lwp = get_current_lwp (GET_PID(ret)); |
773 |
ret = thread_from_lwp (BUILD_LWP(lwp, GET_PID(ret)), |
774 |
&th, &ti); |
775 |
if (!in_thread_list(ret)) { |
776 |
/* |
777 |
* We have to enable event reporting for initial thread |
778 |
* which was not mapped before. |
779 |
*/ |
780 |
attach_thread(ret, &th, &ti, 1); |
781 |
} |
782 |
if (ourstatus->value.sig == GDB_SIGNAL_TRAP) |
783 |
check_event(ret); |
784 |
/* this is a hack, if an event won't cause gdb to stop, for example, |
785 |
SIGALRM, gdb resumes the process immediatly without setting |
786 |
inferior_ptid to the new thread returned here, this is a bug |
787 |
because inferior_ptid may already not exist there, and passing |
788 |
a non-existing thread to fbsd_thread_resume causes error. However, |
789 |
if the exiting thread is the currently selected thread, |
790 |
then that is handled later in handle_inferior_event(), and we must |
791 |
not delete the currently selected thread. |
792 |
*/ |
793 |
if (!fbsd_thread_alive (ops, inferior_ptid) && !ptid_equal(inferior_ptid, ret)) |
794 |
{ |
795 |
ptid_t save_ptid; |
796 |
save_ptid = inferior_ptid; |
797 |
inferior_ptid = ret; |
798 |
delete_thread (save_ptid); |
799 |
} |
800 |
} |
801 |
|
802 |
return (ret); |
803 |
} |
804 |
|
805 |
static void |
806 |
fbsd_thread_fetch_registers (struct target_ops *ops, |
807 |
struct regcache *regcache, int regnum) |
808 |
{ |
809 |
prgregset_t gregset; |
810 |
prfpregset_t fpregset; |
811 |
td_thrhandle_t th; |
812 |
td_thrinfo_t ti; |
813 |
td_err_e err; |
814 |
#ifdef PT_GETXMMREGS |
815 |
char xmmregs[512]; |
816 |
#endif |
817 |
|
818 |
if (!IS_THREAD (inferior_ptid)) |
819 |
{ |
820 |
struct target_ops *beneath = find_target_beneath (ops); |
821 |
|
822 |
beneath->to_fetch_registers (ops, regcache, regnum); |
823 |
return; |
824 |
} |
825 |
|
826 |
err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (inferior_ptid), &th); |
827 |
if (err != TD_OK) |
828 |
error ("Cannot find thread %d: Thread ID=%ld, %s", |
829 |
pid_to_thread_id (inferior_ptid), |
830 |
GET_THREAD (inferior_ptid), thread_db_err_str (err)); |
831 |
|
832 |
err = td_thr_get_info_p (&th, &ti); |
833 |
if (err != TD_OK) |
834 |
error ("Cannot get thread info, Thread ID=%ld, %s", |
835 |
GET_THREAD (inferior_ptid), thread_db_err_str (err)); |
836 |
|
837 |
if (ti.ti_lid != 0) |
838 |
{ |
839 |
struct target_ops *beneath = find_target_beneath (ops); |
840 |
struct cleanup *old_chain; |
841 |
|
842 |
old_chain = save_inferior_ptid (); |
843 |
|
844 |
inferior_ptid = BUILD_LWP (ti.ti_lid, GET_PID (inferior_ptid)); |
845 |
beneath->to_fetch_registers (ops, regcache, regnum); |
846 |
|
847 |
do_cleanups (old_chain); |
848 |
return; |
849 |
} |
850 |
|
851 |
err = td_thr_getgregs_p (&th, gregset); |
852 |
if (err != TD_OK) |
853 |
error ("Cannot fetch general-purpose registers for thread %d: Thread ID=%ld, %s", |
854 |
pid_to_thread_id (inferior_ptid), |
855 |
GET_THREAD (inferior_ptid), thread_db_err_str (err)); |
856 |
#ifdef PT_GETXMMREGS |
857 |
err = td_thr_getxmmregs_p (&th, xmmregs); |
858 |
if (err == TD_OK) |
859 |
{ |
860 |
i387_supply_fxsave (regcache, -1, xmmregs); |
861 |
} |
862 |
else |
863 |
{ |
864 |
#endif |
865 |
err = td_thr_getfpregs_p (&th, &fpregset); |
866 |
if (err != TD_OK) |
867 |
error ("Cannot get floating-point registers for thread %d: Thread ID=%ld, %s", |
868 |
pid_to_thread_id (inferior_ptid), |
869 |
GET_THREAD (inferior_ptid), thread_db_err_str (err)); |
870 |
supply_fpregset (regcache, &fpregset); |
871 |
#ifdef PT_GETXMMREGS |
872 |
} |
873 |
#endif |
874 |
|
875 |
supply_gregset (regcache, gregset); |
876 |
} |
877 |
|
878 |
static void |
879 |
fbsd_thread_store_registers (struct target_ops *ops, |
880 |
struct regcache *regcache, int regnum) |
881 |
{ |
882 |
prgregset_t gregset; |
883 |
prfpregset_t fpregset; |
884 |
td_thrhandle_t th; |
885 |
td_thrinfo_t ti; |
886 |
td_err_e err; |
887 |
#ifdef PT_GETXMMREGS |
888 |
char xmmregs[512]; |
889 |
#endif |
890 |
|
891 |
if (!IS_THREAD (inferior_ptid)) |
892 |
{ |
893 |
struct target_ops *beneath = find_target_beneath (ops); |
894 |
|
895 |
beneath->to_store_registers (ops, regcache, regnum); |
896 |
return; |
897 |
} |
898 |
|
899 |
err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (inferior_ptid), &th); |
900 |
if (err != TD_OK) |
901 |
error ("Cannot find thread %d: Thread ID=%ld, %s", |
902 |
pid_to_thread_id (inferior_ptid), |
903 |
GET_THREAD (inferior_ptid), |
904 |
thread_db_err_str (err)); |
905 |
|
906 |
err = td_thr_get_info_p (&th, &ti); |
907 |
if (err != TD_OK) |
908 |
error ("Cannot get thread info, Thread ID=%ld, %s", |
909 |
GET_THREAD (inferior_ptid), thread_db_err_str (err)); |
910 |
|
911 |
if (ti.ti_lid != 0) |
912 |
{ |
913 |
struct target_ops *beneath = find_target_beneath (ops); |
914 |
struct cleanup *old_chain; |
915 |
|
916 |
old_chain = save_inferior_ptid (); |
917 |
|
918 |
inferior_ptid = BUILD_LWP (ti.ti_lid, GET_PID (inferior_ptid)); |
919 |
beneath->to_store_registers (ops, regcache, regnum); |
920 |
|
921 |
do_cleanups (old_chain); |
922 |
return; |
923 |
} |
924 |
|
925 |
if (regnum != -1) |
926 |
{ |
927 |
char old_value[MAX_REGISTER_SIZE]; |
928 |
|
929 |
regcache_raw_collect (regcache, regnum, old_value); |
930 |
err = td_thr_getgregs_p (&th, gregset); |
931 |
if (err != TD_OK) |
932 |
error ("%s: td_thr_getgregs %s", __func__, thread_db_err_str (err)); |
933 |
#ifdef PT_GETXMMREGS |
934 |
err = td_thr_getxmmregs_p (&th, xmmregs); |
935 |
if (err != TD_OK) |
936 |
{ |
937 |
#endif |
938 |
err = td_thr_getfpregs_p (&th, &fpregset); |
939 |
if (err != TD_OK) |
940 |
error ("%s: td_thr_getfpgregs %s", __func__, thread_db_err_str (err)); |
941 |
#ifdef PT_GETXMMREGS |
942 |
} |
943 |
#endif |
944 |
regcache_raw_supply (regcache, regnum, old_value); |
945 |
} |
946 |
|
947 |
fill_gregset (regcache, gregset, regnum); |
948 |
err = td_thr_setgregs_p (&th, gregset); |
949 |
if (err != TD_OK) |
950 |
error ("Cannot store general-purpose registers for thread %d: Thread ID=%ld, %s", |
951 |
pid_to_thread_id (inferior_ptid), GET_THREAD (inferior_ptid), |
952 |
thread_db_err_str (err)); |
953 |
|
954 |
#ifdef PT_GETXMMREGS |
955 |
i387_collect_fxsave (regcache, regnum, xmmregs); |
956 |
err = td_thr_setxmmregs_p (&th, xmmregs); |
957 |
if (err == TD_OK) |
958 |
return; |
959 |
#endif |
960 |
|
961 |
fill_fpregset (regcache, &fpregset, regnum); |
962 |
err = td_thr_setfpregs_p (&th, &fpregset); |
963 |
if (err != TD_OK) |
964 |
error ("Cannot store floating-point registers for thread %d: Thread ID=%ld, %s", |
965 |
pid_to_thread_id (inferior_ptid), GET_THREAD (inferior_ptid), |
966 |
thread_db_err_str (err)); |
967 |
} |
968 |
|
969 |
static void |
970 |
fbsd_thread_mourn_inferior (struct target_ops *ops) |
971 |
{ |
972 |
struct target_ops *beneath = find_target_beneath (ops); |
973 |
|
974 |
fbsd_thread_deactivate (); |
975 |
|
976 |
beneath->to_mourn_inferior (beneath); |
977 |
|
978 |
/* Delete thread event breakpoints, if any. */ |
979 |
remove_thread_event_breakpoints (); |
980 |
|
981 |
unpush_target (ops); |
982 |
} |
983 |
|
984 |
static void |
985 |
fbsd_core_check_lwp (bfd *abfd, asection *asect, void *obj) |
986 |
{ |
987 |
lwpid_t lwp; |
988 |
|
989 |
if (strncmp (bfd_section_name (abfd, asect), ".reg/", 5) != 0) |
990 |
return; |
991 |
|
992 |
/* already found */ |
993 |
if (*(lwpid_t *)obj == 0) |
994 |
return; |
995 |
|
996 |
lwp = atoi (bfd_section_name (abfd, asect) + 5); |
997 |
if (*(lwpid_t *)obj == lwp) |
998 |
*(lwpid_t *)obj = 0; |
999 |
} |
1000 |
|
1001 |
static int |
1002 |
fbsd_thread_alive (struct target_ops *ops, ptid_t ptid) |
1003 |
{ |
1004 |
td_thrhandle_t th; |
1005 |
td_thrinfo_t ti; |
1006 |
td_err_e err; |
1007 |
gregset_t gregs; |
1008 |
lwpid_t lwp; |
1009 |
|
1010 |
if (IS_THREAD (ptid)) |
1011 |
{ |
1012 |
err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (ptid), &th); |
1013 |
if (err != TD_OK) |
1014 |
return 0; |
1015 |
|
1016 |
err = td_thr_get_info_p (&th, &ti); |
1017 |
if (err != TD_OK) |
1018 |
return 0; |
1019 |
|
1020 |
/* A zombie thread. */ |
1021 |
if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE) |
1022 |
return 0; |
1023 |
|
1024 |
return 1; |
1025 |
} |
1026 |
else if (GET_LWP (ptid) == 0) |
1027 |
{ |
1028 |
/* we sometimes are called with lwp == 0 */ |
1029 |
return 1; |
1030 |
} |
1031 |
|
1032 |
if (fbsd_thread_active) |
1033 |
{ |
1034 |
err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), &th); |
1035 |
|
1036 |
/* |
1037 |
* if the lwp was already mapped to user thread, don't use it |
1038 |
* directly, please use user thread id instead. |
1039 |
*/ |
1040 |
if (err == TD_OK) |
1041 |
return 0; |
1042 |
} |
1043 |
|
1044 |
if (!target_has_execution) |
1045 |
{ |
1046 |
lwp = GET_LWP (ptid); |
1047 |
bfd_map_over_sections (core_bfd, fbsd_core_check_lwp, &lwp); |
1048 |
return (lwp == 0); |
1049 |
} |
1050 |
|
1051 |
/* check lwp in kernel */ |
1052 |
return ptrace (PT_GETREGS, GET_LWP (ptid), (caddr_t)&gregs, 0) == 0; |
1053 |
} |
1054 |
|
1055 |
static int |
1056 |
update_thread_list_callback (const td_thrhandle_t *th_p, void *data) |
1057 |
{ |
1058 |
td_thrinfo_t ti; |
1059 |
td_err_e err; |
1060 |
ptid_t ptid; |
1061 |
|
1062 |
err = td_thr_get_info_p (th_p, &ti); |
1063 |
if (err != TD_OK) |
1064 |
error ("Cannot get thread info: %s", thread_db_err_str (err)); |
1065 |
|
1066 |
/* Ignore zombie */ |
1067 |
if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE) |
1068 |
return 0; |
1069 |
|
1070 |
ptid = BUILD_THREAD (ti.ti_tid, proc_handle.pid); |
1071 |
attach_thread (ptid, th_p, &ti, 1); |
1072 |
return 0; |
1073 |
} |
1074 |
|
1075 |
static void |
1076 |
fbsd_thread_update_thread_list (struct target_ops *ops) |
1077 |
{ |
1078 |
td_err_e err; |
1079 |
|
1080 |
/* Delete dead threads. */ |
1081 |
prune_threads(); |
1082 |
|
1083 |
/* Iterate over all user-space threads to discover new threads. */ |
1084 |
err = td_ta_thr_iter_p (thread_agent, update_thread_list_callback, NULL, |
1085 |
TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, |
1086 |
TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS); |
1087 |
if (err != TD_OK) |
1088 |
error ("Cannot find new threads: %s", thread_db_err_str (err)); |
1089 |
} |
1090 |
|
1091 |
static void |
1092 |
fbsd_find_lwp_name(long lwpid, struct private_thread_info *info) |
1093 |
{ |
1094 |
struct cleanup *old_chain; |
1095 |
int error, name[4]; |
1096 |
unsigned int i; |
1097 |
struct kinfo_proc *kipp, *kip; |
1098 |
char *lwpstr = info->lwp_name; |
1099 |
int pid = inferior_ptid.pid; |
1100 |
size_t len = 0; |
1101 |
|
1102 |
if (!target_has_execution) |
1103 |
return; |
1104 |
|
1105 |
name[0] = CTL_KERN; |
1106 |
name[1] = KERN_PROC; |
1107 |
name[2] = KERN_PROC_PID | KERN_PROC_INC_THREAD; |
1108 |
name[3] = pid; |
1109 |
|
1110 |
error = sysctl(name, 4, NULL, &len, NULL, 0); |
1111 |
if (error < 0) { |
1112 |
if (errno != ESRCH) |
1113 |
warning (_("sysctl: kern.proc.pid: %d: %s"), pid, |
1114 |
safe_strerror (errno)); |
1115 |
return; |
1116 |
} |
1117 |
|
1118 |
kip = xmalloc(len); |
1119 |
if (kip == NULL) |
1120 |
return; |
1121 |
old_chain = make_cleanup(xfree, kip); |
1122 |
|
1123 |
if (sysctl(name, 4, kip, &len, NULL, 0) < 0) { |
1124 |
warning (_("sysctl: kern.proc.pid: %d: %s"), pid, safe_strerror(errno)); |
1125 |
do_cleanups(old_chain); |
1126 |
return; |
1127 |
} |
1128 |
|
1129 |
for (i = 0; i < len / sizeof(*kipp); i++) { |
1130 |
kipp = &kip[i]; |
1131 |
if ((kipp->ki_tid == lwpid) && strlen(kipp->ki_ocomm) && |
1132 |
(strcmp(kipp->ki_comm, kipp->ki_ocomm) != 0)) |
1133 |
{ |
1134 |
// Found the LWP, update the name field |
1135 |
if (lwpstr != NULL) |
1136 |
{ |
1137 |
if (strcmp(lwpstr, kipp->ki_ocomm) != 0) |
1138 |
{ |
1139 |
xfree(lwpstr); |
1140 |
} |
1141 |
else |
1142 |
{ |
1143 |
// Name hasn't changed, just return |
1144 |
break; |
1145 |
} |
1146 |
} |
1147 |
|
1148 |
lwpstr = xstrdup(kipp->ki_ocomm); |
1149 |
info->lwp_name = lwpstr; |
1150 |
break; |
1151 |
} |
1152 |
} |
1153 |
|
1154 |
do_cleanups(old_chain); |
1155 |
} |
1156 |
|
1157 |
static char * |
1158 |
fbsd_thread_pid_to_str (struct target_ops *ops, ptid_t ptid) |
1159 |
{ |
1160 |
static char buf[64]; |
1161 |
struct thread_info *tinfo = NULL; |
1162 |
|
1163 |
if (IS_THREAD (ptid)) |
1164 |
{ |
1165 |
td_thrhandle_t th; |
1166 |
td_thrinfo_t ti; |
1167 |
td_err_e err; |
1168 |
|
1169 |
err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (ptid), &th); |
1170 |
if (err != TD_OK) |
1171 |
error ("Cannot find thread, Thread ID=%ld, %s", |
1172 |
GET_THREAD (ptid), thread_db_err_str (err)); |
1173 |
|
1174 |
err = td_thr_get_info_p (&th, &ti); |
1175 |
if (err != TD_OK) |
1176 |
error ("Cannot get thread info, Thread ID=%ld, %s", |
1177 |
GET_THREAD (ptid), thread_db_err_str (err)); |
1178 |
|
1179 |
tinfo = find_thread_ptid(ptid); |
1180 |
gdb_assert(tinfo != NULL); |
1181 |
|
1182 |
if (ti.ti_lid != 0) |
1183 |
{ |
1184 |
// Need to find the name of this LWP, even though it shouldn't change |
1185 |
fbsd_find_lwp_name(ti.ti_lid, tinfo->priv); |
1186 |
|
1187 |
if (tinfo->priv->lwp_name == NULL) |
1188 |
{ |
1189 |
snprintf(buf, sizeof (buf), "Thread %llx (LWP %d)", |
1190 |
(unsigned long long)th.th_thread, ti.ti_lid); |
1191 |
} |
1192 |
else |
1193 |
{ |
1194 |
snprintf(buf, sizeof (buf), "Thread %llx (LWP %d %s)", |
1195 |
(unsigned long long)th.th_thread, ti.ti_lid, |
1196 |
tinfo->priv->lwp_name); |
1197 |
} |
1198 |
} |
1199 |
else |
1200 |
{ |
1201 |
snprintf (buf, sizeof (buf), "Thread %llx (%s)", |
1202 |
(unsigned long long)th.th_thread, |
1203 |
thread_db_state_str (ti.ti_state)); |
1204 |
} |
1205 |
|
1206 |
return buf; |
1207 |
} |
1208 |
else if (IS_LWP (ptid)) |
1209 |
{ |
1210 |
snprintf (buf, sizeof (buf), "LWP %d", (int) GET_LWP (ptid)); |
1211 |
return buf; |
1212 |
} |
1213 |
return normal_pid_to_str (ptid); |
1214 |
} |
1215 |
|
1216 |
CORE_ADDR |
1217 |
fbsd_thread_get_local_address(struct target_ops *ops, |
1218 |
ptid_t ptid, |
1219 |
CORE_ADDR lm, |
1220 |
CORE_ADDR offset) |
1221 |
{ |
1222 |
td_thrhandle_t th; |
1223 |
void *address; |
1224 |
int ret; |
1225 |
|
1226 |
if (IS_THREAD (ptid)) |
1227 |
{ |
1228 |
if (!td_thr_tls_get_addr_p) |
1229 |
error ("Cannot find thread-local interface in thread_db library."); |
1230 |
|
1231 |
ret = td_ta_map_id2thr_p (thread_agent, GET_THREAD(ptid), &th); |
1232 |
|
1233 |
/* get the address of the variable. */ |
1234 |
ret = td_thr_tls_get_addr_p (&th, (void *)lm, offset, &address); |
1235 |
|
1236 |
if (ret != TD_OK) |
1237 |
{ |
1238 |
error ("Cannot find thread-local storage for thread %ld\n%s", |
1239 |
(long) GET_THREAD (ptid), thread_db_err_str (ret)); |
1240 |
} |
1241 |
|
1242 |
/* Cast assuming host == target. */ |
1243 |
return extract_data_ptr (&address); |
1244 |
} |
1245 |
return (0); |
1246 |
} |
1247 |
|
1248 |
static int |
1249 |
tsd_cb (thread_key_t key, void (*destructor)(void *), void *ignore) |
1250 |
{ |
1251 |
struct bound_minimal_symbol bms; |
1252 |
const char *name; |
1253 |
|
1254 |
bms = lookup_minimal_symbol_by_pc (extract_func_ptr (&destructor)); |
1255 |
if (!bms.minsym) |
1256 |
name = "???"; |
1257 |
else |
1258 |
name = MSYMBOL_PRINT_NAME (bms.minsym); |
1259 |
|
1260 |
printf_filtered ("Key %d, destructor %p <%s>\n", key, destructor, name); |
1261 |
return 0; |
1262 |
} |
1263 |
|
1264 |
static void |
1265 |
fbsd_thread_tsd_cmd (char *exp, int from_tty) |
1266 |
{ |
1267 |
if (fbsd_thread_active) |
1268 |
td_ta_tsd_iter_p (thread_agent, tsd_cb, NULL); |
1269 |
} |
1270 |
|
1271 |
static void |
1272 |
fbsd_print_sigset (sigset_t *set) |
1273 |
{ |
1274 |
int i; |
1275 |
|
1276 |
for (i = 1; i <= _SIG_MAXSIG; ++i) { |
1277 |
if (sigismember(set, i)) { |
1278 |
if (i < sizeof(sys_signame)/sizeof(sys_signame[0])) |
1279 |
printf_filtered("%s ", sys_signame[i]); |
1280 |
else |
1281 |
printf_filtered("sig%d ", i); |
1282 |
} |
1283 |
} |
1284 |
printf_filtered("\n"); |
1285 |
} |
1286 |
|
1287 |
static void |
1288 |
fbsd_thread_signal_cmd (char *exp, int from_tty) |
1289 |
{ |
1290 |
td_thrhandle_t th; |
1291 |
td_thrinfo_t ti; |
1292 |
td_err_e err; |
1293 |
#ifdef PL_FLAG_SI |
1294 |
const char *code; |
1295 |
#endif |
1296 |
|
1297 |
if (!fbsd_thread_active || !IS_THREAD(inferior_ptid)) |
1298 |
return; |
1299 |
|
1300 |
err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (inferior_ptid), &th); |
1301 |
if (err != TD_OK) |
1302 |
return; |
1303 |
|
1304 |
err = td_thr_get_info_p (&th, &ti); |
1305 |
if (err != TD_OK) |
1306 |
return; |
1307 |
|
1308 |
printf_filtered("signal mask:\n"); |
1309 |
fbsd_print_sigset(&ti.ti_sigmask); |
1310 |
printf_filtered("signal pending:\n"); |
1311 |
fbsd_print_sigset(&ti.ti_pending); |
1312 |
#ifdef PL_FLAG_SI |
1313 |
if (ti.ti_siginfo.si_signo != 0) { |
1314 |
printf_filtered("si_signo %d si_errno %d", ti.ti_siginfo.si_signo, |
1315 |
ti.ti_siginfo.si_errno); |
1316 |
if (ti.ti_siginfo.si_errno != 0) |
1317 |
printf_filtered(" (%s)", strerror(ti.ti_siginfo.si_errno)); |
1318 |
printf_filtered("\n"); |
1319 |
switch (ti.ti_siginfo.si_code) { |
1320 |
case SI_NOINFO: |
1321 |
code = "NOINFO"; |
1322 |
break; |
1323 |
case SI_USER: |
1324 |
code = "USER"; |
1325 |
break; |
1326 |
case SI_QUEUE: |
1327 |
code = "QUEUE"; |
1328 |
break; |
1329 |
case SI_TIMER: |
1330 |
code = "TIMER"; |
1331 |
break; |
1332 |
case SI_ASYNCIO: |
1333 |
code = "ASYNCIO"; |
1334 |
break; |
1335 |
case SI_MESGQ: |
1336 |
code = "MESGQ"; |
1337 |
break; |
1338 |
case SI_KERNEL: |
1339 |
code = "KERNEL"; |
1340 |
break; |
1341 |
default: |
1342 |
code = "UNKNOWN"; |
1343 |
break; |
1344 |
} |
1345 |
printf_filtered("si_code %s si_pid %d si_uid %d si_status %x si_addr %p\n", |
1346 |
code, ti.ti_siginfo.si_pid, ti.ti_siginfo.si_uid, ti.ti_siginfo.si_status, |
1347 |
ti.ti_siginfo.si_addr); |
1348 |
} |
1349 |
#endif |
1350 |
} |
1351 |
|
1352 |
static void |
1353 |
init_fbsd_thread_ops (void) |
1354 |
{ |
1355 |
fbsd_thread_ops.to_shortname = "freebsd-threads"; |
1356 |
fbsd_thread_ops.to_longname = "FreeBSD multithreaded child process."; |
1357 |
fbsd_thread_ops.to_doc = "FreeBSD threads support."; |
1358 |
fbsd_thread_ops.to_detach = fbsd_thread_detach; |
1359 |
fbsd_thread_ops.to_resume = fbsd_thread_resume; |
1360 |
fbsd_thread_ops.to_wait = fbsd_thread_wait; |
1361 |
fbsd_thread_ops.to_fetch_registers = fbsd_thread_fetch_registers; |
1362 |
fbsd_thread_ops.to_store_registers = fbsd_thread_store_registers; |
1363 |
fbsd_thread_ops.to_mourn_inferior = fbsd_thread_mourn_inferior; |
1364 |
fbsd_thread_ops.to_thread_alive = fbsd_thread_alive; |
1365 |
fbsd_thread_ops.to_update_thread_list = fbsd_thread_update_thread_list; |
1366 |
fbsd_thread_ops.to_pid_to_str = fbsd_thread_pid_to_str; |
1367 |
fbsd_thread_ops.to_stratum = thread_stratum; |
1368 |
fbsd_thread_ops.to_get_thread_local_address = fbsd_thread_get_local_address; |
1369 |
fbsd_thread_ops.to_magic = OPS_MAGIC; |
1370 |
} |
1371 |
|
1372 |
static int |
1373 |
thread_db_load (void) |
1374 |
{ |
1375 |
void *handle; |
1376 |
td_err_e err; |
1377 |
|
1378 |
handle = dlopen (LIBTHREAD_DB_SO, RTLD_NOW); |
1379 |
if (handle == NULL) |
1380 |
return 0; |
1381 |
|
1382 |
#define resolve(X) \ |
1383 |
if (!(X##_p = dlsym (handle, #X))) \ |
1384 |
return 0; |
1385 |
|
1386 |
resolve(td_init); |
1387 |
resolve(td_ta_new); |
1388 |
resolve(td_ta_delete); |
1389 |
resolve(td_ta_map_id2thr); |
1390 |
resolve(td_ta_map_lwp2thr); |
1391 |
resolve(td_ta_thr_iter); |
1392 |
resolve(td_thr_get_info); |
1393 |
#ifdef PT_GETXMMREGS |
1394 |
resolve(td_thr_getxmmregs); |
1395 |
#endif |
1396 |
resolve(td_thr_getfpregs); |
1397 |
resolve(td_thr_getgregs); |
1398 |
#ifdef PT_GETXMMREGS |
1399 |
resolve(td_thr_setxmmregs); |
1400 |
#endif |
1401 |
resolve(td_thr_setfpregs); |
1402 |
resolve(td_thr_setgregs); |
1403 |
resolve(td_thr_sstep); |
1404 |
resolve(td_ta_tsd_iter); |
1405 |
resolve(td_thr_dbsuspend); |
1406 |
resolve(td_thr_dbresume); |
1407 |
resolve(td_thr_tls_get_addr); |
1408 |
|
1409 |
/* These are not essential. */ |
1410 |
td_ta_event_addr_p = dlsym (handle, "td_ta_event_addr"); |
1411 |
td_ta_set_event_p = dlsym (handle, "td_ta_set_event"); |
1412 |
td_ta_event_getmsg_p = dlsym (handle, "td_ta_event_getmsg"); |
1413 |
td_thr_event_enable_p = dlsym (handle, "td_thr_event_enable"); |
1414 |
td_thr_tls_get_addr_p = dlsym (handle, "td_thr_tls_get_addr"); |
1415 |
|
1416 |
return 1; |
1417 |
} |
1418 |
|
1419 |
void |
1420 |
_initialize_thread_db (void) |
1421 |
{ |
1422 |
|
1423 |
init_fbsd_thread_ops (); |
1424 |
|
1425 |
if (thread_db_load ()) |
1426 |
{ |
1427 |
add_target (&fbsd_thread_ops); |
1428 |
|
1429 |
/* "thread tsd" command */ |
1430 |
add_cmd ("tsd", class_run, fbsd_thread_tsd_cmd, |
1431 |
"Show the thread-specific data keys and destructors " |
1432 |
"for the process.\n", |
1433 |
&thread_cmd_list); |
1434 |
|
1435 |
add_cmd ("signal", class_run, fbsd_thread_signal_cmd, |
1436 |
"Show the thread signal info.\n", |
1437 |
&thread_cmd_list); |
1438 |
|
1439 |
/* Hook into new_objfile notification. */ |
1440 |
observer_attach_new_objfile (fbsd_thread_new_objfile); |
1441 |
} |
1442 |
else |
1443 |
{ |
1444 |
fprintf_unfiltered (gdb_stderr, |
1445 |
"[GDB will not be able to debug user-mode threads: %s]\n", dlerror()); |
1446 |
} |
1447 |
} |
1448 |
|
1449 |
/* proc service functions */ |
1450 |
void |
1451 |
ps_plog (const char *fmt, ...) |
1452 |
{ |
1453 |
va_list args; |
1454 |
|
1455 |
va_start (args, fmt); |
1456 |
vfprintf_filtered (gdb_stderr, fmt, args); |
1457 |
va_end (args); |
1458 |
} |
1459 |
|
1460 |
ps_err_e |
1461 |
ps_pglobal_lookup (struct ps_prochandle *ph, const char *obj, |
1462 |
const char *name, psaddr_t *sym_addr) |
1463 |
{ |
1464 |
struct bound_minimal_symbol ms; |
1465 |
CORE_ADDR addr; |
1466 |
|
1467 |
ms = lookup_minimal_symbol (name, NULL, NULL); |
1468 |
if (!ms.minsym) |
1469 |
return PS_NOSYM; |
1470 |
|
1471 |
*sym_addr = BMSYMBOL_VALUE_ADDRESS (ms); |
1472 |
return PS_OK; |
1473 |
} |
1474 |
|
1475 |
ps_err_e |
1476 |
ps_pread (struct ps_prochandle *ph, psaddr_t addr, void *buf, size_t len) |
1477 |
{ |
1478 |
int err = target_read_memory (extract_data_ptr (&addr), buf, len); |
1479 |
return (err == 0 ? PS_OK : PS_ERR); |
1480 |
} |
1481 |
|
1482 |
ps_err_e |
1483 |
ps_pwrite (struct ps_prochandle *ph, psaddr_t addr, const void *buf, |
1484 |
size_t len) |
1485 |
{ |
1486 |
int err = target_write_memory (extract_data_ptr (&addr), (void *)buf, len); |
1487 |
return (err == 0 ? PS_OK : PS_ERR); |
1488 |
} |
1489 |
|
1490 |
ps_err_e |
1491 |
ps_lgetregs (struct ps_prochandle *ph, lwpid_t lwpid, prgregset_t gregset) |
1492 |
{ |
1493 |
struct cleanup *old_chain; |
1494 |
struct regcache *regcache; |
1495 |
|
1496 |
old_chain = save_inferior_ptid (); |
1497 |
|
1498 |
inferior_ptid = BUILD_LWP (lwpid, ph->pid); |
1499 |
regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch ()); |
1500 |
|
1501 |
target_fetch_registers (regcache, -1); |
1502 |
fill_gregset (regcache, gregset, -1); |
1503 |
do_cleanups (old_chain); |
1504 |
return PS_OK; |
1505 |
} |
1506 |
|
1507 |
ps_err_e |
1508 |
ps_lsetregs (struct ps_prochandle *ph, lwpid_t lwpid, const prgregset_t gregset) |
1509 |
{ |
1510 |
struct cleanup *old_chain; |
1511 |
struct regcache *regcache; |
1512 |
|
1513 |
old_chain = save_inferior_ptid (); |
1514 |
inferior_ptid = BUILD_LWP (lwpid, ph->pid); |
1515 |
regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch ()); |
1516 |
|
1517 |
supply_gregset (regcache, gregset); |
1518 |
target_store_registers (regcache, -1); |
1519 |
do_cleanups (old_chain); |
1520 |
return PS_OK; |
1521 |
} |
1522 |
|
1523 |
ps_err_e |
1524 |
ps_lgetfpregs (struct ps_prochandle *ph, lwpid_t lwpid, prfpregset_t *fpregset) |
1525 |
{ |
1526 |
struct cleanup *old_chain; |
1527 |
struct regcache *regcache; |
1528 |
|
1529 |
old_chain = save_inferior_ptid (); |
1530 |
inferior_ptid = BUILD_LWP (lwpid, ph->pid); |
1531 |
regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch ()); |
1532 |
|
1533 |
target_fetch_registers (regcache, -1); |
1534 |
fill_fpregset (regcache, fpregset, -1); |
1535 |
do_cleanups (old_chain); |
1536 |
return PS_OK; |
1537 |
} |
1538 |
|
1539 |
ps_err_e |
1540 |
ps_lsetfpregs (struct ps_prochandle *ph, lwpid_t lwpid, |
1541 |
const prfpregset_t *fpregset) |
1542 |
{ |
1543 |
struct cleanup *old_chain; |
1544 |
struct regcache *regcache; |
1545 |
|
1546 |
old_chain = save_inferior_ptid (); |
1547 |
inferior_ptid = BUILD_LWP (lwpid, ph->pid); |
1548 |
regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch ()); |
1549 |
|
1550 |
supply_fpregset (regcache, fpregset); |
1551 |
target_store_registers (regcache, -1); |
1552 |
do_cleanups (old_chain); |
1553 |
return PS_OK; |
1554 |
} |
1555 |
|
1556 |
#ifdef PT_GETXMMREGS |
1557 |
ps_err_e |
1558 |
ps_lgetxmmregs (struct ps_prochandle *ph, lwpid_t lwpid, char *xmmregs) |
1559 |
{ |
1560 |
struct cleanup *old_chain; |
1561 |
struct regcache *regcache; |
1562 |
|
1563 |
old_chain = save_inferior_ptid (); |
1564 |
inferior_ptid = BUILD_LWP (lwpid, ph->pid); |
1565 |
regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch ()); |
1566 |
|
1567 |
target_fetch_registers (regcache, -1); |
1568 |
i387_collect_fxsave (regcache, -1, xmmregs); |
1569 |
do_cleanups (old_chain); |
1570 |
return PS_OK; |
1571 |
} |
1572 |
|
1573 |
ps_err_e |
1574 |
ps_lsetxmmregs (struct ps_prochandle *ph, lwpid_t lwpid, |
1575 |
const char *xmmregs) |
1576 |
{ |
1577 |
struct cleanup *old_chain; |
1578 |
struct regcache *regcache; |
1579 |
|
1580 |
old_chain = save_inferior_ptid (); |
1581 |
inferior_ptid = BUILD_LWP (lwpid, ph->pid); |
1582 |
regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch ()); |
1583 |
|
1584 |
i387_supply_fxsave (regcache, -1, xmmregs); |
1585 |
target_store_registers (regcache, -1); |
1586 |
do_cleanups (old_chain); |
1587 |
return PS_OK; |
1588 |
} |
1589 |
#endif |
1590 |
|
1591 |
ps_err_e |
1592 |
ps_lstop(struct ps_prochandle *ph, lwpid_t lwpid) |
1593 |
{ |
1594 |
if (ptrace (PT_SUSPEND, lwpid, 0, 0) == -1) |
1595 |
return PS_ERR; |
1596 |
return PS_OK; |
1597 |
} |
1598 |
|
1599 |
ps_err_e |
1600 |
ps_lcontinue(struct ps_prochandle *ph, lwpid_t lwpid) |
1601 |
{ |
1602 |
if (ptrace (PT_RESUME, lwpid, 0, 0) == -1) |
1603 |
return PS_ERR; |
1604 |
return PS_OK; |
1605 |
} |
1606 |
|
1607 |
ps_err_e |
1608 |
ps_linfo(struct ps_prochandle *ph, lwpid_t lwpid, void *info) |
1609 |
{ |
1610 |
if (!target_has_execution) { |
1611 |
/* XXX should verify lwpid and make a pseudo lwp info */ |
1612 |
memset(info, 0, sizeof(struct ptrace_lwpinfo)); |
1613 |
return PS_OK; |
1614 |
} |
1615 |
|
1616 |
if (ptrace (PT_LWPINFO, lwpid, info, sizeof(struct ptrace_lwpinfo)) == -1) |
1617 |
return PS_ERR; |
1618 |
return PS_OK; |
1619 |
} |