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