thread_db.c revision 133342
1132332Smarcel/*
2132332Smarcel * Copyright (c) 2004 David Xu <davidxu@freebsd.org>
3132332Smarcel * All rights reserved.
4132332Smarcel *
5132332Smarcel * Redistribution and use in source and binary forms, with or without
6132332Smarcel * modification, are permitted provided that the following conditions
7132332Smarcel * are met:
8132332Smarcel * 1. Redistributions of source code must retain the above copyright
9132332Smarcel *    notice, this list of conditions and the following disclaimer.
10132332Smarcel * 2. Redistributions in binary form must reproduce the above copyright
11132332Smarcel *    notice, this list of conditions and the following disclaimer in the
12132332Smarcel *    documentation and/or other materials provided with the distribution.
13132332Smarcel *
14132332Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15132332Smarcel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16132332Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17132332Smarcel * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18132332Smarcel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19132332Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20132332Smarcel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21132332Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22132332Smarcel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23132332Smarcel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24132332Smarcel * SUCH DAMAGE.
25132332Smarcel */
26132332Smarcel
27132332Smarcel#include <sys/cdefs.h>
28132332Smarcel__FBSDID("$FreeBSD: head/lib/libthread_db/thread_db.c 133342 2004-08-08 22:37:53Z davidxu $");
29132332Smarcel
30132332Smarcel#include <proc_service.h>
31132332Smarcel#include <stddef.h>
32132332Smarcel#include <thread_db.h>
33132332Smarcel#include <unistd.h>
34132332Smarcel
35132332Smarcel#include "thread_db_int.h"
36132332Smarcel
37132332Smarcelstruct td_thragent
38132332Smarcel{
39132332Smarcel	TD_THRAGENT_FIELDS;
40132332Smarcel};
41132332Smarcel
42132332Smarcelstatic TAILQ_HEAD(, td_thragent) proclist = TAILQ_HEAD_INITIALIZER(proclist);
43132332Smarcel
44132332Smarcelextern struct ta_ops libc_r_db_ops;
45132332Smarcelextern struct ta_ops libpthread_db_ops;
46132332Smarcelextern struct ta_ops libthr_db_ops;
47132332Smarcel
48132332Smarcelstatic struct ta_ops *ops[] = {
49132332Smarcel	&libpthread_db_ops,
50132332Smarcel	&libthr_db_ops,
51132332Smarcel	&libc_r_db_ops
52132332Smarcel};
53132332Smarcel
54132332Smarceltd_err_e
55132332Smarceltd_init(void)
56132332Smarcel{
57132332Smarcel	td_err_e ret, tmp;
58132332Smarcel	size_t i;
59132332Smarcel
60132332Smarcel	ret = 0;
61132332Smarcel	for (i = 0; i < sizeof(ops)/sizeof(ops[0]); i++) {
62132332Smarcel		if (ops[i]->to_init != NULL) {
63132332Smarcel			tmp = ops[i]->to_init();
64132332Smarcel			if (tmp != TD_OK)
65132332Smarcel				ret = tmp;
66132332Smarcel		}
67132332Smarcel	}
68132332Smarcel	return (ret);
69132332Smarcel}
70132332Smarcel
71132332Smarceltd_err_e
72132332Smarceltd_ta_clear_event(const td_thragent_t *ta, td_thr_events_t *events)
73132332Smarcel{
74132332Smarcel	return (ta->ta_ops->to_ta_clear_event(ta, events));
75132332Smarcel}
76132332Smarcel
77132332Smarceltd_err_e
78132332Smarceltd_ta_delete(td_thragent_t *ta)
79132332Smarcel{
80132332Smarcel	TAILQ_REMOVE(&proclist, ta, ta_next);
81132332Smarcel	return (ta->ta_ops->to_ta_delete(ta));
82132332Smarcel}
83132332Smarcel
84132332Smarceltd_err_e
85132332Smarceltd_ta_event_addr(const td_thragent_t *ta, td_event_e event, td_notify_t *ptr)
86132332Smarcel{
87132332Smarcel	return (ta->ta_ops->to_ta_event_addr(ta, event, ptr));
88132332Smarcel}
89132332Smarcel
90132332Smarceltd_err_e
91132332Smarceltd_ta_event_getmsg(const td_thragent_t *ta, td_event_msg_t *msg)
92132332Smarcel{
93132332Smarcel	return (ta->ta_ops->to_ta_event_getmsg(ta, msg));
94132332Smarcel}
95132332Smarcel
96132332Smarceltd_err_e
97132332Smarceltd_ta_map_id2thr(const td_thragent_t *ta, thread_t id, td_thrhandle_t *th)
98132332Smarcel{
99132332Smarcel	return (ta->ta_ops->to_ta_map_id2thr(ta, id, th));
100132332Smarcel}
101132332Smarcel
102132332Smarceltd_err_e
103132332Smarceltd_ta_map_lwp2thr(const td_thragent_t *ta, lwpid_t lwpid, td_thrhandle_t *th)
104132332Smarcel{
105132332Smarcel	return (ta->ta_ops->to_ta_map_lwp2thr(ta, lwpid, th));
106132332Smarcel}
107132332Smarcel
108132332Smarceltd_err_e
109132332Smarceltd_ta_new(struct ps_prochandle *ph, td_thragent_t **pta)
110132332Smarcel{
111132332Smarcel	size_t i;
112132332Smarcel
113132332Smarcel	for (i = 0; i < sizeof(ops)/sizeof(ops[0]); ++i) {
114132332Smarcel		if (ops[i]->to_ta_new(ph, pta) == TD_OK) {
115132332Smarcel			TAILQ_INSERT_HEAD(&proclist, *pta, ta_next);
116132332Smarcel			(*pta)->ta_ops = ops[i];
117132332Smarcel			return (TD_OK);
118132332Smarcel		}
119132332Smarcel	}
120132332Smarcel	return (TD_NOLIBTHREAD);
121132332Smarcel}
122132332Smarcel
123132332Smarceltd_err_e
124132332Smarceltd_ta_set_event(const td_thragent_t *ta, td_thr_events_t *events)
125132332Smarcel{
126132332Smarcel	return (ta->ta_ops->to_ta_set_event(ta, events));
127132332Smarcel}
128132332Smarcel
129132332Smarceltd_err_e
130132332Smarceltd_ta_thr_iter(const td_thragent_t *ta, td_thr_iter_f *callback,
131132332Smarcel    void *cbdata_p, td_thr_state_e state, int ti_pri, sigset_t *ti_sigmask_p,
132132332Smarcel    unsigned int ti_user_flags)
133132332Smarcel{
134132332Smarcel	return (ta->ta_ops->to_ta_thr_iter(ta, callback, cbdata_p, state,
135132332Smarcel		    ti_pri, ti_sigmask_p, ti_user_flags));
136132332Smarcel}
137132332Smarcel
138132332Smarceltd_err_e
139132332Smarceltd_ta_tsd_iter(const td_thragent_t *ta, td_key_iter_f *callback,
140132332Smarcel    void *cbdata_p)
141132332Smarcel{
142132332Smarcel	return (ta->ta_ops->to_ta_tsd_iter(ta, callback, cbdata_p));
143132332Smarcel}
144132332Smarcel
145132332Smarceltd_err_e
146132332Smarceltd_thr_clear_event(const td_thrhandle_t *th, td_thr_events_t *events)
147132332Smarcel{
148132332Smarcel	const td_thragent_t *ta = th->th_ta;
149132332Smarcel	return (ta->ta_ops->to_thr_clear_event(th, events));
150132332Smarcel}
151132332Smarcel
152132332Smarceltd_err_e
153132332Smarceltd_thr_dbresume(const td_thrhandle_t *th)
154132332Smarcel{
155132332Smarcel	const td_thragent_t *ta = th->th_ta;
156132332Smarcel	return (ta->ta_ops->to_thr_dbresume(th));
157132332Smarcel}
158132332Smarcel
159132332Smarceltd_err_e
160132332Smarceltd_thr_dbsuspend(const td_thrhandle_t *th)
161132332Smarcel{
162132332Smarcel	const td_thragent_t *ta = th->th_ta;
163132332Smarcel	return (ta->ta_ops->to_thr_dbsuspend(th));
164132332Smarcel}
165132332Smarcel
166132332Smarceltd_err_e
167132332Smarceltd_thr_event_enable(const td_thrhandle_t *th, int en)
168132332Smarcel{
169132332Smarcel	const td_thragent_t *ta = th->th_ta;
170132332Smarcel	return (ta->ta_ops->to_thr_event_enable(th, en));
171132332Smarcel}
172132332Smarcel
173132332Smarceltd_err_e
174132332Smarceltd_thr_event_getmsg(const td_thrhandle_t *th, td_event_msg_t *msg)
175132332Smarcel{
176132332Smarcel	const td_thragent_t *ta = th->th_ta;
177132332Smarcel	return (ta->ta_ops->to_thr_event_getmsg(th, msg));
178132332Smarcel}
179132332Smarcel
180132332Smarceltd_err_e
181132332Smarceltd_thr_get_info(const td_thrhandle_t *th, td_thrinfo_t *info)
182132332Smarcel{
183132332Smarcel	const td_thragent_t *ta = th->th_ta;
184132332Smarcel	return (ta->ta_ops->to_thr_get_info(th, info));
185132332Smarcel}
186132332Smarcel
187132332Smarceltd_err_e
188132332Smarceltd_thr_getfpregs(const td_thrhandle_t *th, prfpregset_t *fpregset)
189132332Smarcel{
190132332Smarcel	const td_thragent_t *ta = th->th_ta;
191132332Smarcel	return (ta->ta_ops->to_thr_getfpregs(th, fpregset));
192132332Smarcel}
193132332Smarcel
194132332Smarceltd_err_e
195132332Smarceltd_thr_getgregs(const td_thrhandle_t *th, prgregset_t gregs)
196132332Smarcel{
197132332Smarcel	const td_thragent_t *ta = th->th_ta;
198132332Smarcel	return (ta->ta_ops->to_thr_getgregs(th, gregs));
199132332Smarcel}
200132332Smarcel
201132332Smarceltd_err_e
202132332Smarceltd_thr_set_event(const td_thrhandle_t *th, td_thr_events_t *events)
203132332Smarcel{
204132332Smarcel	const td_thragent_t *ta = th->th_ta;
205132332Smarcel	return (ta->ta_ops->to_thr_set_event(th, events));
206132332Smarcel}
207132332Smarcel
208132332Smarceltd_err_e
209132332Smarceltd_thr_setfpregs(const td_thrhandle_t *th, const prfpregset_t *fpregs)
210132332Smarcel{
211132332Smarcel	const td_thragent_t *ta = th->th_ta;
212132332Smarcel	return (ta->ta_ops->to_thr_setfpregs(th, fpregs));
213132332Smarcel}
214132332Smarcel
215132332Smarceltd_err_e
216132332Smarceltd_thr_setgregs(const td_thrhandle_t *th, const prgregset_t gregs)
217132332Smarcel{
218132332Smarcel	const td_thragent_t *ta = th->th_ta;
219132332Smarcel	return (ta->ta_ops->to_thr_setgregs(th, gregs));
220132332Smarcel}
221132332Smarcel
222132332Smarceltd_err_e
223132332Smarceltd_thr_validate(const td_thrhandle_t *th)
224132332Smarcel{
225132332Smarcel	const td_thragent_t *ta = th->th_ta;
226132332Smarcel	return (ta->ta_ops->to_thr_validate(th));
227132332Smarcel}
228132332Smarcel
229133342Sdavidxutd_err_e
230133342Sdavidxutd_thr_tls_get_addr(const td_thrhandle_t *th, void *linkmap, size_t offset,
231133342Sdavidxu		    void **address)
232133342Sdavidxu{
233133342Sdavidxu	const td_thragent_t *ta = th->th_ta;
234133342Sdavidxu	return (ta->ta_ops->to_thr_tls_get_addr(th, linkmap, offset, address));
235133342Sdavidxu}
236133342Sdavidxu
237132332Smarcel/* FreeBSD specific extensions. */
238132332Smarcel
239132332Smarceltd_err_e
240132332Smarceltd_thr_sstep(const td_thrhandle_t *th, int step)
241132332Smarcel{
242132332Smarcel	const td_thragent_t *ta = th->th_ta;
243132332Smarcel	return (ta->ta_ops->to_thr_sstep(th, step));
244132332Smarcel}
245