0d9bb0eb8073d151ce6582e2fc330e027d4a018c
[kopensolaris-gnu/glibc.git] / fetch-value.c
1 /* Helper routines for libthread_db.
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, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #include "thread_dbP.h"
21 #include <byteswap.h>
22 #include <assert.h>
23
24 td_err_e
25 _td_check_sizeof (td_thragent_t *ta, uint32_t *sizep, int sizep_name)
26 {
27   if (*sizep == 0)
28     {
29       psaddr_t descptr;
30       ps_err_e err = td_lookup (ta->ph, sizep_name, &descptr);
31       if (err == PS_NOSYM)
32         return TD_NOCAPAB;
33       if (err == PS_OK)
34         err = ps_pdread (ta->ph, descptr, sizep, sizeof *sizep);
35       if (err != PS_OK)
36         return TD_ERR;
37       if (*sizep & 0xff000000U)
38         *sizep = bswap_32 (*sizep);
39     }
40   return TD_OK;
41 }
42
43 td_err_e
44 _td_locate_field (td_thragent_t *ta,
45                   db_desc_t desc, int descriptor_name,
46                   psaddr_t idx, psaddr_t *address)
47 {
48   uint32_t elemsize;
49
50   if (DB_DESC_SIZE (desc) == 0)
51     {
52       /* Read the information about this field from the inferior.  */
53       psaddr_t descptr;
54       ps_err_e err = td_lookup (ta->ph, descriptor_name, &descptr);
55       if (err == PS_NOSYM)
56         return TD_NOCAPAB;
57       if (err == PS_OK)
58         err = ps_pdread (ta->ph, descptr, desc, DB_SIZEOF_DESC);
59       if (err != PS_OK)
60         return TD_ERR;
61       if (DB_DESC_SIZE (desc) == 0)
62         return TD_DBERR;
63       if (DB_DESC_SIZE (desc) & 0xff000000U)
64         {
65           /* Byte-swap these words, though we leave the size word
66              in native order as the handy way to distinguish.  */
67           DB_DESC_OFFSET (desc) = bswap_32 (DB_DESC_OFFSET (desc));
68           DB_DESC_NELEM (desc) = bswap_32 (DB_DESC_NELEM (desc));
69         }
70     }
71
72   if (idx != 0 && idx - (psaddr_t) 0 > DB_DESC_NELEM (desc))
73     /* This is an internal indicator to callers with nonzero IDX
74        that the IDX value is too big.  */
75     return TD_NOAPLIC;
76
77   elemsize = DB_DESC_SIZE (desc);
78   if (elemsize & 0xff000000U)
79     elemsize = bswap_32 (elemsize);
80
81   *address += (int32_t) DB_DESC_OFFSET (desc);
82   *address += (elemsize / 8 * (idx - (psaddr_t) 0));
83   return TD_OK;
84 }
85
86 td_err_e
87 _td_fetch_value (td_thragent_t *ta,
88                  db_desc_t desc, int descriptor_name,
89                  psaddr_t idx, psaddr_t address,
90                  psaddr_t *result)
91 {
92   ps_err_e err;
93   td_err_e terr = _td_locate_field (ta, desc, descriptor_name, idx, &address);
94   if (terr != TD_OK)
95     return terr;
96
97   if (DB_DESC_SIZE (desc) == 8 || DB_DESC_SIZE (desc) == bswap_32 (8))
98     {
99       uint8_t value;
100       err = ps_pdread (ta->ph, address, &value, sizeof value);
101       *result = (psaddr_t) 0 + value;
102     }
103   else if (DB_DESC_SIZE (desc) == 32)
104     {
105       uint32_t value;
106       err = ps_pdread (ta->ph, address, &value, sizeof value);
107       *result = (psaddr_t) 0 + value;
108     }
109   else if (DB_DESC_SIZE (desc) == 64)
110     {
111       uint64_t value;
112       if (sizeof (psaddr_t) < 8)
113         return TD_NOCAPAB;
114       err = ps_pdread (ta->ph, address, &value, sizeof value);
115       *result = (psaddr_t) 0 + value;
116     }
117   else if (DB_DESC_SIZE (desc) == bswap_32 (32))
118     {
119       uint32_t value;
120       err = ps_pdread (ta->ph, address, &value, sizeof value);
121       value = bswap_32 (value);
122       *result = (psaddr_t) 0 + value;
123     }
124   else if (DB_DESC_SIZE (desc) == bswap_32 (64))
125     {
126       uint64_t value;
127       if (sizeof (psaddr_t) < 8)
128         return TD_NOCAPAB;
129       err = ps_pdread (ta->ph, address, &value, sizeof value);
130       value = bswap_64 (value);
131       *result = (psaddr_t) 0 + value;
132     }
133   else
134     return TD_DBERR;
135
136   return err == PS_OK ? TD_OK : TD_ERR;
137 }
138
139
140 td_err_e
141 _td_store_value (td_thragent_t *ta,
142                  uint32_t desc[2], int descriptor_name, psaddr_t idx,
143                  psaddr_t address, psaddr_t widened_value)
144 {
145   ps_err_e err;
146   td_err_e terr = _td_locate_field (ta, desc, descriptor_name, idx, &address);
147   if (terr != TD_OK)
148     return terr;
149
150   if (DB_DESC_SIZE (desc) == 8 || DB_DESC_SIZE (desc) == bswap_32 (8))
151     {
152       uint8_t value = widened_value - (psaddr_t) 0;
153       err = ps_pdwrite (ta->ph, address, &value, sizeof value);
154     }
155   else if (DB_DESC_SIZE (desc) == 32)
156     {
157       uint32_t value = widened_value - (psaddr_t) 0;
158       err = ps_pdwrite (ta->ph, address, &value, sizeof value);
159     }
160   else if (DB_DESC_SIZE (desc) == 64)
161     {
162       uint64_t value = widened_value - (psaddr_t) 0;
163       if (sizeof (psaddr_t) < 8)
164         return TD_NOCAPAB;
165       err = ps_pdwrite (ta->ph, address, &value, sizeof value);
166     }
167   else if (DB_DESC_SIZE (desc) == bswap_32 (32))
168     {
169       uint32_t value = widened_value - (psaddr_t) 0;
170       value = bswap_32 (value);
171       err = ps_pdwrite (ta->ph, address, &value, sizeof value);
172     }
173   else if (DB_DESC_SIZE (desc) == bswap_32 (64))
174     {
175       uint64_t value = widened_value - (psaddr_t) 0;
176       if (sizeof (psaddr_t) < 8)
177         return TD_NOCAPAB;
178       value = bswap_64 (value);
179       err = ps_pdwrite (ta->ph, address, &value, sizeof value);
180     }
181   else
182     return TD_DBERR;
183
184   return err == PS_OK ? TD_OK : TD_ERR;
185 }
186
187 td_err_e
188 _td_fetch_value_local (td_thragent_t *ta,
189                        db_desc_t desc, int descriptor_name, psaddr_t idx,
190                        void *address,
191                        psaddr_t *result)
192 {
193   td_err_e terr = _td_locate_field (ta, desc, descriptor_name, idx, &address);
194   if (terr != TD_OK)
195     return terr;
196
197   if (DB_DESC_SIZE (desc) == 8 || DB_DESC_SIZE (desc) == bswap_32 (8))
198     {
199       uint8_t value;
200       memcpy (&value, address, sizeof value);
201       *result = (psaddr_t) 0 + value;
202     }
203   else if (DB_DESC_SIZE (desc) == 32)
204     {
205       uint32_t value;
206       memcpy (&value, address, sizeof value);
207       *result = (psaddr_t) 0 + value;
208     }
209   else if (DB_DESC_SIZE (desc) == 64)
210     {
211       uint64_t value;
212       if (sizeof (psaddr_t) < 8)
213         return TD_NOCAPAB;
214       memcpy (&value, address, sizeof value);
215       *result = (psaddr_t) 0 + value;
216     }
217   else if (DB_DESC_SIZE (desc) == bswap_32 (32))
218     {
219       uint32_t value;
220       memcpy (&value, address, sizeof value);
221       value = bswap_32 (value);
222       *result = (psaddr_t) 0 + value;
223     }
224   else if (DB_DESC_SIZE (desc) == bswap_32 (64))
225     {
226       uint64_t value;
227       if (sizeof (psaddr_t) < 8)
228         return TD_NOCAPAB;
229       memcpy (&value, address, sizeof value);
230       value = bswap_64 (value);
231       *result = (psaddr_t) 0 + value;
232     }
233   else
234     return TD_DBERR;
235
236   return TD_OK;
237 }
238
239
240 td_err_e
241 _td_store_value_local (td_thragent_t *ta,
242                        uint32_t desc[2], int descriptor_name, psaddr_t idx,
243                        void *address, psaddr_t widened_value)
244 {
245   td_err_e terr = _td_locate_field (ta, desc, descriptor_name, idx, &address);
246   if (terr != TD_OK)
247     return terr;
248
249   if (DB_DESC_SIZE (desc) == 8 || DB_DESC_SIZE (desc) == bswap_32 (8))
250     {
251       uint8_t value = widened_value - (psaddr_t) 0;
252       memcpy (address, &value, sizeof value);
253     }
254   else if (DB_DESC_SIZE (desc) == 32)
255     {
256       uint32_t value = widened_value - (psaddr_t) 0;
257       memcpy (address, &value, sizeof value);
258     }
259   else if (DB_DESC_SIZE (desc) == 64)
260     {
261       uint64_t value = widened_value - (psaddr_t) 0;
262       if (sizeof (psaddr_t) < 8)
263         return TD_NOCAPAB;
264       memcpy (address, &value, sizeof value);
265     }
266   else if (DB_DESC_SIZE (desc) == bswap_32 (32))
267     {
268       uint32_t value = widened_value - (psaddr_t) 0;
269       value = bswap_32 (value);
270       memcpy (address, &value, sizeof value);
271     }
272   else if (DB_DESC_SIZE (desc) == bswap_32 (64))
273     {
274       uint64_t value = widened_value - (psaddr_t) 0;
275       if (sizeof (psaddr_t) < 8)
276         return TD_NOCAPAB;
277       value = bswap_64 (value);
278       memcpy (address, &value, sizeof value);
279     }
280   else
281     return TD_DBERR;
282
283   return TD_OK;
284 }