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