]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_map_lwp2thr.c
update
[l4.git] / l4 / pkg / uclibc / lib / contrib / uclibc / libpthread / nptl_db / td_ta_map_lwp2thr.c
1 /* Which thread is running on an LWP?
2    Copyright (C) 2003, 2004 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <http://www.gnu.org/licenses/>.  */
18
19 #include "thread_dbP.h"
20 #include <stdlib.h>
21 #include <byteswap.h>
22 #include <sys/procfs.h>
23
24
25 td_err_e
26 td_ta_map_lwp2thr (const td_thragent_t *ta_arg,
27                    lwpid_t lwpid, td_thrhandle_t *th)
28 {
29   td_thragent_t *const ta = (td_thragent_t *) ta_arg;
30   ps_err_e err;
31   td_err_e terr;
32   prgregset_t regs;
33   psaddr_t addr;
34
35   LOG ("td_ta_map_lwp2thr");
36
37   /* Test whether the TA parameter is ok.  */
38   if (! ta_ok (ta))
39     return TD_BADTA;
40
41   if (ta->ta_howto == ta_howto_unknown)
42     {
43       /* We need to read in from the inferior the instructions what to do.  */
44       psaddr_t howto;
45
46       err = td_lookup (ta->ph, SYM_TH_UNIQUE_CONST_THREAD_AREA, &howto);
47       if (err == PS_OK)
48         {
49           err = ps_pdread (ta->ph, howto,
50                            &ta->ta_howto_data.const_thread_area,
51                            sizeof ta->ta_howto_data.const_thread_area);
52           if (err != PS_OK)
53             return TD_ERR;
54           ta->ta_howto = ta_howto_const_thread_area;
55           if (ta->ta_howto_data.const_thread_area & 0xff000000U)
56             ta->ta_howto_data.const_thread_area
57               = bswap_32 (ta->ta_howto_data.const_thread_area);
58         }
59       else
60         {
61           switch (sizeof (regs[0]))
62             {
63             case 8:
64               err = td_lookup (ta->ph, SYM_TH_UNIQUE_REGISTER64, &howto);
65               if (err == PS_OK)
66                 ta->ta_howto = ta_howto_reg;
67               else if (err == PS_NOSYM)
68                 {
69                   err = td_lookup (ta->ph,
70                                    SYM_TH_UNIQUE_REGISTER64_THREAD_AREA,
71                                    &howto);
72                   if (err == PS_OK)
73                     ta->ta_howto = ta_howto_reg_thread_area;
74                 }
75               break;
76
77             case 4:
78               err = td_lookup (ta->ph, SYM_TH_UNIQUE_REGISTER32, &howto);
79               if (err == PS_OK)
80                 ta->ta_howto = ta_howto_reg;
81               else if (err == PS_NOSYM)
82                 {
83                   err = td_lookup (ta->ph,
84                                    SYM_TH_UNIQUE_REGISTER32_THREAD_AREA,
85                                    &howto);
86                   if (err == PS_OK)
87                     ta->ta_howto = ta_howto_reg_thread_area;
88                 }
89               break;
90
91             default:
92               abort ();
93               return TD_DBERR;
94             }
95
96           if (err != PS_OK)
97             return TD_DBERR;
98
99           /* For either of these methods we read in the same descriptor.  */
100           err = ps_pdread (ta->ph, howto,
101                            ta->ta_howto_data.reg, DB_SIZEOF_DESC);
102           if (err != PS_OK)
103             return TD_ERR;
104           if (DB_DESC_SIZE (ta->ta_howto_data.reg) == 0)
105             return TD_DBERR;
106           if (DB_DESC_SIZE (ta->ta_howto_data.reg) & 0xff000000U)
107             {
108               /* Byte-swap these words, though we leave the size word
109                  in native order as the handy way to distinguish.  */
110               DB_DESC_OFFSET (ta->ta_howto_data.reg)
111                 = bswap_32 (DB_DESC_OFFSET (ta->ta_howto_data.reg));
112               DB_DESC_NELEM (ta->ta_howto_data.reg)
113                 = bswap_32 (DB_DESC_NELEM (ta->ta_howto_data.reg));
114             }
115         }
116     }
117
118   switch (ta->ta_howto)
119     {
120     case ta_howto_unknown:
121       return TD_DBERR;
122
123     default:
124       return TD_DBERR;
125
126     case ta_howto_reg:
127       /* On most machines, we are just looking at a register.  */
128       if (ps_lgetregs (ta->ph, lwpid, regs) != PS_OK)
129         return TD_ERR;
130       terr = _td_fetch_value_local (ta, ta->ta_howto_data.reg, -1,
131                                     0, regs, &addr);
132       if (terr != TD_OK)
133         return terr;
134       /* In this descriptor the nelem word is overloaded as the bias.  */
135       addr += (int32_t) DB_DESC_NELEM (ta->ta_howto_data.reg);
136       th->th_unique = addr;
137       break;
138
139     case ta_howto_const_thread_area:
140       /* Some hosts don't have this call and this case won't be used.  */
141 # pragma weak ps_get_thread_area
142       if (&ps_get_thread_area == NULL)
143         return TD_NOCAPAB;
144
145        /* A la x86-64, there is a constant magic index for get_thread_area.  */
146        if (ps_get_thread_area (ta->ph, lwpid,
147                                ta->ta_howto_data.const_thread_area,
148                                &th->th_unique) != PS_OK)
149          return TD_ERR; /* XXX Other error value?  */
150        break;
151
152      case ta_howto_reg_thread_area:
153       if (&ps_get_thread_area == NULL)
154         return TD_NOCAPAB;
155
156        /* A la i386, there is a register with an index for get_thread_area.  */
157        if (ps_lgetregs (ta->ph, lwpid, regs) != PS_OK)
158          return TD_ERR;
159        terr = _td_fetch_value_local (ta, ta->ta_howto_data.reg_thread_area, -1,
160                                      0, regs, &addr);
161       if (terr != TD_OK)
162         return terr;
163       /* In this descriptor the nelem word is overloaded as scale factor.  */
164       if (ps_get_thread_area
165           (ta->ph, lwpid,
166            ((addr - (psaddr_t) 0)
167             >> DB_DESC_NELEM (ta->ta_howto_data.reg_thread_area)),
168            &th->th_unique) != PS_OK)
169         return TD_ERR;  /* XXX Other error value?  */
170       break;
171     }
172
173   /* Found it.  Now complete the `td_thrhandle_t' object.  */
174   th->th_ta_p = (td_thragent_t *) ta;
175
176   return TD_OK;
177 }