value.c revision 40bab82b523d5e80272bcbd8854516b01265549e
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, 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 208size_t 209value_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 237int 238value_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 274int 275value_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 314union 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 323void 324value_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 358static int 359value_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 370int 371value_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 407int 408value_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 418struct value * 419value_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 428int 429value_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 449int 450value_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 467int 468value_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} 486