value.c revision 4767187d0d7924bfe5028fe3e29e3b018bc9c99b
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 30static void 31value_common_init(struct value *valp, struct Process *inferior, 32 struct value *parent, struct arg_type_info *type, 33 int own_type) 34{ 35 valp->type = type; 36 valp->own_type = own_type; 37 valp->inferior = inferior; 38 memset(&valp->u, 0, sizeof(valp->u)); 39 valp->where = VAL_LOC_NODATA; 40 valp->parent = parent; 41 valp->size = (size_t)-1; 42} 43 44void 45value_init(struct value *valp, struct Process *inferior, struct value *parent, 46 struct arg_type_info *type, int own_type) 47{ 48 assert(inferior != NULL); 49 value_common_init(valp, inferior, parent, type, own_type); 50} 51 52void 53value_init_detached(struct value *valp, struct value *parent, 54 struct arg_type_info *type, int own_type) 55{ 56 value_common_init(valp, NULL, parent, type, own_type); 57} 58 59void 60value_set_type(struct value *value, struct arg_type_info *type, int own_type) 61{ 62 if (value->own_type) 63 type_destroy(value->type); 64 value->type = type; 65 value->own_type = own_type; 66} 67 68void 69value_take_type(struct value *value, struct arg_type_info **type, 70 int *own_type) 71{ 72 *type = value->type; 73 *own_type = value->own_type; 74 value->own_type = 0; 75} 76 77void 78value_release(struct value *val) 79{ 80 if (val == NULL) 81 return; 82 if (val->where == VAL_LOC_COPY) { 83 free(val->u.address); 84 val->where = VAL_LOC_NODATA; 85 } 86} 87 88void 89value_destroy(struct value *val) 90{ 91 if (val == NULL) 92 return; 93 value_release(val); 94 value_set_type(val, NULL, 0); 95} 96 97void 98value_set_long(struct value *valp, long value) 99{ 100 valp->where = VAL_LOC_WORD; 101 valp->u.value = value; 102} 103 104unsigned char * 105value_reserve(struct value *valp, size_t size) 106{ 107 if (size <= sizeof(valp->u.value)) { 108 value_set_long(valp, 0); 109 } else { 110 valp->where = VAL_LOC_COPY; 111 valp->u.address = calloc(size, 1); 112 if (valp->u.address == 0) 113 return NULL; 114 } 115 return value_get_raw_data(valp); 116} 117 118int 119value_reify(struct value *val, struct value_dict *arguments) 120{ 121 if (val->where != VAL_LOC_INFERIOR) 122 return 0; 123 assert(val->inferior != NULL); 124 125 size_t size = value_size(val, arguments); 126 if (size == (size_t)-1) 127 return -1; 128 129 void *data; 130 enum value_location_t nloc; 131 if (size <= sizeof(val->u.value)) { 132 data = &val->u.value; 133 nloc = VAL_LOC_WORD; 134 } else { 135 data = malloc(size); 136 if (data == NULL) 137 return -1; 138 nloc = VAL_LOC_COPY; 139 } 140 141 if (umovebytes(val->inferior, val->u.address, data, size) < size) { 142 if (nloc == VAL_LOC_COPY) 143 free(data); 144 return -1; 145 } 146 147 val->where = nloc; 148 if (nloc == VAL_LOC_COPY) 149 val->u.address = data; 150 151 return 0; 152} 153 154unsigned char * 155value_get_data(struct value *val, struct value_dict *arguments) 156{ 157 if (value_reify(val, arguments) < 0) 158 return NULL; 159 return value_get_raw_data(val); 160} 161 162unsigned char * 163value_get_raw_data(struct value *val) 164{ 165 switch (val->where) { 166 case VAL_LOC_INFERIOR: 167 abort(); 168 case VAL_LOC_NODATA: 169 return NULL; 170 case VAL_LOC_COPY: 171 case VAL_LOC_SHARED: 172 return val->u.address; 173 case VAL_LOC_WORD: 174 return val->u.buf; 175 } 176 177 assert(!"Unexpected value of val->where"); 178 abort(); 179} 180 181int 182value_clone(struct value *retp, struct value *val) 183{ 184 *retp = *val; 185 if (val->where == VAL_LOC_COPY) { 186 assert(val->inferior != NULL); 187 size_t size = type_sizeof(val->inferior, val->type); 188 if (size == (size_t)-1) 189 return -1; 190 191 retp->u.address = malloc(size); 192 if (retp->u.address == NULL) 193 return -1; 194 195 memcpy(retp->u.address, val->u.address, size); 196 } 197 198 return 0; 199} 200 201struct value * 202value_string_to_charp(struct value *value) 203{ 204 struct arg_type_info *info = malloc(sizeof(*info) * 2); 205 if (info == NULL) { 206 fail: 207 free(info); 208 return NULL; 209 } 210 type_init_array(&info[1], type_get_simple(ARGTYPE_CHAR), 0, 211 value->type->u.string_n_info.length, 0); 212 type_init_pointer(&info[0], &info[1], 0); 213 214 struct value *tmp = malloc(sizeof(*tmp)); 215 if (tmp == NULL) 216 goto fail; 217 218 value_clone(tmp, value); 219 value_set_type(tmp, info, 1); 220 return tmp; 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.address = val->u.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 typedef char assert__long_enough_long[-(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 311int 312value_extract_word(struct value *value, long *retp, struct value_dict *arguments) 313{ 314 union { 315 long val; 316 unsigned char buf[0]; 317 } u; 318 memset(u.buf, 0, sizeof(u)); 319 if (value_extract_buf(value, u.buf, arguments) < 0) 320 return -1; 321 *retp = u.val; 322 return 0; 323} 324 325int 326value_extract_buf(struct value *value, unsigned char *tgt, 327 struct value_dict *arguments) 328{ 329 unsigned char *data = value_get_data(value, arguments); 330 if (data == NULL) 331 return -1; 332 333 size_t sz = type_sizeof(value->inferior, value->type); 334 if (sz == (size_t)-1) 335 return -1; 336 337 memcpy(tgt, data, sz); 338 return 0; 339} 340 341struct value * 342value_get_parental_struct(struct value *val) 343{ 344 struct value *parent; 345 for (parent = val->parent; parent != NULL; parent = parent->parent) 346 if (parent->type->type == ARGTYPE_STRUCT) 347 return parent; 348 return NULL; 349} 350 351int 352value_is_zero(struct value *val, struct value_dict *arguments) 353{ 354 unsigned char *data = value_get_data(val, arguments); 355 if (data == NULL) 356 return -1; 357 size_t sz = type_sizeof(val->inferior, val->type); 358 if (sz == (size_t)-1) 359 return -1; 360 361 int zero = 1; 362 size_t j; 363 for (j = 0; j < sz; ++j) { 364 if (data[j] != 0) { 365 zero = 0; 366 break; 367 } 368 } 369 return zero; 370} 371