1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2004 David Xu <[email protected]>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 #include <stddef.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <unistd.h>
36 #include <pthread.h>
37 #include <sys/types.h>
38 #include <sys/linker_set.h>
39 #include <sys/ptrace.h>
40 #include <proc_service.h>
41 #include <thread_db.h>
42
43 #include "libpthread_db.h"
44 #include "kse.h"
45
46 #define P2T(c) ps2td(c)
47
48 static void pt_unmap_lwp(const td_thragent_t *ta, lwpid_t lwp);
49 static int pt_validate(const td_thrhandle_t *th);
50
51 static int
ps2td(int c)52 ps2td(int c)
53 {
54 switch (c) {
55 case PS_OK:
56 return TD_OK;
57 case PS_ERR:
58 return TD_ERR;
59 case PS_BADPID:
60 return TD_BADPH;
61 case PS_BADLID:
62 return TD_NOLWP;
63 case PS_BADADDR:
64 return TD_ERR;
65 case PS_NOSYM:
66 return TD_NOLIBTHREAD;
67 case PS_NOFREGS:
68 return TD_NOFPREGS;
69 default:
70 return TD_ERR;
71 }
72 }
73
74 static long
pt_map_thread(const td_thragent_t * const_ta,psaddr_t pt,enum pt_type type)75 pt_map_thread(const td_thragent_t *const_ta, psaddr_t pt, enum pt_type type)
76 {
77 td_thragent_t *ta = __DECONST(td_thragent_t *, const_ta);
78 struct pt_map *new;
79 int first = -1;
80 unsigned int i;
81
82 /* leave zero out */
83 for (i = 1; i < ta->map_len; ++i) {
84 if (ta->map[i].type == PT_NONE) {
85 if (first == -1)
86 first = i;
87 } else if (ta->map[i].type == type && ta->map[i].thr == pt) {
88 return (i);
89 }
90 }
91
92 if (first == -1) {
93 if (ta->map_len == 0) {
94 ta->map = calloc(20, sizeof(struct pt_map));
95 if (ta->map == NULL)
96 return (-1);
97 ta->map_len = 20;
98 first = 1;
99 } else {
100 new = reallocarray(ta->map, ta->map_len,
101 2 * sizeof(struct pt_map));
102 if (new == NULL)
103 return (-1);
104 memset(new + ta->map_len, '\0', ta->map_len *
105 sizeof(struct pt_map));
106 first = ta->map_len;
107 ta->map = new;
108 ta->map_len *= 2;
109 }
110 }
111
112 ta->map[first].type = type;
113 ta->map[first].thr = pt;
114 return (first);
115 }
116
117 static td_err_e
pt_init(void)118 pt_init(void)
119 {
120 pt_md_init();
121 return (0);
122 }
123
124 static td_err_e
pt_ta_new(struct ps_prochandle * ph,td_thragent_t ** pta)125 pt_ta_new(struct ps_prochandle *ph, td_thragent_t **pta)
126 {
127 #define LOOKUP_SYM(proc, sym, addr) \
128 ret = ps_pglobal_lookup(proc, NULL, sym, addr); \
129 if (ret != 0) { \
130 TDBG("can not find symbol: %s\n", sym); \
131 ret = TD_NOLIBTHREAD; \
132 goto error; \
133 }
134
135 #define LOOKUP_VAL(proc, sym, val) \
136 ret = ps_pglobal_lookup(proc, NULL, sym, &vaddr);\
137 if (ret != 0) { \
138 TDBG("can not find symbol: %s\n", sym); \
139 ret = TD_NOLIBTHREAD; \
140 goto error; \
141 } \
142 ret = ps_pread(proc, vaddr, val, sizeof(int)); \
143 if (ret != 0) { \
144 TDBG("can not read value of %s\n", sym);\
145 ret = TD_NOLIBTHREAD; \
146 goto error; \
147 }
148
149 td_thragent_t *ta;
150 psaddr_t vaddr;
151 int dbg;
152 int ret;
153
154 TDBG_FUNC();
155
156 ta = malloc(sizeof(td_thragent_t));
157 if (ta == NULL)
158 return (TD_MALLOC);
159
160 ta->ph = ph;
161 ta->thread_activated = 0;
162 ta->map = NULL;
163 ta->map_len = 0;
164
165 LOOKUP_SYM(ph, "_libkse_debug", &ta->libkse_debug_addr);
166 LOOKUP_SYM(ph, "_thread_list", &ta->thread_list_addr);
167 LOOKUP_SYM(ph, "_thread_activated", &ta->thread_activated_addr);
168 LOOKUP_SYM(ph, "_thread_active_threads",&ta->thread_active_threads_addr);
169 LOOKUP_SYM(ph, "_thread_keytable", &ta->thread_keytable_addr);
170 LOOKUP_VAL(ph, "_thread_off_dtv", &ta->thread_off_dtv);
171 LOOKUP_VAL(ph, "_thread_off_kse_locklevel", &ta->thread_off_kse_locklevel);
172 LOOKUP_VAL(ph, "_thread_off_kse", &ta->thread_off_kse);
173 LOOKUP_VAL(ph, "_thread_off_tlsindex", &ta->thread_off_tlsindex);
174 LOOKUP_VAL(ph, "_thread_off_attr_flags", &ta->thread_off_attr_flags);
175 LOOKUP_VAL(ph, "_thread_size_key", &ta->thread_size_key);
176 LOOKUP_VAL(ph, "_thread_off_tcb", &ta->thread_off_tcb);
177 LOOKUP_VAL(ph, "_thread_off_linkmap", &ta->thread_off_linkmap);
178 LOOKUP_VAL(ph, "_thread_off_tmbx", &ta->thread_off_tmbx);
179 LOOKUP_VAL(ph, "_thread_off_thr_locklevel", &ta->thread_off_thr_locklevel);
180 LOOKUP_VAL(ph, "_thread_off_next", &ta->thread_off_next);
181 LOOKUP_VAL(ph, "_thread_off_state", &ta->thread_off_state);
182 LOOKUP_VAL(ph, "_thread_max_keys", &ta->thread_max_keys);
183 LOOKUP_VAL(ph, "_thread_off_key_allocated", &ta->thread_off_key_allocated);
184 LOOKUP_VAL(ph, "_thread_off_key_destructor", &ta->thread_off_key_destructor);
185 LOOKUP_VAL(ph, "_thread_state_running", &ta->thread_state_running);
186 LOOKUP_VAL(ph, "_thread_state_zoombie", &ta->thread_state_zoombie);
187 LOOKUP_VAL(ph, "_thread_off_sigmask", &ta->thread_off_sigmask);
188 LOOKUP_VAL(ph, "_thread_off_sigpend", &ta->thread_off_sigpend);
189 dbg = getpid();
190 /*
191 * If this fails it probably means we're debugging a core file and
192 * can't write to it.
193 */
194 ps_pwrite(ph, ta->libkse_debug_addr, &dbg, sizeof(int));
195 *pta = ta;
196 return (0);
197
198 error:
199 free(ta);
200 return (ret);
201 }
202
203 static td_err_e
pt_ta_delete(td_thragent_t * ta)204 pt_ta_delete(td_thragent_t *ta)
205 {
206 int dbg;
207
208 TDBG_FUNC();
209
210 dbg = 0;
211 /*
212 * Error returns from this write are not really a problem;
213 * the process doesn't exist any more.
214 */
215 ps_pwrite(ta->ph, ta->libkse_debug_addr, &dbg, sizeof(int));
216 if (ta->map)
217 free(ta->map);
218 free(ta);
219 return (TD_OK);
220 }
221
222 static td_err_e
pt_ta_map_id2thr(const td_thragent_t * ta,thread_t id,td_thrhandle_t * th)223 pt_ta_map_id2thr(const td_thragent_t *ta, thread_t id, td_thrhandle_t *th)
224 {
225 prgregset_t gregs;
226 psaddr_t pt, tcb_addr;
227 lwpid_t lwp;
228 int ret;
229
230 TDBG_FUNC();
231
232 if (id < 0 || id >= (long)ta->map_len || ta->map[id].type == PT_NONE)
233 return (TD_NOTHR);
234
235 ret = thr_pread_ptr(ta, ta->thread_list_addr, &pt);
236 if (ret != 0)
237 return (TD_ERR);
238 if (ta->map[id].type == PT_LWP) {
239 /*
240 * if we are referencing a lwp, make sure it was not already
241 * mapped to user thread.
242 */
243 while (pt != 0) {
244 ret = thr_pread_ptr(ta, pt + ta->thread_off_tcb,
245 &tcb_addr);
246 if (ret != 0)
247 return (TD_ERR);
248 ret = thr_pread_int(ta, tcb_addr + ta->thread_off_tmbx +
249 offsetof(struct kse_thr_mailbox, tm_lwp), &lwp);
250 if (ret != 0)
251 return (TD_ERR);
252 /*
253 * If the lwp was already mapped to userland thread,
254 * we shouldn't reference it directly in future.
255 */
256 if (lwp == ta->map[id].lwp) {
257 ta->map[id].type = PT_NONE;
258 return (TD_NOTHR);
259 }
260 /* get next thread */
261 ret = thr_pread_ptr(ta, pt + ta->thread_off_next, &pt);
262 if (ret != 0)
263 return (TD_ERR);
264 }
265 /* check lwp */
266 ret = ps_lgetregs(ta->ph, ta->map[id].lwp, gregs);
267 if (ret != PS_OK) {
268 /* no longer exists */
269 ta->map[id].type = PT_NONE;
270 return (TD_NOTHR);
271 }
272 } else {
273 while (pt != 0 && ta->map[id].thr != pt) {
274 ret = thr_pread_ptr(ta, pt + ta->thread_off_tcb,
275 &tcb_addr);
276 if (ret != 0)
277 return (TD_ERR);
278 /* get next thread */
279 ret = thr_pread_ptr(ta, pt + ta->thread_off_next, &pt);
280 if (ret != 0)
281 return (TD_ERR);
282 }
283
284 if (pt == 0) {
285 /* no longer exists */
286 ta->map[id].type = PT_NONE;
287 return (TD_NOTHR);
288 }
289 }
290 th->th_ta = ta;
291 th->th_tid = id;
292 th->th_thread = pt;
293 return (TD_OK);
294 }
295
296 static td_err_e
pt_ta_map_lwp2thr(const td_thragent_t * ta,lwpid_t lwp,td_thrhandle_t * th)297 pt_ta_map_lwp2thr(const td_thragent_t *ta, lwpid_t lwp, td_thrhandle_t *th)
298 {
299 psaddr_t pt, tcb_addr;
300 lwpid_t lwp1;
301 int ret;
302
303 TDBG_FUNC();
304
305 ret = thr_pread_ptr(ta, ta->thread_list_addr, &pt);
306 if (ret != 0)
307 return (TD_ERR);
308 while (pt != 0) {
309 ret = thr_pread_ptr(ta, pt + ta->thread_off_tcb, &tcb_addr);
310 if (ret != 0)
311 return (TD_ERR);
312 ret = thr_pread_int(ta, tcb_addr + ta->thread_off_tmbx +
313 offsetof(struct kse_thr_mailbox, tm_lwp), &lwp1);
314 if (ret != 0)
315 return (TD_ERR);
316 if (lwp1 == lwp) {
317 th->th_ta = ta;
318 th->th_tid = pt_map_thread(ta, pt, PT_USER);
319 if (th->th_tid == -1)
320 return (TD_MALLOC);
321 pt_unmap_lwp(ta, lwp);
322 th->th_thread = pt;
323 return (TD_OK);
324 }
325
326 /* get next thread */
327 ret = thr_pread_ptr(ta, pt + ta->thread_off_next, &pt);
328 if (ret != 0)
329 return (TD_ERR);
330 }
331
332 return (TD_NOTHR);
333 }
334
335 static td_err_e
pt_ta_thr_iter(const td_thragent_t * ta,td_thr_iter_f * callback,void * cbdata_p,td_thr_state_e state __unused,int ti_pri __unused,sigset_t * ti_sigmask_p __unused,unsigned int ti_user_flags __unused)336 pt_ta_thr_iter(const td_thragent_t *ta, td_thr_iter_f *callback,
337 void *cbdata_p, td_thr_state_e state __unused, int ti_pri __unused,
338 sigset_t *ti_sigmask_p __unused, unsigned int ti_user_flags __unused)
339 {
340 td_thrhandle_t th;
341 psaddr_t pt;
342 ps_err_e pserr;
343 int activated, ret;
344
345 TDBG_FUNC();
346
347 pserr = ps_pread(ta->ph, ta->thread_activated_addr, &activated,
348 sizeof(int));
349 if (pserr != PS_OK)
350 return (P2T(pserr));
351 if (!activated)
352 return (TD_OK);
353
354 ret = thr_pread_ptr(ta, ta->thread_list_addr, &pt);
355 if (ret != 0)
356 return (TD_ERR);
357 while (pt != 0) {
358 th.th_ta = ta;
359 th.th_tid = pt_map_thread(ta, pt, PT_USER);
360 th.th_thread = pt;
361 /* should we unmap lwp here ? */
362 if (th.th_tid == -1)
363 return (TD_MALLOC);
364 if ((*callback)(&th, cbdata_p))
365 return (TD_DBERR);
366 /* get next thread */
367 ret = thr_pread_ptr(ta, pt + ta->thread_off_next, &pt);
368 if (ret != 0)
369 return (TD_ERR);
370 }
371 return (TD_OK);
372 }
373
374 static td_err_e
pt_ta_tsd_iter(const td_thragent_t * ta,td_key_iter_f * ki,void * arg)375 pt_ta_tsd_iter(const td_thragent_t *ta, td_key_iter_f *ki, void *arg)
376 {
377 void *keytable;
378 void *destructor;
379 int i, ret, allocated;
380
381 TDBG_FUNC();
382
383 keytable = malloc(ta->thread_max_keys * ta->thread_size_key);
384 if (keytable == NULL)
385 return (TD_MALLOC);
386 ret = ps_pread(ta->ph, (psaddr_t)ta->thread_keytable_addr, keytable,
387 ta->thread_max_keys * ta->thread_size_key);
388 if (ret != 0) {
389 free(keytable);
390 return (P2T(ret));
391 }
392 for (i = 0; i < ta->thread_max_keys; i++) {
393 allocated = *(int *)(void *)((uintptr_t)keytable +
394 i * ta->thread_size_key + ta->thread_off_key_allocated);
395 destructor = *(void **)(void *)((uintptr_t)keytable +
396 i * ta->thread_size_key + ta->thread_off_key_destructor);
397 if (allocated) {
398 ret = (ki)(i, destructor, arg);
399 if (ret != 0) {
400 free(keytable);
401 return (TD_DBERR);
402 }
403 }
404 }
405 free(keytable);
406 return (TD_OK);
407 }
408
409 static td_err_e
pt_ta_event_addr(const td_thragent_t * ta __unused,td_event_e event __unused,td_notify_t * ptr __unused)410 pt_ta_event_addr(const td_thragent_t *ta __unused, td_event_e event __unused,
411 td_notify_t *ptr __unused)
412 {
413 TDBG_FUNC();
414 return (TD_ERR);
415 }
416
417 static td_err_e
pt_ta_set_event(const td_thragent_t * ta __unused,td_thr_events_t * events __unused)418 pt_ta_set_event(const td_thragent_t *ta __unused,
419 td_thr_events_t *events __unused)
420 {
421 TDBG_FUNC();
422 return (0);
423 }
424
425 static td_err_e
pt_ta_clear_event(const td_thragent_t * ta __unused,td_thr_events_t * events __unused)426 pt_ta_clear_event(const td_thragent_t *ta __unused,
427 td_thr_events_t *events __unused)
428 {
429 TDBG_FUNC();
430 return (0);
431 }
432
433 static td_err_e
pt_ta_event_getmsg(const td_thragent_t * ta __unused,td_event_msg_t * msg __unused)434 pt_ta_event_getmsg(const td_thragent_t *ta __unused,
435 td_event_msg_t *msg __unused)
436 {
437 TDBG_FUNC();
438 return (TD_NOMSG);
439 }
440
441 static td_err_e
pt_dbsuspend(const td_thrhandle_t * th,int suspend)442 pt_dbsuspend(const td_thrhandle_t *th, int suspend)
443 {
444 const td_thragent_t *ta = th->th_ta;
445 psaddr_t tcb_addr, tmbx_addr, ptr;
446 lwpid_t lwp;
447 uint32_t dflags;
448 int attrflags, locklevel, ret;
449
450 TDBG_FUNC();
451
452 ret = pt_validate(th);
453 if (ret)
454 return (ret);
455
456 if (ta->map[th->th_tid].type == PT_LWP) {
457 if (suspend)
458 ret = ps_lstop(ta->ph, ta->map[th->th_tid].lwp);
459 else
460 ret = ps_lcontinue(ta->ph, ta->map[th->th_tid].lwp);
461 return (P2T(ret));
462 }
463
464 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr +
465 ta->thread_off_attr_flags,
466 &attrflags, sizeof(attrflags));
467 if (ret != 0)
468 return (P2T(ret));
469 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr +
470 ta->thread_off_tcb,
471 &tcb_addr, sizeof(tcb_addr));
472 if (ret != 0)
473 return (P2T(ret));
474 tmbx_addr = tcb_addr + ta->thread_off_tmbx;
475 ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp);
476 ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t));
477 if (ret != 0)
478 return (P2T(ret));
479
480 if (lwp != 0) {
481 /* don't suspend signal thread */
482 if (attrflags & 0x200)
483 return (0);
484 if (attrflags & PTHREAD_SCOPE_SYSTEM) {
485 /*
486 * don't suspend system scope thread if it is holding
487 * some low level locks
488 */
489 ptr = ta->map[th->th_tid].thr + ta->thread_off_kse;
490 ret = ps_pread(ta->ph, ptr, &ptr, sizeof(ptr));
491 if (ret != 0)
492 return (P2T(ret));
493 ret = ps_pread(ta->ph, ptr + ta->thread_off_kse_locklevel,
494 &locklevel, sizeof(int));
495 if (ret != 0)
496 return (P2T(ret));
497 if (locklevel <= 0) {
498 ptr = ta->map[th->th_tid].thr +
499 ta->thread_off_thr_locklevel;
500 ret = ps_pread(ta->ph, ptr, &locklevel,
501 sizeof(int));
502 if (ret != 0)
503 return (P2T(ret));
504 }
505 if (suspend) {
506 if (locklevel <= 0)
507 ret = ps_lstop(ta->ph, lwp);
508 } else {
509 ret = ps_lcontinue(ta->ph, lwp);
510 }
511 if (ret != 0)
512 return (P2T(ret));
513 /* FALLTHROUGH */
514 } else {
515 struct ptrace_lwpinfo pl;
516
517 if (ps_linfo(ta->ph, lwp, (caddr_t)&pl))
518 return (TD_ERR);
519 if (suspend) {
520 if (!(pl.pl_flags & PL_FLAG_BOUND))
521 ret = ps_lstop(ta->ph, lwp);
522 } else {
523 ret = ps_lcontinue(ta->ph, lwp);
524 }
525 if (ret != 0)
526 return (P2T(ret));
527 /* FALLTHROUGH */
528 }
529 }
530 /* read tm_dflags */
531 ret = ps_pread(ta->ph,
532 tmbx_addr + offsetof(struct kse_thr_mailbox, tm_dflags),
533 &dflags, sizeof(dflags));
534 if (ret != 0)
535 return (P2T(ret));
536 if (suspend)
537 dflags |= TMDF_SUSPEND;
538 else
539 dflags &= ~TMDF_SUSPEND;
540 ret = ps_pwrite(ta->ph,
541 tmbx_addr + offsetof(struct kse_thr_mailbox, tm_dflags),
542 &dflags, sizeof(dflags));
543 return (P2T(ret));
544 }
545
546 static td_err_e
pt_thr_dbresume(const td_thrhandle_t * th)547 pt_thr_dbresume(const td_thrhandle_t *th)
548 {
549 TDBG_FUNC();
550
551 return pt_dbsuspend(th, 0);
552 }
553
554 static td_err_e
pt_thr_dbsuspend(const td_thrhandle_t * th)555 pt_thr_dbsuspend(const td_thrhandle_t *th)
556 {
557 TDBG_FUNC();
558
559 return pt_dbsuspend(th, 1);
560 }
561
562 static td_err_e
pt_thr_validate(const td_thrhandle_t * th)563 pt_thr_validate(const td_thrhandle_t *th)
564 {
565 td_thrhandle_t temp;
566 int ret;
567
568 TDBG_FUNC();
569
570 ret = pt_ta_map_id2thr(th->th_ta, th->th_tid,
571 &temp);
572 return (ret);
573 }
574
575 static td_err_e
pt_thr_old_get_info(const td_thrhandle_t * th,td_old_thrinfo_t * info)576 pt_thr_old_get_info(const td_thrhandle_t *th, td_old_thrinfo_t *info)
577 {
578 const td_thragent_t *ta = th->th_ta;
579 struct ptrace_lwpinfo linfo;
580 psaddr_t tcb_addr;
581 uint32_t dflags;
582 lwpid_t lwp;
583 int state;
584 int ret;
585 int attrflags;
586
587 TDBG_FUNC();
588
589 bzero(info, sizeof(*info));
590 ret = pt_validate(th);
591 if (ret)
592 return (ret);
593
594 memset(info, 0, sizeof(*info));
595 if (ta->map[th->th_tid].type == PT_LWP) {
596 info->ti_type = TD_THR_SYSTEM;
597 info->ti_lid = ta->map[th->th_tid].lwp;
598 info->ti_tid = th->th_tid;
599 info->ti_state = TD_THR_RUN;
600 info->ti_type = TD_THR_SYSTEM;
601 return (TD_OK);
602 }
603
604 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr +
605 ta->thread_off_attr_flags,
606 &attrflags, sizeof(attrflags));
607 if (ret != 0)
608 return (P2T(ret));
609 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + ta->thread_off_tcb,
610 &tcb_addr, sizeof(tcb_addr));
611 if (ret != 0)
612 return (P2T(ret));
613 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + ta->thread_off_state,
614 &state, sizeof(state));
615 ret = ps_pread(ta->ph,
616 tcb_addr + ta->thread_off_tmbx +
617 offsetof(struct kse_thr_mailbox, tm_lwp),
618 &info->ti_lid, sizeof(lwpid_t));
619 if (ret != 0)
620 return (P2T(ret));
621 ret = ps_pread(ta->ph,
622 tcb_addr + ta->thread_off_tmbx +
623 offsetof(struct kse_thr_mailbox, tm_dflags),
624 &dflags, sizeof(dflags));
625 if (ret != 0)
626 return (P2T(ret));
627 ret = ps_pread(ta->ph, tcb_addr + ta->thread_off_tmbx +
628 offsetof(struct kse_thr_mailbox, tm_lwp), &lwp, sizeof(lwpid_t));
629 if (ret != 0)
630 return (P2T(ret));
631 info->ti_ta_p = th->th_ta;
632 info->ti_tid = th->th_tid;
633
634 if (attrflags & PTHREAD_SCOPE_SYSTEM) {
635 ret = ps_linfo(ta->ph, lwp, &linfo);
636 if (ret == PS_OK) {
637 info->ti_sigmask = linfo.pl_sigmask;
638 info->ti_pending = linfo.pl_siglist;
639 } else
640 return (ret);
641 } else {
642 ret = ps_pread(ta->ph,
643 ta->map[th->th_tid].thr + ta->thread_off_sigmask,
644 &info->ti_sigmask, sizeof(sigset_t));
645 if (ret)
646 return (ret);
647 ret = ps_pread(ta->ph,
648 ta->map[th->th_tid].thr + ta->thread_off_sigpend,
649 &info->ti_pending, sizeof(sigset_t));
650 if (ret)
651 return (ret);
652 }
653
654 if (state == ta->thread_state_running)
655 info->ti_state = TD_THR_RUN;
656 else if (state == ta->thread_state_zoombie)
657 info->ti_state = TD_THR_ZOMBIE;
658 else
659 info->ti_state = TD_THR_SLEEP;
660 info->ti_db_suspended = ((dflags & TMDF_SUSPEND) != 0);
661 info->ti_type = TD_THR_USER;
662 return (0);
663 }
664
665 static td_err_e
pt_thr_get_info(const td_thrhandle_t * th,td_thrinfo_t * info)666 pt_thr_get_info(const td_thrhandle_t *th, td_thrinfo_t *info)
667 {
668 td_err_e e;
669
670 e = pt_thr_old_get_info(th, (td_old_thrinfo_t *)info);
671 bzero(&info->ti_siginfo, sizeof(info->ti_siginfo));
672 return (e);
673 }
674
675 #ifdef __i386__
676 static td_err_e
pt_thr_getxmmregs(const td_thrhandle_t * th,char * fxsave)677 pt_thr_getxmmregs(const td_thrhandle_t *th, char *fxsave)
678 {
679 const td_thragent_t *ta = th->th_ta;
680 struct kse_thr_mailbox tmbx;
681 psaddr_t tcb_addr, tmbx_addr, ptr;
682 lwpid_t lwp;
683 int ret;
684
685 return TD_ERR;
686
687 TDBG_FUNC();
688
689 ret = pt_validate(th);
690 if (ret)
691 return (ret);
692
693 if (ta->map[th->th_tid].type == PT_LWP) {
694 ret = ps_lgetxmmregs(ta->ph, ta->map[th->th_tid].lwp, fxsave);
695 return (P2T(ret));
696 }
697
698 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + ta->thread_off_tcb,
699 &tcb_addr, sizeof(tcb_addr));
700 if (ret != 0)
701 return (P2T(ret));
702 tmbx_addr = tcb_addr + ta->thread_off_tmbx;
703 ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp);
704 ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t));
705 if (ret != 0)
706 return (P2T(ret));
707 if (lwp != 0) {
708 ret = ps_lgetxmmregs(ta->ph, lwp, fxsave);
709 return (P2T(ret));
710 }
711
712 ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx));
713 if (ret != 0)
714 return (P2T(ret));
715 pt_ucontext_to_fxsave(&tmbx.tm_context, fxsave);
716 return (0);
717 }
718 #endif
719
720 static td_err_e
pt_thr_getfpregs(const td_thrhandle_t * th,prfpregset_t * fpregs)721 pt_thr_getfpregs(const td_thrhandle_t *th, prfpregset_t *fpregs)
722 {
723 const td_thragent_t *ta = th->th_ta;
724 struct kse_thr_mailbox tmbx;
725 psaddr_t tcb_addr, tmbx_addr, ptr;
726 lwpid_t lwp;
727 int ret;
728
729 TDBG_FUNC();
730
731 ret = pt_validate(th);
732 if (ret)
733 return (ret);
734
735 if (ta->map[th->th_tid].type == PT_LWP) {
736 ret = ps_lgetfpregs(ta->ph, ta->map[th->th_tid].lwp, fpregs);
737 return (P2T(ret));
738 }
739
740 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + ta->thread_off_tcb,
741 &tcb_addr, sizeof(tcb_addr));
742 if (ret != 0)
743 return (P2T(ret));
744 tmbx_addr = tcb_addr + ta->thread_off_tmbx;
745 ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp);
746 ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t));
747 if (ret != 0)
748 return (P2T(ret));
749 if (lwp != 0) {
750 ret = ps_lgetfpregs(ta->ph, lwp, fpregs);
751 return (P2T(ret));
752 }
753
754 ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx));
755 if (ret != 0)
756 return (P2T(ret));
757 pt_ucontext_to_fpreg(&tmbx.tm_context, fpregs);
758 return (0);
759 }
760
761 static td_err_e
pt_thr_getgregs(const td_thrhandle_t * th,prgregset_t gregs)762 pt_thr_getgregs(const td_thrhandle_t *th, prgregset_t gregs)
763 {
764 const td_thragent_t *ta = th->th_ta;
765 struct kse_thr_mailbox tmbx;
766 psaddr_t tcb_addr, tmbx_addr, ptr;
767 lwpid_t lwp;
768 int ret;
769
770 TDBG_FUNC();
771
772 ret = pt_validate(th);
773 if (ret)
774 return (ret);
775
776 if (ta->map[th->th_tid].type == PT_LWP) {
777 ret = ps_lgetregs(ta->ph,
778 ta->map[th->th_tid].lwp, gregs);
779 return (P2T(ret));
780 }
781
782 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + ta->thread_off_tcb,
783 &tcb_addr, sizeof(tcb_addr));
784 if (ret != 0)
785 return (P2T(ret));
786 tmbx_addr = tcb_addr + ta->thread_off_tmbx;
787 ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp);
788 ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t));
789 if (ret != 0)
790 return (P2T(ret));
791 if (lwp != 0) {
792 ret = ps_lgetregs(ta->ph, lwp, gregs);
793 return (P2T(ret));
794 }
795 ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx));
796 if (ret != 0)
797 return (P2T(ret));
798 pt_ucontext_to_reg(&tmbx.tm_context, gregs);
799 return (0);
800 }
801
802 #ifdef __i386__
803 static td_err_e
pt_thr_setxmmregs(const td_thrhandle_t * th,const char * fxsave)804 pt_thr_setxmmregs(const td_thrhandle_t *th, const char *fxsave)
805 {
806 const td_thragent_t *ta = th->th_ta;
807 struct kse_thr_mailbox tmbx;
808 psaddr_t tcb_addr, tmbx_addr, ptr;
809 lwpid_t lwp;
810 int ret;
811
812 return TD_ERR;
813
814 TDBG_FUNC();
815
816 ret = pt_validate(th);
817 if (ret)
818 return (ret);
819
820 if (ta->map[th->th_tid].type == PT_LWP) {
821 ret = ps_lsetxmmregs(ta->ph, ta->map[th->th_tid].lwp, fxsave);
822 return (P2T(ret));
823 }
824
825 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr +
826 ta->thread_off_tcb,
827 &tcb_addr, sizeof(tcb_addr));
828 if (ret != 0)
829 return (P2T(ret));
830 tmbx_addr = tcb_addr + ta->thread_off_tmbx;
831 ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp);
832 ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t));
833 if (ret != 0)
834 return (P2T(ret));
835 if (lwp != 0) {
836 ret = ps_lsetxmmregs(ta->ph, lwp, fxsave);
837 return (P2T(ret));
838 }
839 /*
840 * Read a copy of context, this makes sure that registers
841 * not covered by structure reg won't be clobbered
842 */
843 ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx));
844 if (ret != 0)
845 return (P2T(ret));
846
847 pt_fxsave_to_ucontext(fxsave, &tmbx.tm_context);
848 ret = ps_pwrite(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx));
849 return (P2T(ret));
850 }
851 #endif
852
853 static td_err_e
pt_thr_setfpregs(const td_thrhandle_t * th,const prfpregset_t * fpregs)854 pt_thr_setfpregs(const td_thrhandle_t *th, const prfpregset_t *fpregs)
855 {
856 const td_thragent_t *ta = th->th_ta;
857 struct kse_thr_mailbox tmbx;
858 psaddr_t tcb_addr, tmbx_addr, ptr;
859 lwpid_t lwp;
860 int ret;
861
862 TDBG_FUNC();
863
864 ret = pt_validate(th);
865 if (ret)
866 return (ret);
867
868 if (ta->map[th->th_tid].type == PT_LWP) {
869 ret = ps_lsetfpregs(ta->ph, ta->map[th->th_tid].lwp, fpregs);
870 return (P2T(ret));
871 }
872
873 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr +
874 ta->thread_off_tcb,
875 &tcb_addr, sizeof(tcb_addr));
876 if (ret != 0)
877 return (P2T(ret));
878 tmbx_addr = tcb_addr + ta->thread_off_tmbx;
879 ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp);
880 ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t));
881 if (ret != 0)
882 return (P2T(ret));
883 if (lwp != 0) {
884 ret = ps_lsetfpregs(ta->ph, lwp, fpregs);
885 return (P2T(ret));
886 }
887 /*
888 * Read a copy of context, this makes sure that registers
889 * not covered by structure reg won't be clobbered
890 */
891 ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx));
892 if (ret != 0)
893 return (P2T(ret));
894
895 pt_fpreg_to_ucontext(fpregs, &tmbx.tm_context);
896 ret = ps_pwrite(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx));
897 return (P2T(ret));
898 }
899
900 static td_err_e
pt_thr_setgregs(const td_thrhandle_t * th,const prgregset_t gregs)901 pt_thr_setgregs(const td_thrhandle_t *th, const prgregset_t gregs)
902 {
903 const td_thragent_t *ta = th->th_ta;
904 struct kse_thr_mailbox tmbx;
905 psaddr_t tcb_addr, tmbx_addr, ptr;
906 lwpid_t lwp;
907 int ret;
908
909 TDBG_FUNC();
910
911 ret = pt_validate(th);
912 if (ret)
913 return (ret);
914
915 if (ta->map[th->th_tid].type == PT_LWP) {
916 ret = ps_lsetregs(ta->ph, ta->map[th->th_tid].lwp, gregs);
917 return (P2T(ret));
918 }
919
920 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr +
921 ta->thread_off_tcb,
922 &tcb_addr, sizeof(tcb_addr));
923 if (ret != 0)
924 return (P2T(ret));
925 tmbx_addr = tcb_addr + ta->thread_off_tmbx;
926 ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp);
927 ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t));
928 if (ret != 0)
929 return (P2T(ret));
930 if (lwp != 0) {
931 ret = ps_lsetregs(ta->ph, lwp, gregs);
932 return (P2T(ret));
933 }
934
935 /*
936 * Read a copy of context, make sure that registers
937 * not covered by structure reg won't be clobbered
938 */
939 ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx));
940 if (ret != 0)
941 return (P2T(ret));
942 pt_reg_to_ucontext(gregs, &tmbx.tm_context);
943 ret = ps_pwrite(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx));
944 return (P2T(ret));
945 }
946
947 static td_err_e
pt_thr_event_enable(const td_thrhandle_t * th __unused,int en __unused)948 pt_thr_event_enable(const td_thrhandle_t *th __unused, int en __unused)
949 {
950 TDBG_FUNC();
951 return (0);
952 }
953
954 static td_err_e
pt_thr_set_event(const td_thrhandle_t * th __unused,td_thr_events_t * setp __unused)955 pt_thr_set_event(const td_thrhandle_t *th __unused,
956 td_thr_events_t *setp __unused)
957 {
958 TDBG_FUNC();
959 return (0);
960 }
961
962 static td_err_e
pt_thr_clear_event(const td_thrhandle_t * th __unused,td_thr_events_t * setp __unused)963 pt_thr_clear_event(const td_thrhandle_t *th __unused,
964 td_thr_events_t *setp __unused)
965 {
966 TDBG_FUNC();
967 return (0);
968 }
969
970 static td_err_e
pt_thr_event_getmsg(const td_thrhandle_t * th __unused,td_event_msg_t * msg __unused)971 pt_thr_event_getmsg(const td_thrhandle_t *th __unused,
972 td_event_msg_t *msg __unused)
973 {
974 TDBG_FUNC();
975 return (TD_NOMSG);
976 }
977
978 static td_err_e
pt_thr_sstep(const td_thrhandle_t * th,int step)979 pt_thr_sstep(const td_thrhandle_t *th, int step)
980 {
981 const td_thragent_t *ta = th->th_ta;
982 struct kse_thr_mailbox tmbx;
983 struct reg regs;
984 psaddr_t tcb_addr, tmbx_addr;
985 uint32_t dflags;
986 lwpid_t lwp;
987 int ret;
988
989 TDBG_FUNC();
990
991 ret = pt_validate(th);
992 if (ret)
993 return (ret);
994
995 if (ta->map[th->th_tid].type == PT_LWP)
996 return (TD_BADTH);
997
998 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr +
999 ta->thread_off_tcb,
1000 &tcb_addr, sizeof(tcb_addr));
1001 if (ret != 0)
1002 return (P2T(ret));
1003
1004 /* Clear or set single step flag in thread mailbox */
1005 ret = ps_pread(ta->ph,
1006 tcb_addr + ta->thread_off_tmbx +
1007 offsetof(struct kse_thr_mailbox, tm_dflags),
1008 &dflags, sizeof(uint32_t));
1009 if (ret != 0)
1010 return (P2T(ret));
1011 if (step != 0)
1012 dflags |= TMDF_SSTEP;
1013 else
1014 dflags &= ~TMDF_SSTEP;
1015 ret = ps_pwrite(ta->ph,
1016 tcb_addr + ta->thread_off_tmbx +
1017 offsetof(struct kse_thr_mailbox, tm_dflags),
1018 &dflags, sizeof(uint32_t));
1019 if (ret != 0)
1020 return (P2T(ret));
1021 /* Get lwp */
1022 ret = ps_pread(ta->ph,
1023 tcb_addr + ta->thread_off_tmbx +
1024 offsetof(struct kse_thr_mailbox, tm_lwp),
1025 &lwp, sizeof(lwpid_t));
1026 if (ret != 0)
1027 return (P2T(ret));
1028 if (lwp != 0)
1029 return (0);
1030
1031 tmbx_addr = tcb_addr + ta->thread_off_tmbx;
1032 /*
1033 * context is in userland, some architectures store
1034 * single step status in registers, we should change
1035 * these registers.
1036 */
1037 ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx));
1038 if (ret == 0) {
1039 pt_ucontext_to_reg(&tmbx.tm_context, ®s);
1040 /* only write out if it is really changed. */
1041 if (pt_reg_sstep(®s, step) != 0) {
1042 pt_reg_to_ucontext(®s, &tmbx.tm_context);
1043 ret = ps_pwrite(ta->ph, tmbx_addr, &tmbx,
1044 sizeof(tmbx));
1045 }
1046 }
1047 return (P2T(ret));
1048 }
1049
1050 static void
pt_unmap_lwp(const td_thragent_t * ta,lwpid_t lwp)1051 pt_unmap_lwp(const td_thragent_t *ta, lwpid_t lwp)
1052 {
1053 unsigned int i;
1054
1055 for (i = 0; i < ta->map_len; ++i) {
1056 if (ta->map[i].type == PT_LWP && ta->map[i].lwp == lwp) {
1057 ta->map[i].type = PT_NONE;
1058 return;
1059 }
1060 }
1061 }
1062
1063 static int
pt_validate(const td_thrhandle_t * th)1064 pt_validate(const td_thrhandle_t *th)
1065 {
1066
1067 if (th->th_tid < 0 || th->th_tid >= (long)th->th_ta->map_len ||
1068 th->th_ta->map[th->th_tid].type == PT_NONE)
1069 return (TD_NOTHR);
1070 return (TD_OK);
1071 }
1072
1073 static td_err_e
pt_thr_tls_get_addr(const td_thrhandle_t * th,psaddr_t _linkmap,size_t offset,psaddr_t * address)1074 pt_thr_tls_get_addr(const td_thrhandle_t *th, psaddr_t _linkmap, size_t offset,
1075 psaddr_t *address)
1076 {
1077 const td_thragent_t *ta = th->th_ta;
1078 psaddr_t dtv_addr, obj_entry, tcb_addr;
1079 int tls_index, ret;
1080
1081 /* linkmap is a member of Obj_Entry */
1082 obj_entry = _linkmap - ta->thread_off_linkmap;
1083
1084 /* get tlsindex of the object file */
1085 ret = ps_pread(ta->ph,
1086 obj_entry + ta->thread_off_tlsindex,
1087 &tls_index, sizeof(tls_index));
1088 if (ret != 0)
1089 return (P2T(ret));
1090
1091 /* get thread tcb */
1092 ret = ps_pread(ta->ph, ta->map[th->th_tid].thr +
1093 ta->thread_off_tcb,
1094 &tcb_addr, sizeof(tcb_addr));
1095 if (ret != 0)
1096 return (P2T(ret));
1097
1098 /* get dtv array address */
1099 ret = ps_pread(ta->ph, tcb_addr + ta->thread_off_dtv,
1100 &dtv_addr, sizeof(dtv_addr));
1101 if (ret != 0)
1102 return (P2T(ret));
1103 /* now get the object's tls block base address */
1104 ret = ps_pread(ta->ph, dtv_addr + sizeof(void *) * (tls_index + 1),
1105 address, sizeof(*address));
1106 if (ret != 0)
1107 return (P2T(ret));
1108
1109 *address += offset;
1110 return (TD_OK);
1111 }
1112
1113 static struct ta_ops libpthread_db_ops = {
1114 .to_init = pt_init,
1115 .to_ta_clear_event = pt_ta_clear_event,
1116 .to_ta_delete = pt_ta_delete,
1117 .to_ta_event_addr = pt_ta_event_addr,
1118 .to_ta_event_getmsg = pt_ta_event_getmsg,
1119 .to_ta_map_id2thr = pt_ta_map_id2thr,
1120 .to_ta_map_lwp2thr = pt_ta_map_lwp2thr,
1121 .to_ta_new = pt_ta_new,
1122 .to_ta_set_event = pt_ta_set_event,
1123 .to_ta_thr_iter = pt_ta_thr_iter,
1124 .to_ta_tsd_iter = pt_ta_tsd_iter,
1125 .to_thr_clear_event = pt_thr_clear_event,
1126 .to_thr_dbresume = pt_thr_dbresume,
1127 .to_thr_dbsuspend = pt_thr_dbsuspend,
1128 .to_thr_event_enable = pt_thr_event_enable,
1129 .to_thr_event_getmsg = pt_thr_event_getmsg,
1130 .to_thr_old_get_info = pt_thr_old_get_info,
1131 .to_thr_get_info = pt_thr_get_info,
1132 .to_thr_getfpregs = pt_thr_getfpregs,
1133 .to_thr_getgregs = pt_thr_getgregs,
1134 .to_thr_set_event = pt_thr_set_event,
1135 .to_thr_setfpregs = pt_thr_setfpregs,
1136 .to_thr_setgregs = pt_thr_setgregs,
1137 .to_thr_validate = pt_thr_validate,
1138 .to_thr_tls_get_addr = pt_thr_tls_get_addr,
1139
1140 /* FreeBSD specific extensions. */
1141 .to_thr_sstep = pt_thr_sstep,
1142 #ifdef __i386__
1143 .to_thr_getxmmregs = pt_thr_getxmmregs,
1144 .to_thr_setxmmregs = pt_thr_setxmmregs,
1145 #endif
1146 };
1147
1148 DATA_SET(__ta_ops, libpthread_db_ops);
1149