Home | History | Annotate | Download | only in ltrace
      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 
    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 
    223 size_t
    224 value_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 
    252 int
    253 value_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 
    289 int
    290 value_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 
    329 union 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 
    338 void
    339 value_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 
    373 static int
    374 value_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 
    385 int
    386 value_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 
    422 int
    423 value_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 
    433 struct value *
    434 value_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 
    443 int
    444 value_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 
    464 int
    465 value_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 
    482 int
    483 value_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