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