1*86d7f5d3SJohn Marino /*
2*86d7f5d3SJohn Marino * Copyright (c) 2004 Marcel Moolenaar
3*86d7f5d3SJohn Marino * Copyright (c) 2005 David Xu
4*86d7f5d3SJohn Marino * All rights reserved.
5*86d7f5d3SJohn Marino *
6*86d7f5d3SJohn Marino * Redistribution and use in source and binary forms, with or without
7*86d7f5d3SJohn Marino * modification, are permitted provided that the following conditions
8*86d7f5d3SJohn Marino * are met:
9*86d7f5d3SJohn Marino *
10*86d7f5d3SJohn Marino * 1. Redistributions of source code must retain the above copyright
11*86d7f5d3SJohn Marino * notice, this list of conditions and the following disclaimer.
12*86d7f5d3SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright
13*86d7f5d3SJohn Marino * notice, this list of conditions and the following disclaimer in the
14*86d7f5d3SJohn Marino * documentation and/or other materials provided with the distribution.
15*86d7f5d3SJohn Marino *
16*86d7f5d3SJohn Marino * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17*86d7f5d3SJohn Marino * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18*86d7f5d3SJohn Marino * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19*86d7f5d3SJohn Marino * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20*86d7f5d3SJohn Marino * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21*86d7f5d3SJohn Marino * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22*86d7f5d3SJohn Marino * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23*86d7f5d3SJohn Marino * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24*86d7f5d3SJohn Marino * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25*86d7f5d3SJohn Marino * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*86d7f5d3SJohn Marino *
27*86d7f5d3SJohn Marino * $DragonFly: src/lib/libthread_db/libthread_xu.c,v 1.3 2005/05/07 10:08:08 davidxu Exp $
28*86d7f5d3SJohn Marino */
29*86d7f5d3SJohn Marino
30*86d7f5d3SJohn Marino #include <sys/cdefs.h>
31*86d7f5d3SJohn Marino
32*86d7f5d3SJohn Marino #include <proc_service.h>
33*86d7f5d3SJohn Marino #include <stddef.h>
34*86d7f5d3SJohn Marino #include <stdlib.h>
35*86d7f5d3SJohn Marino #include <string.h>
36*86d7f5d3SJohn Marino #include <machine/tls.h>
37*86d7f5d3SJohn Marino #include <sys/types.h>
38*86d7f5d3SJohn Marino #include <sys/ptrace.h>
39*86d7f5d3SJohn Marino #include <rtld.h>
40*86d7f5d3SJohn Marino #include <thread_db.h>
41*86d7f5d3SJohn Marino #include <unistd.h>
42*86d7f5d3SJohn Marino
43*86d7f5d3SJohn Marino #include "thread_db_int.h"
44*86d7f5d3SJohn Marino
45*86d7f5d3SJohn Marino #define TERMINATED 1
46*86d7f5d3SJohn Marino
47*86d7f5d3SJohn Marino struct td_thragent {
48*86d7f5d3SJohn Marino TD_THRAGENT_FIELDS;
49*86d7f5d3SJohn Marino psaddr_t libthread_xu_debug_addr;
50*86d7f5d3SJohn Marino psaddr_t thread_active_threads_addr;
51*86d7f5d3SJohn Marino psaddr_t thread_bp_create_addr;
52*86d7f5d3SJohn Marino psaddr_t thread_bp_death_addr;
53*86d7f5d3SJohn Marino psaddr_t thread_event_mask_addr;
54*86d7f5d3SJohn Marino psaddr_t thread_keytable_addr;
55*86d7f5d3SJohn Marino psaddr_t thread_last_event_addr;
56*86d7f5d3SJohn Marino psaddr_t thread_list_addr;
57*86d7f5d3SJohn Marino int thread_max_keys;
58*86d7f5d3SJohn Marino int thread_off_attr_flags;
59*86d7f5d3SJohn Marino int thread_off_dtv;
60*86d7f5d3SJohn Marino int thread_off_event_buf;
61*86d7f5d3SJohn Marino int thread_off_event_mask;
62*86d7f5d3SJohn Marino int thread_off_key_allocated;
63*86d7f5d3SJohn Marino int thread_off_key_destructor;
64*86d7f5d3SJohn Marino int thread_off_linkmap;
65*86d7f5d3SJohn Marino int thread_off_next;
66*86d7f5d3SJohn Marino int thread_off_report_events;
67*86d7f5d3SJohn Marino int thread_off_state;
68*86d7f5d3SJohn Marino int thread_off_tcb;
69*86d7f5d3SJohn Marino int thread_off_tid;
70*86d7f5d3SJohn Marino int thread_off_tlsindex;
71*86d7f5d3SJohn Marino int thread_size_key;
72*86d7f5d3SJohn Marino int thread_state_running;
73*86d7f5d3SJohn Marino int thread_state_zoombie;
74*86d7f5d3SJohn Marino };
75*86d7f5d3SJohn Marino
76*86d7f5d3SJohn Marino #define P2T(c) ps2td(c)
77*86d7f5d3SJohn Marino
78*86d7f5d3SJohn Marino static int pt_validate(const td_thrhandle_t *th);
79*86d7f5d3SJohn Marino
80*86d7f5d3SJohn Marino static int
ps2td(int c)81*86d7f5d3SJohn Marino ps2td(int c)
82*86d7f5d3SJohn Marino {
83*86d7f5d3SJohn Marino switch (c) {
84*86d7f5d3SJohn Marino case PS_OK:
85*86d7f5d3SJohn Marino return TD_OK;
86*86d7f5d3SJohn Marino case PS_ERR:
87*86d7f5d3SJohn Marino return TD_ERR;
88*86d7f5d3SJohn Marino case PS_BADPID:
89*86d7f5d3SJohn Marino return TD_BADPH;
90*86d7f5d3SJohn Marino case PS_BADLID:
91*86d7f5d3SJohn Marino return TD_NOLWP;
92*86d7f5d3SJohn Marino case PS_BADADDR:
93*86d7f5d3SJohn Marino return TD_ERR;
94*86d7f5d3SJohn Marino case PS_NOSYM:
95*86d7f5d3SJohn Marino return TD_NOLIBTHREAD;
96*86d7f5d3SJohn Marino case PS_NOFREGS:
97*86d7f5d3SJohn Marino return TD_NOFPREGS;
98*86d7f5d3SJohn Marino default:
99*86d7f5d3SJohn Marino return TD_ERR;
100*86d7f5d3SJohn Marino }
101*86d7f5d3SJohn Marino }
102*86d7f5d3SJohn Marino
103*86d7f5d3SJohn Marino static td_err_e
pt_init(void)104*86d7f5d3SJohn Marino pt_init(void)
105*86d7f5d3SJohn Marino {
106*86d7f5d3SJohn Marino return (0);
107*86d7f5d3SJohn Marino }
108*86d7f5d3SJohn Marino
109*86d7f5d3SJohn Marino static td_err_e
pt_ta_new(struct ps_prochandle * ph,td_thragent_t ** pta)110*86d7f5d3SJohn Marino pt_ta_new(struct ps_prochandle *ph, td_thragent_t **pta)
111*86d7f5d3SJohn Marino {
112*86d7f5d3SJohn Marino #define LOOKUP_SYM(proc, sym, addr) \
113*86d7f5d3SJohn Marino ret = ps_pglobal_lookup(proc, NULL, sym, addr); \
114*86d7f5d3SJohn Marino if (ret != 0) { \
115*86d7f5d3SJohn Marino TDBG("can not find symbol: %s\n", sym); \
116*86d7f5d3SJohn Marino ret = TD_NOLIBTHREAD; \
117*86d7f5d3SJohn Marino goto error; \
118*86d7f5d3SJohn Marino }
119*86d7f5d3SJohn Marino
120*86d7f5d3SJohn Marino #define LOOKUP_VAL(proc, sym, val) \
121*86d7f5d3SJohn Marino ret = ps_pglobal_lookup(proc, NULL, sym, &vaddr);\
122*86d7f5d3SJohn Marino if (ret != 0) { \
123*86d7f5d3SJohn Marino TDBG("can not find symbol: %s\n", sym); \
124*86d7f5d3SJohn Marino ret = TD_NOLIBTHREAD; \
125*86d7f5d3SJohn Marino goto error; \
126*86d7f5d3SJohn Marino } \
127*86d7f5d3SJohn Marino ret = ps_pread(proc, vaddr, val, sizeof(int)); \
128*86d7f5d3SJohn Marino if (ret != 0) { \
129*86d7f5d3SJohn Marino TDBG("can not read value of %s\n", sym);\
130*86d7f5d3SJohn Marino ret = TD_NOLIBTHREAD; \
131*86d7f5d3SJohn Marino goto error; \
132*86d7f5d3SJohn Marino }
133*86d7f5d3SJohn Marino
134*86d7f5d3SJohn Marino td_thragent_t *ta;
135*86d7f5d3SJohn Marino psaddr_t vaddr;
136*86d7f5d3SJohn Marino int dbg;
137*86d7f5d3SJohn Marino int ret;
138*86d7f5d3SJohn Marino
139*86d7f5d3SJohn Marino TDBG_FUNC();
140*86d7f5d3SJohn Marino
141*86d7f5d3SJohn Marino ta = malloc(sizeof(td_thragent_t));
142*86d7f5d3SJohn Marino if (ta == NULL)
143*86d7f5d3SJohn Marino return (TD_MALLOC);
144*86d7f5d3SJohn Marino
145*86d7f5d3SJohn Marino ta->ph = ph;
146*86d7f5d3SJohn Marino
147*86d7f5d3SJohn Marino LOOKUP_SYM(ph, "_libthread_xu_debug", &ta->libthread_xu_debug_addr);
148*86d7f5d3SJohn Marino LOOKUP_SYM(ph, "_thread_active_threads",&ta->thread_active_threads_addr);
149*86d7f5d3SJohn Marino LOOKUP_SYM(ph, "_thread_bp_create", &ta->thread_bp_create_addr);
150*86d7f5d3SJohn Marino LOOKUP_SYM(ph, "_thread_bp_death", &ta->thread_bp_death_addr);
151*86d7f5d3SJohn Marino LOOKUP_SYM(ph, "_thread_event_mask", &ta->thread_event_mask_addr);
152*86d7f5d3SJohn Marino LOOKUP_SYM(ph, "_thread_keytable", &ta->thread_keytable_addr);
153*86d7f5d3SJohn Marino LOOKUP_SYM(ph, "_thread_last_event", &ta->thread_last_event_addr);
154*86d7f5d3SJohn Marino LOOKUP_SYM(ph, "_thread_list", &ta->thread_list_addr);
155*86d7f5d3SJohn Marino LOOKUP_VAL(ph, "_thread_max_keys", &ta->thread_max_keys);
156*86d7f5d3SJohn Marino LOOKUP_VAL(ph, "_thread_off_attr_flags", &ta->thread_off_attr_flags);
157*86d7f5d3SJohn Marino LOOKUP_VAL(ph, "_thread_off_event_buf", &ta->thread_off_event_buf);
158*86d7f5d3SJohn Marino LOOKUP_VAL(ph, "_thread_off_event_mask", &ta->thread_off_event_mask);
159*86d7f5d3SJohn Marino LOOKUP_VAL(ph, "_thread_off_key_allocated", &ta->thread_off_key_allocated);
160*86d7f5d3SJohn Marino LOOKUP_VAL(ph, "_thread_off_key_destructor", &ta->thread_off_key_destructor);
161*86d7f5d3SJohn Marino LOOKUP_VAL(ph, "_thread_off_next", &ta->thread_off_next);
162*86d7f5d3SJohn Marino LOOKUP_VAL(ph, "_thread_off_report_events", &ta->thread_off_report_events);
163*86d7f5d3SJohn Marino LOOKUP_VAL(ph, "_thread_off_state", &ta->thread_off_state);
164*86d7f5d3SJohn Marino LOOKUP_VAL(ph, "_thread_off_tcb", &ta->thread_off_tcb);
165*86d7f5d3SJohn Marino LOOKUP_VAL(ph, "_thread_off_tid", &ta->thread_off_tid);
166*86d7f5d3SJohn Marino LOOKUP_VAL(ph, "_thread_size_key", &ta->thread_size_key);
167*86d7f5d3SJohn Marino LOOKUP_VAL(ph, "_thread_state_running", &ta->thread_state_running);
168*86d7f5d3SJohn Marino LOOKUP_VAL(ph, "_thread_state_zoombie", &ta->thread_state_zoombie);
169*86d7f5d3SJohn Marino
170*86d7f5d3SJohn Marino ta->thread_off_linkmap = offsetof(Obj_Entry, linkmap);
171*86d7f5d3SJohn Marino ta->thread_off_tlsindex = offsetof(Obj_Entry, tlsindex);
172*86d7f5d3SJohn Marino ta->thread_off_dtv = offsetof(struct tls_tcb, tcb_dtv);
173*86d7f5d3SJohn Marino
174*86d7f5d3SJohn Marino dbg = getpid();
175*86d7f5d3SJohn Marino /*
176*86d7f5d3SJohn Marino * If this fails it probably means we're debugging a core file and
177*86d7f5d3SJohn Marino * can't write to it.
178*86d7f5d3SJohn Marino */
179*86d7f5d3SJohn Marino ps_pwrite(ph, ta->libthread_xu_debug_addr, &dbg, sizeof(int));
180*86d7f5d3SJohn Marino *pta = ta;
181*86d7f5d3SJohn Marino return (0);
182*86d7f5d3SJohn Marino
183*86d7f5d3SJohn Marino error:
184*86d7f5d3SJohn Marino free(ta);
185*86d7f5d3SJohn Marino return (ret);
186*86d7f5d3SJohn Marino }
187*86d7f5d3SJohn Marino
188*86d7f5d3SJohn Marino static td_err_e
pt_ta_delete(td_thragent_t * ta)189*86d7f5d3SJohn Marino pt_ta_delete(td_thragent_t *ta)
190*86d7f5d3SJohn Marino {
191*86d7f5d3SJohn Marino int dbg;
192*86d7f5d3SJohn Marino
193*86d7f5d3SJohn Marino TDBG_FUNC();
194*86d7f5d3SJohn Marino
195*86d7f5d3SJohn Marino dbg = 0;
196*86d7f5d3SJohn Marino /*
197*86d7f5d3SJohn Marino * Error returns from this write are not really a problem;
198*86d7f5d3SJohn Marino * the process doesn't exist any more.
199*86d7f5d3SJohn Marino */
200*86d7f5d3SJohn Marino ps_pwrite(ta->ph, ta->libthread_xu_debug_addr, &dbg, sizeof(int));
201*86d7f5d3SJohn Marino free(ta);
202*86d7f5d3SJohn Marino return (TD_OK);
203*86d7f5d3SJohn Marino }
204*86d7f5d3SJohn Marino
205*86d7f5d3SJohn Marino static td_err_e
pt_ta_map_id2thr(const td_thragent_t * ta,thread_t id,td_thrhandle_t * th)206*86d7f5d3SJohn Marino pt_ta_map_id2thr(const td_thragent_t *ta, thread_t id, td_thrhandle_t *th)
207*86d7f5d3SJohn Marino {
208*86d7f5d3SJohn Marino prgregset_t gregs;
209*86d7f5d3SJohn Marino TAILQ_HEAD(, pthread) thread_list;
210*86d7f5d3SJohn Marino psaddr_t pt;
211*86d7f5d3SJohn Marino long lwp;
212*86d7f5d3SJohn Marino int ret;
213*86d7f5d3SJohn Marino
214*86d7f5d3SJohn Marino TDBG_FUNC();
215*86d7f5d3SJohn Marino
216*86d7f5d3SJohn Marino if (id == 0)
217*86d7f5d3SJohn Marino return (TD_NOTHR);
218*86d7f5d3SJohn Marino ret = ps_pread(ta->ph, ta->thread_list_addr, &thread_list,
219*86d7f5d3SJohn Marino sizeof(thread_list));
220*86d7f5d3SJohn Marino if (ret != 0)
221*86d7f5d3SJohn Marino return (P2T(ret));
222*86d7f5d3SJohn Marino /* Iterate through thread list to find pthread */
223*86d7f5d3SJohn Marino pt = (psaddr_t)thread_list.tqh_first;
224*86d7f5d3SJohn Marino while (pt != NULL) {
225*86d7f5d3SJohn Marino ret = ps_pread(ta->ph, pt + ta->thread_off_tid,
226*86d7f5d3SJohn Marino &lwp, sizeof(lwp));
227*86d7f5d3SJohn Marino if (ret != 0)
228*86d7f5d3SJohn Marino return (P2T(ret));
229*86d7f5d3SJohn Marino if (lwp == id)
230*86d7f5d3SJohn Marino break;
231*86d7f5d3SJohn Marino /* get next thread */
232*86d7f5d3SJohn Marino ret = ps_pread(ta->ph,
233*86d7f5d3SJohn Marino pt + ta->thread_off_next,
234*86d7f5d3SJohn Marino &pt, sizeof(pt));
235*86d7f5d3SJohn Marino if (ret != 0)
236*86d7f5d3SJohn Marino return (P2T(ret));
237*86d7f5d3SJohn Marino }
238*86d7f5d3SJohn Marino if (pt == NULL)
239*86d7f5d3SJohn Marino return (TD_NOTHR);
240*86d7f5d3SJohn Marino th->th_ta = ta;
241*86d7f5d3SJohn Marino th->th_tid = id;
242*86d7f5d3SJohn Marino th->th_thread = pt;
243*86d7f5d3SJohn Marino return (TD_OK);
244*86d7f5d3SJohn Marino }
245*86d7f5d3SJohn Marino
246*86d7f5d3SJohn Marino static td_err_e
pt_ta_map_lwp2thr(const td_thragent_t * ta,lwpid_t lwp,td_thrhandle_t * th)247*86d7f5d3SJohn Marino pt_ta_map_lwp2thr(const td_thragent_t *ta, lwpid_t lwp, td_thrhandle_t *th)
248*86d7f5d3SJohn Marino {
249*86d7f5d3SJohn Marino return (pt_ta_map_id2thr(ta, lwp, th));
250*86d7f5d3SJohn Marino }
251*86d7f5d3SJohn Marino
252*86d7f5d3SJohn Marino static td_err_e
pt_ta_thr_iter(const td_thragent_t * ta,td_thr_iter_f * callback,void * cbdata_p,td_thr_state_e state,int ti_pri,sigset_t * ti_sigmask_p,unsigned int ti_user_flags)253*86d7f5d3SJohn Marino pt_ta_thr_iter(const td_thragent_t *ta,
254*86d7f5d3SJohn Marino td_thr_iter_f *callback, void *cbdata_p,
255*86d7f5d3SJohn Marino td_thr_state_e state, int ti_pri,
256*86d7f5d3SJohn Marino sigset_t *ti_sigmask_p,
257*86d7f5d3SJohn Marino unsigned int ti_user_flags)
258*86d7f5d3SJohn Marino {
259*86d7f5d3SJohn Marino TAILQ_HEAD(, pthread) thread_list;
260*86d7f5d3SJohn Marino td_thrhandle_t th;
261*86d7f5d3SJohn Marino psaddr_t pt;
262*86d7f5d3SJohn Marino long lwp;
263*86d7f5d3SJohn Marino int ret;
264*86d7f5d3SJohn Marino
265*86d7f5d3SJohn Marino TDBG_FUNC();
266*86d7f5d3SJohn Marino
267*86d7f5d3SJohn Marino ret = ps_pread(ta->ph, ta->thread_list_addr, &thread_list,
268*86d7f5d3SJohn Marino sizeof(thread_list));
269*86d7f5d3SJohn Marino if (ret != 0)
270*86d7f5d3SJohn Marino return (P2T(ret));
271*86d7f5d3SJohn Marino pt = (psaddr_t)thread_list.tqh_first;
272*86d7f5d3SJohn Marino while (pt != 0) {
273*86d7f5d3SJohn Marino ret = ps_pread(ta->ph, pt + ta->thread_off_tid, &lwp,
274*86d7f5d3SJohn Marino sizeof(lwp));
275*86d7f5d3SJohn Marino if (ret != 0)
276*86d7f5d3SJohn Marino return (P2T(ret));
277*86d7f5d3SJohn Marino if (lwp != 0 && lwp != TERMINATED) {
278*86d7f5d3SJohn Marino th.th_ta = ta;
279*86d7f5d3SJohn Marino th.th_tid = (thread_t)lwp;
280*86d7f5d3SJohn Marino th.th_thread = pt;
281*86d7f5d3SJohn Marino if ((*callback)(&th, cbdata_p))
282*86d7f5d3SJohn Marino return (TD_DBERR);
283*86d7f5d3SJohn Marino }
284*86d7f5d3SJohn Marino /* get next thread */
285*86d7f5d3SJohn Marino ret = ps_pread(ta->ph, pt + ta->thread_off_next, &pt,
286*86d7f5d3SJohn Marino sizeof(pt));
287*86d7f5d3SJohn Marino if (ret != 0)
288*86d7f5d3SJohn Marino return (P2T(ret));
289*86d7f5d3SJohn Marino }
290*86d7f5d3SJohn Marino return (TD_OK);
291*86d7f5d3SJohn Marino }
292*86d7f5d3SJohn Marino
293*86d7f5d3SJohn Marino static td_err_e
pt_ta_tsd_iter(const td_thragent_t * ta,td_key_iter_f * ki,void * arg)294*86d7f5d3SJohn Marino pt_ta_tsd_iter(const td_thragent_t *ta, td_key_iter_f *ki, void *arg)
295*86d7f5d3SJohn Marino {
296*86d7f5d3SJohn Marino char *keytable;
297*86d7f5d3SJohn Marino void *destructor;
298*86d7f5d3SJohn Marino int i, ret, allocated;
299*86d7f5d3SJohn Marino
300*86d7f5d3SJohn Marino TDBG_FUNC();
301*86d7f5d3SJohn Marino
302*86d7f5d3SJohn Marino keytable = malloc(ta->thread_max_keys * ta->thread_size_key);
303*86d7f5d3SJohn Marino if (keytable == NULL)
304*86d7f5d3SJohn Marino return (TD_MALLOC);
305*86d7f5d3SJohn Marino ret = ps_pread(ta->ph, (psaddr_t)ta->thread_keytable_addr, keytable,
306*86d7f5d3SJohn Marino ta->thread_max_keys * ta->thread_size_key);
307*86d7f5d3SJohn Marino if (ret != 0) {
308*86d7f5d3SJohn Marino free(keytable);
309*86d7f5d3SJohn Marino return (P2T(ret));
310*86d7f5d3SJohn Marino }
311*86d7f5d3SJohn Marino for (i = 0; i < ta->thread_max_keys; i++) {
312*86d7f5d3SJohn Marino allocated = *(int *)(keytable + i * ta->thread_size_key +
313*86d7f5d3SJohn Marino ta->thread_off_key_allocated);
314*86d7f5d3SJohn Marino destructor = *(void **)(keytable + i * ta->thread_size_key +
315*86d7f5d3SJohn Marino ta->thread_off_key_destructor);
316*86d7f5d3SJohn Marino if (allocated) {
317*86d7f5d3SJohn Marino ret = (ki)(i, destructor, arg);
318*86d7f5d3SJohn Marino if (ret != 0) {
319*86d7f5d3SJohn Marino free(keytable);
320*86d7f5d3SJohn Marino return (TD_DBERR);
321*86d7f5d3SJohn Marino }
322*86d7f5d3SJohn Marino }
323*86d7f5d3SJohn Marino }
324*86d7f5d3SJohn Marino free(keytable);
325*86d7f5d3SJohn Marino return (TD_OK);
326*86d7f5d3SJohn Marino }
327*86d7f5d3SJohn Marino
328*86d7f5d3SJohn Marino static td_err_e
pt_ta_event_addr(const td_thragent_t * ta,td_event_e event,td_notify_t * ptr)329*86d7f5d3SJohn Marino pt_ta_event_addr(const td_thragent_t *ta, td_event_e event, td_notify_t *ptr)
330*86d7f5d3SJohn Marino {
331*86d7f5d3SJohn Marino
332*86d7f5d3SJohn Marino TDBG_FUNC();
333*86d7f5d3SJohn Marino
334*86d7f5d3SJohn Marino switch (event) {
335*86d7f5d3SJohn Marino case TD_CREATE:
336*86d7f5d3SJohn Marino ptr->type = NOTIFY_BPT;
337*86d7f5d3SJohn Marino ptr->u.bptaddr = ta->thread_bp_create_addr;
338*86d7f5d3SJohn Marino return (0);
339*86d7f5d3SJohn Marino case TD_DEATH:
340*86d7f5d3SJohn Marino ptr->type = NOTIFY_BPT;
341*86d7f5d3SJohn Marino ptr->u.bptaddr = ta->thread_bp_death_addr;
342*86d7f5d3SJohn Marino return (0);
343*86d7f5d3SJohn Marino default:
344*86d7f5d3SJohn Marino return (TD_ERR);
345*86d7f5d3SJohn Marino }
346*86d7f5d3SJohn Marino }
347*86d7f5d3SJohn Marino
348*86d7f5d3SJohn Marino static td_err_e
pt_ta_set_event(const td_thragent_t * ta,td_thr_events_t * events)349*86d7f5d3SJohn Marino pt_ta_set_event(const td_thragent_t *ta, td_thr_events_t *events)
350*86d7f5d3SJohn Marino {
351*86d7f5d3SJohn Marino td_thr_events_t mask;
352*86d7f5d3SJohn Marino int ret;
353*86d7f5d3SJohn Marino
354*86d7f5d3SJohn Marino TDBG_FUNC();
355*86d7f5d3SJohn Marino ret = ps_pread(ta->ph, ta->thread_event_mask_addr, &mask,
356*86d7f5d3SJohn Marino sizeof(mask));
357*86d7f5d3SJohn Marino if (ret != 0)
358*86d7f5d3SJohn Marino return (P2T(ret));
359*86d7f5d3SJohn Marino mask |= *events;
360*86d7f5d3SJohn Marino ret = ps_pwrite(ta->ph, ta->thread_event_mask_addr, &mask,
361*86d7f5d3SJohn Marino sizeof(mask));
362*86d7f5d3SJohn Marino return (P2T(ret));
363*86d7f5d3SJohn Marino }
364*86d7f5d3SJohn Marino
365*86d7f5d3SJohn Marino static td_err_e
pt_ta_clear_event(const td_thragent_t * ta,td_thr_events_t * events)366*86d7f5d3SJohn Marino pt_ta_clear_event(const td_thragent_t *ta, td_thr_events_t *events)
367*86d7f5d3SJohn Marino {
368*86d7f5d3SJohn Marino td_thr_events_t mask;
369*86d7f5d3SJohn Marino int ret;
370*86d7f5d3SJohn Marino
371*86d7f5d3SJohn Marino TDBG_FUNC();
372*86d7f5d3SJohn Marino ret = ps_pread(ta->ph, ta->thread_event_mask_addr, &mask,
373*86d7f5d3SJohn Marino sizeof(mask));
374*86d7f5d3SJohn Marino if (ret != 0)
375*86d7f5d3SJohn Marino return (P2T(ret));
376*86d7f5d3SJohn Marino mask &= ~*events;
377*86d7f5d3SJohn Marino ret = ps_pwrite(ta->ph, ta->thread_event_mask_addr, &mask,
378*86d7f5d3SJohn Marino sizeof(mask));
379*86d7f5d3SJohn Marino return (P2T(ret));
380*86d7f5d3SJohn Marino }
381*86d7f5d3SJohn Marino
382*86d7f5d3SJohn Marino static td_err_e
pt_ta_event_getmsg(const td_thragent_t * ta,td_event_msg_t * msg)383*86d7f5d3SJohn Marino pt_ta_event_getmsg(const td_thragent_t *ta, td_event_msg_t *msg)
384*86d7f5d3SJohn Marino {
385*86d7f5d3SJohn Marino static td_thrhandle_t handle;
386*86d7f5d3SJohn Marino
387*86d7f5d3SJohn Marino psaddr_t pt, pt_temp;
388*86d7f5d3SJohn Marino td_thr_events_e tmp;
389*86d7f5d3SJohn Marino long lwp;
390*86d7f5d3SJohn Marino int ret;
391*86d7f5d3SJohn Marino
392*86d7f5d3SJohn Marino TDBG_FUNC();
393*86d7f5d3SJohn Marino
394*86d7f5d3SJohn Marino ret = ps_pread(ta->ph, ta->thread_last_event_addr, &pt, sizeof(pt));
395*86d7f5d3SJohn Marino if (ret != 0)
396*86d7f5d3SJohn Marino return (P2T(ret));
397*86d7f5d3SJohn Marino if (pt == NULL)
398*86d7f5d3SJohn Marino return (TD_NOMSG);
399*86d7f5d3SJohn Marino /*
400*86d7f5d3SJohn Marino * Take the event pointer, at the time, libthr only reports event
401*86d7f5d3SJohn Marino * once a time, so it is not a link list.
402*86d7f5d3SJohn Marino */
403*86d7f5d3SJohn Marino pt_temp = NULL;
404*86d7f5d3SJohn Marino ps_pwrite(ta->ph, ta->thread_last_event_addr, &pt_temp, sizeof(pt_temp));
405*86d7f5d3SJohn Marino
406*86d7f5d3SJohn Marino /* Read event info */
407*86d7f5d3SJohn Marino ret = ps_pread(ta->ph, pt + ta->thread_off_event_buf, msg, sizeof(*msg));
408*86d7f5d3SJohn Marino if (ret != 0)
409*86d7f5d3SJohn Marino return (P2T(ret));
410*86d7f5d3SJohn Marino if (msg->event == 0)
411*86d7f5d3SJohn Marino return (TD_NOMSG);
412*86d7f5d3SJohn Marino /* Clear event */
413*86d7f5d3SJohn Marino tmp = 0;
414*86d7f5d3SJohn Marino ps_pwrite(ta->ph, pt + ta->thread_off_event_buf, &tmp, sizeof(tmp));
415*86d7f5d3SJohn Marino /* Convert event */
416*86d7f5d3SJohn Marino pt = (psaddr_t)msg->th_p;
417*86d7f5d3SJohn Marino ret = ps_pread(ta->ph, pt + ta->thread_off_tid, &lwp, sizeof(lwp));
418*86d7f5d3SJohn Marino if (ret != 0)
419*86d7f5d3SJohn Marino return (P2T(ret));
420*86d7f5d3SJohn Marino handle.th_ta = ta;
421*86d7f5d3SJohn Marino handle.th_tid = lwp;
422*86d7f5d3SJohn Marino handle.th_thread = pt;
423*86d7f5d3SJohn Marino msg->th_p = &handle;
424*86d7f5d3SJohn Marino return (0);
425*86d7f5d3SJohn Marino }
426*86d7f5d3SJohn Marino
427*86d7f5d3SJohn Marino static td_err_e
pt_dbsuspend(const td_thrhandle_t * th,int suspend)428*86d7f5d3SJohn Marino pt_dbsuspend(const td_thrhandle_t *th, int suspend)
429*86d7f5d3SJohn Marino {
430*86d7f5d3SJohn Marino td_thragent_t *ta = (td_thragent_t *)th->th_ta;
431*86d7f5d3SJohn Marino int ret;
432*86d7f5d3SJohn Marino
433*86d7f5d3SJohn Marino TDBG_FUNC();
434*86d7f5d3SJohn Marino
435*86d7f5d3SJohn Marino ret = pt_validate(th);
436*86d7f5d3SJohn Marino if (ret)
437*86d7f5d3SJohn Marino return (ret);
438*86d7f5d3SJohn Marino
439*86d7f5d3SJohn Marino if (suspend)
440*86d7f5d3SJohn Marino ret = ps_lstop(ta->ph, th->th_tid);
441*86d7f5d3SJohn Marino else
442*86d7f5d3SJohn Marino ret = ps_lcontinue(ta->ph, th->th_tid);
443*86d7f5d3SJohn Marino return (P2T(ret));
444*86d7f5d3SJohn Marino }
445*86d7f5d3SJohn Marino
446*86d7f5d3SJohn Marino static td_err_e
pt_thr_dbresume(const td_thrhandle_t * th)447*86d7f5d3SJohn Marino pt_thr_dbresume(const td_thrhandle_t *th)
448*86d7f5d3SJohn Marino {
449*86d7f5d3SJohn Marino TDBG_FUNC();
450*86d7f5d3SJohn Marino
451*86d7f5d3SJohn Marino return pt_dbsuspend(th, 0);
452*86d7f5d3SJohn Marino }
453*86d7f5d3SJohn Marino
454*86d7f5d3SJohn Marino static td_err_e
pt_thr_dbsuspend(const td_thrhandle_t * th)455*86d7f5d3SJohn Marino pt_thr_dbsuspend(const td_thrhandle_t *th)
456*86d7f5d3SJohn Marino {
457*86d7f5d3SJohn Marino TDBG_FUNC();
458*86d7f5d3SJohn Marino
459*86d7f5d3SJohn Marino return pt_dbsuspend(th, 1);
460*86d7f5d3SJohn Marino }
461*86d7f5d3SJohn Marino
462*86d7f5d3SJohn Marino static td_err_e
pt_thr_validate(const td_thrhandle_t * th)463*86d7f5d3SJohn Marino pt_thr_validate(const td_thrhandle_t *th)
464*86d7f5d3SJohn Marino {
465*86d7f5d3SJohn Marino td_thrhandle_t temp;
466*86d7f5d3SJohn Marino int ret;
467*86d7f5d3SJohn Marino
468*86d7f5d3SJohn Marino TDBG_FUNC();
469*86d7f5d3SJohn Marino
470*86d7f5d3SJohn Marino ret = pt_ta_map_id2thr(th->th_ta, th->th_tid, &temp);
471*86d7f5d3SJohn Marino return (ret);
472*86d7f5d3SJohn Marino }
473*86d7f5d3SJohn Marino
474*86d7f5d3SJohn Marino static td_err_e
pt_thr_get_info(const td_thrhandle_t * th,td_thrinfo_t * info)475*86d7f5d3SJohn Marino pt_thr_get_info(const td_thrhandle_t *th, td_thrinfo_t *info)
476*86d7f5d3SJohn Marino {
477*86d7f5d3SJohn Marino const td_thragent_t *ta = th->th_ta;
478*86d7f5d3SJohn Marino int state;
479*86d7f5d3SJohn Marino int ret;
480*86d7f5d3SJohn Marino
481*86d7f5d3SJohn Marino TDBG_FUNC();
482*86d7f5d3SJohn Marino
483*86d7f5d3SJohn Marino ret = pt_validate(th);
484*86d7f5d3SJohn Marino if (ret)
485*86d7f5d3SJohn Marino return (ret);
486*86d7f5d3SJohn Marino ret = ps_pread(ta->ph, th->th_thread + ta->thread_off_state,
487*86d7f5d3SJohn Marino &state, sizeof(state));
488*86d7f5d3SJohn Marino if (ret != 0)
489*86d7f5d3SJohn Marino return (P2T(ret));
490*86d7f5d3SJohn Marino ret = ps_pread(ta->ph, th->th_thread + ta->thread_off_report_events,
491*86d7f5d3SJohn Marino &info->ti_traceme, sizeof(int));
492*86d7f5d3SJohn Marino if (ret != 0)
493*86d7f5d3SJohn Marino return (P2T(ret));
494*86d7f5d3SJohn Marino ret = ps_pread(ta->ph, th->th_thread + ta->thread_off_event_mask,
495*86d7f5d3SJohn Marino &info->ti_events, sizeof(td_thr_events_t));
496*86d7f5d3SJohn Marino if (ret != 0)
497*86d7f5d3SJohn Marino return (P2T(ret));
498*86d7f5d3SJohn Marino ret = ps_pread(ta->ph, th->th_thread + ta->thread_off_tcb,
499*86d7f5d3SJohn Marino &info->ti_tls, sizeof(void *));
500*86d7f5d3SJohn Marino info->ti_lid = th->th_tid;
501*86d7f5d3SJohn Marino info->ti_tid = th->th_tid;
502*86d7f5d3SJohn Marino info->ti_thread = th->th_thread;
503*86d7f5d3SJohn Marino info->ti_ta_p = th->th_ta;
504*86d7f5d3SJohn Marino if (state == ta->thread_state_running)
505*86d7f5d3SJohn Marino info->ti_state = TD_THR_RUN;
506*86d7f5d3SJohn Marino else if (state == ta->thread_state_zoombie)
507*86d7f5d3SJohn Marino info->ti_state = TD_THR_ZOMBIE;
508*86d7f5d3SJohn Marino else
509*86d7f5d3SJohn Marino info->ti_state = TD_THR_SLEEP;
510*86d7f5d3SJohn Marino info->ti_type = TD_THR_USER;
511*86d7f5d3SJohn Marino return (0);
512*86d7f5d3SJohn Marino }
513*86d7f5d3SJohn Marino
514*86d7f5d3SJohn Marino static td_err_e
pt_thr_getfpregs(const td_thrhandle_t * th,prfpregset_t * fpregs)515*86d7f5d3SJohn Marino pt_thr_getfpregs(const td_thrhandle_t *th, prfpregset_t *fpregs)
516*86d7f5d3SJohn Marino {
517*86d7f5d3SJohn Marino const td_thragent_t *ta = th->th_ta;
518*86d7f5d3SJohn Marino int ret;
519*86d7f5d3SJohn Marino
520*86d7f5d3SJohn Marino TDBG_FUNC();
521*86d7f5d3SJohn Marino
522*86d7f5d3SJohn Marino ret = pt_validate(th);
523*86d7f5d3SJohn Marino if (ret)
524*86d7f5d3SJohn Marino return (ret);
525*86d7f5d3SJohn Marino
526*86d7f5d3SJohn Marino ret = ps_lgetfpregs(ta->ph, th->th_tid, fpregs);
527*86d7f5d3SJohn Marino return (P2T(ret));
528*86d7f5d3SJohn Marino }
529*86d7f5d3SJohn Marino
530*86d7f5d3SJohn Marino static td_err_e
pt_thr_getgregs(const td_thrhandle_t * th,prgregset_t gregs)531*86d7f5d3SJohn Marino pt_thr_getgregs(const td_thrhandle_t *th, prgregset_t gregs)
532*86d7f5d3SJohn Marino {
533*86d7f5d3SJohn Marino const td_thragent_t *ta = th->th_ta;
534*86d7f5d3SJohn Marino int ret;
535*86d7f5d3SJohn Marino
536*86d7f5d3SJohn Marino TDBG_FUNC();
537*86d7f5d3SJohn Marino
538*86d7f5d3SJohn Marino ret = pt_validate(th);
539*86d7f5d3SJohn Marino if (ret)
540*86d7f5d3SJohn Marino return (ret);
541*86d7f5d3SJohn Marino
542*86d7f5d3SJohn Marino ret = ps_lgetregs(ta->ph, th->th_tid, gregs);
543*86d7f5d3SJohn Marino return (P2T(ret));
544*86d7f5d3SJohn Marino }
545*86d7f5d3SJohn Marino
546*86d7f5d3SJohn Marino static td_err_e
pt_thr_setfpregs(const td_thrhandle_t * th,const prfpregset_t * fpregs)547*86d7f5d3SJohn Marino pt_thr_setfpregs(const td_thrhandle_t *th, const prfpregset_t *fpregs)
548*86d7f5d3SJohn Marino {
549*86d7f5d3SJohn Marino const td_thragent_t *ta = th->th_ta;
550*86d7f5d3SJohn Marino int ret;
551*86d7f5d3SJohn Marino
552*86d7f5d3SJohn Marino TDBG_FUNC();
553*86d7f5d3SJohn Marino
554*86d7f5d3SJohn Marino ret = pt_validate(th);
555*86d7f5d3SJohn Marino if (ret)
556*86d7f5d3SJohn Marino return (ret);
557*86d7f5d3SJohn Marino
558*86d7f5d3SJohn Marino ret = ps_lsetfpregs(ta->ph, th->th_tid, fpregs);
559*86d7f5d3SJohn Marino return (P2T(ret));
560*86d7f5d3SJohn Marino }
561*86d7f5d3SJohn Marino
562*86d7f5d3SJohn Marino static td_err_e
pt_thr_setgregs(const td_thrhandle_t * th,const prgregset_t gregs)563*86d7f5d3SJohn Marino pt_thr_setgregs(const td_thrhandle_t *th, const prgregset_t gregs)
564*86d7f5d3SJohn Marino {
565*86d7f5d3SJohn Marino const td_thragent_t *ta = th->th_ta;
566*86d7f5d3SJohn Marino int ret;
567*86d7f5d3SJohn Marino
568*86d7f5d3SJohn Marino TDBG_FUNC();
569*86d7f5d3SJohn Marino
570*86d7f5d3SJohn Marino ret = pt_validate(th);
571*86d7f5d3SJohn Marino if (ret)
572*86d7f5d3SJohn Marino return (ret);
573*86d7f5d3SJohn Marino
574*86d7f5d3SJohn Marino ret = ps_lsetregs(ta->ph, th->th_tid, gregs);
575*86d7f5d3SJohn Marino return (P2T(ret));
576*86d7f5d3SJohn Marino }
577*86d7f5d3SJohn Marino
578*86d7f5d3SJohn Marino static td_err_e
pt_thr_event_enable(const td_thrhandle_t * th,int en)579*86d7f5d3SJohn Marino pt_thr_event_enable(const td_thrhandle_t *th, int en)
580*86d7f5d3SJohn Marino {
581*86d7f5d3SJohn Marino const td_thragent_t *ta = th->th_ta;
582*86d7f5d3SJohn Marino int ret;
583*86d7f5d3SJohn Marino
584*86d7f5d3SJohn Marino TDBG_FUNC();
585*86d7f5d3SJohn Marino ret = ps_pwrite(ta->ph, th->th_thread + ta->thread_off_report_events,
586*86d7f5d3SJohn Marino &en, sizeof(int));
587*86d7f5d3SJohn Marino return (P2T(ret));
588*86d7f5d3SJohn Marino }
589*86d7f5d3SJohn Marino
590*86d7f5d3SJohn Marino static td_err_e
pt_thr_set_event(const td_thrhandle_t * th,td_thr_events_t * setp)591*86d7f5d3SJohn Marino pt_thr_set_event(const td_thrhandle_t *th, td_thr_events_t *setp)
592*86d7f5d3SJohn Marino {
593*86d7f5d3SJohn Marino const td_thragent_t *ta = th->th_ta;
594*86d7f5d3SJohn Marino td_thr_events_t mask;
595*86d7f5d3SJohn Marino int ret;
596*86d7f5d3SJohn Marino
597*86d7f5d3SJohn Marino TDBG_FUNC();
598*86d7f5d3SJohn Marino ret = ps_pread(ta->ph, th->th_thread + ta->thread_off_event_mask,
599*86d7f5d3SJohn Marino &mask, sizeof(mask));
600*86d7f5d3SJohn Marino mask |= *setp;
601*86d7f5d3SJohn Marino ret = ps_pwrite(ta->ph, th->th_thread + ta->thread_off_event_mask,
602*86d7f5d3SJohn Marino &mask, sizeof(mask));
603*86d7f5d3SJohn Marino return (P2T(ret));
604*86d7f5d3SJohn Marino }
605*86d7f5d3SJohn Marino
606*86d7f5d3SJohn Marino static td_err_e
pt_thr_clear_event(const td_thrhandle_t * th,td_thr_events_t * setp)607*86d7f5d3SJohn Marino pt_thr_clear_event(const td_thrhandle_t *th, td_thr_events_t *setp)
608*86d7f5d3SJohn Marino {
609*86d7f5d3SJohn Marino const td_thragent_t *ta = th->th_ta;
610*86d7f5d3SJohn Marino td_thr_events_t mask;
611*86d7f5d3SJohn Marino int ret;
612*86d7f5d3SJohn Marino
613*86d7f5d3SJohn Marino TDBG_FUNC();
614*86d7f5d3SJohn Marino ret = ps_pread(ta->ph, th->th_thread + ta->thread_off_event_mask,
615*86d7f5d3SJohn Marino &mask, sizeof(mask));
616*86d7f5d3SJohn Marino mask &= ~*setp;
617*86d7f5d3SJohn Marino ret = ps_pwrite(ta->ph, th->th_thread + ta->thread_off_event_mask,
618*86d7f5d3SJohn Marino &mask, sizeof(mask));
619*86d7f5d3SJohn Marino return (P2T(ret));
620*86d7f5d3SJohn Marino }
621*86d7f5d3SJohn Marino
622*86d7f5d3SJohn Marino static td_err_e
pt_thr_event_getmsg(const td_thrhandle_t * th,td_event_msg_t * msg)623*86d7f5d3SJohn Marino pt_thr_event_getmsg(const td_thrhandle_t *th, td_event_msg_t *msg)
624*86d7f5d3SJohn Marino {
625*86d7f5d3SJohn Marino static td_thrhandle_t handle;
626*86d7f5d3SJohn Marino td_thragent_t *ta = (td_thragent_t *)th->th_ta;
627*86d7f5d3SJohn Marino psaddr_t pt, pt_temp;
628*86d7f5d3SJohn Marino long lwp;
629*86d7f5d3SJohn Marino int ret;
630*86d7f5d3SJohn Marino td_thr_events_e tmp;
631*86d7f5d3SJohn Marino
632*86d7f5d3SJohn Marino TDBG_FUNC();
633*86d7f5d3SJohn Marino pt = th->th_thread;
634*86d7f5d3SJohn Marino ret = ps_pread(ta->ph, ta->thread_last_event_addr, &pt_temp, sizeof(pt_temp));
635*86d7f5d3SJohn Marino if (ret != 0)
636*86d7f5d3SJohn Marino return (P2T(ret));
637*86d7f5d3SJohn Marino /* Get event */
638*86d7f5d3SJohn Marino ret = ps_pread(ta->ph, pt + ta->thread_off_event_buf, msg, sizeof(*msg));
639*86d7f5d3SJohn Marino if (ret != 0)
640*86d7f5d3SJohn Marino return (P2T(ret));
641*86d7f5d3SJohn Marino if (msg->event == 0)
642*86d7f5d3SJohn Marino return (TD_NOMSG);
643*86d7f5d3SJohn Marino /*
644*86d7f5d3SJohn Marino * Take the event pointer, at the time, libthr only reports event
645*86d7f5d3SJohn Marino * once a time, so it is not a link list.
646*86d7f5d3SJohn Marino */
647*86d7f5d3SJohn Marino if (pt == pt_temp) {
648*86d7f5d3SJohn Marino pt_temp = NULL;
649*86d7f5d3SJohn Marino ps_pwrite(ta->ph, ta->thread_last_event_addr, &pt_temp, sizeof(pt_temp));
650*86d7f5d3SJohn Marino }
651*86d7f5d3SJohn Marino /* Clear event */
652*86d7f5d3SJohn Marino tmp = 0;
653*86d7f5d3SJohn Marino ps_pwrite(ta->ph, pt + ta->thread_off_event_buf, &tmp, sizeof(tmp));
654*86d7f5d3SJohn Marino /* Convert event */
655*86d7f5d3SJohn Marino pt = (psaddr_t)msg->th_p;
656*86d7f5d3SJohn Marino ret = ps_pread(ta->ph, pt + ta->thread_off_tid, &lwp, sizeof(lwp));
657*86d7f5d3SJohn Marino if (ret != 0)
658*86d7f5d3SJohn Marino return (P2T(ret));
659*86d7f5d3SJohn Marino handle.th_ta = ta;
660*86d7f5d3SJohn Marino handle.th_tid = lwp;
661*86d7f5d3SJohn Marino handle.th_thread = pt;
662*86d7f5d3SJohn Marino msg->th_p = &handle;
663*86d7f5d3SJohn Marino return (0);
664*86d7f5d3SJohn Marino }
665*86d7f5d3SJohn Marino
666*86d7f5d3SJohn Marino static int
pt_validate(const td_thrhandle_t * th)667*86d7f5d3SJohn Marino pt_validate(const td_thrhandle_t *th)
668*86d7f5d3SJohn Marino {
669*86d7f5d3SJohn Marino
670*86d7f5d3SJohn Marino if (th->th_tid == 0 || th->th_thread == NULL)
671*86d7f5d3SJohn Marino return (TD_ERR);
672*86d7f5d3SJohn Marino return (TD_OK);
673*86d7f5d3SJohn Marino }
674*86d7f5d3SJohn Marino
675*86d7f5d3SJohn Marino static td_err_e
pt_thr_tls_get_addr(const td_thrhandle_t * th,void * _linkmap,size_t offset,void ** address)676*86d7f5d3SJohn Marino pt_thr_tls_get_addr(const td_thrhandle_t *th, void *_linkmap, size_t offset,
677*86d7f5d3SJohn Marino void **address)
678*86d7f5d3SJohn Marino {
679*86d7f5d3SJohn Marino char *obj_entry;
680*86d7f5d3SJohn Marino const td_thragent_t *ta = th->th_ta;
681*86d7f5d3SJohn Marino psaddr_t tcb_addr, *dtv_addr, tcb_tp;
682*86d7f5d3SJohn Marino int tls_index, ret;
683*86d7f5d3SJohn Marino
684*86d7f5d3SJohn Marino /* linkmap is a member of Obj_Entry */
685*86d7f5d3SJohn Marino obj_entry = (char *)_linkmap - ta->thread_off_linkmap;
686*86d7f5d3SJohn Marino
687*86d7f5d3SJohn Marino /* get tlsindex of the object file */
688*86d7f5d3SJohn Marino ret = ps_pread(ta->ph,
689*86d7f5d3SJohn Marino obj_entry + ta->thread_off_tlsindex,
690*86d7f5d3SJohn Marino &tls_index, sizeof(tls_index));
691*86d7f5d3SJohn Marino if (ret != 0)
692*86d7f5d3SJohn Marino return (P2T(ret));
693*86d7f5d3SJohn Marino
694*86d7f5d3SJohn Marino /* get thread tcb */
695*86d7f5d3SJohn Marino ret = ps_pread(ta->ph, th->th_thread + ta->thread_off_tcb,
696*86d7f5d3SJohn Marino &tcb_addr, sizeof(tcb_addr));
697*86d7f5d3SJohn Marino if (ret != 0)
698*86d7f5d3SJohn Marino return (P2T(ret));
699*86d7f5d3SJohn Marino
700*86d7f5d3SJohn Marino /* get dtv array address */
701*86d7f5d3SJohn Marino ret = ps_pread(ta->ph, tcb_addr + ta->thread_off_dtv,
702*86d7f5d3SJohn Marino &dtv_addr, sizeof(dtv_addr));
703*86d7f5d3SJohn Marino if (ret != 0)
704*86d7f5d3SJohn Marino return (P2T(ret));
705*86d7f5d3SJohn Marino /* now get the object's tls block base address */
706*86d7f5d3SJohn Marino ret = ps_pread(ta->ph, &dtv_addr[tls_index+1], address,
707*86d7f5d3SJohn Marino sizeof(*address));
708*86d7f5d3SJohn Marino if (ret != 0)
709*86d7f5d3SJohn Marino return (P2T(ret));
710*86d7f5d3SJohn Marino
711*86d7f5d3SJohn Marino *address += offset;
712*86d7f5d3SJohn Marino return (TD_OK);
713*86d7f5d3SJohn Marino }
714*86d7f5d3SJohn Marino
715*86d7f5d3SJohn Marino struct ta_ops libthread_xu_ops = {
716*86d7f5d3SJohn Marino .to_init = pt_init,
717*86d7f5d3SJohn Marino .to_ta_clear_event = pt_ta_clear_event,
718*86d7f5d3SJohn Marino .to_ta_delete = pt_ta_delete,
719*86d7f5d3SJohn Marino .to_ta_event_addr = pt_ta_event_addr,
720*86d7f5d3SJohn Marino .to_ta_event_getmsg = pt_ta_event_getmsg,
721*86d7f5d3SJohn Marino .to_ta_map_id2thr = pt_ta_map_id2thr,
722*86d7f5d3SJohn Marino .to_ta_map_lwp2thr = pt_ta_map_lwp2thr,
723*86d7f5d3SJohn Marino .to_ta_new = pt_ta_new,
724*86d7f5d3SJohn Marino .to_ta_set_event = pt_ta_set_event,
725*86d7f5d3SJohn Marino .to_ta_thr_iter = pt_ta_thr_iter,
726*86d7f5d3SJohn Marino .to_ta_tsd_iter = pt_ta_tsd_iter,
727*86d7f5d3SJohn Marino .to_thr_clear_event = pt_thr_clear_event,
728*86d7f5d3SJohn Marino .to_thr_dbresume = pt_thr_dbresume,
729*86d7f5d3SJohn Marino .to_thr_dbsuspend = pt_thr_dbsuspend,
730*86d7f5d3SJohn Marino .to_thr_event_enable = pt_thr_event_enable,
731*86d7f5d3SJohn Marino .to_thr_event_getmsg = pt_thr_event_getmsg,
732*86d7f5d3SJohn Marino .to_thr_get_info = pt_thr_get_info,
733*86d7f5d3SJohn Marino .to_thr_getfpregs = pt_thr_getfpregs,
734*86d7f5d3SJohn Marino .to_thr_getgregs = pt_thr_getgregs,
735*86d7f5d3SJohn Marino .to_thr_set_event = pt_thr_set_event,
736*86d7f5d3SJohn Marino .to_thr_setfpregs = pt_thr_setfpregs,
737*86d7f5d3SJohn Marino .to_thr_setgregs = pt_thr_setgregs,
738*86d7f5d3SJohn Marino .to_thr_validate = pt_thr_validate,
739*86d7f5d3SJohn Marino .to_thr_tls_get_addr = pt_thr_tls_get_addr,
740*86d7f5d3SJohn Marino };
741