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