value.c revision 0d40d115a2e09bd0d432cc276d5cfc3c013468b0
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 117int 118value_reify(struct value *val, struct value_dict *arguments) 119{ 120 if (val->where != VAL_LOC_INFERIOR) 121 return 0; 122 assert(val->inferior != NULL); 123 124 size_t size = value_size(val, arguments); 125 if (size == (size_t)-1) 126 return -1; 127 128 void *data; 129 enum value_location_t nloc; 130 if (size <= sizeof(val->u.value)) { 131 data = &val->u.value; 132 nloc = VAL_LOC_WORD; 133 } else { 134 data = malloc(size); 135 if (data == NULL) 136 return -1; 137 nloc = VAL_LOC_COPY; 138 } 139 140 if (umovebytes(val->inferior, val->u.inf_address, data, size) < size) { 141 if (nloc == VAL_LOC_COPY) 142 free(data); 143 return -1; 144 } 145 146 val->where = nloc; 147 if (nloc == VAL_LOC_COPY) 148 val->u.address = data; 149 150 return 0; 151} 152 153unsigned char * 154value_get_data(struct value *val, struct value_dict *arguments) 155{ 156 if (value_reify(val, arguments) < 0) 157 return NULL; 158 return value_get_raw_data(val); 159} 160 161unsigned char * 162value_get_raw_data(struct value *val) 163{ 164 switch (val->where) { 165 case VAL_LOC_INFERIOR: 166 abort(); 167 case VAL_LOC_NODATA: 168 return NULL; 169 case VAL_LOC_COPY: 170 case VAL_LOC_SHARED: 171 return val->u.address; 172 case VAL_LOC_WORD: 173 return val->u.buf; 174 } 175 176 assert(!"Unexpected value of val->where"); 177 abort(); 178} 179 180int 181value_clone(struct value *retp, struct value *val) 182{ 183 *retp = *val; 184 if (val->where == VAL_LOC_COPY) { 185 assert(val->inferior != NULL); 186 size_t size = type_sizeof(val->inferior, val->type); 187 if (size == (size_t)-1) 188 return -1; 189 190 retp->u.address = malloc(size); 191 if (retp->u.address == NULL) 192 return -1; 193 194 memcpy(retp->u.address, val->u.address, size); 195 } 196 197 return 0; 198} 199 200size_t 201value_size(struct value *val, struct value_dict *arguments) 202{ 203 if (val->size != (size_t)-1) 204 return val->size; 205 206 if (val->type->type != ARGTYPE_ARRAY) 207 return val->size = type_sizeof(val->inferior, val->type); 208 209 struct value length; 210 if (expr_eval(val->type->u.array_info.length, val, 211 arguments, &length) < 0) 212 return (size_t)-1; 213 214 size_t l; 215 int o = value_extract_word(&length, (long *)&l, arguments); 216 value_destroy(&length); 217 218 if (o < 0) 219 return (size_t)-1; 220 221 size_t elt_size = type_sizeof(val->inferior, 222 val->type->u.array_info.elt_type); 223 if (elt_size == (size_t)-1) 224 return (size_t)-1; 225 226 return val->size = elt_size * l; 227} 228 229int 230value_init_element(struct value *ret_val, struct value *val, size_t element) 231{ 232 size_t off = type_offsetof(val->inferior, val->type, element); 233 if (off == (size_t)-1) 234 return -1; 235 236 struct arg_type_info *e_info = type_element(val->type, element); 237 if (e_info == NULL) 238 return -1; 239 240 value_common_init(ret_val, val->inferior, val, e_info, 0); 241 242 switch (val->where) { 243 case VAL_LOC_COPY: 244 case VAL_LOC_SHARED: 245 ret_val->u.address = val->u.address + off; 246 ret_val->where = VAL_LOC_SHARED; 247 return 0; 248 249 case VAL_LOC_WORD: 250 ret_val->u.address = value_get_raw_data(val) + off; 251 ret_val->where = VAL_LOC_SHARED; 252 return 0; 253 254 case VAL_LOC_INFERIOR: 255 ret_val->u.inf_address = val->u.inf_address + off; 256 ret_val->where = VAL_LOC_INFERIOR; 257 return 0; 258 259 case VAL_LOC_NODATA: 260 assert(!"Can't offset NODATA."); 261 abort(); 262 } 263 abort(); 264} 265 266int 267value_init_deref(struct value *ret_val, struct value *valp) 268{ 269 assert(valp->type->type == ARGTYPE_POINTER); 270 271 /* Note: extracting a pointer value should not need value_dict 272 * with function arguments. */ 273 long l; 274 if (value_extract_word(valp, &l, NULL) < 0) 275 return -1; 276 277 /* We need "long" to be long enough to hold platform 278 * pointers. */ 279 typedef char assert__long_enough_long[-(sizeof(l) < sizeof(void *))]; 280 281 value_common_init(ret_val, valp->inferior, valp, 282 valp->type->u.ptr_info.info, 0); 283 ret_val->u.value = l; /* Set the address. */ 284 ret_val->where = VAL_LOC_INFERIOR; 285 return 0; 286} 287 288/* The functions value_extract_buf and value_extract_word assume that 289 * data in VALUE is stored at the start of the internal buffer. For 290 * value_extract_buf in particular there's no other reasonable 291 * default. If we need to copy out four bytes, they need to be the 292 * bytes pointed to by the buffer pointer. 293 * 294 * But actually the situation is similar for value_extract_word as 295 * well. This function is used e.g. to extract characters from 296 * strings. Those weren't stored by value_set_word, they might still 297 * be in client for all we know. So value_extract_word has to assume 298 * that the whole of data is data is stored at the buffer pointer. 299 * 300 * This is a problem on big endian machines, where 2-byte quantity 301 * carried in 4- or 8-byte long is stored at the end of that long. 302 * (Though that quantity itself is still big endian.) So we need to 303 * make a little dance to shift the value to the right part of the 304 * buffer. */ 305 306union word_data { 307 uint8_t u8; 308 uint16_t u16; 309 uint32_t u32; 310 uint64_t u64; 311 long l; 312 unsigned char buf[0]; 313} u; 314 315void 316value_set_word(struct value *value, long word) 317{ 318 size_t sz = type_sizeof(value->inferior, value->type); 319 assert(sz != (size_t)-1); 320 assert(sz <= sizeof(value->u.value)); 321 322 value->where = VAL_LOC_WORD; 323 324 union word_data u = {}; 325 326 switch (sz) { 327 case 0: 328 u.l = 0; 329 break; 330 case 1: 331 u.u8 = word; 332 break; 333 case 2: 334 u.u16 = word; 335 break; 336 case 4: 337 u.u32 = word; 338 break; 339 case 8: 340 u.u64 = word; 341 break; 342 default: 343 assert(sz != sz); 344 abort(); 345 } 346 347 value->u.value = u.l; 348} 349 350static int 351value_extract_buf_sz(struct value *value, unsigned char *tgt, size_t sz, 352 struct value_dict *arguments) 353{ 354 unsigned char *data = value_get_data(value, arguments); 355 if (data == NULL) 356 return -1; 357 358 memcpy(tgt, data, sz); 359 return 0; 360} 361 362int 363value_extract_word(struct value *value, long *retp, 364 struct value_dict *arguments) 365{ 366 size_t sz = type_sizeof(value->inferior, value->type); 367 if (sz == (size_t)-1) 368 return -1; 369 assert(sz <= sizeof(value->u.value)); 370 371 if (sz == 0) { 372 *retp = 0; 373 return 0; 374 } 375 376 union word_data u = {}; 377 if (value_extract_buf_sz(value, u.buf, sz, arguments) < 0) 378 return -1; 379 380 switch (sz) { 381 case 1: 382 *retp = (long)u.u8; 383 return 0; 384 case 2: 385 *retp = (long)u.u16; 386 return 0; 387 case 4: 388 *retp = (long)u.u32; 389 return 0; 390 case 8: 391 *retp = (long)u.u64; 392 return 0; 393 default: 394 assert(sz != sz); 395 abort(); 396 } 397} 398 399int 400value_extract_buf(struct value *value, unsigned char *tgt, 401 struct value_dict *arguments) 402{ 403 size_t sz = type_sizeof(value->inferior, value->type); 404 if (sz == (size_t)-1) 405 return -1; 406 407 return value_extract_buf_sz(value, tgt, sz, arguments); 408} 409 410struct value * 411value_get_parental_struct(struct value *val) 412{ 413 struct value *parent; 414 for (parent = val->parent; parent != NULL; parent = parent->parent) 415 if (parent->type->type == ARGTYPE_STRUCT) 416 return parent; 417 return NULL; 418} 419 420int 421value_is_zero(struct value *val, struct value_dict *arguments) 422{ 423 unsigned char *data = value_get_data(val, arguments); 424 if (data == NULL) 425 return -1; 426 size_t sz = type_sizeof(val->inferior, val->type); 427 if (sz == (size_t)-1) 428 return -1; 429 430 int zero = 1; 431 size_t j; 432 for (j = 0; j < sz; ++j) { 433 if (data[j] != 0) { 434 zero = 0; 435 break; 436 } 437 } 438 return zero; 439} 440 441int 442value_pass_by_reference(struct value *value) 443{ 444 assert(value != NULL); 445 assert(value->type->type == ARGTYPE_STRUCT); 446 447 struct arg_type_info *new_info = calloc(sizeof(*new_info), 1); 448 if (new_info == NULL) 449 return -1; 450 451 int own; 452 struct arg_type_info *orig; 453 value_take_type(value, &orig, &own); 454 type_init_pointer(new_info, orig, own); 455 new_info->lens = orig->lens; 456 value_set_type(value, new_info, 1); 457 458 return 0; 459} 460