xref: /freebsd/lib/libthread_db/thread_db.c (revision 3e93cc3ae35baf2f2398b3bee5ce38393eb7a595)
13c1e38eaSMarcel Moolenaar /*
23c1e38eaSMarcel Moolenaar  * Copyright (c) 2004 David Xu <davidxu@freebsd.org>
33c1e38eaSMarcel Moolenaar  * All rights reserved.
43c1e38eaSMarcel Moolenaar  *
53c1e38eaSMarcel Moolenaar  * Redistribution and use in source and binary forms, with or without
63c1e38eaSMarcel Moolenaar  * modification, are permitted provided that the following conditions
73c1e38eaSMarcel Moolenaar  * are met:
83c1e38eaSMarcel Moolenaar  * 1. Redistributions of source code must retain the above copyright
93c1e38eaSMarcel Moolenaar  *    notice, this list of conditions and the following disclaimer.
103c1e38eaSMarcel Moolenaar  * 2. Redistributions in binary form must reproduce the above copyright
113c1e38eaSMarcel Moolenaar  *    notice, this list of conditions and the following disclaimer in the
123c1e38eaSMarcel Moolenaar  *    documentation and/or other materials provided with the distribution.
133c1e38eaSMarcel Moolenaar  *
143c1e38eaSMarcel Moolenaar  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
153c1e38eaSMarcel Moolenaar  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
163c1e38eaSMarcel Moolenaar  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
173c1e38eaSMarcel Moolenaar  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
183c1e38eaSMarcel Moolenaar  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
193c1e38eaSMarcel Moolenaar  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
203c1e38eaSMarcel Moolenaar  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
213c1e38eaSMarcel Moolenaar  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
223c1e38eaSMarcel Moolenaar  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
233c1e38eaSMarcel Moolenaar  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
243c1e38eaSMarcel Moolenaar  * SUCH DAMAGE.
253c1e38eaSMarcel Moolenaar  */
263c1e38eaSMarcel Moolenaar 
273c1e38eaSMarcel Moolenaar #include <sys/cdefs.h>
283c1e38eaSMarcel Moolenaar __FBSDID("$FreeBSD$");
293c1e38eaSMarcel Moolenaar 
303c1e38eaSMarcel Moolenaar #include <proc_service.h>
313c1e38eaSMarcel Moolenaar #include <stddef.h>
323c1e38eaSMarcel Moolenaar #include <thread_db.h>
333c1e38eaSMarcel Moolenaar #include <unistd.h>
343c1e38eaSMarcel Moolenaar 
353c1e38eaSMarcel Moolenaar #include "thread_db_int.h"
363c1e38eaSMarcel Moolenaar 
373c1e38eaSMarcel Moolenaar struct td_thragent
383c1e38eaSMarcel Moolenaar {
393c1e38eaSMarcel Moolenaar 	TD_THRAGENT_FIELDS;
403c1e38eaSMarcel Moolenaar };
413c1e38eaSMarcel Moolenaar 
423c1e38eaSMarcel Moolenaar static TAILQ_HEAD(, td_thragent) proclist = TAILQ_HEAD_INITIALIZER(proclist);
433c1e38eaSMarcel Moolenaar 
443c1e38eaSMarcel Moolenaar extern struct ta_ops libc_r_db_ops;
453c1e38eaSMarcel Moolenaar extern struct ta_ops libpthread_db_ops;
463c1e38eaSMarcel Moolenaar extern struct ta_ops libthr_db_ops;
473c1e38eaSMarcel Moolenaar 
483c1e38eaSMarcel Moolenaar static struct ta_ops *ops[] = {
493c1e38eaSMarcel Moolenaar 	&libpthread_db_ops,
503c1e38eaSMarcel Moolenaar 	&libthr_db_ops,
513c1e38eaSMarcel Moolenaar 	&libc_r_db_ops
523c1e38eaSMarcel Moolenaar };
533c1e38eaSMarcel Moolenaar 
543c1e38eaSMarcel Moolenaar td_err_e
553c1e38eaSMarcel Moolenaar td_init(void)
563c1e38eaSMarcel Moolenaar {
573c1e38eaSMarcel Moolenaar 	td_err_e ret, tmp;
583c1e38eaSMarcel Moolenaar 	size_t i;
593c1e38eaSMarcel Moolenaar 
603c1e38eaSMarcel Moolenaar 	ret = 0;
613c1e38eaSMarcel Moolenaar 	for (i = 0; i < sizeof(ops)/sizeof(ops[0]); i++) {
623c1e38eaSMarcel Moolenaar 		if (ops[i]->to_init != NULL) {
633c1e38eaSMarcel Moolenaar 			tmp = ops[i]->to_init();
643c1e38eaSMarcel Moolenaar 			if (tmp != TD_OK)
653c1e38eaSMarcel Moolenaar 				ret = tmp;
663c1e38eaSMarcel Moolenaar 		}
673c1e38eaSMarcel Moolenaar 	}
683c1e38eaSMarcel Moolenaar 	return (ret);
693c1e38eaSMarcel Moolenaar }
703c1e38eaSMarcel Moolenaar 
713c1e38eaSMarcel Moolenaar td_err_e
723c1e38eaSMarcel Moolenaar td_ta_clear_event(const td_thragent_t *ta, td_thr_events_t *events)
733c1e38eaSMarcel Moolenaar {
743c1e38eaSMarcel Moolenaar 	return (ta->ta_ops->to_ta_clear_event(ta, events));
753c1e38eaSMarcel Moolenaar }
763c1e38eaSMarcel Moolenaar 
773c1e38eaSMarcel Moolenaar td_err_e
783c1e38eaSMarcel Moolenaar td_ta_delete(td_thragent_t *ta)
793c1e38eaSMarcel Moolenaar {
803c1e38eaSMarcel Moolenaar 	TAILQ_REMOVE(&proclist, ta, ta_next);
813c1e38eaSMarcel Moolenaar 	return (ta->ta_ops->to_ta_delete(ta));
823c1e38eaSMarcel Moolenaar }
833c1e38eaSMarcel Moolenaar 
843c1e38eaSMarcel Moolenaar td_err_e
853c1e38eaSMarcel Moolenaar td_ta_event_addr(const td_thragent_t *ta, td_event_e event, td_notify_t *ptr)
863c1e38eaSMarcel Moolenaar {
873c1e38eaSMarcel Moolenaar 	return (ta->ta_ops->to_ta_event_addr(ta, event, ptr));
883c1e38eaSMarcel Moolenaar }
893c1e38eaSMarcel Moolenaar 
903c1e38eaSMarcel Moolenaar td_err_e
913c1e38eaSMarcel Moolenaar td_ta_event_getmsg(const td_thragent_t *ta, td_event_msg_t *msg)
923c1e38eaSMarcel Moolenaar {
933c1e38eaSMarcel Moolenaar 	return (ta->ta_ops->to_ta_event_getmsg(ta, msg));
943c1e38eaSMarcel Moolenaar }
953c1e38eaSMarcel Moolenaar 
963c1e38eaSMarcel Moolenaar td_err_e
973c1e38eaSMarcel Moolenaar td_ta_map_id2thr(const td_thragent_t *ta, thread_t id, td_thrhandle_t *th)
983c1e38eaSMarcel Moolenaar {
993c1e38eaSMarcel Moolenaar 	return (ta->ta_ops->to_ta_map_id2thr(ta, id, th));
1003c1e38eaSMarcel Moolenaar }
1013c1e38eaSMarcel Moolenaar 
1023c1e38eaSMarcel Moolenaar td_err_e
1033c1e38eaSMarcel Moolenaar td_ta_map_lwp2thr(const td_thragent_t *ta, lwpid_t lwpid, td_thrhandle_t *th)
1043c1e38eaSMarcel Moolenaar {
1053c1e38eaSMarcel Moolenaar 	return (ta->ta_ops->to_ta_map_lwp2thr(ta, lwpid, th));
1063c1e38eaSMarcel Moolenaar }
1073c1e38eaSMarcel Moolenaar 
1083c1e38eaSMarcel Moolenaar td_err_e
1093c1e38eaSMarcel Moolenaar td_ta_new(struct ps_prochandle *ph, td_thragent_t **pta)
1103c1e38eaSMarcel Moolenaar {
1113c1e38eaSMarcel Moolenaar 	size_t i;
1123c1e38eaSMarcel Moolenaar 
1133c1e38eaSMarcel Moolenaar 	for (i = 0; i < sizeof(ops)/sizeof(ops[0]); ++i) {
1143c1e38eaSMarcel Moolenaar 		if (ops[i]->to_ta_new(ph, pta) == TD_OK) {
1153c1e38eaSMarcel Moolenaar 			TAILQ_INSERT_HEAD(&proclist, *pta, ta_next);
1163c1e38eaSMarcel Moolenaar 			(*pta)->ta_ops = ops[i];
1173c1e38eaSMarcel Moolenaar 			return (TD_OK);
1183c1e38eaSMarcel Moolenaar 		}
1193c1e38eaSMarcel Moolenaar 	}
1203c1e38eaSMarcel Moolenaar 	return (TD_NOLIBTHREAD);
1213c1e38eaSMarcel Moolenaar }
1223c1e38eaSMarcel Moolenaar 
1233c1e38eaSMarcel Moolenaar td_err_e
1243c1e38eaSMarcel Moolenaar td_ta_set_event(const td_thragent_t *ta, td_thr_events_t *events)
1253c1e38eaSMarcel Moolenaar {
1263c1e38eaSMarcel Moolenaar 	return (ta->ta_ops->to_ta_set_event(ta, events));
1273c1e38eaSMarcel Moolenaar }
1283c1e38eaSMarcel Moolenaar 
1293c1e38eaSMarcel Moolenaar td_err_e
1303c1e38eaSMarcel Moolenaar td_ta_thr_iter(const td_thragent_t *ta, td_thr_iter_f *callback,
1313c1e38eaSMarcel Moolenaar     void *cbdata_p, td_thr_state_e state, int ti_pri, sigset_t *ti_sigmask_p,
1323c1e38eaSMarcel Moolenaar     unsigned int ti_user_flags)
1333c1e38eaSMarcel Moolenaar {
1343c1e38eaSMarcel Moolenaar 	return (ta->ta_ops->to_ta_thr_iter(ta, callback, cbdata_p, state,
1353c1e38eaSMarcel Moolenaar 		    ti_pri, ti_sigmask_p, ti_user_flags));
1363c1e38eaSMarcel Moolenaar }
1373c1e38eaSMarcel Moolenaar 
1383c1e38eaSMarcel Moolenaar td_err_e
1393c1e38eaSMarcel Moolenaar td_ta_tsd_iter(const td_thragent_t *ta, td_key_iter_f *callback,
1403c1e38eaSMarcel Moolenaar     void *cbdata_p)
1413c1e38eaSMarcel Moolenaar {
1423c1e38eaSMarcel Moolenaar 	return (ta->ta_ops->to_ta_tsd_iter(ta, callback, cbdata_p));
1433c1e38eaSMarcel Moolenaar }
1443c1e38eaSMarcel Moolenaar 
1453c1e38eaSMarcel Moolenaar td_err_e
1463c1e38eaSMarcel Moolenaar td_thr_clear_event(const td_thrhandle_t *th, td_thr_events_t *events)
1473c1e38eaSMarcel Moolenaar {
1483c1e38eaSMarcel Moolenaar 	const td_thragent_t *ta = th->th_ta;
1493c1e38eaSMarcel Moolenaar 	return (ta->ta_ops->to_thr_clear_event(th, events));
1503c1e38eaSMarcel Moolenaar }
1513c1e38eaSMarcel Moolenaar 
1523c1e38eaSMarcel Moolenaar td_err_e
1533c1e38eaSMarcel Moolenaar td_thr_dbresume(const td_thrhandle_t *th)
1543c1e38eaSMarcel Moolenaar {
1553c1e38eaSMarcel Moolenaar 	const td_thragent_t *ta = th->th_ta;
1563c1e38eaSMarcel Moolenaar 	return (ta->ta_ops->to_thr_dbresume(th));
1573c1e38eaSMarcel Moolenaar }
1583c1e38eaSMarcel Moolenaar 
1593c1e38eaSMarcel Moolenaar td_err_e
1603c1e38eaSMarcel Moolenaar td_thr_dbsuspend(const td_thrhandle_t *th)
1613c1e38eaSMarcel Moolenaar {
1623c1e38eaSMarcel Moolenaar 	const td_thragent_t *ta = th->th_ta;
1633c1e38eaSMarcel Moolenaar 	return (ta->ta_ops->to_thr_dbsuspend(th));
1643c1e38eaSMarcel Moolenaar }
1653c1e38eaSMarcel Moolenaar 
1663c1e38eaSMarcel Moolenaar td_err_e
1673c1e38eaSMarcel Moolenaar td_thr_event_enable(const td_thrhandle_t *th, int en)
1683c1e38eaSMarcel Moolenaar {
1693c1e38eaSMarcel Moolenaar 	const td_thragent_t *ta = th->th_ta;
1703c1e38eaSMarcel Moolenaar 	return (ta->ta_ops->to_thr_event_enable(th, en));
1713c1e38eaSMarcel Moolenaar }
1723c1e38eaSMarcel Moolenaar 
1733c1e38eaSMarcel Moolenaar td_err_e
1743c1e38eaSMarcel Moolenaar td_thr_event_getmsg(const td_thrhandle_t *th, td_event_msg_t *msg)
1753c1e38eaSMarcel Moolenaar {
1763c1e38eaSMarcel Moolenaar 	const td_thragent_t *ta = th->th_ta;
1773c1e38eaSMarcel Moolenaar 	return (ta->ta_ops->to_thr_event_getmsg(th, msg));
1783c1e38eaSMarcel Moolenaar }
1793c1e38eaSMarcel Moolenaar 
1803c1e38eaSMarcel Moolenaar td_err_e
1813c1e38eaSMarcel Moolenaar td_thr_get_info(const td_thrhandle_t *th, td_thrinfo_t *info)
1823c1e38eaSMarcel Moolenaar {
1833c1e38eaSMarcel Moolenaar 	const td_thragent_t *ta = th->th_ta;
1843c1e38eaSMarcel Moolenaar 	return (ta->ta_ops->to_thr_get_info(th, info));
1853c1e38eaSMarcel Moolenaar }
1863c1e38eaSMarcel Moolenaar 
1873c1e38eaSMarcel Moolenaar td_err_e
1883c1e38eaSMarcel Moolenaar td_thr_getfpregs(const td_thrhandle_t *th, prfpregset_t *fpregset)
1893c1e38eaSMarcel Moolenaar {
1903c1e38eaSMarcel Moolenaar 	const td_thragent_t *ta = th->th_ta;
1913c1e38eaSMarcel Moolenaar 	return (ta->ta_ops->to_thr_getfpregs(th, fpregset));
1923c1e38eaSMarcel Moolenaar }
1933c1e38eaSMarcel Moolenaar 
1943c1e38eaSMarcel Moolenaar td_err_e
1953c1e38eaSMarcel Moolenaar td_thr_getgregs(const td_thrhandle_t *th, prgregset_t gregs)
1963c1e38eaSMarcel Moolenaar {
1973c1e38eaSMarcel Moolenaar 	const td_thragent_t *ta = th->th_ta;
1983c1e38eaSMarcel Moolenaar 	return (ta->ta_ops->to_thr_getgregs(th, gregs));
1993c1e38eaSMarcel Moolenaar }
2003c1e38eaSMarcel Moolenaar 
2013c1e38eaSMarcel Moolenaar td_err_e
2023c1e38eaSMarcel Moolenaar td_thr_set_event(const td_thrhandle_t *th, td_thr_events_t *events)
2033c1e38eaSMarcel Moolenaar {
2043c1e38eaSMarcel Moolenaar 	const td_thragent_t *ta = th->th_ta;
2053c1e38eaSMarcel Moolenaar 	return (ta->ta_ops->to_thr_set_event(th, events));
2063c1e38eaSMarcel Moolenaar }
2073c1e38eaSMarcel Moolenaar 
2083c1e38eaSMarcel Moolenaar td_err_e
2093c1e38eaSMarcel Moolenaar td_thr_setfpregs(const td_thrhandle_t *th, const prfpregset_t *fpregs)
2103c1e38eaSMarcel Moolenaar {
2113c1e38eaSMarcel Moolenaar 	const td_thragent_t *ta = th->th_ta;
2123c1e38eaSMarcel Moolenaar 	return (ta->ta_ops->to_thr_setfpregs(th, fpregs));
2133c1e38eaSMarcel Moolenaar }
2143c1e38eaSMarcel Moolenaar 
2153c1e38eaSMarcel Moolenaar td_err_e
2163c1e38eaSMarcel Moolenaar td_thr_setgregs(const td_thrhandle_t *th, const prgregset_t gregs)
2173c1e38eaSMarcel Moolenaar {
2183c1e38eaSMarcel Moolenaar 	const td_thragent_t *ta = th->th_ta;
2193c1e38eaSMarcel Moolenaar 	return (ta->ta_ops->to_thr_setgregs(th, gregs));
2203c1e38eaSMarcel Moolenaar }
2213c1e38eaSMarcel Moolenaar 
2223c1e38eaSMarcel Moolenaar td_err_e
2233c1e38eaSMarcel Moolenaar td_thr_validate(const td_thrhandle_t *th)
2243c1e38eaSMarcel Moolenaar {
2253c1e38eaSMarcel Moolenaar 	const td_thragent_t *ta = th->th_ta;
2263c1e38eaSMarcel Moolenaar 	return (ta->ta_ops->to_thr_validate(th));
2273c1e38eaSMarcel Moolenaar }
2283c1e38eaSMarcel Moolenaar 
2293e93cc3aSDavid Xu td_err_e
2303e93cc3aSDavid Xu td_thr_tls_get_addr(const td_thrhandle_t *th, void *linkmap, size_t offset,
2313e93cc3aSDavid Xu 		    void **address)
2323e93cc3aSDavid Xu {
2333e93cc3aSDavid Xu 	const td_thragent_t *ta = th->th_ta;
2343e93cc3aSDavid Xu 	return (ta->ta_ops->to_thr_tls_get_addr(th, linkmap, offset, address));
2353e93cc3aSDavid Xu }
2363e93cc3aSDavid Xu 
2373c1e38eaSMarcel Moolenaar /* FreeBSD specific extensions. */
2383c1e38eaSMarcel Moolenaar 
2393c1e38eaSMarcel Moolenaar td_err_e
2403c1e38eaSMarcel Moolenaar td_thr_sstep(const td_thrhandle_t *th, int step)
2413c1e38eaSMarcel Moolenaar {
2423c1e38eaSMarcel Moolenaar 	const td_thragent_t *ta = th->th_ta;
2433c1e38eaSMarcel Moolenaar 	return (ta->ta_ops->to_thr_sstep(th, step));
2443c1e38eaSMarcel Moolenaar }
245