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