1 2 #include <magic_analysis.h> 3 4 PUBLIC char magic_ne_str[] = "NULL_TYPE"; 5 PUBLIC char magic_enf_str[] = "UNKNOWN_TYPE"; 6 PUBLIC char magic_bo_str[] = "BAD_TYPE"; 7 PUBLIC char magic_be_str[] = "BAD_ENTRY_TYPE"; 8 PUBLIC char magic_bv_str[] = "BAD_VALUE_TYPE"; 9 PUBLIC char magic_vf_str[] = "VALUE_FOUND_TYPE"; 10 PUBLIC const struct _magic_type magic_NULL_ENTRY_TYPE = MAGIC_TYPE_SPECIAL_INIT(magic_ne_str); 11 PUBLIC const struct _magic_type magic_ENTRY_NOT_FOUND_TYPE = MAGIC_TYPE_SPECIAL_INIT(magic_enf_str); 12 PUBLIC const struct _magic_type magic_BAD_OFFSET_TYPE = MAGIC_TYPE_SPECIAL_INIT(magic_bo_str); 13 PUBLIC const struct _magic_type magic_BAD_ENTRY_TYPE = MAGIC_TYPE_SPECIAL_INIT(magic_be_str); 14 PUBLIC const struct _magic_type magic_BAD_VALUE_TYPE = MAGIC_TYPE_SPECIAL_INIT(magic_bv_str); 15 PUBLIC const struct _magic_type magic_VALUE_FOUND = MAGIC_TYPE_SPECIAL_INIT(magic_vf_str); 16 17 PRIVATE magic_cb_sentries_analyze_pre_t magic_sentries_analyze_pre_cb = NULL; 18 19 /*===========================================================================* 20 * magic_setcb_sentries_analyze_pre * 21 *===========================================================================*/ 22 PUBLIC void magic_setcb_sentries_analyze_pre(magic_cb_sentries_analyze_pre_t cb) 23 { 24 magic_sentries_analyze_pre_cb = cb; 25 } 26 27 /*===========================================================================* 28 * magic_sentry_print_ptr_types * 29 *===========================================================================*/ 30 PUBLIC int magic_sentry_print_ptr_types(struct _magic_sentry* entry) 31 { 32 int ret, ptrs_found = 0; 33 void* args_array[2]; 34 args_array[0] = entry; 35 args_array[1] = &ptrs_found; 36 ret = magic_type_walk_root_all(entry->type, magic_type_examine_ptr_cb, args_array); 37 assert(ret >= 0); 38 return ptrs_found; 39 } 40 41 /*===========================================================================* 42 * magic_sentry_extract_ptrs * 43 *===========================================================================*/ 44 PUBLIC int magic_sentry_extract_ptrs(struct _magic_sentry* entry, void ****ptr_map, const struct _magic_type ***ptr_type_map, int *ptr_num) 45 { 46 int from_wrapper = MAGIC_MEM_WRAPPER_IS_ACTIVE(); 47 int ret = magic_type_count_ptrs(entry->type, ptr_num); 48 assert(ret == 0); 49 if(*ptr_num == 0) { 50 *ptr_map = NULL; 51 *ptr_type_map = NULL; 52 } 53 else { 54 void* args_array[4]; 55 int ptr_num2 = 0; 56 if(!from_wrapper) { 57 MAGIC_MEM_WRAPPER_BEGIN(); 58 } 59 *ptr_map = (void ***) malloc((*ptr_num)*sizeof(void **)); 60 *ptr_type_map = (const struct _magic_type **) malloc((*ptr_num)*sizeof(const struct _magic_type *)); 61 if(!from_wrapper) { 62 MAGIC_MEM_WRAPPER_END(); 63 } 64 args_array[0] = entry; 65 args_array[1] = *ptr_map; 66 args_array[2] = *ptr_type_map; 67 args_array[3] = &ptr_num2; 68 ret = magic_type_walk_root_all(entry->type, magic_type_extract_ptr_cb, args_array); 69 assert(ret >= 0); 70 assert(*ptr_num == ptr_num2); 71 } 72 return 0; 73 } 74 75 /*===========================================================================* 76 * magic_sentry_analyze * 77 *===========================================================================*/ 78 PUBLIC int magic_sentry_analyze(struct _magic_sentry* sentry, int flags, 79 const magic_sentry_analyze_cb_t cb, void* cb_args, 80 _magic_sel_stats_t *sentry_stats) 81 { 82 int ret; 83 int selement_num = 0, sel_analyzed_num = 0; 84 void* args_array[7]; 85 args_array[0] = (void*) &flags; 86 args_array[1] = (void*) __UNCONST(&cb); 87 args_array[2] = (void*) cb_args; 88 args_array[3] = (void*) sentry; 89 args_array[4] = (void*) sentry_stats; 90 args_array[5] = (void*) &selement_num; 91 args_array[6] = (void*) &sel_analyzed_num; 92 ret = magic_type_walk_root_all(sentry->type, magic_type_analyzer_cb, 93 args_array); 94 if(ret < 0) { 95 return ret; 96 } 97 98 return flags; 99 } 100 101 /*===========================================================================* 102 * magic_sentries_analyze * 103 *===========================================================================*/ 104 PUBLIC int magic_sentries_analyze(int flags, const magic_sentry_analyze_cb_t cb, 105 void *cb_args, _magic_sel_stats_t *sentries_stats) 106 { 107 int i, ret; 108 struct _magic_sentry *sentry; 109 110 if (flags & MAGIC_SEL_ANALYZE_RETURN_TRG_PTRS) 111 magic_reentrant_disable(); 112 113 /* See if any pre-analyze callback has been registered. */ 114 if (magic_sentries_analyze_pre_cb) { 115 ret = magic_sentries_analyze_pre_cb(); 116 if (ret < 0) { 117 return ret; 118 } 119 } 120 121 /* Analyze all the sentries. */ 122 for (i = 0 ; i < _magic_sentries_num ; i++) { 123 sentry = &_magic_sentries[i]; 124 ret = magic_sentry_analyze(sentry, flags, cb, cb_args, sentries_stats); 125 if (ret < 0) { 126 return ret; 127 } 128 else { 129 flags |= ret; 130 } 131 } 132 133 /* Analyze all the dsentries if asked to. */ 134 if (flags & MAGIC_SEL_ANALYZE_DYNAMIC) { 135 return magic_dsentries_analyze(flags, cb, cb_args, sentries_stats); 136 } 137 138 if (flags & MAGIC_SEL_ANALYZE_RETURN_TRG_PTRS) 139 magic_reentrant_enable(); 140 141 return flags; 142 } 143 144 /*===========================================================================* 145 * magic_sentry_print_selements * 146 *===========================================================================*/ 147 PUBLIC int magic_sentry_print_selements(struct _magic_sentry* sentry) 148 { 149 int flags = (MAGIC_SEL_ANALYZE_POINTERS|MAGIC_SEL_ANALYZE_NONPOINTERS|MAGIC_SEL_ANALYZE_DATA|MAGIC_SEL_ANALYZE_INVARIANTS|MAGIC_SEL_ANALYZE_VIOLATIONS); 150 return magic_sentry_analyze(sentry, flags, magic_sentry_print_el_cb, NULL, NULL); 151 } 152 153 /*===========================================================================* 154 * magic_sentry_print_ptr_selements * 155 *===========================================================================*/ 156 PUBLIC int magic_sentry_print_ptr_selements(struct _magic_sentry* sentry, 157 int skip_null_ptrs, int max_target_recusions) 158 { 159 int flags = (MAGIC_SEL_ANALYZE_POINTERS|MAGIC_SEL_ANALYZE_DATA|MAGIC_SEL_ANALYZE_INVARIANTS|MAGIC_SEL_ANALYZE_VIOLATIONS); 160 void* args_array[2]; 161 args_array[0] = &skip_null_ptrs; 162 args_array[1] = &max_target_recusions; 163 return magic_sentry_analyze(sentry, flags, magic_sentry_print_ptr_el_cb, args_array, NULL); 164 } 165 166 /*===========================================================================* 167 * magic_dsentries_analyze * 168 *===========================================================================*/ 169 PUBLIC int magic_dsentries_analyze(int flags, const magic_sentry_analyze_cb_t cb, 170 void *cb_args, _magic_sel_stats_t *dsentries_stats) 171 { 172 int ret = 0; 173 struct _magic_dsentry *prev_dsentry, *dsentry; 174 struct _magic_sentry* sentry; 175 176 /* If dead dsentries are enabled, garbage collect them to ensure consistency. */ 177 if (magic_allow_dead_dsentries) 178 magic_free_dead_dsentries(); 179 180 /* Analyze all the dsentries. */ 181 /* 182 * We need to hold the DSENTRY, DFUNCTION and DSODESC locks for the 183 * magic_range_lookup_by_addr() function. 184 */ 185 MAGIC_MULTIPLE_LOCK(1, 1, 1, 0); 186 MAGIC_DSENTRY_ALIVE_BLOCK_ITER(_magic_first_dsentry, prev_dsentry, dsentry, 187 sentry, 188 189 /* 190 * Check if we should analyze out-of-band dsentries. 191 */ 192 if (!(flags & MAGIC_SEL_ANALYZE_OUT_OF_BAND) && 193 MAGIC_STATE_FLAG(sentry, MAGIC_STATE_OUT_OF_BAND)) { 194 continue; 195 } 196 197 /* 198 * Check if we should analyze shlib state dsentries. 199 */ 200 if (!(flags & MAGIC_SEL_ANALYZE_LIB_SRC) && 201 MAGIC_STATE_FLAG(sentry, MAGIC_STATE_LIB)) { 202 continue; 203 } 204 205 ret = magic_sentry_analyze(sentry, flags, cb, cb_args, dsentries_stats); 206 if (ret < 0) { 207 break; 208 } 209 else { 210 flags |= ret; 211 } 212 ); 213 MAGIC_MULTIPLE_UNLOCK(1, 1, 1, 0); 214 215 return ret < 0 ? ret : flags; 216 } 217 218 /*===========================================================================* 219 * magic_sentry_print_el_cb * 220 *===========================================================================*/ 221 PUBLIC int magic_sentry_print_el_cb(_magic_selement_t* selement, 222 _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, 223 void* cb_args) 224 { 225 if(sel_analyzed->num == 1) { 226 MAGIC_SENTRY_PRINT(selement->sentry, MAGIC_EXPAND_TYPE_STR); 227 _magic_printf("\n"); 228 } 229 230 MAGIC_SELEMENT_PRINT(selement, MAGIC_EXPAND_TYPE_STR); 231 _magic_printf("\n"); 232 MAGIC_SEL_ANALYZED_PRINT(sel_analyzed, MAGIC_EXPAND_TYPE_STR); 233 _magic_printf("\n"); 234 MAGIC_SEL_STATS_PRINT(sel_stats); 235 _magic_printf("\n\n"); 236 237 return MAGIC_SENTRY_ANALYZE_CONTINUE; 238 } 239 240 /*===========================================================================* 241 * magic_sentry_print_ptr_el_cb * 242 *===========================================================================*/ 243 PUBLIC int magic_sentry_print_ptr_el_cb(_magic_selement_t* selement, 244 _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, 245 void* cb_args) 246 { 247 int r; 248 void** args_array = (void**) cb_args; 249 int skip_null_ptrs = args_array ? *((int*)args_array[0]) : 0; 250 int max_target_recursions = args_array ? *((int*)args_array[1]) : 0; 251 252 if(sel_analyzed->type_id != MAGIC_TYPE_POINTER) { 253 return MAGIC_SENTRY_ANALYZE_CONTINUE; 254 } 255 if(skip_null_ptrs && sel_analyzed->u.ptr.value == 0) { 256 return MAGIC_SENTRY_ANALYZE_CONTINUE; 257 } 258 magic_sentry_print_el_cb(selement, sel_analyzed, sel_stats, cb_args); 259 if(max_target_recursions>0 && !(sel_analyzed->flags & MAGIC_SEL_FOUND_VIOLATIONS)) { 260 struct _magic_sentry *sentry = &sel_analyzed->u.ptr.trg.dsentry.sentry; 261 if(MAGIC_SEL_ANALYZED_PTR_HAS_TRG_SENTRY(sel_analyzed) && MAGIC_SENTRY_ID(sentry)!=MAGIC_SENTRY_ID(selement->sentry)) { 262 r = magic_sentry_print_ptr_selements(sentry, skip_null_ptrs, 263 max_target_recursions-1); 264 if(r < 0) { 265 _magic_printf("magic_sentry_print_ptr_el_cb: recursive step reported error %d\n", r); 266 return r; 267 } 268 } 269 } 270 271 return MAGIC_SENTRY_ANALYZE_CONTINUE; 272 } 273 274 /*===========================================================================* 275 * magic_sentry_print_el_with_trg_reg_cb * 276 *===========================================================================*/ 277 PUBLIC int magic_sentry_print_el_with_trg_reg_cb(_magic_selement_t* selement, 278 _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, 279 void* cb_args) 280 { 281 if(MAGIC_SEL_ANALYZED_TRG_FLAGS(sel_analyzed)) { 282 return magic_sentry_print_el_cb(selement, sel_analyzed, sel_stats, 283 cb_args); 284 } 285 286 return MAGIC_SENTRY_ANALYZE_CONTINUE; 287 } 288 289 /*===========================================================================* 290 * magic_sentry_print_el_with_trg_cb * 291 *===========================================================================*/ 292 PUBLIC int magic_sentry_print_el_with_trg_cb(_magic_selement_t* selement, 293 _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, 294 void* cb_args) 295 { 296 if(MAGIC_SEL_ANALYZED_TRG_FLAGS(sel_analyzed) 297 && MAGIC_SELEMENT_HAS_TRG(selement)) { 298 return magic_sentry_print_el_cb(selement, sel_analyzed, sel_stats, 299 cb_args); 300 } 301 302 return MAGIC_SENTRY_ANALYZE_CONTINUE; 303 } 304 305 /*===========================================================================* 306 * magic_type_count_ptrs * 307 *===========================================================================*/ 308 PUBLIC int magic_type_count_ptrs(const struct _magic_type* type, int* ptr_num) 309 { 310 int ret; 311 void* args_array[4] = { NULL, NULL, NULL }; 312 args_array[3] = ptr_num; 313 *ptr_num = 0; 314 ret = magic_type_walk_root_all(type, magic_type_extract_ptr_cb, args_array); 315 assert(ret >= 0); 316 return 0; 317 } 318 319 /*===========================================================================* 320 * magic_type_examine_ptr_cb * 321 *===========================================================================*/ 322 PUBLIC int magic_type_examine_ptr_cb(const struct _magic_type* parent_type, 323 const unsigned parent_offset, int child_num, 324 const struct _magic_type* type, const unsigned offset, int depth, void* cb_args) 325 { 326 int ret; 327 void** args_array = (void**) cb_args; 328 if(type->type_id == MAGIC_TYPE_POINTER) { 329 const struct _magic_sentry *root_entry = (const struct _magic_sentry *) args_array[0]; 330 int *ptrs_found = (int*) args_array[1]; 331 char* root_address = root_entry->address; 332 void* ptr_address = root_address ? root_address+offset : NULL; 333 void* target_address = ptr_address ? *((void**)ptr_address) : NULL; 334 (*ptrs_found)++; 335 _magic_printf("Pointer found for root entry (name=%s, address=0x%08x) at offset %d, static target type is: ", root_entry->name, (unsigned) root_address, offset); 336 magic_type_str_print(type->contained_types[0]); 337 _magic_printf(" - dynamic target types are: "); 338 if(!target_address) { 339 _magic_printf("NULL"); 340 } 341 else { 342 ret = magic_type_str_print_from_target(target_address); 343 if(ret < 0) { 344 _magic_printf("ENTRY NOT FOUND"); 345 } 346 } 347 _magic_printf("\n"); 348 } 349 return MAGIC_TYPE_WALK_CONTINUE; 350 } 351 352 /*===========================================================================* 353 * magic_type_extract_ptr_cb * 354 *===========================================================================*/ 355 PUBLIC int magic_type_extract_ptr_cb(const struct _magic_type* parent_type, 356 const unsigned parent_offset, int child_num, 357 const struct _magic_type* type, const unsigned offset, int depth, void* cb_args) 358 { 359 void** args_array = (void**) cb_args; 360 static void* null_ptr=NULL; 361 if(type->type_id == MAGIC_TYPE_POINTER) { 362 const struct _magic_sentry *root_entry = (const struct _magic_sentry *) args_array[0]; 363 void ***ptr_map = (void ***) args_array[1]; 364 const struct _magic_type **ptr_type_map = (const struct _magic_type **) args_array[2]; 365 int *ptr_num = (int*) args_array[3]; 366 char* root_ptr; 367 void** ptr_ptr; 368 assert(ptr_num); 369 if(root_entry && ptr_map && ptr_type_map) { 370 root_ptr = root_entry->address; 371 ptr_ptr= root_ptr ? (void**)(root_ptr+offset) : &null_ptr; 372 ptr_map[*ptr_num] = ptr_ptr; 373 ptr_type_map[*ptr_num] = type; 374 } 375 (*ptr_num)++; 376 } 377 return MAGIC_TYPE_WALK_CONTINUE; 378 } 379 380 /*===========================================================================* 381 * magic_type_analyzer_cb * 382 *===========================================================================*/ 383 PUBLIC int magic_type_analyzer_cb(const struct _magic_type* parent_type, 384 const unsigned parent_offset, int child_num, const struct _magic_type* type, 385 const unsigned offset, int depth, void* cb_args) 386 { 387 int ret; 388 void **args_array = (void **) cb_args; 389 int *flags = (int *)args_array[0]; 390 magic_sentry_analyze_cb_t sentry_analyze_cb = 391 *((magic_sentry_analyze_cb_t *) args_array[1]); 392 void *sentry_analyze_cb_args = (void *) args_array[2]; 393 struct _magic_sentry* sentry = (struct _magic_sentry *) args_array[3]; 394 _magic_sel_stats_t *sentry_stats = (_magic_sel_stats_t *) args_array[4]; 395 int *selement_num = (int *) args_array[5]; 396 int *sel_analyzed_num = (int *) args_array[6]; 397 static int likely_pointer_orig_type_id; 398 static int likely_pointer_orig_contained_type_id; 399 _magic_selement_t selement; 400 _magic_sel_analyzed_t sel_analyzed; 401 _magic_sel_stats_t sel_stats; 402 403 if (type->type_id == MAGIC_TYPE_UNION && 404 ((*flags) & MAGIC_SEL_SKIP_UNIONS)) { 405 /* Skip unions when requested. */ 406 return MAGIC_TYPE_WALK_SKIP_PATH; 407 } 408 409 if ((type->type_id == MAGIC_TYPE_INTEGER || 410 type->type_id == MAGIC_TYPE_ENUM) && 411 ((*flags) & MAGIC_SEL_SKIP_INTEGERS)) { 412 /* Skip integers when requested. */ 413 return MAGIC_TYPE_WALK_SKIP_PATH; 414 } 415 416 if (((*flags) & MAGIC_SEL_ANALYZE_LIKELYPOINTERS) && 417 (MAGIC_TYPE_IS_RAW_ARRAY(type) || 418 (MAGIC_TYPE_IS_INT_ARRAY(type) && 419 type->contained_types[0]->size != sizeof(void *) && 420 type->size >= sizeof(void *)) || 421 (type->type_id == MAGIC_TYPE_INTEGER && type->size > sizeof(void *)))) { 422 /* This can be either UNION, INTEGER or ARRAY (of VOID or INTEGER). */ 423 likely_pointer_orig_type_id = type->type_id; 424 if (type->type_id == MAGIC_TYPE_ARRAY) 425 likely_pointer_orig_contained_type_id = 426 type->contained_types[0]->type_id; 427 /* Try to find likely pointers in raw arrays. */ 428 ret = magic_type_walk_as_ptrint_array(parent_type, parent_offset, 429 child_num, type, (char *)sentry->address + offset, offset, 430 0, ULONG_MAX, magic_type_analyzer_cb, cb_args); 431 likely_pointer_orig_type_id = likely_pointer_orig_contained_type_id = 0; 432 if (ret != MAGIC_EBADWALK) { 433 return ret == 0 ? MAGIC_TYPE_WALK_SKIP_PATH : ret; 434 } 435 } 436 437 selement.sentry = sentry; 438 selement.parent_type = parent_type; 439 selement.parent_address = (char *)sentry->address + parent_offset; 440 selement.child_num = child_num; 441 selement.type = type; 442 selement.address = (char *)sentry->address + offset; 443 selement.depth = depth; 444 selement.num = ++(*selement_num); 445 selement.cb_args = cb_args; 446 447 ret = magic_selement_analyze(&selement, *flags, &sel_analyzed, &sel_stats); 448 if (ret && 449 (((ret & MAGIC_SEL_FOUND_DATA) && 450 ((*flags) & MAGIC_SEL_ANALYZE_DATA)) || 451 ((ret & MAGIC_SEL_FOUND_INVARIANTS) && 452 ((*flags) & MAGIC_SEL_ANALYZE_INVARIANTS)) || 453 ((ret & MAGIC_SEL_FOUND_VIOLATIONS) && 454 ((*flags) & MAGIC_SEL_ANALYZE_VIOLATIONS)) || 455 ((ret & MAGIC_SEL_FOUND_WALKABLE) && 456 ((*flags) & MAGIC_SEL_ANALYZE_WALKABLE)) 457 )) { 458 *flags |= ret; 459 sel_analyzed.num = ++(*sel_analyzed_num); 460 if (likely_pointer_orig_type_id) { 461 sel_analyzed.type_id = likely_pointer_orig_type_id; 462 sel_analyzed.contained_type_id = 463 likely_pointer_orig_contained_type_id; 464 } 465 ret = sentry_analyze_cb(&selement, &sel_analyzed, &sel_stats, 466 sentry_analyze_cb_args); 467 if (sel_analyzed.flags & MAGIC_SEL_FOUND_INVARIANTS) { 468 _magic_sel_stats_t* sel_stats_ptr = &sel_stats; 469 if (sentry_stats) { 470 MAGIC_SEL_STATS_INCR(sentry_stats, sel_stats_ptr); 471 } 472 } 473 if (ret != MAGIC_SENTRY_ANALYZE_CONTINUE) { 474 switch (ret) { 475 case MAGIC_SENTRY_ANALYZE_SKIP_PATH: 476 ret = MAGIC_TYPE_WALK_SKIP_PATH; 477 break; 478 case MAGIC_SENTRY_ANALYZE_STOP: 479 ret = MAGIC_TYPE_WALK_STOP; 480 break; 481 default: 482 assert(ret < 0 && "Invalid error code!"); 483 break; 484 } 485 return ret; 486 } 487 } 488 489 return MAGIC_TYPE_WALK_CONTINUE; 490 } 491 492 /*===========================================================================* 493 * magic_selement_analyze * 494 *===========================================================================*/ 495 PUBLIC int magic_selement_analyze(_magic_selement_t *selement, int flags, 496 _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats) 497 { 498 const struct _magic_type *type = selement->type; 499 short is_ptr_el = type->type_id == MAGIC_TYPE_POINTER; 500 short is_nonptr_el = type->num_child_types == 0 || (type->type_id == MAGIC_TYPE_INTEGER && type->num_child_types > 0); 501 short analyze_ptr_el, analyze_nonptr_el; 502 503 if (!is_ptr_el && !is_nonptr_el) { 504 if (MAGIC_TYPE_IS_WALKABLE(type)) { 505 sel_analyzed->type_id = MAGIC_TYPE_OPAQUE; 506 return MAGIC_SEL_FOUND_WALKABLE; 507 } 508 /* Not an element to analyze. */ 509 return 0; 510 } 511 assert(is_ptr_el ^ is_nonptr_el); 512 513 analyze_ptr_el = is_ptr_el && (flags & MAGIC_SEL_ANALYZE_POINTERS); 514 analyze_nonptr_el = 0; 515 if (is_nonptr_el && ((flags & MAGIC_SEL_ANALYZE_DATA) || MAGIC_TYPE_HAS_VALUE_SET(type))) { 516 if (flags & MAGIC_SEL_ANALYZE_NONPOINTERS) { 517 analyze_nonptr_el = 1; 518 } 519 else if (flags & MAGIC_SEL_ANALYZE_LIKELYPOINTERS) { 520 short is_intvalue_el = type->type_id == MAGIC_TYPE_ENUM 521 || type->type_id == MAGIC_TYPE_INTEGER; 522 if (is_intvalue_el && type->size == sizeof(void *)) { 523 long value = magic_selement_to_int(selement); 524 analyze_nonptr_el = MAGIC_INT_IS_LIKELY_PTR(value); 525 } 526 } 527 } 528 529 if (analyze_nonptr_el && (flags & MAGIC_SEL_ANALYZE_NONPTRS_AS_PTRS) && 530 type->size == sizeof(void *)) { 531 struct _magic_type tmp_type; 532 int ret; 533 tmp_type = *(selement->type); 534 tmp_type.type_id = MAGIC_TYPE_POINTER; 535 selement->type = &tmp_type; 536 537 /* Analyze non-pointer element as a pointer. */ 538 ret = magic_selement_analyze_ptr(selement, flags, sel_analyzed, sel_stats); 539 540 selement->type = type; 541 /* Keep original type in sel_analyzed. */ 542 sel_analyzed->type_id = type->type_id; 543 544 return ret; 545 } 546 547 assert(!analyze_ptr_el || !analyze_nonptr_el); 548 549 if (analyze_ptr_el) { 550 /* Analyze pointer element. */ 551 return magic_selement_analyze_ptr(selement, flags, sel_analyzed, 552 sel_stats); 553 } 554 if (analyze_nonptr_el) { 555 /* Analyze nonpointer element. */ 556 return magic_selement_analyze_nonptr(selement, flags, sel_analyzed, 557 sel_stats); 558 } 559 560 /* Nothing to analyze. */ 561 return 0; 562 } 563 564 /*===========================================================================* 565 * magic_selement_analyze_ptr_value_invs * 566 *===========================================================================*/ 567 PUBLIC int magic_selement_analyze_ptr_value_invs(_magic_selement_t *selement, 568 _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats) 569 { 570 const struct _magic_type* ptr_type = selement->type; 571 int i, ret = 0; 572 const struct _magic_type *first_trg_type; 573 void* value = sel_analyzed->u.ptr.value; 574 575 first_trg_type = MAGIC_SEL_ANALYZED_PTR_FIRST_TRG_TYPE(sel_analyzed); 576 assert(sel_analyzed->u.ptr.num_trg_types > 0 && first_trg_type); 577 if(first_trg_type == MAGIC_TYPE_NULL_ENTRY) { 578 ret |= MAGIC_SEL_FOUND_INVARIANTS; 579 sel_stats->null_type_found++; 580 } 581 else if(MAGIC_TYPE_FLAG(ptr_type, MAGIC_TYPE_INT_CAST)) { 582 if(MAGIC_TYPE_HAS_VALUE_SET(ptr_type)) { 583 i=0; 584 while(MAGIC_TYPE_HAS_VALUE(ptr_type, i)) { 585 int trg_value = MAGIC_TYPE_VALUE(ptr_type, i); 586 if(trg_value == (int) value) { 587 ret |= MAGIC_SEL_FOUND_INVARIANTS; 588 MAGIC_SEL_ANALYZED_PTR_SET_SPECIAL_TRG_TYPE(sel_analyzed, MAGIC_TYPE_VALUE_FOUND); 589 sel_stats->value_found++; 590 break; 591 } 592 i++; 593 } 594 if(!(ret & MAGIC_SEL_FOUND_INVARIANTS) && MAGIC_TYPE_FLAG(ptr_type, MAGIC_TYPE_STRICT_VALUE_SET)) { 595 ret |= MAGIC_SEL_FOUND_INVARIANTS; 596 MAGIC_SEL_ANALYZED_PTR_SET_SPECIAL_TRG_TYPE(sel_analyzed, MAGIC_TYPE_BAD_VALUE); 597 sel_stats->badvalue_found++; 598 } 599 } 600 else if(MAGIC_PTR_IS_LIKELY_INT(value)) { 601 ret |= MAGIC_SEL_FOUND_INVARIANTS; 602 MAGIC_SEL_ANALYZED_PTR_SET_SPECIAL_TRG_TYPE(sel_analyzed, MAGIC_TYPE_VALUE_FOUND); 603 sel_stats->value_found++; 604 } 605 } 606 607 return ret; 608 } 609 610 /*===========================================================================* 611 * magic_selement_analyze_ptr_trg_invs * 612 *===========================================================================*/ 613 PUBLIC int magic_selement_analyze_ptr_trg_invs(_magic_selement_t *selement, 614 _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats) 615 { 616 int ret = 0; 617 const struct _magic_type *first_trg_type; 618 619 first_trg_type = MAGIC_SEL_ANALYZED_PTR_FIRST_TRG_TYPE(sel_analyzed); 620 assert(sel_analyzed->u.ptr.num_trg_types > 0 && first_trg_type); 621 sel_stats->trg_flags |= sel_analyzed->u.ptr.trg_flags; 622 if(first_trg_type == MAGIC_TYPE_ENTRY_NOT_FOUND) { 623 ret |= MAGIC_SEL_FOUND_INVARIANTS; 624 sel_stats->unknown_found++; 625 } 626 else if(first_trg_type == MAGIC_TYPE_BAD_ENTRY) { 627 ret |= MAGIC_SEL_FOUND_INVARIANTS; 628 sel_stats->badentry_found++; 629 } 630 else if(first_trg_type == MAGIC_TYPE_BAD_OFFSET) { 631 ret |= MAGIC_SEL_FOUND_INVARIANTS; 632 sel_stats->badoffset_found++; 633 } 634 635 return ret; 636 } 637 638 /*===========================================================================* 639 * magic_selement_analyze_ptr_target * 640 *===========================================================================*/ 641 PUBLIC _magic_trg_stats_t magic_selement_analyze_ptr_target(const struct _magic_type *ptr_type, 642 const struct _magic_type *trg_type, int trg_flags) 643 { 644 const struct _magic_type* type = ptr_type->contained_types[0]; 645 646 /* Analyze void target types first. */ 647 if(MAGIC_TYPE_IS_VOID(trg_type)) { 648 int ptr_can_point_to_text = magic_type_ptr_is_text(ptr_type); 649 int ptr_can_point_to_data = magic_type_ptr_is_data(ptr_type); 650 int is_trg_data = (MAGIC_STATE_FLAGS_REGION(trg_flags) & ~MAGIC_STATE_TEXT) != 0; 651 int is_trg_text = trg_flags & MAGIC_STATE_TEXT; 652 assert(ptr_can_point_to_text || ptr_can_point_to_data); 653 assert(is_trg_text || is_trg_data); 654 if((!ptr_can_point_to_text && is_trg_text) 655 || (!ptr_can_point_to_data && is_trg_data)) { 656 return _badentry_found; 657 } 658 else { 659 return _void_type_found; 660 } 661 } 662 663 /* Analyze void types next. */ 664 if(MAGIC_TYPE_IS_VOID(type)) { 665 /* Pretend the pointer has been found, void* can point to any valid target. */ 666 return _ptr_type_found; 667 } 668 669 /* See if the target type is compatible with the static type. */ 670 if(magic_type_compatible(trg_type, type, 0)) { 671 return _ptr_type_found; 672 } 673 674 /* See if the target type is compatible with some static cast type. */ 675 if(MAGIC_TYPE_HAS_COMP_TYPES(ptr_type) && magic_type_comp_compatible(ptr_type, trg_type)) { 676 return _comp_trg_types_found; 677 } 678 679 /* No chance. The pointer is pointing to some other invalid type. */ 680 return _other_types_found; 681 } 682 683 /*===========================================================================* 684 * magic_selement_analyze_ptr_type_invs * 685 *===========================================================================*/ 686 PUBLIC int magic_selement_analyze_ptr_type_invs(_magic_selement_t *selement, 687 _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats) 688 { 689 const struct _magic_type* ptr_type = selement->type; 690 unsigned int i; 691 int ret = 0; 692 int trg_flags; 693 const struct _magic_type *trg_type; 694 _magic_trg_stats_t trg_stats; 695 696 assert(sel_analyzed->u.ptr.num_trg_types > 0); 697 if(MAGIC_SEL_ANALYZED_PTR_HAS_SPECIAL_TRG_TYPE(sel_analyzed)) { 698 /* No invariants if we only have a special target type. */ 699 return ret; 700 } 701 trg_flags= sel_analyzed->u.ptr.trg_flags; 702 sel_stats->trg_flags |= trg_flags; 703 ret |= MAGIC_SEL_FOUND_INVARIANTS; 704 705 /* Analyze targets. */ 706 sel_analyzed->u.ptr.first_legal_trg_type = -1; 707 sel_analyzed->u.ptr.num_legal_trg_types = 0; 708 for(i=0;i<sel_analyzed->u.ptr.num_trg_types;i++) { 709 trg_type = sel_analyzed->u.ptr.trg_selements[i].type; 710 trg_stats = magic_selement_analyze_ptr_target(ptr_type, trg_type, trg_flags); 711 sel_analyzed->u.ptr.trg_stats[i] = trg_stats; 712 if(!MAGIC_SEL_ANALYZED_TRG_STATS_HAS_VIOLATIONS(trg_stats)) { 713 sel_analyzed->u.ptr.num_legal_trg_types++; 714 if(sel_analyzed->u.ptr.first_legal_trg_type == -1) { 715 sel_analyzed->u.ptr.first_legal_trg_type = i; 716 } 717 } 718 } 719 720 /* Set global stats. */ 721 for(i=0;i<sel_analyzed->u.ptr.num_trg_types;i++) { 722 trg_stats = sel_analyzed->u.ptr.trg_stats[i]; 723 if(trg_stats == _badentry_found) { 724 sel_stats->badentry_found++; 725 return ret; 726 } 727 else if(trg_stats == _void_type_found) { 728 sel_stats->void_type_found++; 729 return ret; 730 } 731 } 732 for(i=0;i<sel_analyzed->u.ptr.num_trg_types;i++) { 733 trg_stats = sel_analyzed->u.ptr.trg_stats[i]; 734 if(trg_stats == _ptr_type_found) { 735 sel_stats->ptr_type_found++; 736 return ret; 737 } 738 } 739 for(i=0;i<sel_analyzed->u.ptr.num_trg_types;i++) { 740 trg_stats = sel_analyzed->u.ptr.trg_stats[i]; 741 if(trg_stats == _comp_trg_types_found) { 742 sel_stats->comp_trg_types_found++; 743 return ret; 744 } 745 } 746 sel_stats->other_types_found++; 747 return ret; 748 } 749 750 /*===========================================================================* 751 * magic_selement_recurse_ptr * 752 *===========================================================================*/ 753 PUBLIC int magic_selement_recurse_ptr(_magic_selement_t *selement, 754 _magic_selement_t *new_selement, int max_steps) 755 { 756 _magic_sel_stats_t sel_stats; 757 _magic_sel_analyzed_t sel_analyzed; 758 int steps = 0; 759 760 if(selement->type->type_id != MAGIC_TYPE_POINTER) { 761 return MAGIC_EINVAL; 762 } 763 764 *new_selement = *selement; 765 while(1) { 766 magic_selement_analyze_ptr(new_selement, MAGIC_SEL_ANALYZE_ALL, 767 &sel_analyzed, &sel_stats); 768 if(MAGIC_SEL_ANALYZED_PTR_HAS_SPECIAL_TRG_TYPE(&sel_analyzed)) { 769 return steps; 770 } 771 *new_selement = sel_analyzed.u.ptr.trg_selements[0]; 772 steps++; 773 if(new_selement->type->type_id != MAGIC_TYPE_POINTER || (max_steps > 0 && steps >= max_steps)) { 774 break; 775 } 776 } 777 778 return steps; 779 } 780 781 /*===========================================================================* 782 * magic_sentry_analyze_ptr_trg_cb * 783 *===========================================================================*/ 784 PRIVATE int magic_sentry_analyze_ptr_trg_cb(const struct _magic_type *trg_parent_type, 785 const unsigned parent_offset, int child_num, 786 const struct _magic_type *trg_type, const unsigned offset, int depth, void *cb_args) 787 { 788 void **args_array = (void **) cb_args; 789 _magic_sel_analyzed_t *sel_analyzed = (_magic_sel_analyzed_t *) args_array[3]; 790 _magic_selement_t *sel; 791 char *trg_address; 792 int analysis_flags = (*(int *)(args_array[4])); 793 794 if (trg_type->type_id == MAGIC_TYPE_ARRAY) { 795 /* Skip arrays. */ 796 return MAGIC_TYPE_WALK_CONTINUE; 797 } 798 799 if (!sel_analyzed->u.ptr.trg_flags) { 800 /* Set trg flags and offset only the first time. */ 801 struct _magic_dsentry **trg_dsentry = (struct _magic_dsentry **) args_array[0]; 802 struct _magic_dfunction **trg_dfunction = (struct _magic_dfunction **) args_array[1]; 803 int flags; 804 if (*trg_dsentry) { 805 assert(!(*trg_dfunction)); 806 flags = MAGIC_DSENTRY_TO_SENTRY(*trg_dsentry)->flags; 807 if (flags & MAGIC_STATE_DYNAMIC) { 808 assert(!(flags & MAGIC_STATE_DATA) || (flags & MAGIC_STATE_LIB)); 809 assert(MAGIC_STATE_REGION(MAGIC_DSENTRY_TO_SENTRY(*trg_dsentry))); 810 } 811 else { 812 assert((flags & MAGIC_STATE_DATA) && !(flags & MAGIC_STATE_LIB)); 813 } 814 } 815 else { 816 assert(*trg_dfunction); 817 flags = MAGIC_DFUNCTION_TO_FUNCTION(*trg_dfunction)->flags; 818 assert(flags & MAGIC_STATE_TEXT); 819 } 820 sel_analyzed->u.ptr.trg_flags = flags; 821 if (analysis_flags & MAGIC_SEL_ANALYZE_RETURN_TRG_PTRS) 822 sel_analyzed->u.ptr.trg_flags |= MAGIC_SEL_ANALYZE_RETURN_TRG_PTRS; 823 sel_analyzed->u.ptr.trg_offset = offset; 824 } 825 826 /* Add target types. */ 827 trg_address = MAGIC_SEL_ANALYZED_PTR_TRG_ADDRESS(sel_analyzed); 828 assert(trg_address); 829 sel = &sel_analyzed->u.ptr.trg_selements[sel_analyzed->u.ptr.num_trg_types]; 830 if (!(analysis_flags & MAGIC_SEL_ANALYZE_RETURN_TRG_PTRS)) { 831 sel->sentry = MAGIC_SEL_ANALYZED_PTR_HAS_TRG_SENTRY(sel_analyzed) ? MAGIC_DSENTRY_TO_SENTRY(&sel_analyzed->u.ptr.trg.dsentry) : NULL; 832 } else { 833 sel->sentry = MAGIC_SEL_ANALYZED_PTR_HAS_TRG_SENTRY(sel_analyzed) ? MAGIC_DSENTRY_TO_SENTRY(sel_analyzed->u.ptr.trg_p.dsentry) : NULL; 834 } 835 sel->parent_type = trg_parent_type; 836 sel->parent_address = trg_address + parent_offset; 837 sel->child_num = child_num; 838 sel->type = trg_type; 839 sel->address = trg_address + offset; 840 sel_analyzed->u.ptr.num_trg_types++; 841 842 return MAGIC_TYPE_WALK_CONTINUE; 843 } 844 845 /*===========================================================================* 846 * magic_selement_analyze_ptr * 847 *===========================================================================*/ 848 PUBLIC int magic_selement_analyze_ptr(_magic_selement_t *selement, int flags, 849 _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats) 850 { 851 const struct _magic_type *ptr_type = selement->type; 852 short is_ptr_el = ptr_type->type_id == MAGIC_TYPE_POINTER; 853 int r, ret = 0; 854 855 sel_analyzed->type_id = 0; 856 if (!is_ptr_el) { 857 /* Nothing to do. */ 858 return 0; 859 } 860 memset(&sel_analyzed->u.ptr, 0, sizeof(sel_analyzed->u.ptr)); 861 memset(sel_stats, 0, sizeof(_magic_sel_stats_t)); 862 863 if (flags & (MAGIC_SEL_ANALYZE_DATA | MAGIC_SEL_ANALYZE_INVARIANTS | MAGIC_SEL_ANALYZE_VIOLATIONS)) { 864 /* Analyze data first. */ 865 void *value = magic_selement_to_ptr(selement); 866 sel_analyzed->type_id = MAGIC_TYPE_POINTER; 867 sel_analyzed->u.ptr.value = value; 868 ret |= MAGIC_SEL_FOUND_DATA; 869 if (value == NULL) { 870 /* Null pointer. */ 871 MAGIC_SEL_ANALYZED_PTR_SET_SPECIAL_TRG_TYPE(sel_analyzed, MAGIC_TYPE_NULL_ENTRY); 872 } 873 else { 874 /* Check target. */ 875 struct _magic_dsentry *trg_dsentry_ptr; 876 struct _magic_dfunction *trg_dfunction_ptr; 877 void *args_array[5]; 878 if (!(flags & MAGIC_SEL_ANALYZE_RETURN_TRG_PTRS)) { 879 trg_dsentry_ptr = &sel_analyzed->u.ptr.trg.dsentry; 880 trg_dfunction_ptr = &sel_analyzed->u.ptr.trg.dfunction; 881 args_array[0] = &trg_dsentry_ptr; 882 args_array[1] = &trg_dfunction_ptr; 883 } else { 884 args_array[0] = &sel_analyzed->u.ptr.trg_p.dsentry; 885 args_array[1] = &sel_analyzed->u.ptr.trg_p.dfunction; 886 } 887 args_array[2] = selement; 888 args_array[3] = sel_analyzed; 889 args_array[4] = &flags; 890 r = magic_type_target_walk(value, args_array[0], args_array[1], 891 magic_sentry_analyze_ptr_trg_cb, args_array); 892 if (r == MAGIC_ENOENT) { 893 MAGIC_SEL_ANALYZED_PTR_SET_SPECIAL_TRG_TYPE(sel_analyzed, MAGIC_TYPE_ENTRY_NOT_FOUND); 894 sel_analyzed->u.ptr.trg_flags = magic_range_lookup_by_addr(value, NULL); 895 } 896 else if (r == MAGIC_EBADENT) { 897 MAGIC_SEL_ANALYZED_PTR_SET_SPECIAL_TRG_TYPE(sel_analyzed, MAGIC_TYPE_BAD_ENTRY); 898 sel_analyzed->u.ptr.trg_flags = magic_range_lookup_by_addr(value, NULL); 899 } 900 else if (sel_analyzed->u.ptr.num_trg_types == 0) { 901 MAGIC_SEL_ANALYZED_PTR_SET_SPECIAL_TRG_TYPE(sel_analyzed, MAGIC_TYPE_BAD_OFFSET); 902 sel_analyzed->u.ptr.trg_flags = magic_range_lookup_by_addr(value, NULL); 903 } 904 } 905 906 if (flags & (MAGIC_SEL_ANALYZE_INVARIANTS | MAGIC_SEL_ANALYZE_VIOLATIONS)) { 907 /* Check value-based invariants. */ 908 ret |= magic_selement_analyze_ptr_value_invs(selement, 909 sel_analyzed, sel_stats); 910 911 /* Check target-based invariants. */ 912 if (!(ret & MAGIC_SEL_FOUND_INVARIANTS)) { 913 ret |= magic_selement_analyze_ptr_trg_invs(selement, 914 sel_analyzed, sel_stats); 915 } 916 917 /* Check type-based invariants. */ 918 if (!(ret & MAGIC_SEL_FOUND_INVARIANTS)) { 919 ret |= magic_selement_analyze_ptr_type_invs(selement, 920 sel_analyzed, sel_stats); 921 } 922 923 assert(ret & MAGIC_SEL_FOUND_INVARIANTS); 924 sel_stats->ptr_found++; 925 if (MAGIC_SEL_STATS_HAS_VIOLATIONS(sel_stats)) { 926 ret |= MAGIC_SEL_FOUND_VIOLATIONS; 927 } 928 } 929 } 930 931 sel_analyzed->flags = ret; 932 return ret; 933 } 934 935 /*===========================================================================* 936 * magic_selement_analyze_nonptr_value_invs * 937 *===========================================================================*/ 938 PRIVATE int magic_selement_analyze_nonptr_value_invs(_magic_selement_t *selement, 939 _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats) 940 { 941 const struct _magic_type* type = selement->type; 942 int i, ret = 0; 943 int value = sel_analyzed->u.nonptr.value; 944 945 if(MAGIC_STATE_FLAG(selement->sentry, MAGIC_STATE_EXTERNAL)) 946 return 0; 947 948 if(MAGIC_TYPE_HAS_VALUE_SET(type)) { 949 i=0; 950 ret |= MAGIC_SEL_FOUND_INVARIANTS; 951 while(MAGIC_TYPE_HAS_VALUE(type, i)) { 952 int trg_value = MAGIC_TYPE_VALUE(type, i); 953 if(trg_value == value) { 954 sel_stats->value_found++; 955 break; 956 } 957 i++; 958 } 959 if(!MAGIC_TYPE_HAS_VALUE(type, i)) { 960 sel_stats->badvalue_found++; 961 } 962 } 963 964 return ret; 965 } 966 967 /*===========================================================================* 968 * magic_selement_analyze_nonptr * 969 *===========================================================================*/ 970 PUBLIC int magic_selement_analyze_nonptr(_magic_selement_t *selement, int flags, 971 _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats) 972 { 973 int ret = 0; 974 975 sel_analyzed->type_id = 0; 976 memset(&sel_analyzed->u.nonptr, 0, sizeof(sel_analyzed->u.nonptr)); 977 memset(sel_stats, 0, sizeof(_magic_sel_stats_t)); 978 979 if(flags & (MAGIC_SEL_ANALYZE_DATA|MAGIC_SEL_ANALYZE_INVARIANTS|MAGIC_SEL_ANALYZE_VIOLATIONS)) { 980 /* Analyze data first. */ 981 switch(selement->type->type_id) { 982 case MAGIC_TYPE_VOID: 983 sel_analyzed->type_id = MAGIC_TYPE_VOID; 984 sel_analyzed->u.nonptr.value = (long) *((char*)selement->address); 985 ret |= MAGIC_SEL_FOUND_DATA; 986 break; 987 988 case MAGIC_TYPE_FLOAT: 989 sel_analyzed->type_id = MAGIC_TYPE_FLOAT; 990 sel_analyzed->u.nonptr.value = (long) magic_selement_to_float(selement); 991 ret |= MAGIC_SEL_FOUND_DATA; 992 break; 993 994 case MAGIC_TYPE_INTEGER: 995 case MAGIC_TYPE_ENUM: 996 sel_analyzed->type_id = selement->type->type_id; 997 sel_analyzed->u.nonptr.value = magic_selement_to_int(selement); 998 ret |= MAGIC_SEL_FOUND_DATA; 999 if((flags & MAGIC_SEL_ANALYZE_LIKELYPOINTERS) && selement->type->size == sizeof(void*)) { 1000 sel_analyzed->u.nonptr.trg_flags = magic_range_lookup_by_addr((void*) sel_analyzed->u.nonptr.value, NULL); 1001 } 1002 if(flags & (MAGIC_SEL_ANALYZE_INVARIANTS|MAGIC_SEL_ANALYZE_VIOLATIONS)) { 1003 /* Check value-based invariants. */ 1004 ret |= magic_selement_analyze_nonptr_value_invs(selement, 1005 sel_analyzed, sel_stats); 1006 1007 if(ret & MAGIC_SEL_FOUND_INVARIANTS) { 1008 sel_stats->nonptr_found++; 1009 if(MAGIC_SEL_STATS_HAS_VIOLATIONS(sel_stats)) { 1010 ret |= MAGIC_SEL_FOUND_VIOLATIONS; 1011 } 1012 } 1013 else { 1014 sel_stats->nonptr_unconstrained_found++; 1015 } 1016 } 1017 break; 1018 } 1019 } 1020 1021 sel_analyzed->flags = ret; 1022 return ret; 1023 } 1024 1025 /*===========================================================================* 1026 * magic_sel_analyzed_trg_selements_print * 1027 *===========================================================================*/ 1028 PUBLIC void magic_sel_analyzed_trg_selements_print(_magic_sel_analyzed_t *sel_analyzed, 1029 int flags) 1030 { 1031 int num; 1032 int i=0; 1033 const _magic_selement_t* trg_selement; 1034 _magic_trg_stats_t trg_stats; 1035 1036 num = sel_analyzed->u.ptr.num_trg_types; 1037 if(num == 0) { 1038 return; 1039 } 1040 _magic_printf("#%d|%d", num, sel_analyzed->u.ptr.num_legal_trg_types); 1041 1042 for(;i<num;i++) { 1043 trg_selement = &sel_analyzed->u.ptr.trg_selements[i]; 1044 trg_stats = sel_analyzed->u.ptr.trg_stats[i]; 1045 _magic_printf("%s%d|%c=", (i==0 ? ": " : ", "), i+1, MAGIC_SEL_ANALYZED_TRG_STATS_C(trg_stats)); 1046 MAGIC_SELEMENT_PRINT(trg_selement, flags|MAGIC_SKIP_COMP_TYPES); 1047 } 1048 } 1049 1050 /*===========================================================================* 1051 * magic_selement_type_cast * 1052 *===========================================================================*/ 1053 PUBLIC _magic_selement_t* magic_selement_type_cast( 1054 _magic_selement_t *selement, int flags, const struct _magic_type* type, 1055 _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats) 1056 { 1057 _magic_sel_stats_t my_sel_stats; 1058 1059 selement->type = type; 1060 if(sel_analyzed) { 1061 magic_selement_analyze(selement, flags, 1062 sel_analyzed, sel_stats ? sel_stats : &my_sel_stats); 1063 } 1064 return selement; 1065 } 1066 1067