2 * Copyright (c) 2004 Marcel Moolenaar
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
30 #include <machine/setjmp.h>
31 #include <sys/linker_set.h>
32 #include <proc_service.h>
35 #include <thread_db.h>
37 #include "thread_db_int.h"
39 void libc_r_md_getfpregs(jmp_buf jb
, prfpregset_t
*);
40 void libc_r_md_getgregs(jmp_buf jb
, prgregset_t
);
44 struct ps_prochandle
*ta_ph
;
45 psaddr_t ta_thread_initial
;
46 psaddr_t ta_thread_list
;
47 psaddr_t ta_thread_run
;
60 libc_r_db_ta_clear_event(const td_thragent_t
*ta
, td_thr_events_t
*ev
)
66 libc_r_db_ta_delete(td_thragent_t
*ta
)
73 libc_r_db_ta_event_addr(const td_thragent_t
*ta
, td_thr_events_e ev
,
80 libc_r_db_ta_event_getmsg(const td_thragent_t
*ta
, td_event_msg_t
*msg
)
86 libc_r_db_ta_map_id2thr(const td_thragent_t
*ta
, thread_t tid
,
93 libc_r_db_ta_map_lwp2thr(const td_thragent_t
*ta
, lwpid_t lwpid
,
100 err
= ps_pread(ta
->ta_ph
, ta
->ta_thread_initial
, &addr
, sizeof(addr
));
105 err
= ps_pread(ta
->ta_ph
, ta
->ta_thread_run
, &th
->th_thread
,
107 return ((err
== PS_OK
) ? TD_OK
: TD_ERR
);
111 libc_r_db_ta_new(struct ps_prochandle
*ph
, td_thragent_t
**ta_p
)
117 ta
= malloc(sizeof(td_thragent_t
));
123 err
= ps_pglobal_lookup(ph
, NULL
, "_thread_initial",
124 &ta
->ta_thread_initial
);
127 err
= ps_pglobal_lookup(ph
, NULL
, "_thread_list", &ta
->ta_thread_list
);
130 err
= ps_pglobal_lookup(ph
, NULL
, "_thread_run", &ta
->ta_thread_run
);
133 err
= ps_pglobal_lookup(ph
, NULL
, "_thread_ctx_offset", &addr
);
136 err
= ps_pread(ph
, addr
, &ta
->ta_ofs_ctx
, sizeof(int));
139 err
= ps_pglobal_lookup(ph
, NULL
, "_thread_next_offset", &addr
);
142 err
= ps_pread(ph
, addr
, &ta
->ta_ofs_next
, sizeof(int));
145 err
= ps_pglobal_lookup(ph
, NULL
, "_thread_uniqueid_offset", &addr
);
148 err
= ps_pread(ph
, addr
, &ta
->ta_ofs_uniqueid
, sizeof(int));
162 libc_r_db_ta_set_event(const td_thragent_t
*ta
, td_thr_events_t
*ev
)
168 libc_r_db_ta_thr_iter(const td_thragent_t
*ta
, td_thr_iter_f
*cb
, void *data
,
169 td_thr_state_e state
, int pri
, sigset_t
*mask
, unsigned int flags
)
177 err
= ps_pread(ta
->ta_ph
, ta
->ta_thread_list
, &th
.th_thread
,
178 sizeof(th
.th_thread
));
181 while (th
.th_thread
!= NULL
) {
182 if (cb(&th
, data
) != 0)
184 addr
= (psaddr_t
)((uintptr_t)th
.th_thread
+ ta
->ta_ofs_next
);
185 err
= ps_pread(ta
->ta_ph
, addr
, &th
.th_thread
,
186 sizeof(th
.th_thread
));
194 libc_r_db_thr_clear_event(const td_thrhandle_t
*th
, td_thr_events_t
*ev
)
200 libc_r_db_thr_event_enable(const td_thrhandle_t
*th
, int oo
)
206 libc_r_db_thr_event_getmsg(const td_thrhandle_t
*th
, td_event_msg_t
*msg
)
212 libc_r_db_thr_get_info(const td_thrhandle_t
*th
, td_thrinfo_t
*ti
)
214 const td_thragent_t
*ta
;
215 psaddr_t addr
, current
;
220 err
= ps_pread(ta
->ta_ph
, ta
->ta_thread_run
, ¤t
,
224 ti
->ti_lid
= (th
->th_thread
== current
) ? -1 : 0;
225 addr
= (psaddr_t
)((uintptr_t)th
->th_thread
+ ta
->ta_ofs_uniqueid
);
226 err
= ps_pread(ta
->ta_ph
, addr
, &ti
->ti_tid
, sizeof(thread_t
));
227 /* libc_r numbers its threads starting with 0. Not smart. */
229 return ((err
== PS_OK
) ? TD_OK
: TD_ERR
);
234 libc_r_db_thr_getxmmregs(const td_thrhandle_t
*th
, char *fxsave
)
236 return (TD_NOFPREGS
);
241 libc_r_db_thr_getfpregs(const td_thrhandle_t
*th
, prfpregset_t
*r
)
244 const td_thragent_t
*ta
;
249 err
= ps_lgetfpregs(ta
->ta_ph
, -1, r
);
252 err
= ps_pread(ta
->ta_ph
, ta
->ta_thread_run
, &addr
, sizeof(psaddr_t
));
255 if (th
->th_thread
== addr
)
257 addr
= (psaddr_t
)((uintptr_t)th
->th_thread
+ ta
->ta_ofs_ctx
);
258 err
= ps_pread(ta
->ta_ph
, addr
, jb
, sizeof(jb
));
261 libc_r_md_getfpregs(jb
, r
);
266 libc_r_db_thr_getgregs(const td_thrhandle_t
*th
, prgregset_t r
)
269 const td_thragent_t
*ta
;
274 err
= ps_lgetregs(ta
->ta_ph
, -1, r
);
277 err
= ps_pread(ta
->ta_ph
, ta
->ta_thread_run
, &addr
, sizeof(psaddr_t
));
280 if (th
->th_thread
== addr
)
282 addr
= (psaddr_t
)((uintptr_t)th
->th_thread
+ ta
->ta_ofs_ctx
);
283 err
= ps_pread(ta
->ta_ph
, addr
, jb
, sizeof(jb
));
286 libc_r_md_getgregs(jb
, r
);
291 libc_r_db_thr_set_event(const td_thrhandle_t
*th
, td_thr_events_t
*ev
)
298 libc_r_db_thr_setxmmregs(const td_thrhandle_t
*th
, const char *fxsave
)
300 return (TD_NOFPREGS
);
305 libc_r_db_thr_setfpregs(const td_thrhandle_t
*th
, const prfpregset_t
*r
)
311 libc_r_db_thr_setgregs(const td_thrhandle_t
*th
, const prgregset_t r
)
317 libc_r_db_thr_validate(const td_thrhandle_t
*th
)
322 struct ta_ops libc_r_db_ops
= {
323 .to_init
= libc_r_db_init
,
325 .to_ta_clear_event
= libc_r_db_ta_clear_event
,
326 .to_ta_delete
= libc_r_db_ta_delete
,
327 .to_ta_event_addr
= libc_r_db_ta_event_addr
,
328 .to_ta_event_getmsg
= libc_r_db_ta_event_getmsg
,
329 .to_ta_map_id2thr
= libc_r_db_ta_map_id2thr
,
330 .to_ta_map_lwp2thr
= libc_r_db_ta_map_lwp2thr
,
331 .to_ta_new
= libc_r_db_ta_new
,
332 .to_ta_set_event
= libc_r_db_ta_set_event
,
333 .to_ta_thr_iter
= libc_r_db_ta_thr_iter
,
335 .to_thr_clear_event
= libc_r_db_thr_clear_event
,
336 .to_thr_event_enable
= libc_r_db_thr_event_enable
,
337 .to_thr_event_getmsg
= libc_r_db_thr_event_getmsg
,
338 .to_thr_get_info
= libc_r_db_thr_get_info
,
339 .to_thr_getfpregs
= libc_r_db_thr_getfpregs
,
340 .to_thr_getgregs
= libc_r_db_thr_getgregs
,
341 .to_thr_set_event
= libc_r_db_thr_set_event
,
342 .to_thr_setfpregs
= libc_r_db_thr_setfpregs
,
343 .to_thr_setgregs
= libc_r_db_thr_setgregs
,
344 .to_thr_validate
= libc_r_db_thr_validate
,
346 .to_thr_getxmmregs
= libc_r_db_thr_getxmmregs
,
347 .to_thr_setxmmregs
= libc_r_db_thr_setxmmregs
,
351 DATA_SET(__ta_ops
, libc_r_db_ops
);