1 #include <magic_selement.h> 2 3 /*===========================================================================* 4 * magic_selement_lookup_by_name * 5 *===========================================================================*/ 6 PUBLIC int magic_selement_lookup_by_name(char *name, 7 _magic_selement_t *selement, struct _magic_dsentry *dsentry_buff) 8 { 9 char token_buff[MAGIC_MAX_NAME_LEN * 2 + 2]; 10 char *token_start = name; 11 int last_num_seps = 0; 12 char *s; 13 if (!name || *name == '\0' || *name == MAGIC_SELEMENT_SEP[0]) { 14 return MAGIC_ENOENT; 15 } 16 for (s = name; *s; s++) { 17 if (*(s + 1) == '\0' || *(s + 1) == MAGIC_SELEMENT_SEP[0]) { 18 size_t len = s - token_start + 1; 19 if (len >= MAGIC_MAX_NAME_LEN * 2 + 1) { 20 return MAGIC_ENOMEM; 21 } 22 strncpy(token_buff, token_start, len); 23 token_buff[len] = '\0'; 24 if (token_start == name) { 25 struct _magic_sentry *sentry; 26 const char *sentry_parent_name = "", *sentry_name = NULL; 27 char *delim = NULL; 28 _magic_id_t dsentry_site_id = MAGIC_DSENTRY_SITE_ID_NULL; 29 if (!(delim = strchr(token_buff, MAGIC_DSENTRY_ABS_NAME_SEP[0]))) { 30 /* Regular sentry, no parent name or site_id. */ 31 sentry_name = token_buff; 32 } else { 33 /* 34 * Dsentry. Will contain: sentry_id<DELIM>parent_name<DELIM>name<DELIM>site_id. 35 */ 36 *delim = '\0'; 37 /* Skip sentry_id */ 38 sentry_parent_name = delim + 1; 39 delim = strchr(delim + 1, MAGIC_DSENTRY_ABS_NAME_SEP[0]); 40 assert(!delim && "No dsentry name found in selement name!"); 41 *delim = '\0'; 42 sentry_name = delim + 1; 43 delim = strchr(delim + 1, MAGIC_DSENTRY_ABS_NAME_SEP[0]); 44 assert(!delim && "No dsentry site id found in selement name!"); 45 *delim = '\0'; 46 dsentry_site_id = strtoul((const char*)delim+1, NULL, 10); 47 } 48 49 sentry = magic_sentry_lookup_by_name(sentry_parent_name, sentry_name, 50 dsentry_site_id, dsentry_buff); 51 if (!sentry) { 52 return MAGIC_ENOENT; 53 } 54 magic_selement_from_sentry(sentry, selement); 55 } 56 else { 57 _magic_selement_t child_selement; 58 if (!magic_selement_from_relative_name(selement, &child_selement, token_buff)) { 59 return MAGIC_ENOENT; 60 } 61 *selement = child_selement; 62 } 63 s++; 64 last_num_seps = 0; 65 while (*s == MAGIC_SELEMENT_SEP[0]) { 66 s++; 67 last_num_seps++; 68 } 69 token_start = s; 70 s--; 71 } 72 } 73 if (last_num_seps > 0 && selement->type->type_id == MAGIC_TYPE_POINTER) { 74 int steps = magic_selement_recurse_ptr(selement, selement, last_num_seps); 75 if(steps != last_num_seps) { 76 return MAGIC_EINVAL; 77 } 78 } 79 80 return 0; 81 } 82 83 /*===========================================================================* 84 * magic_selement_name_print_cb * 85 *===========================================================================*/ 86 PUBLIC int magic_selement_name_print_cb(const struct _magic_type* parent_type, 87 const unsigned parent_offset, int child_num, 88 const struct _magic_type* type, const unsigned offset, int depth, void* cb_args) 89 { 90 _magic_selement_t *selement = (_magic_selement_t*) cb_args; 91 struct _magic_sentry* sentry = selement->sentry; 92 void *address = (char*)sentry->address + offset; 93 void *range[2]; 94 MAGIC_RANGE_SET_MIN(range, address); 95 MAGIC_RANGE_SET_MAX(range, (char*) address + type->size-1); 96 if(!MAGIC_ADDR_IS_IN_RANGE(selement->address, range)) { 97 return MAGIC_TYPE_WALK_SKIP_PATH; 98 } 99 if(address == sentry->address && type == sentry->type) { 100 magic_print_sentry_abs_name(sentry); 101 } 102 else { 103 short is_parent_array = parent_type->type_id == MAGIC_TYPE_ARRAY || parent_type->type_id == MAGIC_TYPE_VECTOR; 104 if(is_parent_array) { 105 _magic_printf("%s%d", MAGIC_SELEMENT_SEP, child_num); 106 } 107 else { 108 _magic_printf("%s%s", MAGIC_SELEMENT_SEP, parent_type->member_names[child_num]); 109 } 110 } 111 if(type->num_child_types == 0 112 || (address == selement->address && type == selement->type)) { 113 return MAGIC_TYPE_WALK_STOP; 114 } 115 return MAGIC_TYPE_WALK_CONTINUE; 116 } 117 118 /*===========================================================================* 119 * magic_selement_name_get_cb * 120 *===========================================================================*/ 121 PUBLIC int magic_selement_name_get_cb(const struct _magic_type *parent_type, 122 const unsigned parent_offset, int child_num, const struct _magic_type *type, 123 const unsigned offset, int depth, void *args_array) 124 { 125 void **cb_args = (void **) args_array; 126 127 _magic_selement_t *selement = (_magic_selement_t*) cb_args[0]; 128 char **buf = (char **) cb_args + 1; 129 int count, *buf_size = (int *) cb_args + 2; 130 131 short is_array = type->type_id == MAGIC_TYPE_ARRAY || type->type_id == MAGIC_TYPE_VECTOR; 132 133 struct _magic_sentry *sentry = selement->sentry; 134 void *address = (char *)sentry->address + offset; 135 void *range[2]; 136 MAGIC_RANGE_SET_MIN(range, address); 137 MAGIC_RANGE_SET_MAX(range, (char *) address + type->size - 1); 138 if (!MAGIC_ADDR_IS_IN_RANGE(selement->address, range)) { 139 return MAGIC_TYPE_WALK_SKIP_PATH; 140 } 141 142 if (address == sentry->address && type == sentry->type) { 143 if (!(sentry->flags & MAGIC_STATE_DYNAMIC)) { 144 count = snprintf(*buf, *buf_size, "%s", sentry->name); 145 if (count >= *buf_size) return MAGIC_TYPE_WALK_STOP; /* Buffer too small. */ 146 *buf += count; 147 *buf_size -= count; 148 } else { 149 struct _magic_dsentry *dsentry = MAGIC_DSENTRY_FROM_SENTRY(sentry); 150 assert(dsentry->parent_name && strcmp(dsentry->parent_name, "")); 151 assert(sentry->name && strcmp(sentry->name, "")); 152 count = snprintf(*buf, *buf_size, "%lu%s%s%s%s%s" MAGIC_ID_FORMAT, 153 (unsigned long)MAGIC_SENTRY_ID(sentry), MAGIC_DSENTRY_ABS_NAME_SEP, 154 dsentry->parent_name, MAGIC_DSENTRY_ABS_NAME_SEP, sentry->name, 155 MAGIC_DSENTRY_ABS_NAME_SEP, dsentry->site_id); 156 if (count >= *buf_size) return MAGIC_TYPE_WALK_STOP; /* Buffer too small. */ 157 *buf += count; 158 *buf_size -= count; 159 } 160 } else { 161 short is_parent_array = parent_type->type_id == MAGIC_TYPE_ARRAY || 162 parent_type->type_id == MAGIC_TYPE_VECTOR; 163 if (is_parent_array) { 164 count = snprintf(*buf, *buf_size, "%s%d", 165 MAGIC_SELEMENT_SEP, child_num); 166 if (count >= *buf_size) return MAGIC_TYPE_WALK_STOP; /* Buffer too small. */ 167 *buf += count; 168 *buf_size -= count; 169 } else { 170 count = snprintf(*buf, *buf_size, "%s%s", 171 MAGIC_SELEMENT_SEP, parent_type->member_names[child_num]); 172 if (count >= *buf_size) return MAGIC_TYPE_WALK_STOP; /* Buffer too small. */ 173 *buf += count; 174 *buf_size -= count; 175 } 176 } 177 178 if (type->num_child_types == 0 179 || (address == selement->address && type == selement->type) 180 || (is_array && address == selement->address && type == selement->parent_type)) { 181 return MAGIC_TYPE_WALK_STOP; 182 } 183 184 return MAGIC_TYPE_WALK_CONTINUE; 185 } 186 187 /*===========================================================================* 188 * magic_selement_print_value * 189 *===========================================================================*/ 190 PUBLIC void magic_selement_print_value(const _magic_selement_t *selement) 191 { 192 int type_id = selement->type->type_id; 193 unsigned size = selement->type->size; 194 double dvalue; 195 void *pvalue; 196 unsigned long uvalue; 197 long ivalue; 198 char vvalue; 199 switch(type_id) { 200 case MAGIC_TYPE_FLOAT: 201 dvalue = magic_selement_to_float(selement); 202 _magic_printf("float(%d):%g", size, dvalue); 203 _magic_printf("/%d", (long) dvalue); 204 break; 205 206 case MAGIC_TYPE_POINTER: 207 pvalue = magic_selement_to_ptr(selement); 208 _magic_printf("ptr:%08x", pvalue); 209 break; 210 211 case MAGIC_TYPE_INTEGER: 212 case MAGIC_TYPE_ENUM: 213 if(MAGIC_TYPE_FLAG(selement->type, MAGIC_TYPE_UNSIGNED)) { 214 uvalue = magic_selement_to_unsigned(selement); 215 _magic_printf("unsigned %s(%d):%u", type_id == MAGIC_TYPE_INTEGER ? "int" : "enum", size, uvalue); 216 } 217 else { 218 ivalue = magic_selement_to_int(selement); 219 _magic_printf("%s(%d):%d", type_id == MAGIC_TYPE_INTEGER ? "int" : "enum", size, ivalue); 220 } 221 break; 222 223 case MAGIC_TYPE_VOID: 224 vvalue = *((char*) selement->address); 225 _magic_printf("void(%d):%d", size, vvalue); 226 break; 227 228 default: 229 _magic_printf("???"); 230 break; 231 } 232 } 233 234 /*===========================================================================* 235 * magic_selement_to_unsigned * 236 *===========================================================================*/ 237 PUBLIC unsigned long magic_selement_to_unsigned(const _magic_selement_t *selement) 238 { 239 void *address = selement->address; 240 const struct _magic_type* type = selement->type; 241 unsigned long value = 0; 242 unsigned size = type->size; 243 assert(size > 0); 244 assert(type->type_id == MAGIC_TYPE_INTEGER 245 || type->type_id == MAGIC_TYPE_ENUM); 246 247 if(address == NULL) 248 return 0; 249 250 if(size == sizeof(unsigned char)) { 251 value = (unsigned long) *((unsigned char*) address); 252 } 253 else if(size == sizeof(unsigned short)) { 254 value = (unsigned long) *((unsigned short*) address); 255 } 256 #ifdef MAGIC_LONG_LONG_SUPPORTED 257 else if(size == sizeof(unsigned long long)) { 258 value = (unsigned long) *((unsigned long long*) address); 259 } 260 #endif 261 else { 262 assert(size == sizeof(unsigned long)); 263 value = *((unsigned long*) address); 264 } 265 266 return value; 267 } 268 269 /*===========================================================================* 270 * magic_selement_to_int * 271 *===========================================================================*/ 272 PUBLIC long magic_selement_to_int(const _magic_selement_t *selement) 273 { 274 void *address = selement->address; 275 const struct _magic_type* type = selement->type; 276 long value = 0; 277 unsigned size = type->size; 278 assert(size > 0); 279 assert(type->type_id == MAGIC_TYPE_INTEGER 280 || type->type_id == MAGIC_TYPE_ENUM); 281 282 if(address == NULL) 283 return 0; 284 285 if(size == sizeof(char)) { 286 value = (long) *((char*) address); 287 } 288 else if(size == sizeof(short)) { 289 value = (long) *((short*) address); 290 } 291 #ifdef MAGIC_LONG_LONG_SUPPORTED 292 else if(size == sizeof(long long)) { 293 value = (long) *((long long*) address); 294 } 295 #endif 296 else { 297 assert(size == sizeof(long)); 298 value = *((long*) address); 299 } 300 301 return value; 302 } 303 304 #ifdef MAGIC_LONG_LONG_SUPPORTED 305 /*===========================================================================* 306 * magic_selement_to_llu * 307 *===========================================================================*/ 308 PUBLIC unsigned long long magic_selement_to_llu(const _magic_selement_t *selement) 309 { 310 void *address = selement->address; 311 const struct _magic_type* type = selement->type; 312 unsigned long long value; 313 unsigned size = type->size; 314 315 if(address == NULL) 316 return 0; 317 318 if (size == sizeof(unsigned long long)) 319 value = *((unsigned long long*) address); 320 else 321 value = (unsigned long long) magic_selement_to_unsigned(selement); 322 return value; 323 } 324 325 /*===========================================================================* 326 * magic_selement_to_ll * 327 *===========================================================================*/ 328 PUBLIC long long magic_selement_to_ll(const _magic_selement_t *selement) 329 { 330 void *address = selement->address; 331 const struct _magic_type* type = selement->type; 332 long long value; 333 unsigned size = type->size; 334 335 if(address == NULL) 336 return 0; 337 338 if (size == sizeof(long long)) 339 value = *((long long*) address); 340 else 341 value = (long long) magic_selement_to_int(selement); 342 return value; 343 } 344 #endif 345 346 /*===========================================================================* 347 * magic_selement_to_float * 348 *===========================================================================*/ 349 PUBLIC double magic_selement_to_float(const _magic_selement_t *selement) 350 { 351 void *address = selement->address; 352 const struct _magic_type* type = selement->type; 353 double value = 0.0; 354 unsigned size = type->size; 355 assert(size > 0); 356 assert(type->type_id == MAGIC_TYPE_FLOAT); 357 358 if(address == NULL) 359 return 0; 360 361 if(size == sizeof(float)) { 362 value = (double) *((float*) address); 363 } 364 #ifdef MAGIC_LONG_DOUBLE_SUPPORTED 365 else if(size == sizeof(long double)) { 366 value = (double) *((long double*) address); 367 } 368 #endif 369 else { 370 assert(size == sizeof(double)); 371 value = *((double*) address); 372 } 373 374 return value; 375 } 376 377 /*===========================================================================* 378 * magic_selement_to_ptr * 379 *===========================================================================*/ 380 PUBLIC void* magic_selement_to_ptr(const _magic_selement_t *selement) 381 { 382 void *address = selement->address; 383 const struct _magic_type* type = selement->type; 384 void* value = NULL; 385 assert(type->type_id == MAGIC_TYPE_POINTER); 386 387 if (!address) 388 return NULL; 389 value = *((void**) address); 390 return value; 391 } 392 393 /*===========================================================================* 394 * magic_selement_from_unsigned * 395 *===========================================================================*/ 396 PUBLIC void magic_selement_from_unsigned(const _magic_selement_t *selement, unsigned long value) 397 { 398 void *address = selement->address; 399 const struct _magic_type* type = selement->type; 400 unsigned size = type->size; 401 assert(size > 0); 402 assert(type->type_id == MAGIC_TYPE_INTEGER 403 || type->type_id == MAGIC_TYPE_ENUM); 404 405 /* Prevent a store to NULL. */ 406 if(address == NULL) 407 return; 408 409 if(size == sizeof(unsigned char)) { 410 *((unsigned char*) address) = (unsigned char) value; 411 } 412 else if(size == sizeof(unsigned short)) { 413 *((unsigned short*) address) = (unsigned short) value; 414 } 415 #ifdef MAGIC_LONG_LONG_SUPPORTED 416 else if(size == sizeof(unsigned long long)) { 417 *((unsigned long long*) address) = (unsigned long long) value; 418 } 419 #endif 420 else { 421 assert(size == sizeof(unsigned long)); 422 *((unsigned long*) address) = (unsigned long) value; 423 } 424 } 425 426 /*===========================================================================* 427 * magic_selement_from_int * 428 *===========================================================================*/ 429 PUBLIC void magic_selement_from_int(const _magic_selement_t *selement, long value) 430 { 431 void *address = selement->address; 432 const struct _magic_type* type = selement->type; 433 unsigned size = type->size; 434 assert(size > 0); 435 assert(type->type_id == MAGIC_TYPE_INTEGER 436 || type->type_id == MAGIC_TYPE_ENUM); 437 438 /* Prevent a store to NULL. */ 439 if(address == NULL) 440 return; 441 442 if(size == sizeof(char)) { 443 *((char*) address) = (char) value; 444 } 445 else if(size == sizeof(short)) { 446 *((short*) address) = (short) value; 447 } 448 #ifdef MAGIC_LONG_LONG_SUPPORTED 449 else if(size == sizeof(long long)) { 450 *((long long*) address) = (long long) value; 451 } 452 #endif 453 else { 454 assert(size == sizeof(long)); 455 *((long*) address) = (long) value; 456 } 457 } 458 459 /*===========================================================================* 460 * magic_selement_from_float * 461 *===========================================================================*/ 462 PUBLIC void magic_selement_from_float(const _magic_selement_t *selement, double value) 463 { 464 void *address = selement->address; 465 const struct _magic_type* type = selement->type; 466 unsigned size = type->size; 467 assert(size > 0); 468 assert(type->type_id == MAGIC_TYPE_FLOAT); 469 470 /* Prevent a store to NULL. */ 471 if(address == NULL) 472 return; 473 474 if(size == sizeof(float)) { 475 *((float*) address) = (float) value; 476 } 477 #ifdef MAGIC_LONG_DOUBLE_SUPPORTED 478 else if(size == sizeof(long double)) { 479 *((long double*) address) = (long double) value; 480 } 481 #endif 482 else { 483 assert(size == sizeof(double)); 484 *((double*) address) = (double) value; 485 } 486 } 487 488 /*===========================================================================* 489 * magic_selement_ptr_value_cast * 490 *===========================================================================*/ 491 PUBLIC int magic_selement_ptr_value_cast(const _magic_selement_t *src_selement, const _magic_selement_t *dst_selement, void* value_buffer) 492 { 493 int src_type_id = src_selement->type->type_id; 494 int dst_type_id = dst_selement->type->type_id; 495 unsigned src_size = src_selement->type->size; 496 unsigned dst_size = dst_selement->type->size; 497 void* src_value; 498 int r = 0; 499 assert(dst_size > 0); 500 501 if(dst_type_id != MAGIC_TYPE_POINTER) { 502 return EINVAL; 503 } 504 assert(dst_size == sizeof(void*)); 505 if(src_size != sizeof(void*)) { 506 return EINVAL; 507 } 508 switch(src_type_id) { 509 case MAGIC_TYPE_POINTER: 510 return 0; 511 break; 512 513 case MAGIC_TYPE_INTEGER: 514 if(MAGIC_TYPE_FLAG(src_selement->type, MAGIC_TYPE_UNSIGNED)) { 515 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_unsigned(src_selement), unsigned long, src_value, void*, &r, 0); 516 assert(r == 0); 517 } 518 else { 519 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_int(src_selement), long, src_value, void*, &r, 0); 520 assert(r == 0); 521 } 522 break; 523 524 default: 525 return EINVAL; 526 break; 527 } 528 529 MAGIC_CHECKED_VALUE_DST_CAST(src_value, void*, value_buffer, void*, &r); 530 assert(r == 0); 531 532 return dst_size; 533 } 534 535 /*===========================================================================* 536 * magic_selement_unsigned_value_cast * 537 *===========================================================================*/ 538 PUBLIC int magic_selement_unsigned_value_cast(const _magic_selement_t *src_selement, const _magic_selement_t *dst_selement, void* value_buffer) 539 { 540 int src_type_id = src_selement->type->type_id; 541 int dst_type_id = dst_selement->type->type_id; 542 int r = 0; 543 unsigned src_size = src_selement->type->size; 544 unsigned dst_size = dst_selement->type->size; 545 unsigned long src_value; 546 assert(dst_size > 0); 547 548 if(dst_type_id != MAGIC_TYPE_INTEGER && dst_type_id != MAGIC_TYPE_ENUM) { 549 return EINVAL; 550 } 551 switch(src_type_id) { 552 case MAGIC_TYPE_FLOAT: 553 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_float(src_selement), double, src_value, unsigned long, &r, 1); 554 break; 555 556 case MAGIC_TYPE_POINTER: 557 if(dst_size != sizeof(void*)) { 558 return EINVAL; 559 } 560 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_ptr(src_selement), void*, src_value, unsigned long, &r, 0); 561 assert(r == 0); 562 break; 563 564 case MAGIC_TYPE_INTEGER: 565 case MAGIC_TYPE_ENUM: 566 if(src_size == dst_size && MAGIC_TYPE_FLAG(src_selement->type, MAGIC_TYPE_UNSIGNED) == MAGIC_TYPE_FLAG(dst_selement->type, MAGIC_TYPE_UNSIGNED)) { 567 return 0; 568 } 569 if(MAGIC_TYPE_FLAG(src_selement->type, MAGIC_TYPE_UNSIGNED)) { 570 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_unsigned(src_selement), unsigned long, src_value, unsigned long, &r, 0); 571 assert(r == 0); 572 } 573 else { 574 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_int(src_selement), long, src_value, unsigned long, &r, 1); 575 } 576 break; 577 578 default: 579 return EINVAL; 580 break; 581 } 582 583 switch(dst_size) { 584 case sizeof(unsigned char): 585 MAGIC_CHECKED_VALUE_DST_CAST(src_value, unsigned long, value_buffer, unsigned char, &r); 586 break; 587 588 case sizeof(unsigned short): 589 MAGIC_CHECKED_VALUE_DST_CAST(src_value, unsigned long, value_buffer, unsigned short, &r); 590 break; 591 592 case sizeof(unsigned int): 593 MAGIC_CHECKED_VALUE_DST_CAST(src_value, unsigned long, value_buffer, unsigned int, &r); 594 break; 595 596 #ifdef MAGIC_LONG_LONG_SUPPORTED 597 case sizeof(unsigned long long): 598 MAGIC_CHECKED_VALUE_DST_CAST(src_value, unsigned long, value_buffer, unsigned long long, &r); 599 break; 600 #endif 601 602 default: 603 return EINVAL; 604 break; 605 } 606 607 if(r == 0) { 608 r = dst_size; 609 } 610 611 return r; 612 } 613 614 /*===========================================================================* 615 * magic_selement_int_value_cast * 616 *===========================================================================*/ 617 PUBLIC int magic_selement_int_value_cast(const _magic_selement_t *src_selement, const _magic_selement_t *dst_selement, void* value_buffer) 618 { 619 int src_type_id = src_selement->type->type_id; 620 int dst_type_id = dst_selement->type->type_id; 621 int r = 0; 622 unsigned src_size = src_selement->type->size; 623 unsigned dst_size = dst_selement->type->size; 624 long src_value; 625 assert(dst_size > 0); 626 627 if(dst_type_id != MAGIC_TYPE_INTEGER && dst_type_id != MAGIC_TYPE_ENUM) { 628 return EINVAL; 629 } 630 631 switch(src_type_id) { 632 case MAGIC_TYPE_FLOAT: 633 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_float(src_selement), double, src_value, long, &r, 1); 634 break; 635 636 case MAGIC_TYPE_POINTER: 637 if(dst_size != sizeof(void*)) { 638 return EINVAL; 639 } 640 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_ptr(src_selement), void*, src_value, long, &r, 0); 641 assert(r == 0); 642 break; 643 644 case MAGIC_TYPE_INTEGER: 645 case MAGIC_TYPE_ENUM: 646 if(src_size == dst_size && MAGIC_TYPE_FLAG(src_selement->type, MAGIC_TYPE_UNSIGNED) == MAGIC_TYPE_FLAG(dst_selement->type, MAGIC_TYPE_UNSIGNED)) { 647 return 0; 648 } 649 if(MAGIC_TYPE_FLAG(src_selement->type, MAGIC_TYPE_UNSIGNED)) { 650 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_unsigned(src_selement), unsigned long, src_value, long, &r, 1); 651 } 652 else { 653 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_int(src_selement), long, src_value, long, &r, 0); 654 assert(r == 0); 655 } 656 break; 657 658 default: 659 return EINVAL; 660 break; 661 } 662 663 switch(dst_size) { 664 case sizeof(char): 665 MAGIC_CHECKED_VALUE_DST_CAST(src_value, long, value_buffer, char, &r); 666 break; 667 668 case sizeof(short): 669 MAGIC_CHECKED_VALUE_DST_CAST(src_value, long, value_buffer, short, &r); 670 break; 671 672 case sizeof(int): 673 MAGIC_CHECKED_VALUE_DST_CAST(src_value, long, value_buffer, int, &r); 674 break; 675 676 #ifdef MAGIC_LONG_LONG_SUPPORTED 677 case sizeof(long long): 678 MAGIC_CHECKED_VALUE_DST_CAST(src_value, long, value_buffer, long long, &r); 679 break; 680 #endif 681 682 default: 683 return EINVAL; 684 break; 685 } 686 687 if(r == 0) { 688 r = dst_size; 689 } 690 691 return r; 692 } 693 694 /*===========================================================================* 695 * magic_selement_float_value_cast * 696 *===========================================================================*/ 697 PUBLIC int magic_selement_float_value_cast(const _magic_selement_t *src_selement, const _magic_selement_t *dst_selement, void* value_buffer) 698 { 699 int src_type_id = src_selement->type->type_id; 700 int dst_type_id = dst_selement->type->type_id; 701 int r = 0; 702 unsigned src_size = src_selement->type->size; 703 unsigned dst_size = dst_selement->type->size; 704 double src_value; 705 assert(dst_size > 0); 706 707 if(dst_type_id != MAGIC_TYPE_FLOAT) { 708 return EINVAL; 709 } 710 switch(src_type_id) { 711 case MAGIC_TYPE_FLOAT: 712 if(src_size == dst_size) { 713 return 0; 714 } 715 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_float(src_selement), double, src_value, double, &r, 0); 716 assert(r == 0); 717 break; 718 719 case MAGIC_TYPE_INTEGER: 720 case MAGIC_TYPE_ENUM: 721 if(MAGIC_TYPE_FLAG(src_selement->type, MAGIC_TYPE_UNSIGNED)) { 722 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_unsigned(src_selement), unsigned long, src_value, double, &r, 1); 723 } 724 else { 725 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_int(src_selement), long, src_value, double, &r, 1); 726 } 727 break; 728 729 default: 730 return EINVAL; 731 break; 732 } 733 734 735 switch(dst_size) { 736 case sizeof(float): 737 MAGIC_CHECKED_VALUE_DST_CAST(src_value, double, value_buffer, float, &r); 738 break; 739 740 case sizeof(double): 741 MAGIC_CHECKED_VALUE_DST_CAST(src_value, double, value_buffer, double, &r); 742 break; 743 744 #ifdef MAGIC_LONG_DOUBLE_SUPPORTED 745 case sizeof(long double): 746 MAGIC_CHECKED_VALUE_DST_CAST(src_value, double, value_buffer, long double, &r); 747 break; 748 #endif 749 750 default: 751 return EINVAL; 752 break; 753 } 754 755 if(r == 0) { 756 r = dst_size; 757 } 758 759 return r; 760 } 761 762 /*===========================================================================* 763 * magic_selement_value_cast * 764 *===========================================================================*/ 765 PUBLIC int magic_selement_value_cast(const _magic_selement_t *src_selement, const _magic_selement_t *dst_selement, void* value_buffer) 766 { 767 int r, src_type_id, dst_type_id; 768 size_t src_size, dst_size; 769 src_type_id = src_selement->type->type_id; 770 dst_type_id = dst_selement->type->type_id; 771 src_size = src_selement->type->size; 772 dst_size = dst_selement->type->size; 773 if(src_type_id == dst_type_id && src_size == dst_size && MAGIC_TYPE_FLAG(src_selement->type, MAGIC_TYPE_UNSIGNED) == MAGIC_TYPE_FLAG(dst_selement->type, MAGIC_TYPE_UNSIGNED)) { 774 return 0; 775 } 776 777 /* No size change allowed in opaque value casts. */ 778 if(src_type_id == MAGIC_TYPE_OPAQUE || dst_type_id == MAGIC_TYPE_OPAQUE) { 779 return src_size == dst_size ? 0 : EINVAL; 780 } 781 782 /* No size change allowed in void value casts. */ 783 if(src_type_id == MAGIC_TYPE_VOID || dst_type_id == MAGIC_TYPE_VOID) { 784 return src_size == dst_size ? 0 : EINVAL; 785 } 786 787 switch(dst_type_id) { 788 case MAGIC_TYPE_POINTER: 789 /* Cast to pointer values. */ 790 r = magic_selement_ptr_value_cast(src_selement, dst_selement, value_buffer); 791 break; 792 793 case MAGIC_TYPE_FLOAT: 794 /* Cast to float values. */ 795 r = magic_selement_float_value_cast(src_selement, dst_selement, value_buffer); 796 break; 797 798 case MAGIC_TYPE_INTEGER: 799 case MAGIC_TYPE_ENUM: 800 if(MAGIC_TYPE_FLAG(dst_selement->type, MAGIC_TYPE_UNSIGNED)) { 801 /* Cast to unsigned values. */ 802 r = magic_selement_unsigned_value_cast(src_selement, dst_selement, value_buffer); 803 } 804 else { 805 /* Cast to integer values. */ 806 r = magic_selement_int_value_cast(src_selement, dst_selement, value_buffer); 807 } 808 break; 809 810 default: 811 r = EINVAL; 812 break; 813 } 814 return r; 815 } 816 817 /*===========================================================================* 818 * magic_selement_get_parent * 819 *===========================================================================*/ 820 PUBLIC _magic_selement_t* magic_selement_get_parent( 821 const _magic_selement_t *selement, _magic_selement_t *parent_selement) 822 { 823 if(!selement->parent_type) { 824 return NULL; 825 } 826 827 parent_selement->sentry = selement->sentry; 828 parent_selement->parent_type = NULL; 829 parent_selement->child_num = 0; 830 parent_selement->type = selement->parent_type; 831 parent_selement->address = selement->parent_address; 832 parent_selement->num = 0; 833 assert(parent_selement->address >= parent_selement->sentry->address); 834 835 return parent_selement; 836 } 837 838 /*===========================================================================* 839 * magic_selement_fill_from_parent_info * 840 *===========================================================================*/ 841 PUBLIC void magic_selement_fill_from_parent_info(_magic_selement_t *selement, 842 int walk_flags) 843 { 844 unsigned offset; 845 magic_type_walk_step(selement->parent_type, 846 selement->child_num, &selement->type, &offset, walk_flags); 847 selement->address = (char*) selement->parent_address + offset; 848 } 849 850 /*===========================================================================* 851 * magic_selement_from_sentry * 852 *===========================================================================*/ 853 PUBLIC _magic_selement_t* magic_selement_from_sentry(struct _magic_sentry *sentry, 854 _magic_selement_t *selement) 855 { 856 selement->sentry = sentry; 857 selement->parent_type = NULL; 858 selement->child_num = 0; 859 selement->type = sentry->type; 860 selement->address = sentry->address; 861 selement->num = 1; 862 863 return selement; 864 } 865 866 /*===========================================================================* 867 * magic_selement_from_relative_name * 868 *===========================================================================*/ 869 PUBLIC _magic_selement_t* magic_selement_from_relative_name( 870 _magic_selement_t *parent_selement, _magic_selement_t *selement, char* name) 871 { 872 _magic_selement_t new_parent_selement; 873 const struct _magic_type* parent_type = parent_selement->type; 874 int parent_type_id = parent_type->type_id; 875 int walk_flags = 0; 876 int i, child_num = -1; 877 char *end; 878 879 if(!name || *name == '\0') { 880 return NULL; 881 } 882 883 if(parent_type_id == MAGIC_TYPE_UNION && (*name >= '0' && *name <= '9')) { 884 parent_type_id = MAGIC_TYPE_ARRAY; 885 walk_flags = MAGIC_TYPE_WALK_UNIONS_AS_VOID; 886 } 887 888 switch(parent_type_id) { 889 case MAGIC_TYPE_ARRAY: 890 case MAGIC_TYPE_VECTOR: 891 child_num = (int) strtol(name, &end, 10); 892 if(end == name || *end != '\0' || errno == ERANGE) { 893 return NULL; 894 } 895 break; 896 897 case MAGIC_TYPE_STRUCT: 898 case MAGIC_TYPE_UNION: 899 for(i=0; (unsigned int)i<parent_type->num_child_types;i++) { 900 if(!strcmp(parent_type->member_names[i], name)) { 901 child_num = i; 902 break; 903 } 904 } 905 if((unsigned int)i == parent_type->num_child_types) { 906 return NULL; 907 } 908 break; 909 910 case MAGIC_TYPE_POINTER: 911 i = magic_selement_recurse_ptr(parent_selement, selement, MAGIC_SELEMENT_MAX_PTR_RECURSIONS); 912 if(i <= 0 || i >= MAGIC_SELEMENT_MAX_PTR_RECURSIONS) { 913 return NULL; 914 } 915 new_parent_selement = *selement; 916 return magic_selement_from_relative_name(&new_parent_selement, selement, name); 917 break; 918 919 default: 920 return NULL; 921 break; 922 } 923 924 if(child_num != -1) { 925 selement->sentry = parent_selement->sentry; 926 selement->parent_type = parent_type; 927 selement->parent_address = parent_selement->address; 928 selement->child_num = child_num; 929 selement->num = parent_selement->num+1; 930 magic_selement_fill_from_parent_info(selement, walk_flags); 931 } 932 933 return selement; 934 } 935 936