]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libthread_db/libthr_db.c
This commit was generated by cvs2svn to compensate for changes in r141867,
[FreeBSD/FreeBSD.git] / lib / libthread_db / libthr_db.c
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$");
29
30 #include <proc_service.h>
31 #include <stdlib.h>
32 #include <thread_db.h>
33
34 #include "thread_db_int.h"
35
36 struct 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
45 static td_err_e
46 libthr_db_init()
47 {
48         return (TD_OK);
49 }
50
51 static td_err_e
52 libthr_db_ta_clear_event(const td_thragent_t *ta, td_thr_events_t *ev)
53 {
54         return (TD_ERR);
55 }
56
57 static td_err_e
58 libthr_db_ta_delete(td_thragent_t *ta)
59 {
60         free(ta);
61         return (TD_OK);
62 }
63
64 static td_err_e
65 libthr_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
71 static td_err_e
72 libthr_db_ta_event_getmsg(const td_thragent_t *ta, td_event_msg_t *msg)
73 {
74         return (TD_ERR);
75 }
76
77 static td_err_e
78 libthr_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
111 static td_err_e
112 libthr_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
144 static td_err_e
145 libthr_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
192 static td_err_e
193 libthr_db_ta_set_event(const td_thragent_t *ta, td_thr_events_t *ev)
194 {
195         return (TD_ERR);
196 }
197
198 static td_err_e
199 libthr_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
229 static td_err_e
230 libthr_db_thr_clear_event(const td_thrhandle_t *th, td_thr_events_t *ev)
231 {
232         return (TD_ERR);
233 }
234
235 static td_err_e
236 libthr_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
244 static td_err_e
245 libthr_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
253 static td_err_e
254 libthr_db_thr_event_enable(const td_thrhandle_t *th, int oo)
255 {
256         return (TD_ERR);
257 }
258
259 static td_err_e
260 libthr_db_thr_event_getmsg(const td_thrhandle_t *th, td_event_msg_t *msg)
261 {
262         return (TD_ERR);
263 }
264
265 static td_err_e
266 libthr_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
282 static td_err_e
283 libthr_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
293 static td_err_e
294 libthr_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
305 static td_err_e
306 libthr_db_thr_set_event(const td_thrhandle_t *th, td_thr_events_t *ev)
307 {
308         return (TD_ERR);
309 }
310
311 static td_err_e
312 libthr_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
320 static td_err_e
321 libthr_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
329 static td_err_e
330 libthr_db_thr_validate(const td_thrhandle_t *th)
331 {
332         return (TD_ERR);
333 }
334
335 static td_err_e
336 libthr_db_sstep(const td_thrhandle_t *th, int step)
337 {
338         return (TD_OK);
339 }
340
341 struct 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 };