]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - lib/libthread_db/libpthread_db.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / lib / libthread_db / libpthread_db.c
1 /*
2  * Copyright (c) 2004 David Xu <davidxu@freebsd.org>
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  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include <stddef.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <unistd.h>
34 #include <pthread.h>
35 #include <sys/types.h>
36 #include <sys/linker_set.h>
37 #include <sys/kse.h>
38 #include <sys/ptrace.h>
39 #include <proc_service.h>
40 #include <thread_db.h>
41
42 #include "libpthread_db.h"
43
44 #define P2T(c) ps2td(c)
45
46 static void pt_unmap_lwp(const td_thragent_t *ta, lwpid_t lwp);
47 static int pt_validate(const td_thrhandle_t *th);
48
49 static int
50 ps2td(int c)
51 {
52         switch (c) {
53         case PS_OK:
54                 return TD_OK;
55         case PS_ERR:
56                 return TD_ERR;
57         case PS_BADPID:
58                 return TD_BADPH;
59         case PS_BADLID:
60                 return TD_NOLWP;
61         case PS_BADADDR:
62                 return TD_ERR;
63         case PS_NOSYM:
64                 return TD_NOLIBTHREAD;
65         case PS_NOFREGS:
66                 return TD_NOFPREGS;
67         default:
68                 return TD_ERR;
69         }
70 }
71
72 static long
73 pt_map_thread(const td_thragent_t *const_ta, psaddr_t pt, int type)
74 {
75         td_thragent_t *ta = __DECONST(td_thragent_t *, const_ta);
76         struct pt_map *new;
77         int i, first = -1;
78
79         /* leave zero out */
80         for (i = 1; i < ta->map_len; ++i) {
81                 if (ta->map[i].type == PT_NONE) {
82                         if (first == -1)
83                                 first = i;
84                 } else if (ta->map[i].type == type && ta->map[i].thr == pt) {
85                                 return (i);
86                 }
87         }
88
89         if (first == -1) {
90                 if (ta->map_len == 0) {
91                         ta->map = calloc(20, sizeof(struct pt_map));
92                         if (ta->map == NULL)
93                                 return (-1);
94                         ta->map_len = 20;
95                         first = 1;
96                 } else {
97                         new = realloc(ta->map,
98                                       sizeof(struct pt_map) * ta->map_len * 2);
99                         if (new == NULL)
100                                 return (-1);
101                         memset(new + ta->map_len, '\0', sizeof(struct pt_map) *
102                                ta->map_len);
103                         first = ta->map_len;
104                         ta->map = new;
105                         ta->map_len *= 2;
106                 }
107         }
108
109         ta->map[first].type = type;
110         ta->map[first].thr = pt;
111         return (first);
112 }
113
114 static td_err_e
115 pt_init(void)
116 {
117         pt_md_init();
118         return (0);
119 }
120
121 static td_err_e
122 pt_ta_new(struct ps_prochandle *ph, td_thragent_t **pta)
123 {
124 #define LOOKUP_SYM(proc, sym, addr)                     \
125         ret = ps_pglobal_lookup(proc, NULL, sym, addr); \
126         if (ret != 0) {                                 \
127                 TDBG("can not find symbol: %s\n", sym); \
128                 ret = TD_NOLIBTHREAD;                   \
129                 goto error;                             \
130         }
131
132 #define LOOKUP_VAL(proc, sym, val)                      \
133         ret = ps_pglobal_lookup(proc, NULL, sym, &vaddr);\
134         if (ret != 0) {                                 \
135                 TDBG("can not find symbol: %s\n", sym); \
136                 ret = TD_NOLIBTHREAD;                   \
137                 goto error;                             \
138         }                                               \
139         ret = ps_pread(proc, vaddr, val, sizeof(int));  \
140         if (ret != 0) {                                 \
141                 TDBG("can not read value of %s\n", sym);\
142                 ret = TD_NOLIBTHREAD;                   \
143                 goto error;                             \
144         }
145
146         td_thragent_t *ta;
147         psaddr_t vaddr;
148         int dbg;
149         int ret;
150
151         TDBG_FUNC();
152
153         ta = malloc(sizeof(td_thragent_t));
154         if (ta == NULL)
155                 return (TD_MALLOC);
156
157         ta->ph = ph;
158         ta->thread_activated = 0;
159         ta->map = NULL;
160         ta->map_len = 0;
161
162         LOOKUP_SYM(ph, "_libkse_debug",         &ta->libkse_debug_addr);
163         LOOKUP_SYM(ph, "_thread_list",          &ta->thread_list_addr);
164         LOOKUP_SYM(ph, "_thread_activated",     &ta->thread_activated_addr);
165         LOOKUP_SYM(ph, "_thread_active_threads",&ta->thread_active_threads_addr);
166         LOOKUP_SYM(ph, "_thread_keytable",      &ta->thread_keytable_addr);
167         LOOKUP_VAL(ph, "_thread_off_dtv",       &ta->thread_off_dtv);
168         LOOKUP_VAL(ph, "_thread_off_kse_locklevel", &ta->thread_off_kse_locklevel);
169         LOOKUP_VAL(ph, "_thread_off_kse",       &ta->thread_off_kse);
170         LOOKUP_VAL(ph, "_thread_off_tlsindex",  &ta->thread_off_tlsindex);
171         LOOKUP_VAL(ph, "_thread_off_attr_flags",        &ta->thread_off_attr_flags);
172         LOOKUP_VAL(ph, "_thread_size_key",      &ta->thread_size_key);
173         LOOKUP_VAL(ph, "_thread_off_tcb",       &ta->thread_off_tcb);
174         LOOKUP_VAL(ph, "_thread_off_linkmap",   &ta->thread_off_linkmap);
175         LOOKUP_VAL(ph, "_thread_off_tmbx",      &ta->thread_off_tmbx);
176         LOOKUP_VAL(ph, "_thread_off_thr_locklevel",     &ta->thread_off_thr_locklevel);
177         LOOKUP_VAL(ph, "_thread_off_next",      &ta->thread_off_next);
178         LOOKUP_VAL(ph, "_thread_off_state",     &ta->thread_off_state);
179         LOOKUP_VAL(ph, "_thread_max_keys",      &ta->thread_max_keys);
180         LOOKUP_VAL(ph, "_thread_off_key_allocated", &ta->thread_off_key_allocated);
181         LOOKUP_VAL(ph, "_thread_off_key_destructor", &ta->thread_off_key_destructor);
182         LOOKUP_VAL(ph, "_thread_state_running", &ta->thread_state_running);
183         LOOKUP_VAL(ph, "_thread_state_zoombie", &ta->thread_state_zoombie);
184         LOOKUP_VAL(ph, "_thread_off_sigmask",   &ta->thread_off_sigmask);
185         LOOKUP_VAL(ph, "_thread_off_sigpend",   &ta->thread_off_sigpend);
186         dbg = getpid();
187         /*
188          * If this fails it probably means we're debugging a core file and
189          * can't write to it.
190          */
191         ps_pwrite(ph, ta->libkse_debug_addr, &dbg, sizeof(int));
192         *pta = ta;
193         return (0);
194
195 error:
196         free(ta);
197         return (ret);
198 }
199
200 static td_err_e
201 pt_ta_delete(td_thragent_t *ta)
202 {
203         int dbg;
204
205         TDBG_FUNC();
206
207         dbg = 0;
208         /*
209          * Error returns from this write are not really a problem;
210          * the process doesn't exist any more.
211          */
212         ps_pwrite(ta->ph, ta->libkse_debug_addr, &dbg, sizeof(int));
213         if (ta->map)
214                 free(ta->map);
215         free(ta);
216         return (TD_OK);
217 }
218
219 static td_err_e
220 pt_ta_map_id2thr(const td_thragent_t *ta, thread_t id, td_thrhandle_t *th)
221 {
222         prgregset_t gregs;
223         TAILQ_HEAD(, pthread) thread_list;
224         psaddr_t pt, tcb_addr;
225         lwpid_t lwp;
226         int ret;
227
228         TDBG_FUNC();
229
230         if (id < 0 || id >= ta->map_len || ta->map[id].type == PT_NONE)
231                 return (TD_NOTHR);
232         ret = ps_pread(ta->ph, ta->thread_list_addr, &thread_list,
233                         sizeof(thread_list));
234         if (ret != 0)
235                 return (P2T(ret));
236         pt = (psaddr_t)thread_list.tqh_first;
237         if (ta->map[id].type == PT_LWP) {
238                 /*
239                  * if we are referencing a lwp, make sure it was not already
240                  * mapped to user thread.
241                  */
242                 while (pt != 0) {
243                         ret = ps_pread(ta->ph,
244                                 pt + ta->thread_off_tcb,
245                                 &tcb_addr, sizeof(tcb_addr));
246                         if (ret != 0)
247                                 return (P2T(ret));
248                         ret = ps_pread(ta->ph,
249                                 tcb_addr + ta->thread_off_tmbx + 
250                                 offsetof(struct kse_thr_mailbox, tm_lwp),
251                                 &lwp, sizeof(lwp));
252                         if (ret != 0)
253                                 return (P2T(ret));
254                         /*
255                          * If the lwp was already mapped to userland thread,
256                          * we shouldn't reference it directly in future.
257                          */
258                         if (lwp == ta->map[id].lwp) {
259                                 ta->map[id].type = PT_NONE;
260                                 return (TD_NOTHR);
261                         }
262                         /* get next thread */
263                         ret = ps_pread(ta->ph,
264                                 pt + ta->thread_off_next,
265                                 &pt, sizeof(pt));
266                         if (ret != 0)
267                                 return (P2T(ret));
268                 }
269                 /* check lwp */
270                 ret = ps_lgetregs(ta->ph, ta->map[id].lwp, gregs);
271                 if (ret != PS_OK) {
272                         /* no longer exists */
273                         ta->map[id].type = PT_NONE;
274                         return (TD_NOTHR);
275                 }
276         } else {
277                 while (pt != 0 && ta->map[id].thr != pt) {
278                         ret = ps_pread(ta->ph,
279                                 pt + ta->thread_off_tcb,
280                                 &tcb_addr, sizeof(tcb_addr));
281                         if (ret != 0)
282                                 return (P2T(ret));
283                         /* get next thread */
284                         ret = ps_pread(ta->ph,
285                                 pt + ta->thread_off_next,
286                                 &pt, sizeof(pt));
287                         if (ret != 0)
288                                 return (P2T(ret));
289                 }
290
291                 if (pt == 0) {
292                         /* no longer exists */
293                         ta->map[id].type = PT_NONE;
294                         return (TD_NOTHR);
295                 }
296         }
297         th->th_ta = ta;
298         th->th_tid = id;
299         th->th_thread = pt;
300         return (TD_OK);
301 }
302
303 static td_err_e
304 pt_ta_map_lwp2thr(const td_thragent_t *ta, lwpid_t lwp, td_thrhandle_t *th)
305 {
306         TAILQ_HEAD(, pthread) thread_list;
307         psaddr_t pt, ptr;
308         lwpid_t tmp_lwp;
309         int ret;
310         
311         TDBG_FUNC();
312
313         ret = ps_pread(ta->ph, ta->thread_list_addr, &thread_list,
314                         sizeof(thread_list));
315         if (ret != 0)
316                 return (P2T(ret));
317         pt = (psaddr_t)thread_list.tqh_first;
318         while (pt != 0) {
319                 ret = ps_pread(ta->ph, pt + ta->thread_off_tcb,
320                                 &ptr, sizeof(ptr));
321                 if (ret != 0)
322                         return (P2T(ret));
323                 ptr += ta->thread_off_tmbx +
324                        offsetof(struct kse_thr_mailbox, tm_lwp);
325                 ret = ps_pread(ta->ph, ptr, &tmp_lwp, sizeof(lwpid_t));
326                 if (ret != 0)
327                         return (P2T(ret));
328                 if (tmp_lwp == lwp) {
329                         th->th_ta = ta;
330                         th->th_tid = pt_map_thread(ta, pt, PT_USER);
331                         if (th->th_tid == -1)
332                                 return (TD_MALLOC);
333                         pt_unmap_lwp(ta, lwp);
334                         th->th_thread = pt;
335                         return (TD_OK);
336                 }
337
338                 /* get next thread */
339                 ret = ps_pread(ta->ph,
340                            pt + ta->thread_off_next,
341                            &pt, sizeof(pt));
342                 if (ret != 0)
343                         return (P2T(ret));
344         }
345
346         return (TD_NOTHR);
347 }
348
349 static td_err_e
350 pt_ta_thr_iter(const td_thragent_t *ta,
351                td_thr_iter_f *callback, void *cbdata_p,
352                td_thr_state_e state, int ti_pri,
353                sigset_t *ti_sigmask_p,
354                unsigned int ti_user_flags)
355 {
356         TAILQ_HEAD(, pthread) thread_list;
357         td_thrhandle_t th;
358         psaddr_t pt;
359         ps_err_e pserr;
360         int activated;
361
362         TDBG_FUNC();
363
364         pserr = ps_pread(ta->ph, ta->thread_activated_addr, &activated,
365             sizeof(int));
366         if (pserr != PS_OK)
367                 return (P2T(pserr));
368         if (!activated)
369                 return (TD_OK);
370
371         pserr = ps_pread(ta->ph, ta->thread_list_addr, &thread_list,
372             sizeof(thread_list));
373         if (pserr != 0)
374                 return (P2T(pserr));
375         pt = (psaddr_t)thread_list.tqh_first;
376         while (pt != 0) {
377                 th.th_ta = ta;
378                 th.th_tid = pt_map_thread(ta, pt, PT_USER);
379                 th.th_thread = pt;
380                 /* should we unmap lwp here ? */
381                 if (th.th_tid == -1)
382                         return (TD_MALLOC);
383                 if ((*callback)(&th, cbdata_p))
384                         return (TD_DBERR);
385                 /* get next thread */
386                 pserr = ps_pread(ta->ph,
387                     pt + ta->thread_off_next, &pt,
388                     sizeof(pt));
389                 if (pserr != PS_OK)
390                         return (P2T(pserr));
391         }
392         return (TD_OK);
393 }
394
395 static td_err_e
396 pt_ta_tsd_iter(const td_thragent_t *ta, td_key_iter_f *ki, void *arg)
397 {
398         char *keytable;
399         void *destructor;
400         int i, ret, allocated;
401
402         TDBG_FUNC();
403
404         keytable = malloc(ta->thread_max_keys * ta->thread_size_key);
405         if (keytable == NULL)
406                 return (TD_MALLOC);
407         ret = ps_pread(ta->ph, (psaddr_t)ta->thread_keytable_addr, keytable,
408                        ta->thread_max_keys * ta->thread_size_key);
409         if (ret != 0) {
410                 free(keytable);
411                 return (P2T(ret));
412         }       
413         for (i = 0; i < ta->thread_max_keys; i++) {
414                 allocated = *(int *)(keytable + i * ta->thread_size_key +
415                         ta->thread_off_key_allocated);
416                 destructor = *(void **)(keytable + i * ta->thread_size_key +
417                         ta->thread_off_key_destructor);
418                 if (allocated) {
419                         ret = (ki)(i, destructor, arg);
420                         if (ret != 0) {
421                                 free(keytable);
422                                 return (TD_DBERR);
423                         }
424                 }
425         }
426         free(keytable);
427         return (TD_OK);
428 }
429
430 static td_err_e
431 pt_ta_event_addr(const td_thragent_t *ta, td_event_e event, td_notify_t *ptr)
432 {
433         TDBG_FUNC();
434         return (TD_ERR);
435 }
436
437 static td_err_e
438 pt_ta_set_event(const td_thragent_t *ta, td_thr_events_t *events)
439 {
440         TDBG_FUNC();
441         return (0);
442 }
443
444 static td_err_e
445 pt_ta_clear_event(const td_thragent_t *ta, td_thr_events_t *events)
446 {
447         TDBG_FUNC();
448         return (0);
449 }
450
451 static td_err_e
452 pt_ta_event_getmsg(const td_thragent_t *ta, td_event_msg_t *msg)
453 {
454         TDBG_FUNC();
455         return (TD_NOMSG);
456 }
457
458 static td_err_e
459 pt_dbsuspend(const td_thrhandle_t *th, int suspend)
460 {
461         td_thragent_t *ta = (td_thragent_t *)th->th_ta;
462         psaddr_t tcb_addr, tmbx_addr, ptr;
463         lwpid_t lwp;
464         uint32_t dflags;
465         int attrflags, locklevel, ret;
466
467         TDBG_FUNC();
468
469         ret = pt_validate(th);
470         if (ret)
471                 return (ret);
472
473         if (ta->map[th->th_tid].type == PT_LWP) {
474                 if (suspend)
475                         ret = ps_lstop(ta->ph, ta->map[th->th_tid].lwp);
476                 else
477                         ret = ps_lcontinue(ta->ph, ta->map[th->th_tid].lwp);
478                 return (P2T(ret));
479         }
480
481         ret = ps_pread(ta->ph, ta->map[th->th_tid].thr +
482                 ta->thread_off_attr_flags,
483                 &attrflags, sizeof(attrflags));
484         if (ret != 0)
485                 return (P2T(ret));
486         ret = ps_pread(ta->ph, ta->map[th->th_tid].thr +
487                        ta->thread_off_tcb,
488                        &tcb_addr, sizeof(tcb_addr));
489         if (ret != 0)
490                 return (P2T(ret));
491         tmbx_addr = tcb_addr + ta->thread_off_tmbx;
492         ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp);
493         ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t));
494         if (ret != 0)
495                 return (P2T(ret));
496
497         if (lwp != 0) {
498                 /* don't suspend signal thread */
499                 if (attrflags & 0x200)
500                         return (0);
501                 if (attrflags & PTHREAD_SCOPE_SYSTEM) {
502                         /*
503                          * don't suspend system scope thread if it is holding
504                          * some low level locks
505                          */
506                         ptr = ta->map[th->th_tid].thr + ta->thread_off_kse;
507                         ret = ps_pread(ta->ph, ptr, &ptr, sizeof(ptr));
508                         if (ret != 0)
509                                 return (P2T(ret));
510                         ret = ps_pread(ta->ph, ptr + ta->thread_off_kse_locklevel,
511                                 &locklevel, sizeof(int));
512                         if (ret != 0)
513                                 return (P2T(ret));
514                         if (locklevel <= 0) {
515                                 ptr = ta->map[th->th_tid].thr +
516                                         ta->thread_off_thr_locklevel;
517                                 ret = ps_pread(ta->ph, ptr, &locklevel,
518                                         sizeof(int));
519                                 if (ret != 0)
520                                         return (P2T(ret));
521                         }
522                         if (suspend) {
523                                 if (locklevel <= 0)
524                                         ret = ps_lstop(ta->ph, lwp);
525                         } else {
526                                 ret = ps_lcontinue(ta->ph, lwp);
527                         }
528                         if (ret != 0)
529                                 return (P2T(ret));
530                         /* FALLTHROUGH */
531                 } else {
532                         struct ptrace_lwpinfo pl;
533
534                         if (ps_linfo(ta->ph, lwp, (caddr_t)&pl))
535                                 return (TD_ERR);
536                         if (suspend) {
537                                 if (!(pl.pl_flags & PL_FLAG_BOUND))
538                                         ret = ps_lstop(ta->ph, lwp);
539                         } else {
540                                 ret = ps_lcontinue(ta->ph, lwp);
541                         }
542                         if (ret != 0)
543                                 return (P2T(ret));
544                         /* FALLTHROUGH */
545                 }
546         }
547         /* read tm_dflags */
548         ret = ps_pread(ta->ph,
549                 tmbx_addr + offsetof(struct kse_thr_mailbox, tm_dflags),
550                 &dflags, sizeof(dflags));
551         if (ret != 0)
552                 return (P2T(ret));
553         if (suspend)
554                 dflags |= TMDF_SUSPEND;
555         else
556                 dflags &= ~TMDF_SUSPEND;
557         ret = ps_pwrite(ta->ph,
558                tmbx_addr + offsetof(struct kse_thr_mailbox, tm_dflags),
559                &dflags, sizeof(dflags));
560         return (P2T(ret));
561 }
562
563 static td_err_e
564 pt_thr_dbresume(const td_thrhandle_t *th)
565 {
566         TDBG_FUNC();
567
568         return pt_dbsuspend(th, 0);
569 }
570
571 static td_err_e
572 pt_thr_dbsuspend(const td_thrhandle_t *th)
573 {
574         TDBG_FUNC();
575
576         return pt_dbsuspend(th, 1);
577 }
578
579 static td_err_e
580 pt_thr_validate(const td_thrhandle_t *th)
581 {
582         td_thrhandle_t temp;
583         int ret;
584
585         TDBG_FUNC();
586
587         ret = pt_ta_map_id2thr(th->th_ta, th->th_tid,
588                                &temp);
589         return (ret);
590 }
591
592 static td_err_e
593 pt_thr_get_info(const td_thrhandle_t *th, td_thrinfo_t *info)
594 {
595         const td_thragent_t *ta = th->th_ta;
596         struct ptrace_lwpinfo linfo;
597         psaddr_t tcb_addr;
598         uint32_t dflags;
599         lwpid_t lwp;
600         int state;
601         int ret;
602         int attrflags;
603
604         TDBG_FUNC();
605
606         bzero(info, sizeof(*info));
607         ret = pt_validate(th);
608         if (ret)
609                 return (ret);
610
611         memset(info, 0, sizeof(*info));
612         if (ta->map[th->th_tid].type == PT_LWP) {
613                 info->ti_type = TD_THR_SYSTEM;
614                 info->ti_lid = ta->map[th->th_tid].lwp;
615                 info->ti_tid = th->th_tid;
616                 info->ti_state = TD_THR_RUN;
617                 info->ti_type = TD_THR_SYSTEM;
618                 return (TD_OK);
619         }
620
621         ret = ps_pread(ta->ph, ta->map[th->th_tid].thr +
622                 ta->thread_off_attr_flags,
623                 &attrflags, sizeof(attrflags));
624         if (ret != 0)
625                 return (P2T(ret));
626         ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + ta->thread_off_tcb,
627                        &tcb_addr, sizeof(tcb_addr));
628         if (ret != 0)
629                 return (P2T(ret));
630         ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + ta->thread_off_state,
631                        &state, sizeof(state));
632         ret = ps_pread(ta->ph,
633                 tcb_addr + ta->thread_off_tmbx +
634                  offsetof(struct kse_thr_mailbox, tm_lwp),
635                 &info->ti_lid, sizeof(lwpid_t));
636         if (ret != 0)
637                 return (P2T(ret));
638         ret = ps_pread(ta->ph,
639                 tcb_addr + ta->thread_off_tmbx +
640                  offsetof(struct kse_thr_mailbox, tm_dflags),
641                 &dflags, sizeof(dflags));
642         if (ret != 0)
643                 return (P2T(ret));
644         ret = ps_pread(ta->ph, tcb_addr + ta->thread_off_tmbx +
645                 offsetof(struct kse_thr_mailbox, tm_lwp), &lwp, sizeof(lwpid_t));
646         if (ret != 0)
647                 return (P2T(ret));
648         info->ti_ta_p = th->th_ta;
649         info->ti_tid = th->th_tid;
650
651         if (attrflags & PTHREAD_SCOPE_SYSTEM) {
652                 ret = ps_linfo(ta->ph, lwp, &linfo);
653                 if (ret == PS_OK) {
654                         info->ti_sigmask = linfo.pl_sigmask;
655                         info->ti_pending = linfo.pl_siglist;
656                 } else
657                         return (ret);
658         } else {
659                 ret = ps_pread(ta->ph,
660                         ta->map[th->th_tid].thr + ta->thread_off_sigmask,
661                         &info->ti_sigmask, sizeof(sigset_t));
662                 if (ret)
663                         return (ret);
664                 ret = ps_pread(ta->ph,
665                         ta->map[th->th_tid].thr + ta->thread_off_sigpend,
666                         &info->ti_pending, sizeof(sigset_t));
667                 if (ret)
668                         return (ret);
669         }
670
671         if (state == ta->thread_state_running)
672                 info->ti_state = TD_THR_RUN;
673         else if (state == ta->thread_state_zoombie)
674                 info->ti_state = TD_THR_ZOMBIE;
675         else
676                 info->ti_state = TD_THR_SLEEP;
677         info->ti_db_suspended = ((dflags & TMDF_SUSPEND) != 0);
678         info->ti_type = TD_THR_USER;
679         return (0);
680 }
681
682 #ifdef __i386__
683 static td_err_e
684 pt_thr_getxmmregs(const td_thrhandle_t *th, char *fxsave)
685 {
686         const td_thragent_t *ta = th->th_ta;
687         struct kse_thr_mailbox tmbx;
688         psaddr_t tcb_addr, tmbx_addr, ptr;
689         lwpid_t lwp;
690         int ret;
691
692         return TD_ERR;
693
694         TDBG_FUNC();
695
696         ret = pt_validate(th);
697         if (ret)
698                 return (ret);
699
700         if (ta->map[th->th_tid].type == PT_LWP) {
701                 ret = ps_lgetxmmregs(ta->ph, ta->map[th->th_tid].lwp, fxsave);
702                 return (P2T(ret));
703         }
704
705         ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + ta->thread_off_tcb,
706                        &tcb_addr, sizeof(tcb_addr));
707         if (ret != 0)
708                 return (P2T(ret));
709         tmbx_addr = tcb_addr + ta->thread_off_tmbx;
710         ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp);
711         ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t));
712         if (ret != 0)
713                 return (P2T(ret));
714         if (lwp != 0) {
715                 ret = ps_lgetxmmregs(ta->ph, lwp, fxsave);
716                 return (P2T(ret));
717         }
718
719         ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx));
720         if (ret != 0)
721                 return (P2T(ret));
722         pt_ucontext_to_fxsave(&tmbx.tm_context, fxsave);
723         return (0);
724 }
725 #endif
726
727 static td_err_e
728 pt_thr_getfpregs(const td_thrhandle_t *th, prfpregset_t *fpregs)
729 {
730         const td_thragent_t *ta = th->th_ta;
731         struct kse_thr_mailbox tmbx;
732         psaddr_t tcb_addr, tmbx_addr, ptr;
733         lwpid_t lwp;
734         int ret;
735
736         TDBG_FUNC();
737
738         ret = pt_validate(th);
739         if (ret)
740                 return (ret);
741
742         if (ta->map[th->th_tid].type == PT_LWP) {
743                 ret = ps_lgetfpregs(ta->ph, ta->map[th->th_tid].lwp, fpregs);
744                 return (P2T(ret));
745         }
746
747         ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + ta->thread_off_tcb,
748                        &tcb_addr, sizeof(tcb_addr));
749         if (ret != 0)
750                 return (P2T(ret));
751         tmbx_addr = tcb_addr + ta->thread_off_tmbx;
752         ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp);
753         ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t));
754         if (ret != 0)
755                 return (P2T(ret));
756         if (lwp != 0) {
757                 ret = ps_lgetfpregs(ta->ph, lwp, fpregs);
758                 return (P2T(ret));
759         }
760
761         ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx));
762         if (ret != 0)
763                 return (P2T(ret));
764         pt_ucontext_to_fpreg(&tmbx.tm_context, fpregs);
765         return (0);
766 }
767
768 static td_err_e
769 pt_thr_getgregs(const td_thrhandle_t *th, prgregset_t gregs)
770 {
771         const td_thragent_t *ta = th->th_ta;
772         struct kse_thr_mailbox tmbx;
773         psaddr_t tcb_addr, tmbx_addr, ptr;
774         lwpid_t lwp;
775         int ret;
776
777         TDBG_FUNC();
778
779         ret = pt_validate(th);
780         if (ret)
781                 return (ret);
782
783         if (ta->map[th->th_tid].type == PT_LWP) {
784                 ret = ps_lgetregs(ta->ph,
785                                   ta->map[th->th_tid].lwp, gregs);
786                 return (P2T(ret));
787         }
788
789         ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + ta->thread_off_tcb,
790                         &tcb_addr, sizeof(tcb_addr));
791         if (ret != 0)
792                 return (P2T(ret));
793         tmbx_addr = tcb_addr + ta->thread_off_tmbx;
794         ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp);
795         ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t));
796         if (ret != 0)
797                 return (P2T(ret));
798         if (lwp != 0) {
799                 ret = ps_lgetregs(ta->ph, lwp, gregs);
800                 return (P2T(ret));
801         }
802         ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx));
803         if (ret != 0)
804                 return (P2T(ret));
805         pt_ucontext_to_reg(&tmbx.tm_context, gregs);
806         return (0);
807 }
808
809 #ifdef __i386__
810 static td_err_e
811 pt_thr_setxmmregs(const td_thrhandle_t *th, const char *fxsave)
812 {
813         const td_thragent_t *ta = th->th_ta;
814         struct kse_thr_mailbox tmbx;
815         psaddr_t tcb_addr, tmbx_addr, ptr;
816         lwpid_t lwp;
817         int ret;
818
819         return TD_ERR;
820
821         TDBG_FUNC();
822
823         ret = pt_validate(th);
824         if (ret)
825                 return (ret);
826
827         if (ta->map[th->th_tid].type == PT_LWP) {
828                 ret = ps_lsetxmmregs(ta->ph, ta->map[th->th_tid].lwp, fxsave);
829                 return (P2T(ret));
830         }
831
832         ret = ps_pread(ta->ph, ta->map[th->th_tid].thr +
833                         ta->thread_off_tcb,
834                         &tcb_addr, sizeof(tcb_addr));
835         if (ret != 0)
836                 return (P2T(ret));
837         tmbx_addr = tcb_addr + ta->thread_off_tmbx;
838         ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp);
839         ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t));
840         if (ret != 0)
841                 return (P2T(ret));
842         if (lwp != 0) {
843                 ret = ps_lsetxmmregs(ta->ph, lwp, fxsave);
844                 return (P2T(ret));
845         }
846         /*
847          * Read a copy of context, this makes sure that registers
848          * not covered by structure reg won't be clobbered
849          */
850         ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx));
851         if (ret != 0)
852                 return (P2T(ret));
853
854         pt_fxsave_to_ucontext(fxsave, &tmbx.tm_context);
855         ret = ps_pwrite(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx));
856         return (P2T(ret));
857 }
858 #endif
859
860 static td_err_e
861 pt_thr_setfpregs(const td_thrhandle_t *th, const prfpregset_t *fpregs)
862 {
863         const td_thragent_t *ta = th->th_ta;
864         struct kse_thr_mailbox tmbx;
865         psaddr_t tcb_addr, tmbx_addr, ptr;
866         lwpid_t lwp;
867         int ret;
868
869         TDBG_FUNC();
870
871         ret = pt_validate(th);
872         if (ret)
873                 return (ret);
874
875         if (ta->map[th->th_tid].type == PT_LWP) {
876                 ret = ps_lsetfpregs(ta->ph, ta->map[th->th_tid].lwp, fpregs);
877                 return (P2T(ret));
878         }
879
880         ret = ps_pread(ta->ph, ta->map[th->th_tid].thr +
881                         ta->thread_off_tcb,
882                         &tcb_addr, sizeof(tcb_addr));
883         if (ret != 0)
884                 return (P2T(ret));
885         tmbx_addr = tcb_addr + ta->thread_off_tmbx;
886         ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp);
887         ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t));
888         if (ret != 0)
889                 return (P2T(ret));
890         if (lwp != 0) {
891                 ret = ps_lsetfpregs(ta->ph, lwp, fpregs);
892                 return (P2T(ret));
893         }
894         /*
895          * Read a copy of context, this makes sure that registers
896          * not covered by structure reg won't be clobbered
897          */
898         ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx));
899         if (ret != 0)
900                 return (P2T(ret));
901
902         pt_fpreg_to_ucontext(fpregs, &tmbx.tm_context);
903         ret = ps_pwrite(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx));
904         return (P2T(ret));
905 }
906
907 static td_err_e
908 pt_thr_setgregs(const td_thrhandle_t *th, const prgregset_t gregs)
909 {
910         const td_thragent_t *ta = th->th_ta;
911         struct kse_thr_mailbox tmbx;
912         psaddr_t tcb_addr, tmbx_addr, ptr;
913         lwpid_t lwp;
914         int ret;
915
916         TDBG_FUNC();
917
918         ret = pt_validate(th);
919         if (ret)
920                 return (ret);
921
922         if (ta->map[th->th_tid].type == PT_LWP) {
923                 ret = ps_lsetregs(ta->ph, ta->map[th->th_tid].lwp, gregs);
924                 return (P2T(ret));
925         }
926
927         ret = ps_pread(ta->ph, ta->map[th->th_tid].thr +
928                         ta->thread_off_tcb,
929                         &tcb_addr, sizeof(tcb_addr));
930         if (ret != 0)
931                 return (P2T(ret));
932         tmbx_addr = tcb_addr + ta->thread_off_tmbx;
933         ptr = tmbx_addr + offsetof(struct kse_thr_mailbox, tm_lwp);
934         ret = ps_pread(ta->ph, ptr, &lwp, sizeof(lwpid_t));
935         if (ret != 0)
936                 return (P2T(ret));
937         if (lwp != 0) {
938                 ret = ps_lsetregs(ta->ph, lwp, gregs);
939                 return (P2T(ret));
940         }
941
942         /*
943          * Read a copy of context, make sure that registers
944          * not covered by structure reg won't be clobbered
945          */
946         ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx));
947         if (ret != 0)
948                 return (P2T(ret));
949         pt_reg_to_ucontext(gregs, &tmbx.tm_context);
950         ret = ps_pwrite(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx));
951         return (P2T(ret));
952 }
953
954 static td_err_e
955 pt_thr_event_enable(const td_thrhandle_t *th, int en)
956 {
957         TDBG_FUNC();
958         return (0);
959 }
960
961 static td_err_e
962 pt_thr_set_event(const td_thrhandle_t *th, td_thr_events_t *setp)
963 {
964         TDBG_FUNC();
965         return (0);
966 }
967
968 static td_err_e
969 pt_thr_clear_event(const td_thrhandle_t *th, td_thr_events_t *setp)
970 {
971         TDBG_FUNC();
972         return (0);
973 }
974
975 static td_err_e
976 pt_thr_event_getmsg(const td_thrhandle_t *th, td_event_msg_t *msg)
977 {
978         TDBG_FUNC();
979         return (TD_NOMSG);
980 }
981
982 static td_err_e
983 pt_thr_sstep(const td_thrhandle_t *th, int step)
984 {
985         const td_thragent_t *ta = th->th_ta;
986         struct kse_thr_mailbox tmbx;
987         struct reg regs;
988         psaddr_t tcb_addr, tmbx_addr;
989         uint32_t dflags;
990         lwpid_t lwp;
991         int ret;
992
993         TDBG_FUNC();
994
995         ret = pt_validate(th);
996         if (ret)
997                 return (ret);
998
999         if (ta->map[th->th_tid].type == PT_LWP)
1000                 return (TD_BADTH);
1001
1002         ret = ps_pread(ta->ph, ta->map[th->th_tid].thr + 
1003                         ta->thread_off_tcb,
1004                         &tcb_addr, sizeof(tcb_addr));
1005         if (ret != 0)
1006                 return (P2T(ret));
1007
1008         /* Clear or set single step flag in thread mailbox */
1009         ret = ps_pread(ta->ph,
1010                 tcb_addr + ta->thread_off_tmbx +
1011                  offsetof(struct kse_thr_mailbox, tm_dflags),
1012                 &dflags, sizeof(uint32_t));
1013         if (ret != 0)
1014                 return (P2T(ret));
1015         if (step != 0)
1016                 dflags |= TMDF_SSTEP;
1017         else
1018                 dflags &= ~TMDF_SSTEP;
1019         ret = ps_pwrite(ta->ph,
1020                 tcb_addr + ta->thread_off_tmbx +
1021                  offsetof(struct kse_thr_mailbox, tm_dflags),
1022                 &dflags, sizeof(uint32_t));
1023         if (ret != 0)
1024                 return (P2T(ret));
1025         /* Get lwp */
1026         ret = ps_pread(ta->ph,
1027                 tcb_addr + ta->thread_off_tmbx +
1028                  offsetof(struct kse_thr_mailbox, tm_lwp),
1029                 &lwp, sizeof(lwpid_t));
1030         if (ret != 0)
1031                 return (P2T(ret));
1032         if (lwp != 0)
1033                 return (0);
1034
1035         tmbx_addr = tcb_addr + ta->thread_off_tmbx;
1036         /*
1037          * context is in userland, some architectures store
1038          * single step status in registers, we should change
1039          * these registers.
1040          */
1041         ret = ps_pread(ta->ph, tmbx_addr, &tmbx, sizeof(tmbx));
1042         if (ret == 0) {
1043                 pt_ucontext_to_reg(&tmbx.tm_context, &regs);
1044                 /* only write out if it is really changed. */
1045                 if (pt_reg_sstep(&regs, step) != 0) {
1046                         pt_reg_to_ucontext(&regs, &tmbx.tm_context);
1047                         ret = ps_pwrite(ta->ph, tmbx_addr, &tmbx,
1048                                          sizeof(tmbx));
1049                 }
1050         }
1051         return (P2T(ret));
1052 }
1053
1054 static void
1055 pt_unmap_lwp(const td_thragent_t *ta, lwpid_t lwp)
1056 {
1057         int i;
1058
1059         for (i = 0; i < ta->map_len; ++i) {
1060                 if (ta->map[i].type == PT_LWP && ta->map[i].lwp == lwp) {
1061                         ta->map[i].type = PT_NONE;
1062                         return;
1063                 }
1064         }
1065 }
1066
1067 static int
1068 pt_validate(const td_thrhandle_t *th)
1069 {
1070
1071         if (th->th_tid < 0 || th->th_tid >= th->th_ta->map_len ||
1072             th->th_ta->map[th->th_tid].type == PT_NONE)
1073                 return (TD_NOTHR);
1074         return (TD_OK);
1075 }
1076
1077 td_err_e
1078 pt_thr_tls_get_addr(const td_thrhandle_t *th, void *_linkmap, size_t offset,
1079                     void **address)
1080 {
1081         char *obj_entry;
1082         const td_thragent_t *ta = th->th_ta;
1083         psaddr_t tcb_addr, *dtv_addr;
1084         int tls_index, ret;
1085
1086         /* linkmap is a member of Obj_Entry */
1087         obj_entry = (char *)_linkmap - ta->thread_off_linkmap;
1088
1089         /* get tlsindex of the object file */
1090         ret = ps_pread(ta->ph,
1091                 obj_entry + ta->thread_off_tlsindex,
1092                 &tls_index, sizeof(tls_index));
1093         if (ret != 0)
1094                 return (P2T(ret));
1095
1096         /* get thread tcb */
1097         ret = ps_pread(ta->ph, ta->map[th->th_tid].thr +
1098                 ta->thread_off_tcb,
1099                 &tcb_addr, sizeof(tcb_addr));
1100         if (ret != 0)
1101                 return (P2T(ret));
1102
1103         /* get dtv array address */
1104         ret = ps_pread(ta->ph, tcb_addr + ta->thread_off_dtv,
1105                 &dtv_addr, sizeof(dtv_addr));
1106         if (ret != 0)
1107                 return (P2T(ret));
1108         /* now get the object's tls block base address */
1109         ret = ps_pread(ta->ph, &dtv_addr[tls_index+1], address,
1110                 sizeof(*address));
1111         if (ret != 0)
1112                 return (P2T(ret));
1113
1114         *address += offset;
1115         return (TD_OK);
1116 }
1117
1118 struct ta_ops libpthread_db_ops = {
1119         .to_init                = pt_init,
1120         .to_ta_clear_event      = pt_ta_clear_event,
1121         .to_ta_delete           = pt_ta_delete,
1122         .to_ta_event_addr       = pt_ta_event_addr,
1123         .to_ta_event_getmsg     = pt_ta_event_getmsg,
1124         .to_ta_map_id2thr       = pt_ta_map_id2thr,
1125         .to_ta_map_lwp2thr      = pt_ta_map_lwp2thr,
1126         .to_ta_new              = pt_ta_new,
1127         .to_ta_set_event        = pt_ta_set_event,
1128         .to_ta_thr_iter         = pt_ta_thr_iter,
1129         .to_ta_tsd_iter         = pt_ta_tsd_iter,
1130         .to_thr_clear_event     = pt_thr_clear_event,
1131         .to_thr_dbresume        = pt_thr_dbresume,
1132         .to_thr_dbsuspend       = pt_thr_dbsuspend,
1133         .to_thr_event_enable    = pt_thr_event_enable,
1134         .to_thr_event_getmsg    = pt_thr_event_getmsg,
1135         .to_thr_get_info        = pt_thr_get_info,
1136         .to_thr_getfpregs       = pt_thr_getfpregs,
1137         .to_thr_getgregs        = pt_thr_getgregs,
1138         .to_thr_set_event       = pt_thr_set_event,
1139         .to_thr_setfpregs       = pt_thr_setfpregs,
1140         .to_thr_setgregs        = pt_thr_setgregs,
1141         .to_thr_validate        = pt_thr_validate,
1142         .to_thr_tls_get_addr    = pt_thr_tls_get_addr,
1143
1144         /* FreeBSD specific extensions. */
1145         .to_thr_sstep           = pt_thr_sstep,
1146 #ifdef __i386__
1147         .to_thr_getxmmregs      = pt_thr_getxmmregs,
1148         .to_thr_setxmmregs      = pt_thr_setxmmregs,
1149 #endif
1150 };
1151
1152 DATA_SET(__ta_ops, libpthread_db_ops);