Imported Upstream version 0.7.2
[platform/upstream/ltrace.git] / value.c
1 /*
2  * This file is part of ltrace.
3  * Copyright (C) 2011,2012 Petr Machata, Red Hat Inc.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18  * 02110-1301 USA
19  */
20
21 #include <string.h>
22 #include <assert.h>
23 #include <stdlib.h>
24
25 #include "value.h"
26 #include "type.h"
27 #include "common.h"
28 #include "expr.h"
29 #include "backend.h"
30
31 static void
32 value_common_init(struct value *valp, struct Process *inferior,
33                   struct value *parent, struct arg_type_info *type,
34                   int own_type)
35 {
36         valp->type = type;
37         valp->own_type = own_type;
38         valp->inferior = inferior;
39         memset(&valp->u, 0, sizeof(valp->u));
40         valp->where = VAL_LOC_NODATA;
41         valp->parent = parent;
42         valp->size = (size_t)-1;
43 }
44
45 void
46 value_init(struct value *valp, struct Process *inferior, struct value *parent,
47            struct arg_type_info *type, int own_type)
48 {
49         assert(inferior != NULL);
50         value_common_init(valp, inferior, parent, type, own_type);
51 }
52
53 void
54 value_init_detached(struct value *valp, struct value *parent,
55                     struct arg_type_info *type, int own_type)
56 {
57         value_common_init(valp, NULL, parent, type, own_type);
58 }
59
60 void
61 value_set_type(struct value *value, struct arg_type_info *type, int own_type)
62 {
63         if (value->own_type) {
64                 type_destroy(value->type);
65                 free(value->type);
66         }
67         value->type = type;
68         value->own_type = own_type;
69 }
70
71 void
72 value_take_type(struct value *value, struct arg_type_info **type,
73                 int *own_type)
74 {
75         *type = value->type;
76         *own_type = value->own_type;
77         value->own_type = 0;
78 }
79
80 void
81 value_release(struct value *val)
82 {
83         if (val == NULL)
84                 return;
85         if (val->where == VAL_LOC_COPY) {
86                 free(val->u.address);
87                 val->where = VAL_LOC_NODATA;
88         }
89 }
90
91 void
92 value_destroy(struct value *val)
93 {
94         if (val == NULL)
95                 return;
96         value_release(val);
97         value_set_type(val, NULL, 0);
98 }
99
100 unsigned char *
101 value_reserve(struct value *valp, size_t size)
102 {
103         value_release(valp);
104
105         if (size <= sizeof(valp->u.value)) {
106                 valp->where = VAL_LOC_WORD;
107                 valp->u.value = 0;
108         } else {
109                 valp->where = VAL_LOC_COPY;
110                 valp->u.address = calloc(size, 1);
111                 if (valp->u.address == 0)
112                         return NULL;
113         }
114         return value_get_raw_data(valp);
115 }
116
117 void
118 value_in_inferior(struct value *valp, arch_addr_t address)
119 {
120         value_release(valp);
121         valp->where = VAL_LOC_INFERIOR;
122         valp->u.address = address;
123 }
124
125 int
126 value_reify(struct value *val, struct value_dict *arguments)
127 {
128         if (val->where != VAL_LOC_INFERIOR)
129                 return 0;
130         assert(val->inferior != NULL);
131
132         size_t size = value_size(val, arguments);
133         if (size == (size_t)-1)
134                 return -1;
135
136         void *data;
137         enum value_location_t nloc;
138         if (size <= sizeof(val->u.value)) {
139                 data = &val->u.value;
140                 nloc = VAL_LOC_WORD;
141         } else {
142                 data = malloc(size);
143                 if (data == NULL)
144                         return -1;
145                 nloc = VAL_LOC_COPY;
146         }
147
148         if (umovebytes(val->inferior, val->u.inf_address, data, size) < size) {
149                 if (nloc == VAL_LOC_COPY)
150                         free(data);
151                 return -1;
152         }
153
154         val->where = nloc;
155         if (nloc == VAL_LOC_COPY)
156                 val->u.address = data;
157
158         return 0;
159 }
160
161 unsigned char *
162 value_get_data(struct value *val, struct value_dict *arguments)
163 {
164         if (value_reify(val, arguments) < 0)
165                 return NULL;
166         return value_get_raw_data(val);
167 }
168
169 unsigned char *
170 value_get_raw_data(struct value *val)
171 {
172         switch (val->where) {
173         case VAL_LOC_INFERIOR:
174                 abort();
175         case VAL_LOC_NODATA:
176                 return NULL;
177         case VAL_LOC_COPY:
178         case VAL_LOC_SHARED:
179                 return val->u.address;
180         case VAL_LOC_WORD:
181                 return val->u.buf;
182         }
183
184         assert(!"Unexpected value of val->where");
185         abort();
186 }
187
188 int
189 value_clone(struct value *retp, const struct value *val)
190 {
191         *retp = *val;
192         if (val->where == VAL_LOC_COPY) {
193                 assert(val->inferior != NULL);
194                 size_t size = type_sizeof(val->inferior, val->type);
195                 if (size == (size_t)-1)
196                         return -1;
197
198                 retp->u.address = malloc(size);
199                 if (retp->u.address == NULL)
200                         return -1;
201
202                 memcpy(retp->u.address, val->u.address, size);
203         }
204
205         return 0;
206 }
207
208 size_t
209 value_size(struct value *val, struct value_dict *arguments)
210 {
211         if (val->size != (size_t)-1)
212                 return val->size;
213
214         if (val->type->type != ARGTYPE_ARRAY)
215                 return val->size = type_sizeof(val->inferior, val->type);
216
217         struct value length;
218         if (expr_eval(val->type->u.array_info.length, val,
219                       arguments, &length) < 0)
220                 return (size_t)-1;
221
222         size_t l;
223         int o = value_extract_word(&length, (long *)&l, arguments);
224         value_destroy(&length);
225
226         if (o < 0)
227                 return (size_t)-1;
228
229         size_t elt_size = type_sizeof(val->inferior,
230                                       val->type->u.array_info.elt_type);
231         if (elt_size == (size_t)-1)
232                 return (size_t)-1;
233
234         return val->size = elt_size * l;
235 }
236
237 int
238 value_init_element(struct value *ret_val, struct value *val, size_t element)
239 {
240         size_t off = type_offsetof(val->inferior, val->type, element);
241         if (off == (size_t)-1)
242                 return -1;
243
244         struct arg_type_info *e_info = type_element(val->type, element);
245         if (e_info == NULL)
246                 return -1;
247
248         value_common_init(ret_val, val->inferior, val, e_info, 0);
249
250         switch (val->where) {
251         case VAL_LOC_COPY:
252         case VAL_LOC_SHARED:
253                 ret_val->u.address = val->u.address + off;
254                 ret_val->where = VAL_LOC_SHARED;
255                 return 0;
256
257         case VAL_LOC_WORD:
258                 ret_val->u.address = value_get_raw_data(val) + off;
259                 ret_val->where = VAL_LOC_SHARED;
260                 return 0;
261
262         case VAL_LOC_INFERIOR:
263                 ret_val->u.inf_address = val->u.inf_address + off;
264                 ret_val->where = VAL_LOC_INFERIOR;
265                 return 0;
266
267         case VAL_LOC_NODATA:
268                 assert(!"Can't offset NODATA.");
269                 abort();
270         }
271         abort();
272 }
273
274 int
275 value_init_deref(struct value *ret_val, struct value *valp)
276 {
277         assert(valp->type->type == ARGTYPE_POINTER);
278
279         /* Note: extracting a pointer value should not need value_dict
280          * with function arguments.  */
281         long l;
282         if (value_extract_word(valp, &l, NULL) < 0)
283                 return -1;
284
285         /* We need "long" to be long enough to hold platform
286          * pointers.  */
287         typedef char assert__long_enough_long[-(sizeof(l) < sizeof(void *))];
288
289         value_common_init(ret_val, valp->inferior, valp,
290                           valp->type->u.ptr_info.info, 0);
291         ret_val->u.value = l; /* Set the address.  */
292         ret_val->where = VAL_LOC_INFERIOR;
293         return 0;
294 }
295
296 /* The functions value_extract_buf and value_extract_word assume that
297  * data in VALUE is stored at the start of the internal buffer.  For
298  * value_extract_buf in particular there's no other reasonable
299  * default.  If we need to copy out four bytes, they need to be the
300  * bytes pointed to by the buffer pointer.
301  *
302  * But actually the situation is similar for value_extract_word as
303  * well.  This function is used e.g. to extract characters from
304  * strings.  Those weren't stored by value_set_word, they might still
305  * be in client for all we know.  So value_extract_word has to assume
306  * that the whole of data is data is stored at the buffer pointer.
307  *
308  * This is a problem on big endian machines, where 2-byte quantity
309  * carried in 4- or 8-byte long is stored at the end of that long.
310  * (Though that quantity itself is still big endian.)  So we need to
311  * make a little dance to shift the value to the right part of the
312  * buffer.  */
313
314 union word_data {
315         uint8_t u8;
316         uint16_t u16;
317         uint32_t u32;
318         uint64_t u64;
319         long l;
320         unsigned char buf[0];
321 } u;
322
323 void
324 value_set_word(struct value *value, long word)
325 {
326         size_t sz = type_sizeof(value->inferior, value->type);
327         assert(sz != (size_t)-1);
328         assert(sz <= sizeof(value->u.value));
329
330         value->where = VAL_LOC_WORD;
331
332         union word_data u = {};
333
334         switch (sz) {
335         case 0:
336                 u.l = 0;
337                 break;
338         case 1:
339                 u.u8 = word;
340                 break;
341         case 2:
342                 u.u16 = word;
343                 break;
344         case 4:
345                 u.u32 = word;
346                 break;
347         case 8:
348                 u.u64 = word;
349                 break;
350         default:
351                 assert(sz != sz);
352                 abort();
353         }
354
355         value->u.value = u.l;
356 }
357
358 static int
359 value_extract_buf_sz(struct value *value, unsigned char *tgt, size_t sz,
360                      struct value_dict *arguments)
361 {
362         unsigned char *data = value_get_data(value, arguments);
363         if (data == NULL)
364                 return -1;
365
366         memcpy(tgt, data, sz);
367         return 0;
368 }
369
370 int
371 value_extract_word(struct value *value, long *retp,
372                    struct value_dict *arguments)
373 {
374         size_t sz = type_sizeof(value->inferior, value->type);
375         if (sz == (size_t)-1)
376                 return -1;
377         assert(sz <= sizeof(value->u.value));
378
379         if (sz == 0) {
380                 *retp = 0;
381                 return 0;
382         }
383
384         union word_data u = {};
385         if (value_extract_buf_sz(value, u.buf, sz, arguments) < 0)
386                 return -1;
387
388         switch (sz) {
389         case 1:
390                 *retp = (long)u.u8;
391                 return 0;
392         case 2:
393                 *retp = (long)u.u16;
394                 return 0;
395         case 4:
396                 *retp = (long)u.u32;
397                 return 0;
398         case 8:
399                 *retp = (long)u.u64;
400                 return 0;
401         default:
402                 assert(sz != sz);
403                 abort();
404         }
405 }
406
407 int
408 value_extract_buf(struct value *value, unsigned char *tgt,
409                   struct value_dict *arguments)
410 {
411         size_t sz = type_sizeof(value->inferior, value->type);
412         if (sz == (size_t)-1)
413                 return -1;
414
415         return value_extract_buf_sz(value, tgt, sz, arguments);
416 }
417
418 struct value *
419 value_get_parental_struct(struct value *val)
420 {
421         struct value *parent;
422         for (parent = val->parent; parent != NULL; parent = parent->parent)
423                 if (parent->type->type == ARGTYPE_STRUCT)
424                         return parent;
425         return NULL;
426 }
427
428 int
429 value_is_zero(struct value *val, struct value_dict *arguments)
430 {
431         unsigned char *data = value_get_data(val, arguments);
432         if (data == NULL)
433                 return -1;
434         size_t sz = type_sizeof(val->inferior, val->type);
435         if (sz == (size_t)-1)
436                 return -1;
437
438         int zero = 1;
439         size_t j;
440         for (j = 0; j < sz; ++j) {
441                 if (data[j] != 0) {
442                         zero = 0;
443                         break;
444                 }
445         }
446         return zero;
447 }
448
449 int
450 value_equal(struct value *val1, struct value *val2,
451             struct value_dict *arguments)
452 {
453         size_t sz1 = type_sizeof(val1->inferior, val1->type);
454         size_t sz2 = type_sizeof(val2->inferior, val2->type);
455         if (sz1 == (size_t)-1 || sz2 == (size_t)-1)
456                 return -1;
457         if (sz1 != sz2)
458                 return 0;
459
460         unsigned char *data1 = value_get_data(val1, arguments);
461         unsigned char *data2 = value_get_data(val2, arguments);
462         if (data1 == NULL || data2 == NULL)
463                 return -1;
464         return memcmp(data1, data2, sz1) == 0 ? 1 : 0;
465 }
466
467 int
468 value_pass_by_reference(struct value *value)
469 {
470         assert(value != NULL);
471         assert(value->type->type == ARGTYPE_STRUCT);
472
473         struct arg_type_info *new_info = calloc(sizeof(*new_info), 1);
474         if (new_info == NULL)
475                 return -1;
476
477         int own;
478         struct arg_type_info *orig;
479         value_take_type(value, &orig, &own);
480         type_init_pointer(new_info, orig, own);
481         new_info->lens = orig->lens;
482         value_set_type(value, new_info, 1);
483
484         return 0;
485 }