2 #include <magic_analysis.h>
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
);
17 PRIVATE magic_cb_sentries_analyze_pre_t magic_sentries_analyze_pre_cb
= NULL
;
19 /*===========================================================================*
20 * magic_setcb_sentries_analyze_pre *
21 *===========================================================================*/
22 PUBLIC
void magic_setcb_sentries_analyze_pre(magic_cb_sentries_analyze_pre_t cb
)
24 magic_sentries_analyze_pre_cb
= cb
;
27 /*===========================================================================*
28 * magic_sentry_print_ptr_types *
29 *===========================================================================*/
30 PUBLIC
int magic_sentry_print_ptr_types(struct _magic_sentry
* entry
)
32 int ret
, ptrs_found
= 0;
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
);
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
)
46 int from_wrapper
= MAGIC_MEM_WRAPPER_IS_ACTIVE();
47 int ret
= magic_type_count_ptrs(entry
->type
, ptr_num
);
57 MAGIC_MEM_WRAPPER_BEGIN();
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
*));
62 MAGIC_MEM_WRAPPER_END();
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
);
70 assert(*ptr_num
== ptr_num2
);
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
)
83 int selement_num
= 0, sel_analyzed_num
= 0;
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
,
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
)
108 struct _magic_sentry
*sentry
;
110 if (flags
& MAGIC_SEL_ANALYZE_RETURN_TRG_PTRS
)
111 magic_reentrant_disable();
113 /* See if any pre-analyze callback has been registered. */
114 if (magic_sentries_analyze_pre_cb
) {
115 ret
= magic_sentries_analyze_pre_cb();
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
);
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
);
138 if (flags
& MAGIC_SEL_ANALYZE_RETURN_TRG_PTRS
)
139 magic_reentrant_enable();
144 /*===========================================================================*
145 * magic_sentry_print_selements *
146 *===========================================================================*/
147 PUBLIC
int magic_sentry_print_selements(struct _magic_sentry
* sentry
)
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
);
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
)
159 int flags
= (MAGIC_SEL_ANALYZE_POINTERS
|MAGIC_SEL_ANALYZE_DATA
|MAGIC_SEL_ANALYZE_INVARIANTS
|MAGIC_SEL_ANALYZE_VIOLATIONS
);
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
);
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
)
173 struct _magic_dsentry
*prev_dsentry
, *dsentry
;
174 struct _magic_sentry
* sentry
;
176 /* If dead dsentries are enabled, garbage collect them to ensure consistency. */
177 if (magic_allow_dead_dsentries
)
178 magic_free_dead_dsentries();
180 /* Analyze all the dsentries. */
182 * We need to hold the DSENTRY, DFUNCTION and DSODESC locks for the
183 * magic_range_lookup_by_addr() function.
185 MAGIC_MULTIPLE_LOCK(1, 1, 1, 0);
186 MAGIC_DSENTRY_ALIVE_BLOCK_ITER(_magic_first_dsentry
, prev_dsentry
, dsentry
,
190 * Check if we should analyze out-of-band dsentries.
192 if (!(flags
& MAGIC_SEL_ANALYZE_OUT_OF_BAND
) &&
193 MAGIC_STATE_FLAG(sentry
, MAGIC_STATE_OUT_OF_BAND
)) {
198 * Check if we should analyze shlib state dsentries.
200 if (!(flags
& MAGIC_SEL_ANALYZE_LIB_SRC
) &&
201 MAGIC_STATE_FLAG(sentry
, MAGIC_STATE_LIB
)) {
205 ret
= magic_sentry_analyze(sentry
, flags
, cb
, cb_args
, dsentries_stats
);
213 MAGIC_MULTIPLE_UNLOCK(1, 1, 1, 0);
215 return ret
< 0 ? ret
: flags
;
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
,
225 if(sel_analyzed
->num
== 1) {
226 MAGIC_SENTRY_PRINT(selement
->sentry
, MAGIC_EXPAND_TYPE_STR
);
230 MAGIC_SELEMENT_PRINT(selement
, MAGIC_EXPAND_TYPE_STR
);
232 MAGIC_SEL_ANALYZED_PRINT(sel_analyzed
, MAGIC_EXPAND_TYPE_STR
);
234 MAGIC_SEL_STATS_PRINT(sel_stats
);
235 _magic_printf("\n\n");
237 return MAGIC_SENTRY_ANALYZE_CONTINUE
;
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
,
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;
252 if(sel_analyzed
->type_id
!= MAGIC_TYPE_POINTER
) {
253 return MAGIC_SENTRY_ANALYZE_CONTINUE
;
255 if(skip_null_ptrs
&& sel_analyzed
->u
.ptr
.value
== 0) {
256 return MAGIC_SENTRY_ANALYZE_CONTINUE
;
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);
265 _magic_printf("magic_sentry_print_ptr_el_cb: recursive step reported error %d\n", r
);
271 return MAGIC_SENTRY_ANALYZE_CONTINUE
;
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
,
281 if(MAGIC_SEL_ANALYZED_TRG_FLAGS(sel_analyzed
)) {
282 return magic_sentry_print_el_cb(selement
, sel_analyzed
, sel_stats
,
286 return MAGIC_SENTRY_ANALYZE_CONTINUE
;
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
,
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
,
302 return MAGIC_SENTRY_ANALYZE_CONTINUE
;
305 /*===========================================================================*
306 * magic_type_count_ptrs *
307 *===========================================================================*/
308 PUBLIC
int magic_type_count_ptrs(const struct _magic_type
* type
, int* ptr_num
)
311 void* args_array
[4] = { NULL
, NULL
, NULL
};
312 args_array
[3] = ptr_num
;
314 ret
= magic_type_walk_root_all(type
, magic_type_extract_ptr_cb
, args_array
);
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
)
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
;
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");
342 ret
= magic_type_str_print_from_target(target_address
);
344 _magic_printf("ENTRY NOT FOUND");
349 return MAGIC_TYPE_WALK_CONTINUE
;
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
)
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];
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
;
377 return MAGIC_TYPE_WALK_CONTINUE
;
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
)
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
;
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
;
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
;
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
;
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
;
447 ret
= magic_selement_analyze(&selement
, *flags
, &sel_analyzed
, &sel_stats
);
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
))
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
;
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
;
470 MAGIC_SEL_STATS_INCR(sentry_stats
, sel_stats_ptr
);
473 if (ret
!= MAGIC_SENTRY_ANALYZE_CONTINUE
) {
475 case MAGIC_SENTRY_ANALYZE_SKIP_PATH
:
476 ret
= MAGIC_TYPE_WALK_SKIP_PATH
;
478 case MAGIC_SENTRY_ANALYZE_STOP
:
479 ret
= MAGIC_TYPE_WALK_STOP
;
482 assert(ret
< 0 && "Invalid error code!");
489 return MAGIC_TYPE_WALK_CONTINUE
;
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
)
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
;
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
;
508 /* Not an element to analyze. */
511 assert(is_ptr_el
^ is_nonptr_el
);
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;
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
);
529 if (analyze_nonptr_el
&& (flags
& MAGIC_SEL_ANALYZE_NONPTRS_AS_PTRS
) &&
530 type
->size
== sizeof(void *)) {
531 struct _magic_type tmp_type
;
533 tmp_type
= *(selement
->type
);
534 tmp_type
.type_id
= MAGIC_TYPE_POINTER
;
535 selement
->type
= &tmp_type
;
537 /* Analyze non-pointer element as a pointer. */
538 ret
= magic_selement_analyze_ptr(selement
, flags
, sel_analyzed
, sel_stats
);
540 selement
->type
= type
;
541 /* Keep original type in sel_analyzed. */
542 sel_analyzed
->type_id
= type
->type_id
;
547 assert(!analyze_ptr_el
|| !analyze_nonptr_el
);
549 if (analyze_ptr_el
) {
550 /* Analyze pointer element. */
551 return magic_selement_analyze_ptr(selement
, flags
, sel_analyzed
,
554 if (analyze_nonptr_el
) {
555 /* Analyze nonpointer element. */
556 return magic_selement_analyze_nonptr(selement
, flags
, sel_analyzed
,
560 /* Nothing to analyze. */
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
)
570 const struct _magic_type
* ptr_type
= selement
->type
;
572 const struct _magic_type
*first_trg_type
;
573 void* value
= sel_analyzed
->u
.ptr
.value
;
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
++;
581 else if(MAGIC_TYPE_FLAG(ptr_type
, MAGIC_TYPE_INT_CAST
)) {
582 if(MAGIC_TYPE_HAS_VALUE_SET(ptr_type
)) {
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
++;
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
++;
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
++;
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
)
617 const struct _magic_type
*first_trg_type
;
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
++;
626 else if(first_trg_type
== MAGIC_TYPE_BAD_ENTRY
) {
627 ret
|= MAGIC_SEL_FOUND_INVARIANTS
;
628 sel_stats
->badentry_found
++;
630 else if(first_trg_type
== MAGIC_TYPE_BAD_OFFSET
) {
631 ret
|= MAGIC_SEL_FOUND_INVARIANTS
;
632 sel_stats
->badoffset_found
++;
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
)
644 const struct _magic_type
* type
= ptr_type
->contained_types
[0];
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
;
659 return _void_type_found
;
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
;
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
;
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
;
679 /* No chance. The pointer is pointing to some other invalid type. */
680 return _other_types_found
;
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
)
689 const struct _magic_type
* ptr_type
= selement
->type
;
693 const struct _magic_type
*trg_type
;
694 _magic_trg_stats_t trg_stats
;
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. */
701 trg_flags
= sel_analyzed
->u
.ptr
.trg_flags
;
702 sel_stats
->trg_flags
|= trg_flags
;
703 ret
|= MAGIC_SEL_FOUND_INVARIANTS
;
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
;
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
++;
727 else if(trg_stats
== _void_type_found
) {
728 sel_stats
->void_type_found
++;
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
++;
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
++;
746 sel_stats
->other_types_found
++;
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
)
756 _magic_sel_stats_t sel_stats
;
757 _magic_sel_analyzed_t sel_analyzed
;
760 if(selement
->type
->type_id
!= MAGIC_TYPE_POINTER
) {
764 *new_selement
= *selement
;
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
)) {
771 *new_selement
= sel_analyzed
.u
.ptr
.trg_selements
[0];
773 if(new_selement
->type
->type_id
!= MAGIC_TYPE_POINTER
|| (max_steps
> 0 && steps
>= max_steps
)) {
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
)
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
;
792 int analysis_flags
= (*(int *)(args_array
[4]));
794 if (trg_type
->type_id
== MAGIC_TYPE_ARRAY
) {
796 return MAGIC_TYPE_WALK_CONTINUE
;
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];
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
)));
812 assert((flags
& MAGIC_STATE_DATA
) && !(flags
& MAGIC_STATE_LIB
));
816 assert(*trg_dfunction
);
817 flags
= MAGIC_DFUNCTION_TO_FUNCTION(*trg_dfunction
)->flags
;
818 assert(flags
& MAGIC_STATE_TEXT
);
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
;
826 /* Add target types. */
827 trg_address
= MAGIC_SEL_ANALYZED_PTR_TRG_ADDRESS(sel_analyzed
);
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
;
833 sel
->sentry
= MAGIC_SEL_ANALYZED_PTR_HAS_TRG_SENTRY(sel_analyzed
) ? MAGIC_DSENTRY_TO_SENTRY(sel_analyzed
->u
.ptr
.trg_p
.dsentry
) : NULL
;
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
++;
842 return MAGIC_TYPE_WALK_CONTINUE
;
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
)
851 const struct _magic_type
*ptr_type
= selement
->type
;
852 short is_ptr_el
= ptr_type
->type_id
== MAGIC_TYPE_POINTER
;
855 sel_analyzed
->type_id
= 0;
860 memset(&sel_analyzed
->u
.ptr
, 0, sizeof(sel_analyzed
->u
.ptr
));
861 memset(sel_stats
, 0, sizeof(_magic_sel_stats_t
));
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
;
871 MAGIC_SEL_ANALYZED_PTR_SET_SPECIAL_TRG_TYPE(sel_analyzed
, MAGIC_TYPE_NULL_ENTRY
);
875 struct _magic_dsentry
*trg_dsentry_ptr
;
876 struct _magic_dfunction
*trg_dfunction_ptr
;
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
;
884 args_array
[0] = &sel_analyzed
->u
.ptr
.trg_p
.dsentry
;
885 args_array
[1] = &sel_analyzed
->u
.ptr
.trg_p
.dfunction
;
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
);
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
);
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
);
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
);
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
);
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
);
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
;
931 sel_analyzed
->flags
= ret
;
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
)
941 const struct _magic_type
* type
= selement
->type
;
943 int value
= sel_analyzed
->u
.nonptr
.value
;
945 if(MAGIC_STATE_FLAG(selement
->sentry
, MAGIC_STATE_EXTERNAL
))
948 if(MAGIC_TYPE_HAS_VALUE_SET(type
)) {
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
++;
959 if(!MAGIC_TYPE_HAS_VALUE(type
, i
)) {
960 sel_stats
->badvalue_found
++;
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
)
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
));
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
;
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
;
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
);
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
);
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
;
1014 sel_stats
->nonptr_unconstrained_found
++;
1021 sel_analyzed
->flags
= ret
;
1025 /*===========================================================================*
1026 * magic_sel_analyzed_trg_selements_print *
1027 *===========================================================================*/
1028 PUBLIC
void magic_sel_analyzed_trg_selements_print(_magic_sel_analyzed_t
*sel_analyzed
,
1033 const _magic_selement_t
* trg_selement
;
1034 _magic_trg_stats_t trg_stats
;
1036 num
= sel_analyzed
->u
.ptr
.num_trg_types
;
1040 _magic_printf("#%d|%d", num
, sel_analyzed
->u
.ptr
.num_legal_trg_types
);
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
);
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
)
1057 _magic_sel_stats_t my_sel_stats
;
1059 selement
->type
= type
;
1061 magic_selement_analyze(selement
, flags
,
1062 sel_analyzed
, sel_stats
? sel_stats
: &my_sel_stats
);