value.c revision 642626096a694c6af279d25d2b1b2fba5b10ddfb
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 value->type = type; 66 value->own_type = own_type; 67} 68 69void 70value_take_type(struct value *value, struct arg_type_info **type, 71 int *own_type) 72{ 73 *type = value->type; 74 *own_type = value->own_type; 75 value->own_type = 0; 76} 77 78void 79value_release(struct value *val) 80{ 81 if (val == NULL) 82 return; 83 if (val->where == VAL_LOC_COPY) { 84 free(val->u.address); 85 val->where = VAL_LOC_NODATA; 86 } 87} 88 89void 90value_destroy(struct value *val) 91{ 92 if (val == NULL) 93 return; 94 value_release(val); 95 value_set_type(val, NULL, 0); 96} 97 98void 99value_set_long(struct value *valp, long value) 100{ 101 valp->where = VAL_LOC_WORD; 102 valp->u.value = value; 103} 104 105unsigned char * 106value_reserve(struct value *valp, size_t size) 107{ 108 if (size <= sizeof(valp->u.value)) { 109 value_set_long(valp, 0); 110 } else { 111 valp->where = VAL_LOC_COPY; 112 valp->u.address = calloc(size, 1); 113 if (valp->u.address == 0) 114 return NULL; 115 } 116 return value_get_raw_data(valp); 117} 118 119int 120value_reify(struct value *val, struct value_dict *arguments) 121{ 122 if (val->where != VAL_LOC_INFERIOR) 123 return 0; 124 assert(val->inferior != NULL); 125 126 size_t size = value_size(val, arguments); 127 if (size == (size_t)-1) 128 return -1; 129 130 void *data; 131 enum value_location_t nloc; 132 if (size <= sizeof(val->u.value)) { 133 data = &val->u.value; 134 nloc = VAL_LOC_WORD; 135 } else { 136 data = malloc(size); 137 if (data == NULL) 138 return -1; 139 nloc = VAL_LOC_COPY; 140 } 141 142 if (umovebytes(val->inferior, val->u.address, data, size) < size) { 143 if (nloc == VAL_LOC_COPY) 144 free(data); 145 return -1; 146 } 147 148 val->where = nloc; 149 if (nloc == VAL_LOC_COPY) 150 val->u.address = data; 151 152 return 0; 153} 154 155unsigned char * 156value_get_data(struct value *val, struct value_dict *arguments) 157{ 158 if (value_reify(val, arguments) < 0) 159 return NULL; 160 return value_get_raw_data(val); 161} 162 163unsigned char * 164value_get_raw_data(struct value *val) 165{ 166 switch (val->where) { 167 case VAL_LOC_INFERIOR: 168 abort(); 169 case VAL_LOC_NODATA: 170 return NULL; 171 case VAL_LOC_COPY: 172 case VAL_LOC_SHARED: 173 return val->u.address; 174 case VAL_LOC_WORD: 175 return val->u.buf; 176 } 177 178 assert(!"Unexpected value of val->where"); 179 abort(); 180} 181 182int 183value_clone(struct value *retp, struct value *val) 184{ 185 *retp = *val; 186 if (val->where == VAL_LOC_COPY) { 187 assert(val->inferior != NULL); 188 size_t size = type_sizeof(val->inferior, val->type); 189 if (size == (size_t)-1) 190 return -1; 191 192 retp->u.address = malloc(size); 193 if (retp->u.address == NULL) 194 return -1; 195 196 memcpy(retp->u.address, val->u.address, size); 197 } 198 199 return 0; 200} 201 202struct value * 203value_string_to_charp(struct value *value) 204{ 205 struct arg_type_info *info = malloc(sizeof(*info) * 2); 206 if (info == NULL) { 207 fail: 208 free(info); 209 return NULL; 210 } 211 type_init_array(&info[1], type_get_simple(ARGTYPE_CHAR), 0, 212 value->type->u.string_n_info.length, 0); 213 type_init_pointer(&info[0], &info[1], 0); 214 215 struct value *tmp = malloc(sizeof(*tmp)); 216 if (tmp == NULL) 217 goto fail; 218 219 value_clone(tmp, value); 220 value_set_type(tmp, info, 1); 221 return tmp; 222} 223 224size_t 225value_size(struct value *val, struct value_dict *arguments) 226{ 227 if (val->size != (size_t)-1) 228 return val->size; 229 230 if (val->type->type != ARGTYPE_ARRAY) 231 return val->size = type_sizeof(val->inferior, val->type); 232 233 struct value length; 234 if (expr_eval(val->type->u.array_info.length, val, 235 arguments, &length) < 0) 236 return (size_t)-1; 237 238 size_t l; 239 int o = value_extract_word(&length, (long *)&l, arguments); 240 value_destroy(&length); 241 242 if (o < 0) 243 return (size_t)-1; 244 245 size_t elt_size = type_sizeof(val->inferior, 246 val->type->u.array_info.elt_type); 247 if (elt_size == (size_t)-1) 248 return (size_t)-1; 249 250 return val->size = elt_size * l; 251} 252 253int 254value_init_element(struct value *ret_val, struct value *val, size_t element) 255{ 256 size_t off = type_offsetof(val->inferior, val->type, element); 257 if (off == (size_t)-1) 258 return -1; 259 260 struct arg_type_info *e_info = type_element(val->type, element); 261 if (e_info == NULL) 262 return -1; 263 264 value_common_init(ret_val, val->inferior, val, e_info, 0); 265 266 switch (val->where) { 267 case VAL_LOC_COPY: 268 case VAL_LOC_SHARED: 269 ret_val->u.address = val->u.address + off; 270 ret_val->where = VAL_LOC_SHARED; 271 return 0; 272 273 case VAL_LOC_WORD: 274 ret_val->u.address = value_get_raw_data(val) + off; 275 ret_val->where = VAL_LOC_SHARED; 276 return 0; 277 278 case VAL_LOC_INFERIOR: 279 ret_val->u.address = val->u.address + off; 280 ret_val->where = VAL_LOC_INFERIOR; 281 return 0; 282 283 case VAL_LOC_NODATA: 284 assert(!"Can't offset NODATA."); 285 abort(); 286 } 287 abort(); 288} 289 290int 291value_init_deref(struct value *ret_val, struct value *valp) 292{ 293 assert(valp->type->type == ARGTYPE_POINTER); 294 295 /* Note: extracting a pointer value should not need value_dict 296 * with function arguments. */ 297 long l; 298 if (value_extract_word(valp, &l, NULL) < 0) 299 return -1; 300 301 /* We need "long" to be long enough to hold platform 302 * pointers. */ 303 typedef char assert__long_enough_long[-(sizeof(l) < sizeof(void *))]; 304 305 value_common_init(ret_val, valp->inferior, valp, 306 valp->type->u.ptr_info.info, 0); 307 ret_val->u.value = l; /* Set the address. */ 308 ret_val->where = VAL_LOC_INFERIOR; 309 return 0; 310} 311 312int 313value_extract_word(struct value *value, long *retp, struct value_dict *arguments) 314{ 315 union { 316 long val; 317 unsigned char buf[0]; 318 } u; 319 memset(u.buf, 0, sizeof(u)); 320 if (value_extract_buf(value, u.buf, arguments) < 0) 321 return -1; 322 *retp = u.val; 323 return 0; 324} 325 326int 327value_extract_buf(struct value *value, unsigned char *tgt, 328 struct value_dict *arguments) 329{ 330 unsigned char *data = value_get_data(value, arguments); 331 if (data == NULL) 332 return -1; 333 334 size_t sz = type_sizeof(value->inferior, value->type); 335 if (sz == (size_t)-1) 336 return -1; 337 338 memcpy(tgt, data, sz); 339 return 0; 340} 341 342struct value * 343value_get_parental_struct(struct value *val) 344{ 345 struct value *parent; 346 for (parent = val->parent; parent != NULL; parent = parent->parent) 347 if (parent->type->type == ARGTYPE_STRUCT) 348 return parent; 349 return NULL; 350} 351 352int 353value_is_zero(struct value *val, struct value_dict *arguments) 354{ 355 unsigned char *data = value_get_data(val, arguments); 356 if (data == NULL) 357 return -1; 358 size_t sz = type_sizeof(val->inferior, val->type); 359 if (sz == (size_t)-1) 360 return -1; 361 362 int zero = 1; 363 size_t j; 364 for (j = 0; j < sz; ++j) { 365 if (data[j] != 0) { 366 zero = 0; 367 break; 368 } 369 } 370 return zero; 371} 372