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