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