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
31static void
32value_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
45void
46value_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
53void
54value_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
60void
61value_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
71void
72value_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
80void
81value_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
91void
92value_destroy(struct value *val)
93{
94	if (val == NULL)
95		return;
96	value_release(val);
97	value_set_type(val, NULL, 0);
98}
99
100unsigned char *
101value_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
117void
118value_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
125int
126value_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
161unsigned char *
162value_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
169unsigned char *
170value_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
188int
189value_clone(struct value *retp, const struct value *val)
190{
191	*retp = *val;
192
193	if (val->own_type) {
194		retp->type = malloc(sizeof(struct arg_type_info));
195		if (type_clone (retp->type, val->type) < 0) {
196			free(retp->type);
197			return -1;
198		}
199	}
200
201	if (val->where == VAL_LOC_COPY) {
202		assert(val->inferior != NULL);
203		size_t size = type_sizeof(val->inferior, val->type);
204		if (size == (size_t)-1) {
205		fail:
206			if (retp->own_type) {
207				type_destroy(retp->type);
208				free(retp->type);
209			}
210			return -1;
211		}
212
213		retp->u.address = malloc(size);
214		if (retp->u.address == NULL)
215			goto fail;
216
217		memcpy(retp->u.address, val->u.address, size);
218	}
219
220	return 0;
221}
222
223size_t
224value_size(struct value *val, struct value_dict *arguments)
225{
226	if (val->size != (size_t)-1)
227		return val->size;
228
229	if (val->type->type != ARGTYPE_ARRAY)
230		return val->size = type_sizeof(val->inferior, val->type);
231
232	struct value length;
233	if (expr_eval(val->type->u.array_info.length, val,
234		      arguments, &length) < 0)
235		return (size_t)-1;
236
237	size_t l;
238	int o = value_extract_word(&length, (long *)&l, arguments);
239	value_destroy(&length);
240
241	if (o < 0)
242		return (size_t)-1;
243
244	size_t elt_size = type_sizeof(val->inferior,
245				      val->type->u.array_info.elt_type);
246	if (elt_size == (size_t)-1)
247		return (size_t)-1;
248
249	return val->size = elt_size * l;
250}
251
252int
253value_init_element(struct value *ret_val, struct value *val, size_t element)
254{
255	size_t off = type_offsetof(val->inferior, val->type, element);
256	if (off == (size_t)-1)
257		return -1;
258
259	struct arg_type_info *e_info = type_element(val->type, element);
260	if (e_info == NULL)
261		return -1;
262
263	value_common_init(ret_val, val->inferior, val, e_info, 0);
264
265	switch (val->where) {
266	case VAL_LOC_COPY:
267	case VAL_LOC_SHARED:
268		ret_val->u.address = val->u.address + off;
269		ret_val->where = VAL_LOC_SHARED;
270		return 0;
271
272	case VAL_LOC_WORD:
273		ret_val->u.address = value_get_raw_data(val) + off;
274		ret_val->where = VAL_LOC_SHARED;
275		return 0;
276
277	case VAL_LOC_INFERIOR:
278		ret_val->u.inf_address = val->u.inf_address + off;
279		ret_val->where = VAL_LOC_INFERIOR;
280		return 0;
281
282	case VAL_LOC_NODATA:
283		assert(!"Can't offset NODATA.");
284		abort();
285	}
286	abort();
287}
288
289int
290value_init_deref(struct value *ret_val, struct value *valp)
291{
292	assert(valp->type->type == ARGTYPE_POINTER);
293
294	/* Note: extracting a pointer value should not need value_dict
295	 * with function arguments.  */
296	long l;
297	if (value_extract_word(valp, &l, NULL) < 0)
298		return -1;
299
300	/* We need "long" to be long enough to hold platform
301	 * pointers.  */
302	(void)sizeof(char[1 - 2*(sizeof(l) < sizeof(void *))]);
303
304	value_common_init(ret_val, valp->inferior, valp,
305			  valp->type->u.ptr_info.info, 0);
306	ret_val->u.value = l; /* Set the address.  */
307	ret_val->where = VAL_LOC_INFERIOR;
308	return 0;
309}
310
311/* The functions value_extract_buf and value_extract_word assume that
312 * data in VALUE is stored at the start of the internal buffer.  For
313 * value_extract_buf in particular there's no other reasonable
314 * default.  If we need to copy out four bytes, they need to be the
315 * bytes pointed to by the buffer pointer.
316 *
317 * But actually the situation is similar for value_extract_word as
318 * well.  This function is used e.g. to extract characters from
319 * strings.  Those weren't stored by value_set_word, they might still
320 * be in client for all we know.  So value_extract_word has to assume
321 * that the whole of data is data is stored at the buffer pointer.
322 *
323 * This is a problem on big endian machines, where 2-byte quantity
324 * carried in 4- or 8-byte long is stored at the end of that long.
325 * (Though that quantity itself is still big endian.)  So we need to
326 * make a little dance to shift the value to the right part of the
327 * buffer.  */
328
329union word_data {
330	uint8_t u8;
331	uint16_t u16;
332	uint32_t u32;
333	uint64_t u64;
334	long l;
335	unsigned char buf[0];
336} u;
337
338void
339value_set_word(struct value *value, long word)
340{
341	size_t sz = type_sizeof(value->inferior, value->type);
342	assert(sz != (size_t)-1);
343	assert(sz <= sizeof(value->u.value));
344
345	value->where = VAL_LOC_WORD;
346
347	union word_data u = {};
348
349	switch (sz) {
350	case 0:
351		u.l = 0;
352		break;
353	case 1:
354		u.u8 = word;
355		break;
356	case 2:
357		u.u16 = word;
358		break;
359	case 4:
360		u.u32 = word;
361		break;
362	case 8:
363		u.u64 = word;
364		break;
365	default:
366		assert(sz != sz);
367		abort();
368	}
369
370	value->u.value = u.l;
371}
372
373static int
374value_extract_buf_sz(struct value *value, unsigned char *tgt, size_t sz,
375		     struct value_dict *arguments)
376{
377	unsigned char *data = value_get_data(value, arguments);
378	if (data == NULL)
379		return -1;
380
381	memcpy(tgt, data, sz);
382	return 0;
383}
384
385int
386value_extract_word(struct value *value, long *retp,
387		   struct value_dict *arguments)
388{
389	size_t sz = type_sizeof(value->inferior, value->type);
390	if (sz == (size_t)-1)
391		return -1;
392	assert(sz <= sizeof(value->u.value));
393
394	if (sz == 0) {
395		*retp = 0;
396		return 0;
397	}
398
399	union word_data u = {};
400	if (value_extract_buf_sz(value, u.buf, sz, arguments) < 0)
401		return -1;
402
403	switch (sz) {
404	case 1:
405		*retp = (long)u.u8;
406		return 0;
407	case 2:
408		*retp = (long)u.u16;
409		return 0;
410	case 4:
411		*retp = (long)u.u32;
412		return 0;
413	case 8:
414		*retp = (long)u.u64;
415		return 0;
416	default:
417		assert(sz != sz);
418		abort();
419	}
420}
421
422int
423value_extract_buf(struct value *value, unsigned char *tgt,
424		  struct value_dict *arguments)
425{
426	size_t sz = type_sizeof(value->inferior, value->type);
427	if (sz == (size_t)-1)
428		return -1;
429
430	return value_extract_buf_sz(value, tgt, sz, arguments);
431}
432
433struct value *
434value_get_parental_struct(struct value *val)
435{
436	struct value *parent;
437	for (parent = val->parent; parent != NULL; parent = parent->parent)
438		if (parent->type->type == ARGTYPE_STRUCT)
439			return parent;
440	return NULL;
441}
442
443int
444value_is_zero(struct value *val, struct value_dict *arguments)
445{
446	unsigned char *data = value_get_data(val, arguments);
447	if (data == NULL)
448		return -1;
449	size_t sz = type_sizeof(val->inferior, val->type);
450	if (sz == (size_t)-1)
451		return -1;
452
453	int zero = 1;
454	size_t j;
455	for (j = 0; j < sz; ++j) {
456		if (data[j] != 0) {
457			zero = 0;
458			break;
459		}
460	}
461	return zero;
462}
463
464int
465value_equal(struct value *val1, struct value *val2,
466	    struct value_dict *arguments)
467{
468	size_t sz1 = type_sizeof(val1->inferior, val1->type);
469	size_t sz2 = type_sizeof(val2->inferior, val2->type);
470	if (sz1 == (size_t)-1 || sz2 == (size_t)-1)
471		return -1;
472	if (sz1 != sz2)
473		return 0;
474
475	unsigned char *data1 = value_get_data(val1, arguments);
476	unsigned char *data2 = value_get_data(val2, arguments);
477	if (data1 == NULL || data2 == NULL)
478		return -1;
479	return memcmp(data1, data2, sz1) == 0 ? 1 : 0;
480}
481
482int
483value_pass_by_reference(struct value *value)
484{
485	assert(value != NULL);
486	assert(value->type->type == ARGTYPE_STRUCT);
487
488	struct arg_type_info *new_info = calloc(sizeof(*new_info), 1);
489	if (new_info == NULL)
490		return -1;
491
492	int own;
493	struct arg_type_info *orig;
494	value_take_type(value, &orig, &own);
495	type_init_pointer(new_info, orig, own);
496	new_info->lens = orig->lens;
497	value_set_type(value, new_info, 1);
498
499	return 0;
500}
501