libthr_db.c revision 133631
1/*
2 * Copyright (c) 2004 Marcel Moolenaar
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 *
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/lib/libthread_db/libthr_db.c 133631 2004-08-13 06:47:33Z davidxu $");
29
30#include <proc_service.h>
31#include <stdlib.h>
32#include <thread_db.h>
33
34#include "thread_db_int.h"
35
36struct td_thragent {
37	TD_THRAGENT_FIELDS;
38	struct ps_prochandle	*ta_ph;
39	psaddr_t ta_thread_list;
40	int	ta_ofs_ctx;
41	int	ta_ofs_next;
42	int	ta_ofs_thr_id;
43};
44
45static td_err_e
46libthr_db_init()
47{
48	return (TD_OK);
49}
50
51static td_err_e
52libthr_db_ta_clear_event(const td_thragent_t *ta, td_thr_events_t *ev)
53{
54	return (TD_ERR);
55}
56
57static td_err_e
58libthr_db_ta_delete(td_thragent_t *ta)
59{
60	free(ta);
61	return (TD_OK);
62}
63
64static td_err_e
65libthr_db_ta_event_addr(const td_thragent_t *ta, td_thr_events_e event,
66    td_notify_t *n)
67{
68	return (TD_ERR);
69}
70
71static td_err_e
72libthr_db_ta_event_getmsg(const td_thragent_t *ta, td_event_msg_t *msg)
73{
74	return (TD_ERR);
75}
76
77static td_err_e
78libthr_db_ta_map_id2thr(const td_thragent_t *ta, thread_t tid,
79    td_thrhandle_t *th)
80{
81	psaddr_t addr;
82	ps_err_e err;
83	thread_t lwpid;
84
85	th->th_ta = ta;
86
87	err = ps_pread(ta->ta_ph, ta->ta_thread_list, &th->th_thread,
88	    sizeof(th->th_thread));
89	if (err != PS_OK)
90		return (TD_ERR);
91	while (th->th_thread != NULL) {
92		addr = (psaddr_t)((uintptr_t)th->th_thread +
93		    ta->ta_ofs_thr_id);
94		err = ps_pread(ta->ta_ph, addr, &lwpid, sizeof(thread_t));
95		if (err != PS_OK)
96			return (TD_ERR);
97		if (tid == lwpid) {
98			th->th_tid = tid;
99			return (TD_OK);
100		}
101		addr = (psaddr_t)((uintptr_t)th->th_thread + ta->ta_ofs_next);
102		err = ps_pread(ta->ta_ph, addr, &th->th_thread,
103		    sizeof(th->th_thread));
104		if (err != PS_OK)
105			return (TD_ERR);
106	}
107
108	return (TD_NOTHR);
109}
110
111static td_err_e
112libthr_db_ta_map_lwp2thr(const td_thragent_t *ta, lwpid_t lwpid,
113    td_thrhandle_t *th)
114{
115	psaddr_t addr;
116	thread_t tid;
117	ps_err_e err;
118
119	th->th_ta = ta;
120
121	err = ps_pread(ta->ta_ph, ta->ta_thread_list, &th->th_thread,
122	    sizeof(th->th_thread));
123	if (err != PS_OK)
124		return (TD_ERR);
125	while (th->th_thread != NULL) {
126		addr = (psaddr_t)((uintptr_t)th->th_thread +
127		    ta->ta_ofs_thr_id);
128		err = ps_pread(ta->ta_ph, addr, &tid, sizeof(thread_t));
129		if (err != PS_OK)
130			return (TD_ERR);
131		if (tid == lwpid) {
132			th->th_tid = tid;
133			return (TD_OK);
134		}
135		addr = (psaddr_t)((uintptr_t)th->th_thread + ta->ta_ofs_next);
136		err = ps_pread(ta->ta_ph, addr, &th->th_thread,
137		    sizeof(th->th_thread));
138		if (err != PS_OK)
139			return (TD_ERR);
140	}
141	return (TD_ERR);
142}
143
144static td_err_e
145libthr_db_ta_new(struct ps_prochandle *ph, td_thragent_t **ta_p)
146{
147	td_thragent_t *ta;
148	psaddr_t addr;
149	ps_err_e err;
150
151	err = ps_pglobal_lookup(ph, NULL, "_libthr_debug", &addr);
152	if (err != PS_OK)
153		return (TD_NOLIBTHREAD);
154
155	ta = malloc(sizeof(td_thragent_t));
156	if (ta == NULL)
157		return (TD_MALLOC);
158
159	ta->ta_ph = ph;
160
161	err = ps_pglobal_lookup(ph, NULL, "_thread_list", &ta->ta_thread_list);
162	if (err != PS_OK)
163		goto fail;
164	err = ps_pglobal_lookup(ph, NULL, "_thread_ctx_offset", &addr);
165	if (err != PS_OK)
166		goto fail;
167	err = ps_pread(ph, addr, &ta->ta_ofs_ctx, sizeof(int));
168	if (err != PS_OK)
169		goto fail;
170	err = ps_pglobal_lookup(ph, NULL, "_thread_next_offset", &addr);
171	if (err != PS_OK)
172		goto fail;
173	err = ps_pread(ph, addr, &ta->ta_ofs_next, sizeof(int));
174	if (err != PS_OK)
175		goto fail;
176	err = ps_pglobal_lookup(ph, NULL, "_thread_thr_id_offset", &addr);
177	if (err != PS_OK)
178		goto fail;
179	err = ps_pread(ph, addr, &ta->ta_ofs_thr_id, sizeof(int));
180	if (err != PS_OK)
181		goto fail;
182
183	*ta_p = ta;
184	return (TD_OK);
185
186 fail:
187	free(ta);
188	*ta_p = NULL;
189	return (TD_ERR);
190}
191
192static td_err_e
193libthr_db_ta_set_event(const td_thragent_t *ta, td_thr_events_t *ev)
194{
195	return (TD_ERR);
196}
197
198static td_err_e
199libthr_db_ta_thr_iter(const td_thragent_t *ta, td_thr_iter_f *cb, void *data,
200    td_thr_state_e state, int pri, sigset_t *mask, unsigned int flags)
201{
202	td_thrhandle_t th;
203	psaddr_t addr;
204	ps_err_e err;
205
206	th.th_ta = ta;
207
208	err = ps_pread(ta->ta_ph, ta->ta_thread_list, &th.th_thread,
209	    sizeof(th.th_thread));
210	if (err != PS_OK)
211		return (TD_ERR);
212	while (th.th_thread != NULL) {
213		addr = (psaddr_t)((uintptr_t)th.th_thread +
214		    ta->ta_ofs_thr_id);
215		err = ps_pread(ta->ta_ph, addr, &th.th_tid, sizeof(thread_t));
216		if (err != PS_OK)
217			return (TD_ERR);
218		if (cb(&th, data) != 0)
219			return (TD_OK);
220		addr = (psaddr_t)((uintptr_t)th.th_thread + ta->ta_ofs_next);
221		err = ps_pread(ta->ta_ph, addr, &th.th_thread,
222		    sizeof(th.th_thread));
223		if (err != PS_OK)
224			return (TD_ERR);
225	}
226	return (TD_OK);
227}
228
229static td_err_e
230libthr_db_thr_clear_event(const td_thrhandle_t *th, td_thr_events_t *ev)
231{
232	return (TD_ERR);
233}
234
235static td_err_e
236libthr_dbresume(const td_thrhandle_t *th)
237{
238	ps_err_e err;
239
240	err = ps_lcontinue(th->th_ta->ta_ph, (lwpid_t)th->th_tid);
241	return ((err == PS_OK) ? TD_OK : TD_ERR);
242}
243
244static td_err_e
245libthr_dbsuspend(const td_thrhandle_t *th)
246{
247	ps_err_e err;
248
249	err = ps_lstop(th->th_ta->ta_ph, (lwpid_t)th->th_tid);
250	return ((err == PS_OK) ? TD_OK : TD_ERR);
251}
252
253static td_err_e
254libthr_db_thr_event_enable(const td_thrhandle_t *th, int oo)
255{
256	return (TD_ERR);
257}
258
259static td_err_e
260libthr_db_thr_event_getmsg(const td_thrhandle_t *th, td_event_msg_t *msg)
261{
262	return (TD_ERR);
263}
264
265static td_err_e
266libthr_db_thr_get_info(const td_thrhandle_t *th, td_thrinfo_t *ti)
267{
268	const td_thragent_t *ta;
269	psaddr_t addr;
270	thread_t tid;
271	ps_err_e err;
272
273	ta = th->th_ta;
274	ti->ti_ta_p = ta;
275	addr = (psaddr_t)((uintptr_t)th->th_thread + ta->ta_ofs_thr_id);
276	err = ps_pread(ta->ta_ph, addr, &tid, sizeof(thread_t));
277	ti->ti_lid = tid;
278	ti->ti_tid = tid;
279	return ((err == PS_OK) ? TD_OK : TD_ERR);
280}
281
282static td_err_e
283libthr_db_thr_getfpregs(const td_thrhandle_t *th, prfpregset_t *r)
284{
285	const td_thragent_t *ta;
286	ps_err_e err;
287
288	ta = th->th_ta;
289	err = ps_lgetfpregs(ta->ta_ph, (lwpid_t)th->th_tid, r);
290	return ((err == PS_OK) ? TD_OK : TD_ERR);
291}
292
293static td_err_e
294libthr_db_thr_getgregs(const td_thrhandle_t *th, prgregset_t r)
295{
296	const td_thragent_t *ta;
297	psaddr_t addr;
298	ps_err_e err;
299
300	ta = th->th_ta;
301	err = ps_lgetregs(ta->ta_ph, (lwpid_t)th->th_tid, r);
302	return ((err == PS_OK) ? TD_OK : TD_ERR);
303}
304
305static td_err_e
306libthr_db_thr_set_event(const td_thrhandle_t *th, td_thr_events_t *ev)
307{
308	return (TD_ERR);
309}
310
311static td_err_e
312libthr_db_thr_setfpregs(const td_thrhandle_t *th, const prfpregset_t *r)
313{
314	ps_err_e err;
315
316	err = ps_lsetfpregs(th->th_ta->ta_ph, (lwpid_t)th->th_tid, r);
317	return ((err == PS_OK) ? TD_OK : TD_ERR);
318}
319
320static td_err_e
321libthr_db_thr_setgregs(const td_thrhandle_t *th, const prgregset_t r)
322{
323	ps_err_e err;
324
325	err = ps_lsetregs(th->th_ta->ta_ph, (lwpid_t)th->th_tid, r);
326	return ((err == PS_OK) ? TD_OK : TD_ERR);
327}
328
329static td_err_e
330libthr_db_thr_validate(const td_thrhandle_t *th)
331{
332	return (TD_ERR);
333}
334
335static td_err_e
336libthr_db_sstep(const td_thrhandle_t *th, int step)
337{
338	return (TD_OK);
339}
340
341struct ta_ops libthr_db_ops = {
342	.to_init		= libthr_db_init,
343
344	.to_ta_clear_event	= libthr_db_ta_clear_event,
345	.to_ta_delete		= libthr_db_ta_delete,
346	.to_ta_event_addr	= libthr_db_ta_event_addr,
347	.to_ta_event_getmsg	= libthr_db_ta_event_getmsg,
348	.to_ta_map_id2thr	= libthr_db_ta_map_id2thr,
349	.to_ta_map_lwp2thr	= libthr_db_ta_map_lwp2thr,
350	.to_ta_new		= libthr_db_ta_new,
351	.to_ta_set_event	= libthr_db_ta_set_event,
352	.to_ta_thr_iter		= libthr_db_ta_thr_iter,
353	.to_thr_clear_event     = libthr_db_thr_clear_event,
354	.to_thr_dbresume	= libthr_dbresume,
355	.to_thr_dbsuspend	= libthr_dbsuspend,
356	.to_thr_event_enable    = libthr_db_thr_event_enable,
357	.to_thr_event_getmsg	= libthr_db_thr_event_getmsg,
358	.to_thr_get_info        = libthr_db_thr_get_info,
359	.to_thr_getfpregs       = libthr_db_thr_getfpregs,
360	.to_thr_getgregs        = libthr_db_thr_getgregs,
361	.to_thr_set_event       = libthr_db_thr_set_event,
362	.to_thr_setfpregs       = libthr_db_thr_setfpregs,
363	.to_thr_setgregs        = libthr_db_thr_setgregs,
364	.to_thr_validate        = libthr_db_thr_validate,
365
366	/* FreeBSD specific extensions. */
367	.to_thr_sstep		= libthr_db_sstep
368};
369