xref: /minix/minix/lib/libmagicrt/magic.c (revision e1cdaee1)
1 #include <magic.h>
2 #include <magic_mem.h>
3 #include <magic_asr.h>
4 #include <magic_eval.h>
5 #include <magic_analysis.h>
6 #include <magic_splay_tree.h>
7 #include <stdarg.h>
8 #if MAGIC_MEM_USAGE_OUTPUT_CTL
9 #include <common/util/time.h>
10 #endif
11 
12 /* Workaround for extern-only structs. */
13 #ifndef __MINIX
14 #include <stdio.h>
15 EXTERN FILE *stdout;
16 PUBLIC FILE **UNUSED(_____magic_instr_FILE_unused) = &stdout;
17 
18 #include <ncurses.h>
19 PUBLIC WINDOW *UNUSED(_____magic_instr_WINDOW_unused);
20 #endif
21 
22 #include <netinet/in.h>
23 PUBLIC struct in6_addr *UNUSED(_____magic_instr_in6_addr_unused);
24 
25 /* Magic printf. */
26 MAGIC_VAR printf_ptr_t _magic_printf = MAGIC_PRINTF_DEFAULT;
27 
28 /* Magic lock primitives. */
29 PUBLIC magic_lock_t magic_dsentry_lock = NULL;
30 PUBLIC magic_unlock_t magic_dsentry_unlock = NULL;
31 PUBLIC void *magic_dsentry_lock_args = NULL;
32 PUBLIC void *magic_dsentry_unlock_args = NULL;
33 
34 PUBLIC magic_lock_t magic_dfunction_lock = NULL;
35 PUBLIC magic_unlock_t magic_dfunction_unlock = NULL;
36 PUBLIC void *magic_dfunction_lock_args = NULL;
37 PUBLIC void *magic_dfunction_unlock_args = NULL;
38 
39 PUBLIC magic_lock_t magic_dsodesc_lock = NULL;
40 PUBLIC magic_unlock_t magic_dsodesc_unlock = NULL;
41 PUBLIC void *magic_dsodesc_lock_args = NULL;
42 PUBLIC void *magic_dsodesc_unlock_args = NULL;
43 
44 PUBLIC magic_lock_t magic_mpdesc_lock = NULL;
45 PUBLIC magic_unlock_t magic_mpdesc_unlock = NULL;
46 PUBLIC void *magic_mpdesc_lock_args = NULL;
47 PUBLIC void *magic_mpdesc_unlock_args = NULL;
48 
49 /* Magic vars references. */
50 MAGIC_VAR struct _magic_vars_t _magic_vars_buff = {
51 
52     /* Address Space Randomization (ASRPass) */
53     0, /* asr_seed */
54     0, /* asr_heap_map_do_permutate */
55     0, /* asr_heap_max_offset */
56     0, /* asr_heap_max_padding */
57     0, /* asr_map_max_offset_pages */
58     0, /* asr_map_max_padding_pages */
59 
60     /* Runtime flags. */
61     0,    /* no_mem_inst */
62 
63     /* Magic type array. */
64     NULL, /* types */
65     0,    /* types_num */
66     0,    /* types_next_id */
67 
68     /* Magic function array. */
69     NULL, /* functions */
70     0,    /* functions_num */
71     0,    /* functions_next_id */
72 
73     /* Magic state entry array. */
74     NULL, /* sentries */
75     0,    /* sentries_num */
76     0,    /* sentries_str_num */
77     0,    /* sentries_next_id */
78 
79     /* Magic dynamic state index array. */
80     NULL, /* dsindexes */
81     0,    /* dsindexes_num */
82 
83     /* Magic dynamic state entry list. */
84     NULL, /* first_dsentry */
85     0,    /* num_dead_sentries */
86     0,    /* size_dead_dsentries */
87 
88     /* Magic memory pool dynamic state entry list. */
89     NULL, /* first_mempool_dsentry */
90 
91     /* Magic dynamic function list. */
92     NULL, /* first_dfunction */
93     NULL, /* last_dfunction */
94     0,    /* dfunctions_num */
95 
96     /* Magic SO library descriptor list. */
97     NULL, /* first_sodesc */
98     NULL, /* last_sodesc */
99     0,    /* sodescs_num */
100 
101     /* Magic DSO library descriptor list. */
102     NULL, /* first_dsodesc */
103     NULL, /* last_dsodesc */
104     0,    /* dsodescs_num */
105 
106     /* Magic stack-related variables. */
107     NULL, /* first_stack_dsentry */
108     NULL, /* last_stack_dsentry */
109 
110     /* Magic memory ranges */
111 
112     { (void*) ULONG_MAX, (void*) 0 }, /* *null_range[2] */
113     {0,0}, /* *data_range[2] */
114     {0,0}, /* *heap_range[2] */
115     {0,0}, /* *map_range[2] */
116     {0,0}, /* *shm_range[2] */
117     {0,0}, /* *stack_range[2] */
118     {0,0}, /* *text_range[2] */
119 
120     {0,0}, /* *sentry_range[2] */
121     {0,0}, /* *function_range[2] */
122     {0,0}, /* *dfunction_range[2] */
123 
124     NULL, /* *heap_start */
125     NULL, /* *heap_end */
126     1,     /* update_dsentry_ranges */
127     1,     /* update_dfunction_ranges */
128 
129 #ifdef __MINIX
130     { { NULL, 0 } }, /* unmap_mem */
131 #endif
132 
133     NULL,  /* sentry_rl_buff */
134     0,     /* sentry_rl_buff_offset */
135     0,     /* sentry_rl_buff_size */
136     NULL,  /* sentry_rl_index */
137 
138     NULL,  /* sentry_hash_buff */
139     0,     /* sentry_hash_buff_offset */
140     0,     /* sentry_hash_buff_size */
141     NULL,  /* sentry_hash_head */
142 
143     NULL,  /* function_hash_buff */
144     0,     /* function_hash_buff_offset */
145     0,     /* function_hash_buff_size */
146     NULL,  /* function_hash_head */
147 
148     0      /* fake_malloc */
149 };
150 
151 PUBLIC struct _magic_vars_t *_magic_vars = &_magic_vars_buff;
152 
153 /* Magic void ptr and array (force at the least 1 void* and 1 void array in the list of globals). */
154 PUBLIC void* MAGIC_VOID_PTR = NULL;
155 PUBLIC char MAGIC_VOID_ARRAY[1];
156 
157 /* Magic special types. */
158 MAGIC_VAR struct _magic_type *MAGIC_VOID_PTR_TYPE = NULL;
159 MAGIC_VAR struct _magic_type *MAGIC_VOID_PTR_INT_CAST_TYPE = NULL;
160 MAGIC_VAR struct _magic_type *MAGIC_VOID_ARRAY_TYPE = NULL;
161 MAGIC_VAR struct _magic_type *MAGIC_PTRINT_TYPE = NULL;
162 MAGIC_VAR struct _magic_type *MAGIC_PTRINT_ARRAY_TYPE = NULL;
163 
164 /* Magic annotations. */
165 MAGIC_VAR VOLATILE int MAGIC_CALL_ANNOTATION_VAR;
166 
167 /* Magic status variables. */
168 PUBLIC int magic_init_done = 0;
169 PUBLIC int magic_libcommon_active = 0;
170 PUBLIC int magic_lookup_nested_dsentries = 1;
171 PUBLIC int magic_allow_dead_dsentries = MAGIC_ALLOW_DEAD_DSENTRIES_DEFAULT;
172 PUBLIC int magic_ignore_dead_dsentries = 0;
173 PUBLIC int magic_mmap_dsentry_header_prot = PROT_READ | PROT_WRITE;
174 MAGIC_VAR int _magic_enabled = 0;
175 MAGIC_VAR int _magic_checkpoint_enabled = 0;
176 MAGIC_VAR int _magic_lazy_checkpoint_enabled = 0;
177 
178 /* Magic out-of-band dsentries. */
179 PUBLIC struct _magic_obdsentry _magic_obdsentries[MAGIC_MAX_OBDSENTRIES];
180 
181 /* Pool management data. */
182 PUBLIC struct _magic_mpdesc _magic_mpdescs[MAGIC_MAX_MEMPOOLS];
183 
184 /* Magic page size. */
185 PUBLIC unsigned long magic_sys_pagesize = 0;
186 
187 /* Private variables. */
188 PUBLIC int magic_type_str_print_style = MAGIC_TYPE_STR_PRINT_STYLE_DEFAULT;
189 PRIVATE THREAD_LOCAL const struct _magic_type* magic_nested_types[MAGIC_MAX_RECURSIVE_TYPES] = {0};
190 PRIVATE THREAD_LOCAL const struct _magic_type* magic_nested_types2[MAGIC_MAX_RECURSIVE_TYPES] = {0};
191 PRIVATE THREAD_LOCAL unsigned magic_level = 0;
192 PRIVATE THREAD_LOCAL unsigned magic_counter;
193 PRIVATE THREAD_LOCAL struct _magic_dsentry magic_dsentry_buff;
194 PRIVATE THREAD_LOCAL struct _magic_dfunction magic_dfunction_buff;
195 
196 /* Magic default stubs. */
197 PUBLIC struct _magic_type magic_default_type = {
198     0, "", NULL, 0, "", 0, 0, NULL, NULL, NULL, NULL, NULL, MAGIC_TYPE_OPAQUE, 0, 0, NULL
199 };
200 
201 PUBLIC struct _magic_dsentry magic_default_dsentry = {
202     MAGIC_DSENTRY_MNUM, /* magic_number */
203     "", /* parent_name */
204     { 0 }, /* name_ext_buff */
205     { 0, "", NULL, MAGIC_STATE_DYNAMIC, NULL, NULL }, /* sentry */
206     { 0, "", NULL, 0, "", 0, 0, NULL, NULL, NULL, NULL, NULL, MAGIC_TYPE_ARRAY, MAGIC_TYPE_IS_ROOT|MAGIC_TYPE_DYNAMIC, 0, NULL }, /* type */
207     { NULL }, /* type_array */
208 #if MAGIC_DSENTRY_ALLOW_PREV
209     NULL, /* prev */
210 #endif
211     NULL, /* next */
212     NULL, /* next_mpool */
213     NULL, /* next_mblock */
214 #ifndef __MINIX
215     NULL, /* next_sobject */
216     NULL, /* sobject_base_addr */
217 #endif
218     NULL, /* ext */
219     MAGIC_DSENTRY_MSTATE_ALIVE, /* magic_state */
220     { { 0, 0 } }, /* alloc_flags */
221     0 /* site_id */
222 };
223 
224 PUBLIC struct _magic_dfunction magic_default_dfunction = {
225     MAGIC_DFUNCTION_MNUM,
226     "",
227     { 0, "", NULL, MAGIC_STATE_DYNAMIC|MAGIC_STATE_TEXT|MAGIC_STATE_CONSTANT, NULL },
228     NULL,
229     NULL
230 };
231 
232 PUBLIC struct _magic_type magic_default_ret_addr_type = {
233     0, "", NULL, 0, "", sizeof(void*), 1, NULL, NULL, NULL, NULL, NULL, MAGIC_TYPE_POINTER, MAGIC_TYPE_IS_ROOT|MAGIC_TYPE_DYNAMIC|MAGIC_TYPE_INT_CAST|MAGIC_TYPE_STRICT_VALUE_SET, 0, NULL
234 };
235 
236 /* Magic code reentrant flag. */
237 PRIVATE int magic_reentrant = 1;
238 
239 /*===========================================================================*
240  *      	            _magic_vars_addr                        *
241  *===========================================================================*/
242 void *_magic_vars_addr()
243 {
244     return _magic_vars;
245 }
246 
247 /*===========================================================================*
248  *      	            _magic_vars_size                        *
249  *===========================================================================*/
250 size_t _magic_vars_size()
251 {
252     return sizeof(struct _magic_vars_t);
253 }
254 
255 /*===========================================================================*
256  *                          magic_null_printf                                *
257  *===========================================================================*/
258 PUBLIC int magic_null_printf(const char *format, ...)
259 {
260   return 0;
261 }
262 
263 #ifndef __MINIX
264 /*===========================================================================*
265  *                           magic_err_printf                                *
266  *===========================================================================*/
267 PUBLIC int magic_err_printf(const char *format, ...)
268 {
269   va_list va;
270   int ret;
271   va_start(va, format);
272   ret = vfprintf(stderr, format, va);
273   va_end(va);
274 
275   return ret;
276 }
277 #endif
278 
279 /*===========================================================================*
280  *                           magic_set_printf                                *
281  *===========================================================================*/
282 PUBLIC void magic_set_printf(printf_ptr_t func_ptr)
283 {
284    assert(func_ptr);
285    _magic_printf = func_ptr;
286 }
287 
288 /*===========================================================================*
289  *                           magic_get_printf                                *
290  *===========================================================================*/
291 PUBLIC printf_ptr_t magic_get_printf(void)
292 {
293    return _magic_printf;
294 }
295 
296 /*===========================================================================*
297  *                        magic_reentrant_enable                             *
298  *===========================================================================*/
299 PUBLIC void magic_reentrant_enable(void)
300 {
301     magic_reentrant = 1;
302 }
303 /*===========================================================================*
304  *                        magic_reentrant_disable                            *
305  *===========================================================================*/
306 PUBLIC void magic_reentrant_disable(void)
307 {
308     magic_reentrant = 0;
309 }
310 
311 /*===========================================================================*
312  *                          magic_assert_failed                              *
313  *===========================================================================*/
314 PUBLIC void __dead magic_assert_failed(const char *assertion, const char *file,
315     const char *function, const int line)
316 {
317     _magic_printf("Assertion '%s' failed in file %s, function %s(), line %d, pid %d\n",
318         assertion, file, function, line, getpid());
319     abort();
320 }
321 
322 /*===========================================================================*
323  *                         magic_get_sys_pagesize                            *
324  *===========================================================================*/
325 PUBLIC unsigned long magic_get_sys_pagesize()
326 {
327     if(!magic_sys_pagesize) {
328         magic_sys_pagesize = SYS_PAGESIZE;
329     }
330     return magic_sys_pagesize;
331 }
332 
333 /*===========================================================================*
334  *                   magic_dsentry_set_lock_primitives                       *
335  *===========================================================================*/
336 PUBLIC void magic_dsentry_set_lock_primitives(magic_lock_t lock,
337     magic_unlock_t unlock, void *lock_args, void *unlock_args)
338 {
339     assert(lock && unlock);
340     magic_dsentry_lock = lock;
341     magic_dsentry_unlock = unlock;
342     magic_dsentry_lock_args = lock_args;
343     magic_dsentry_unlock_args = unlock_args;
344 }
345 
346 /*===========================================================================*
347  *                   magic_dfunction_set_lock_primitives                     *
348  *===========================================================================*/
349 PUBLIC void magic_dfunction_set_lock_primitives(magic_lock_t lock,
350     magic_unlock_t unlock, void *lock_args, void *unlock_args)
351 {
352     assert(lock && unlock);
353     magic_dfunction_lock = lock;
354     magic_dfunction_unlock = unlock;
355     magic_dfunction_lock_args = lock_args;
356     magic_dfunction_unlock_args = unlock_args;
357 }
358 
359 /*===========================================================================*
360  *                    magic_dsodesc_set_lock_primitives                      *
361  *===========================================================================*/
362 PUBLIC void magic_dsodesc_set_lock_primitives(magic_lock_t lock,
363     magic_unlock_t unlock, void *lock_args, void *unlock_args)
364 {
365     assert(lock && unlock);
366     magic_dsodesc_lock = lock;
367     magic_dsodesc_unlock = unlock;
368     magic_dsodesc_lock_args = lock_args;
369     magic_dsodesc_unlock_args = unlock_args;
370 }
371 
372 /*===========================================================================*
373  *                 magic_mpdesc_set_lock_primitives                          *
374  *===========================================================================*/
375 PUBLIC void magic_mpdesc_set_lock_primitives(magic_lock_t lock,
376     magic_unlock_t unlock, void *lock_args, void *unlock_args)
377 {
378     assert(lock && unlock);
379     magic_mpdesc_lock = lock;
380     magic_mpdesc_unlock = unlock;
381     magic_mpdesc_lock_args = lock_args;
382     magic_mpdesc_unlock_args = unlock_args;
383 }
384 
385 /*===========================================================================*
386  *                            magic_types_init                               *
387  *===========================================================================*/
388 PRIVATE void magic_types_init()
389 {
390     static struct _magic_type _magic_void_ptr_type_buff;
391     static struct _magic_type _magic_void_array_type_buff;
392     static struct _magic_type *_magic_void_array_type_contained_types[1];
393     static struct _magic_type _magic_ptrint_type_buff;
394     static const char* _magic_ptrint_type_name = "ptrint";
395     static char _magic_ptrint_type_str_buff[8];
396     static struct _magic_type _magic_ptrint_array_type_buff;
397     static struct _magic_type *_magic_ptrint_array_type_contained_types[1];
398 
399     assert(MAGIC_VOID_PTR_TYPE);
400     assert(MAGIC_VOID_PTR_TYPE->size == sizeof(void*));
401     assert(MAGIC_VOID_TYPE->size == sizeof(char));
402 
403     MAGIC_VOID_PTR_INT_CAST_TYPE = &_magic_void_ptr_type_buff;
404     *MAGIC_VOID_PTR_INT_CAST_TYPE = *MAGIC_VOID_PTR_TYPE;
405     MAGIC_VOID_PTR_INT_CAST_TYPE->flags |= MAGIC_TYPE_INT_CAST;
406 
407     MAGIC_VOID_ARRAY_TYPE = &_magic_void_array_type_buff;
408     *MAGIC_VOID_ARRAY_TYPE = magic_default_type;
409     MAGIC_TYPE_ARRAY_CREATE_FROM_N(MAGIC_VOID_ARRAY_TYPE, MAGIC_VOID_TYPE,
410         _magic_void_array_type_contained_types, 1);
411 
412     MAGIC_PTRINT_TYPE = &_magic_ptrint_type_buff;
413     *MAGIC_PTRINT_TYPE = magic_default_type;
414     MAGIC_TYPE_INT_CREATE(MAGIC_PTRINT_TYPE, MAGIC_VOID_PTR_TYPE->size,
415         _magic_ptrint_type_name, _magic_ptrint_type_str_buff);
416 
417     MAGIC_PTRINT_ARRAY_TYPE = &_magic_ptrint_array_type_buff;
418     *MAGIC_PTRINT_ARRAY_TYPE = magic_default_type;
419     MAGIC_TYPE_ARRAY_CREATE_FROM_N(MAGIC_PTRINT_ARRAY_TYPE, MAGIC_PTRINT_TYPE,
420         _magic_ptrint_array_type_contained_types, 1);
421 }
422 
423 /*===========================================================================*
424  *                           magic_data_init                                 *
425  *===========================================================================*/
426 MAGIC_FUNC void magic_data_init(void)
427 {
428     MAGIC_FUNC_BODY();
429 }
430 
431 /*===========================================================================*
432  *                              magic_init                                   *
433  *===========================================================================*/
434 PUBLIC void magic_init(void)
435 {
436   unsigned i;
437 
438   if(magic_init_done || !_magic_enabled) {
439      return;
440   }
441 
442   /* Initialize magic data structures first. */
443   magic_data_init();
444 
445   /* Initialize asr support. */
446   magic_asr_init();
447 
448   /* Initialize eval support. */
449   magic_eval_init();
450 
451   /* Initialize magic obdsentries. */
452   memset(_magic_obdsentries, 0, MAGIC_MAX_OBDSENTRIES * sizeof(struct _magic_obdsentry));
453 
454   /* Initialize memory pool descriptors. */
455   for (i = 0; i < MAGIC_MAX_MEMPOOLS; i++) {
456       snprintf(_magic_mpdescs[i].name, sizeof(_magic_mpdescs[i].name), "%s%d%s", MAGIC_MEMPOOL_NAME_PREFIX, i, MAGIC_ALLOC_NAME_SUFFIX);
457   }
458 
459   /* Initialize special types. */
460   magic_types_init();
461 
462   /* Initialize magic ranges. */
463   magic_ranges_init();
464 
465   /* Perform stack-related initialization. */
466   magic_stack_init();
467 
468 #if MAGIC_MEM_USAGE_OUTPUT_CTL
469    /* Initialize CPU frequency - used for timestamp logging. */
470    magic_cycles_per_ns = util_time_get_cycles_per_ns(1);
471 #endif
472 
473   /* Checks. */
474   assert(magic_check_sentries() && "Bad sentries!");
475   assert(magic_check_dsentries_safe() && "Bad dsentries!");
476 
477   /* All done. */
478   magic_init_done = 1;
479 }
480 
481 /*===========================================================================*
482  *                          magic_do_check_dfunction                         *
483  *===========================================================================*/
484 PRIVATE INLINE int magic_do_check_dfunction(struct _magic_dfunction *dfunction, int flags)
485 {
486     struct _magic_function *function;
487     int is_mnum_ok, is_flags_ok, is_prev_ok, is_next_ok;
488     assert(dfunction && "NULL dfunction found!");
489     function = MAGIC_DFUNCTION_TO_FUNCTION(dfunction);
490     assert(function && "NULL function found!");
491     is_mnum_ok = MAGIC_DFUNCTION_MNUM_OK(dfunction);
492     if(!is_mnum_ok) {
493         return FALSE;
494     }
495     is_flags_ok = ((function->flags & flags) == flags) && (function->flags & MAGIC_STATE_DYNAMIC) && (MAGIC_STATE_REGION(function) & MAGIC_STATE_TEXT);
496     is_prev_ok = (dfunction->prev ? dfunction->prev->next && dfunction->prev->next == dfunction : dfunction == _magic_first_dfunction);
497     is_next_ok = (dfunction->next ? dfunction->next->prev && dfunction->next->prev == dfunction : dfunction == _magic_last_dfunction);
498     if(!is_flags_ok || !is_prev_ok || !is_next_ok) {
499         _magic_printf("magic_do_check_dfunction: bad dfunction, checks: %d %d %d\n", is_flags_ok, is_prev_ok, is_next_ok);
500         MAGIC_DFUNCTION_PRINT(dfunction, MAGIC_EXPAND_TYPE_STR);
501         _magic_printf("\n");
502         return FALSE;
503     }
504     return TRUE;
505 }
506 
507 /*===========================================================================*
508  *                            magic_check_dfunction                          *
509  *===========================================================================*/
510 PUBLIC int magic_check_dfunction(struct _magic_dfunction *dfunction, int flags)
511 {
512     int check;
513     check = magic_do_check_dfunction(dfunction, flags);
514     if(!check) {
515         return FALSE;
516     }
517 
518 #if MAGIC_CHECK_LEVEL == 2
519     check = magic_check_dfunctions();
520     if(!check) {
521         _magic_printf("magic_check_dfunction: bad other dfunction\n");
522         return FALSE;
523     }
524 #endif
525 
526     return TRUE;
527 }
528 
529 /*===========================================================================*
530  *                          magic_check_dfunctions                           *
531  *===========================================================================*/
532 PUBLIC int magic_check_dfunctions()
533 {
534     int magic_dfunctions_found = 0;
535     struct _magic_dfunction* dfunction = NULL;
536     struct _magic_function* function = NULL;
537     int ret, check = TRUE;
538 
539     MAGIC_DFUNCTION_FUNC_ITER(_magic_first_dfunction, dfunction, function,
540         ret = magic_do_check_dfunction(dfunction, 0);
541         if(ret == FALSE) {
542             check = FALSE;
543         }
544         magic_dfunctions_found++;
545     );
546     if(magic_dfunctions_found != _magic_dfunctions_num) {
547         _magic_printf("magic_check_dfunctions: magic_dfunctions_found=%d != _magic_dfunctions_num%d\n", magic_dfunctions_found, _magic_dfunctions_num);
548         check = FALSE;
549     }
550     if(dfunction != _magic_last_dfunction) {
551         _magic_printf("magic_check_dfunctions: dfunction=0x%08x != _magic_last_dfunction=0x%08x\n", dfunction, _magic_last_dfunction);
552         check = FALSE;
553     }
554     return check;
555 }
556 
557 /*===========================================================================*
558  *                       magic_check_dfunctions_safe                         *
559  *===========================================================================*/
560 PUBLIC int magic_check_dfunctions_safe()
561 {
562     int ret;
563     MAGIC_DFUNCTION_LOCK();
564     ret = magic_check_dfunctions();
565     MAGIC_DFUNCTION_UNLOCK();
566     return ret;
567 }
568 
569 /*===========================================================================*
570  *                         magic_print_dfunction                             *
571  *===========================================================================*/
572 PUBLIC void magic_print_dfunction(struct _magic_dfunction *dfunction)
573 {
574     MAGIC_DFUNCTION_PRINT(dfunction, MAGIC_EXPAND_TYPE_STR);
575 }
576 
577 /*===========================================================================*
578  *                         magic_print_dfunctions                            *
579  *===========================================================================*/
580 PUBLIC void magic_print_dfunctions()
581 {
582     int magic_dfunctions_found = 0;
583     struct _magic_dfunction* dfunction;
584     struct _magic_function* function;
585 
586     _magic_printf("magic_print_dfunctions: Printing %d functions\n", _magic_dfunctions_num);
587     MAGIC_DFUNCTION_FUNC_ITER(_magic_first_dfunction, dfunction, function,
588         MAGIC_DFUNCTION_PRINT(dfunction, MAGIC_EXPAND_TYPE_STR);
589         _magic_printf("\n");
590         magic_dfunctions_found++;
591     );
592     if(magic_dfunctions_found != _magic_dfunctions_num) {
593         _magic_printf("magic_print_dfunctions: magic_dfunctions_found=%d != _magic_dfunctions_num%d\n", magic_dfunctions_found, _magic_dfunctions_num);
594     }
595 }
596 
597 /*===========================================================================*
598  *                      magic_print_dfunctions_safe                          *
599  *===========================================================================*/
600 PUBLIC void magic_print_dfunctions_safe()
601 {
602     MAGIC_DFUNCTION_LOCK();
603     magic_print_dfunctions();
604     MAGIC_DFUNCTION_UNLOCK();
605 }
606 
607 /*===========================================================================*
608  *                             magic_copy_dfunction                          *
609  *===========================================================================*/
610 PUBLIC void magic_copy_dfunction(struct _magic_dfunction *dfunction,
611     struct _magic_dfunction *dst_dfunction)
612 {
613     /* Raw copy. */
614     memcpy(dst_dfunction, dfunction, sizeof(struct _magic_dfunction));
615 }
616 
617 /*===========================================================================*
618  *                          magic_print_dsindex                              *
619  *===========================================================================*/
620 PUBLIC void magic_print_dsindex(struct _magic_dsindex *dsindex)
621 {
622     MAGIC_DSINDEX_PRINT(dsindex, MAGIC_EXPAND_TYPE_STR);
623 }
624 
625 /*===========================================================================*
626  *                         magic_print_dsindexes                             *
627  *===========================================================================*/
628 PUBLIC void magic_print_dsindexes()
629 {
630     int i;
631     struct _magic_dsindex* dsindex;
632 
633     _magic_printf("magic_print_dsindexes: Printing %d indexes\n", _magic_dsindexes_num);
634     for(i=0;i<_magic_dsindexes_num;i++) {
635         dsindex = &_magic_dsindexes[i];
636         MAGIC_DSINDEX_PRINT(dsindex, MAGIC_EXPAND_TYPE_STR);
637         _magic_printf("\n");
638     }
639 }
640 
641 /*===========================================================================*
642  *                           magic_do_check_dsentry                          *
643  *===========================================================================*/
644 PRIVATE INLINE int magic_do_check_dsentry(struct _magic_dsentry *dsentry, int flags)
645 {
646     struct _magic_sentry *sentry;
647     int is_mnum_ok, is_mstate_ok, is_flags_ok;
648     assert(dsentry && "NULL dsentry found!");
649     sentry = MAGIC_DSENTRY_TO_SENTRY(dsentry);
650     assert(sentry && "NULL sentry found!");
651     is_mnum_ok = MAGIC_DSENTRY_MNUM_OK(dsentry);
652     if(!is_mnum_ok) {
653         _magic_printf("magic_do_check_dsentry: bad ~mnum %08x\n", ~(dsentry->magic_number));
654         return FALSE;
655     }
656     is_mstate_ok = MAGIC_DSENTRY_MSTATE_OK(dsentry);
657     is_flags_ok = ((sentry->flags & flags) == flags) && (sentry->flags & MAGIC_STATE_DYNAMIC) && MAGIC_STATE_REGION(sentry);
658     if(!is_mstate_ok || !is_flags_ok) {
659         _magic_printf("magic_do_check_dsentry: bad dsentry, checks: %d %d\n", is_mstate_ok, is_flags_ok);
660         MAGIC_DSENTRY_PRINT(dsentry, MAGIC_EXPAND_TYPE_STR);
661         _magic_printf("\n");
662         return FALSE;
663     }
664     return TRUE;
665 }
666 
667 /*===========================================================================*
668  *                             magic_check_dsentry                           *
669  *===========================================================================*/
670 PUBLIC int magic_check_dsentry(struct _magic_dsentry *dsentry, int flags)
671 {
672 #if MAGIC_CHECK_LEVEL >= 1
673     int check;
674     check = magic_do_check_dsentry(dsentry, flags);
675     if(!check) {
676         return FALSE;
677     }
678 #endif
679 
680 #if MAGIC_CHECK_LEVEL == 2
681     check = magic_check_dsentries();
682     if(!check) {
683         _magic_printf("magic_check_dsentry: bad other dsentry\n");
684         return FALSE;
685     }
686 #endif
687 
688     return TRUE;
689 }
690 
691 /*===========================================================================*
692  *                          magic_check_dsentries                            *
693  *===========================================================================*/
694 PUBLIC int magic_check_dsentries()
695 {
696     struct _magic_dsentry *prev_dsentry, *dsentry;
697     struct _magic_sentry* sentry;
698     int ret, check = TRUE;
699 
700     MAGIC_DSENTRY_NESTED_ITER(_magic_first_dsentry, prev_dsentry, dsentry, sentry,
701         ret = magic_do_check_dsentry(dsentry, 0);
702         if(ret == FALSE) {
703             check = FALSE;
704         }
705     );
706     return check;
707 }
708 
709 /*===========================================================================*
710  *                       magic_check_dsentries_safe                          *
711  *===========================================================================*/
712 PUBLIC int magic_check_dsentries_safe()
713 {
714     int ret;
715     MAGIC_DSENTRY_LOCK();
716     ret = magic_check_dsentries();
717     MAGIC_DSENTRY_UNLOCK();
718     return ret;
719 }
720 
721 /*===========================================================================*
722  *                          magic_print_dsentry                              *
723  *===========================================================================*/
724 PUBLIC void magic_print_dsentry(struct _magic_dsentry *dsentry)
725 {
726     MAGIC_DSENTRY_PRINT(dsentry, MAGIC_EXPAND_TYPE_STR);
727 }
728 
729 /*===========================================================================*
730  *                         magic_print_dsentries                             *
731  *===========================================================================*/
732 PUBLIC void magic_print_dsentries()
733 {
734     struct _magic_dsentry *prev_dsentry, *dsentry;
735     struct _magic_sentry* sentry;
736     int magic_dsentries_num = 0;
737 
738     _magic_printf("magic_print_dsentries: Printing entries\n");
739     MAGIC_DSENTRY_NESTED_ITER(_magic_first_dsentry, prev_dsentry, dsentry, sentry,
740         MAGIC_DSENTRY_PRINT(dsentry, MAGIC_EXPAND_TYPE_STR);
741         _magic_printf("\n");
742         magic_dsentries_num++;
743     );
744     _magic_printf("magic_print_dsentries: %d entries found\n", magic_dsentries_num);
745 }
746 
747 /*===========================================================================*
748  *                       magic_print_dsentries_safe                          *
749  *===========================================================================*/
750 PUBLIC void magic_print_dsentries_safe()
751 {
752     MAGIC_DSENTRY_LOCK();
753     magic_print_dsentries();
754     MAGIC_DSENTRY_UNLOCK();
755 }
756 
757 /*===========================================================================*
758  *                             magic_copy_dsentry                            *
759  *===========================================================================*/
760 PUBLIC void magic_copy_dsentry(struct _magic_dsentry *dsentry,
761     struct _magic_dsentry *dst_dsentry)
762 {
763     struct _magic_sentry *sentry;
764 
765     /* Raw copy. */
766     memcpy(dst_dsentry, dsentry, sizeof(struct _magic_dsentry));
767 
768     /* Adjust pointers. */
769     sentry = MAGIC_DSENTRY_TO_SENTRY(dsentry);
770     if(sentry->type == &dsentry->type) {
771         MAGIC_DSENTRY_TO_SENTRY(dst_dsentry)->type = &dst_dsentry->type;
772         if(sentry->type->contained_types == dsentry->type_array) {
773             MAGIC_DSENTRY_TO_SENTRY(dst_dsentry)->type->contained_types = dst_dsentry->type_array;
774         }
775     }
776 }
777 
778 /*===========================================================================*
779  *                         magic_print_sodesc                                *
780  *===========================================================================*/
781 PUBLIC void magic_print_sodesc(struct _magic_sodesc *sodesc)
782 {
783     MAGIC_SODESC_PRINT(sodesc);
784 }
785 
786 /*===========================================================================*
787  *                         magic_print_sodescs                               *
788  *===========================================================================*/
789 PUBLIC void magic_print_sodescs()
790 {
791     int magic_sodescs_found = 0;
792     struct _magic_sodesc* sodesc;
793 
794     _magic_printf("magic_print_sodescs: Printing %d sodescs\n", _magic_sodescs_num);
795     MAGIC_SODESC_ITER(_magic_first_sodesc, sodesc,
796         MAGIC_SODESC_PRINT(sodesc);
797         _magic_printf("\n");
798         magic_sodescs_found++;
799     );
800     if(magic_sodescs_found != _magic_sodescs_num) {
801         _magic_printf("magic_print_sodescs: magic_sodescs_found=%d != _magic_sodescs_num%d\n", magic_sodescs_found, _magic_sodescs_num);
802     }
803 }
804 
805 /*===========================================================================*
806  *                         magic_print_dsodesc                               *
807  *===========================================================================*/
808 PUBLIC void magic_print_dsodesc(struct _magic_dsodesc *dsodesc)
809 {
810     MAGIC_DSODESC_PRINT(dsodesc);
811 }
812 
813 /*===========================================================================*
814  *                         magic_print_dsodescs                              *
815  *===========================================================================*/
816 PUBLIC void magic_print_dsodescs()
817 {
818     int magic_dsodescs_found = 0;
819     struct _magic_dsodesc* dsodesc;
820 
821     _magic_printf("magic_print_dsodescs: Printing %d dsodescs\n", _magic_dsodescs_num);
822     MAGIC_DSODESC_ITER(_magic_first_dsodesc, dsodesc,
823         MAGIC_DSODESC_PRINT(dsodesc);
824         _magic_printf("\n");
825         magic_dsodescs_found++;
826     );
827     if(magic_dsodescs_found != _magic_dsodescs_num) {
828         _magic_printf("magic_print_dsodescs: magic_dsodescs_found=%d != _magic_dsodescs_num%d\n", magic_dsodescs_found, _magic_dsodescs_num);
829     }
830 }
831 
832 /*===========================================================================*
833  *                       magic_print_dsodescs_safe                           *
834  *===========================================================================*/
835 PUBLIC void magic_print_dsodescs_safe()
836 {
837     MAGIC_DSODESC_LOCK();
838     magic_print_dsodescs();
839     MAGIC_DSODESC_UNLOCK();
840 }
841 
842 /*===========================================================================*
843  *                           magic_print_sections                            *
844  *===========================================================================*/
845 PUBLIC void magic_print_sections(void)
846 {
847     _magic_printf("magic_print_sections: data=[0x%08x;0x%08x], ro=[0x%08x;0x%08x], text=[0x%08x;0x%08x], st_data=[0x%08x;0x%08x], st_ro=[0x%08x;0x%08x], st_text=[0x%08x;0x%08x]",
848             (unsigned long) MAGIC_DATA_SECTION_START, (unsigned long) MAGIC_DATA_SECTION_END,
849             (unsigned long) MAGIC_DATA_RO_SECTION_START, (unsigned long) MAGIC_DATA_RO_SECTION_END,
850             (unsigned long) MAGIC_TEXT_SECTION_START, (unsigned long) MAGIC_TEXT_SECTION_END,
851             (unsigned long) MAGIC_ST_DATA_SECTION_START, (unsigned long) MAGIC_ST_DATA_SECTION_END,
852             (unsigned long) MAGIC_ST_DATA_RO_SECTION_START, (unsigned long) MAGIC_ST_DATA_RO_SECTION_END,
853             (unsigned long) MAGIC_ST_TEXT_SECTION_START, (unsigned long) MAGIC_ST_TEXT_SECTION_END);
854 }
855 
856 /*===========================================================================*
857  *                   magic_mempool_sentry_lookup_by_addr                     *
858  *===========================================================================*/
859 PUBLIC struct _magic_sentry* magic_mempool_sentry_lookup_by_range(void *addr, struct _magic_dsentry *dsentry_buff)
860 {
861     struct _magic_dsentry *prev_dsentry, *dsentry;
862     struct _magic_sentry* sentry;
863     struct _magic_sentry* entry = NULL;
864     void *start_address, *end_address;
865 
866     MAGIC_DSENTRY_LOCK();
867     MAGIC_DSENTRY_MEMPOOL_ALIVE_ITER(_magic_first_mempool_dsentry, prev_dsentry, dsentry, sentry,
868         start_address = sentry->address;
869         end_address = (void*) (((char*)sentry->address) + sentry->type->size - 1);
870         if(MAGIC_ADDR_IS_WITHIN(addr, start_address, end_address)) {
871             if(dsentry_buff) {
872                 magic_copy_dsentry(dsentry, dsentry_buff);
873                 entry = MAGIC_DSENTRY_TO_SENTRY(dsentry_buff);
874             }
875             else {
876                 entry = sentry;
877             }
878             break;
879         }
880     );
881     MAGIC_DSENTRY_UNLOCK();
882 
883     return entry;
884 }
885 
886 /*===========================================================================*
887  *                   magic_dsindex_lookup_by_name                            *
888  *===========================================================================*/
889 PUBLIC struct _magic_dsindex*
890 magic_dsindex_lookup_by_name(const char *parent_name, const char *name)
891 {
892     int i;
893     struct _magic_dsindex* index = NULL;
894     assert(parent_name && name);
895 
896     /* Scan all the indexes and return the one matching the provided names. */
897     for(i=0;i<_magic_dsindexes_num;i++) {
898         if(!strcmp(_magic_dsindexes[i].parent_name, parent_name)
899             && !strcmp(_magic_dsindexes[i].name, name)) {
900             index = &_magic_dsindexes[i];
901             break;
902         }
903     }
904 
905     return index;
906 }
907 
908 /*===========================================================================*
909  *                          magic_dsentry_prev_lookup                        *
910  *===========================================================================*/
911 PUBLIC struct _magic_dsentry* magic_dsentry_prev_lookup(struct _magic_dsentry* dsentry)
912 {
913     struct _magic_dsentry *prev_dsentry, *it_dsentry;
914     struct _magic_sentry *sentry;
915     int found = 0;
916 
917 #if MAGIC_DSENTRY_ALLOW_PREV
918     return dsentry->prev;
919 #else
920     MAGIC_DSENTRY_ITER(_magic_first_dsentry, prev_dsentry, it_dsentry, sentry,
921         if(dsentry == it_dsentry) {
922             found = 1;
923             break;
924         }
925     );
926     if(!found) {
927         return (struct _magic_dsentry*) MAGIC_ENOPTR;
928     }
929     return prev_dsentry;
930 #endif
931 }
932 
933 /*===========================================================================*
934  *                      magic_mempool_dsentry_prev_lookup                    *
935  *===========================================================================*/
936 PUBLIC struct _magic_dsentry* magic_mempool_dsentry_prev_lookup(struct _magic_dsentry* dsentry)
937 {
938     struct _magic_dsentry *prev_dsentry, *it_dsentry;
939     struct _magic_sentry *sentry;
940     int found = 0;
941 
942     MAGIC_DSENTRY_MEMPOOL_ITER(_magic_first_mempool_dsentry, prev_dsentry, it_dsentry, sentry,
943         if(dsentry == it_dsentry) {
944             found = 1;
945             break;
946         }
947     );
948     if(!found) {
949         return (struct _magic_dsentry*) MAGIC_ENOPTR;
950     }
951     return prev_dsentry;
952 }
953 
954 /*===========================================================================*
955  *                         magic_function_lookup_by_id                       *
956  *===========================================================================*/
957 PUBLIC struct _magic_function* magic_function_lookup_by_id(_magic_id_t id,
958     struct _magic_dfunction *dfunction_buff)
959 {
960     struct _magic_function* entry = NULL;
961     struct _magic_function* function;
962     struct _magic_dfunction* dfunction;
963 
964     if(id <= 0) {
965         return NULL;
966     }
967 
968     /* O(1) ID lookup for functions. */
969 #if MAGIC_LOOKUP_FUNCTION
970     if((int)id <= _magic_functions_num) {
971         return &_magic_functions[id - 1];
972     }
973 #endif
974 
975     /* O(N) ID lookup for dfunctions. */
976 #if MAGIC_LOOKUP_DFUNCTION
977     MAGIC_DFUNCTION_LOCK();
978     MAGIC_DFUNCTION_FUNC_ITER(_magic_first_dfunction, dfunction, function,
979         if(function->id == id) {
980             if(dfunction_buff) {
981                 magic_copy_dfunction(dfunction, dfunction_buff);
982                 entry = MAGIC_DFUNCTION_TO_FUNCTION(dfunction_buff);
983             }
984             else {
985                 entry = function;
986             }
987             break;
988         }
989     );
990     MAGIC_DFUNCTION_UNLOCK();
991 #endif
992 
993     return entry;
994 }
995 
996 /*===========================================================================*
997  *                        magic_function_lookup_by_addr                      *
998  *===========================================================================*/
999 PUBLIC struct _magic_function* magic_function_lookup_by_addr(void *addr,
1000     struct _magic_dfunction *dfunction_buff)
1001 {
1002     int i;
1003     struct _magic_function *entry = NULL;
1004     struct _magic_function *function;
1005     struct _magic_dfunction *dfunction;
1006 
1007 #if MAGIC_LOOKUP_FUNCTION_ALLOW_ADDR_HASH
1008     if (magic_function_hash_head) {
1009         return magic_function_lookup_by_addr_hash(addr, dfunction_buff);
1010     }
1011 #endif
1012 
1013     /* Scan all the entries and return the one matching the provided address. */
1014 #if MAGIC_LOOKUP_FUNCTION
1015     if (MAGIC_ADDR_IS_IN_RANGE(addr, magic_function_range)) {
1016         for (i = 0 ; i < _magic_functions_num ; i++) {
1017             if (_magic_functions[i].address == addr) {
1018                 entry = &_magic_functions[i];
1019                 break;
1020             }
1021         }
1022     }
1023 #endif
1024 
1025 #if MAGIC_LOOKUP_DFUNCTION
1026     MAGIC_DFUNCTION_LOCK();
1027     if(!MAGIC_ADDR_LOOKUP_USE_DFUNCTION_RANGES || magic_range_is_dfunction(addr)) {
1028         MAGIC_DFUNCTION_FUNC_ITER(_magic_first_dfunction, dfunction, function,
1029             if(function->address == addr) {
1030                 if(dfunction_buff) {
1031                     magic_copy_dfunction(dfunction, dfunction_buff);
1032                     entry = MAGIC_DFUNCTION_TO_FUNCTION(dfunction_buff);
1033                 }
1034                 else {
1035                     entry = function;
1036                 }
1037                 break;
1038             }
1039         );
1040     }
1041     MAGIC_DFUNCTION_UNLOCK();
1042 #endif
1043 
1044     return entry;
1045 }
1046 
1047 /*===========================================================================*
1048  *                       magic_function_lookup_by_name                       *
1049  *===========================================================================*/
1050 PUBLIC struct _magic_function*
1051 magic_function_lookup_by_name(const char *parent_name, const char *name)
1052 {
1053     int i;
1054     struct _magic_function* entry = NULL;
1055 
1056     /* Scan all the entries and return the one matching the provided name(s). */
1057 #if MAGIC_LOOKUP_FUNCTION
1058     for (i = 0 ; i < _magic_functions_num ; i++) {
1059         if (!strcmp(_magic_functions[i].name, name)) {
1060             if (!parent_name || !strcmp(MAGIC_FUNCTION_PARENT(&_magic_functions[i]), parent_name)) {
1061                 entry = &_magic_functions[i];
1062                 break;
1063             }
1064         }
1065     }
1066 #endif
1067 
1068     return entry;
1069 }
1070 
1071 /*===========================================================================*
1072  *                         magic_function_hash_insert                        *
1073  *===========================================================================*/
1074 PRIVATE void magic_function_hash_insert(struct _magic_function_hash **head,
1075     struct _magic_function_hash *elem)
1076 {
1077     if (head != NULL) {
1078         struct _magic_function_hash *tmp;
1079         HASH_FIND_PTR(*head, &elem->key, tmp);
1080         /* Skip inserting this function if an identical one already exists. */
1081         if (tmp)
1082             return;
1083     }
1084 /*
1085  * **** START UTHASH SPECIFIC DEFINITIONS ****
1086  */
1087 #undef uthash_malloc
1088 #undef uthash_free
1089 #define uthash_malloc(size)             magic_function_hash_alloc(size)
1090 #define uthash_free(addr, size)         magic_function_hash_dealloc(addr, size)
1091 /*
1092  * Since we have a limited buffer, we need to stop bucket expansion when
1093  * reaching a certain limit.
1094  */
1095 #undef uthash_expand_fyi
1096 #define uthash_expand_fyi(tbl)                                                 \
1097     do {                                                                       \
1098         if (tbl->num_buckets == MAGIC_FUNCTION_ADDR_EST_MAX_BUCKETS) {         \
1099             _magic_printf("Warning! Function address hash maximum bucket "     \
1100                 "number reached! Consider increasing "                         \
1101                 "MAGIC_FUNCTION_ADDR_EST_MAX_BUCKETS, unless you are "         \
1102                 "comfortable with the current performance.\n");                \
1103             tbl->noexpand = 1;                                                 \
1104         }                                                                      \
1105     } while(0);
1106 /*
1107  * **** FINISH UTHASH SPECIFIC DEFINITIONS ****
1108  */
1109     HASH_ADD_PTR(*head, key, elem);
1110 /*
1111  * **** START UTHASH DEFINITION REMOVAL ****
1112  */
1113 #undef uthash_malloc
1114 #undef uthash_free
1115 #undef uthash_expand_fyi
1116 /*
1117  * **** FINISH UTHASH DEFINITION REMOVAL ****
1118  */
1119 }
1120 
1121 /*===========================================================================*
1122  *                         magic_function_hash_build                         *
1123  *===========================================================================*/
1124 PUBLIC void magic_function_hash_build(void *buff, size_t buff_size)
1125 {
1126     /*
1127      * XXX:
1128      * Warning: this implementation is thread unsafe and also makes
1129      * magic_function_lookup_by_addr thread unsafe!
1130      */
1131     int i;
1132     struct _magic_dfunction *dfunction;
1133     struct _magic_function *function;
1134     struct _magic_function_hash *function_hash, *head;
1135 
1136     assert(buff && buff_size > 0);
1137     magic_function_hash_buff = buff;
1138     magic_function_hash_buff_offset = 0;
1139     magic_function_hash_buff_size = buff_size;
1140 
1141     head = NULL;
1142 
1143     /* Add all the functions to the hash. */
1144 #if MAGIC_LOOKUP_FUNCTION
1145     for(i = 0 ; i < _magic_functions_num ; i++) {
1146         function_hash = (struct _magic_function_hash *)
1147             magic_function_hash_alloc(sizeof(struct _magic_function_hash));
1148         function = &_magic_functions[i];
1149         MAGIC_FUNCTION_TO_HASH_EL(function, function_hash);
1150         magic_function_hash_insert(&head, function_hash);
1151     }
1152 #endif
1153 
1154     /* Add all the dfunctions to the hash. */
1155 #if MAGIC_LOOKUP_DFUNCTION
1156     MAGIC_DFUNCTION_LOCK();
1157     MAGIC_DFUNCTION_FUNC_ITER(_magic_first_dfunction, dfunction, function,
1158         function_hash = (struct _magic_function_hash *)
1159             magic_function_hash_alloc(sizeof(struct _magic_function_hash));
1160         MAGIC_DFUNCTION_TO_HASH_EL(dfunction, function, function_hash);
1161         magic_function_hash_insert(&head, function_hash);
1162     );
1163     MAGIC_DFUNCTION_UNLOCK();
1164 #endif
1165     magic_function_hash_head = (void *)head;
1166     assert(magic_function_hash_head);
1167 }
1168 
1169 /*===========================================================================*
1170  *                        magic_function_hash_destroy                        *
1171  *===========================================================================*/
1172 PUBLIC void magic_function_hash_destroy(void)
1173 {
1174     magic_function_hash_buff = NULL;
1175     magic_function_hash_buff_offset = 0;
1176     magic_function_hash_buff_size = 0;
1177     magic_function_hash_head = NULL;
1178 }
1179 
1180 /*===========================================================================*
1181  *                    magic_function_hash_estimate_buff_size                 *
1182  *===========================================================================*/
1183 PUBLIC size_t magic_function_hash_estimate_buff_size(int functions_num)
1184 {
1185     if (functions_num == 0) {
1186         functions_num = _magic_dfunctions_num;
1187         functions_num += _magic_functions_num;
1188     }
1189 
1190     return (functions_num * sizeof(struct _magic_function_hash)) +
1191         MAGIC_FUNCTION_ADDR_HASH_OVERHEAD;
1192 }
1193 
1194 /*===========================================================================*
1195  *                           magic_function_hash_alloc                       *
1196  *===========================================================================*/
1197 PUBLIC void* magic_function_hash_alloc(size_t size)
1198 {
1199     void *addr;
1200 
1201     assert(magic_function_hash_buff);
1202     assert(magic_function_hash_buff_offset + size <=
1203         magic_function_hash_buff_size);
1204 
1205     addr = (char*) magic_function_hash_buff + magic_function_hash_buff_offset;
1206     magic_function_hash_buff_offset += size;
1207 
1208     return addr;
1209 }
1210 
1211 /*===========================================================================*
1212  *                          magic_function_hash_dealloc                      *
1213  *===========================================================================*/
1214 PUBLIC void magic_function_hash_dealloc(UNUSED(void *object), UNUSED(size_t sz))
1215 {
1216     return;
1217 }
1218 
1219 /*===========================================================================*
1220  *                      magic_function_lookup_by_addr_hash                   *
1221  *===========================================================================*/
1222 PUBLIC struct _magic_function *magic_function_lookup_by_addr_hash(
1223     void *addr, struct _magic_dfunction *dfunction_buff)
1224 {
1225     /*
1226      * Warning: this implementation is thread unsafe!
1227      */
1228     struct _magic_function_hash *res, *head;
1229     head = (struct _magic_function_hash *) magic_function_hash_head;
1230 
1231     HASH_FIND_PTR(head, &addr, res);
1232     if (res == NULL)
1233         return NULL;
1234 
1235     if (MAGIC_STATE_FLAG(res->function, MAGIC_STATE_DYNAMIC) &&
1236         dfunction_buff != NULL) {
1237         magic_copy_dfunction(MAGIC_DFUNCTION_FROM_FUNCTION(res->function),
1238             dfunction_buff);
1239     }
1240 
1241     return res->function;
1242 }
1243 
1244 /*===========================================================================*
1245  *                         magic_type_lookup_by_name                         *
1246  *===========================================================================*/
1247 PUBLIC struct _magic_type* magic_type_lookup_by_name(const char *name)
1248 {
1249     int i;
1250     unsigned int j;
1251     struct _magic_type* entry = NULL;
1252 
1253     /* Scan all the entries and return the one matching the provided name. */
1254 #if MAGIC_LOOKUP_TYPE
1255     for (i = 0 ; i < _magic_types_num ; i++) {
1256         if (!strcmp(_magic_types[i].name, name)) {
1257             entry = &_magic_types[i];
1258             break;
1259         }
1260         if (_magic_types[i].names) {
1261             for (j = 0 ; j < _magic_types[i].num_names ; j++) {
1262                 if (!strcmp(_magic_types[i].names[j], name)) {
1263                     entry = &_magic_types[i];
1264                     break;
1265                 }
1266             }
1267             if (entry) {
1268                 break;
1269             }
1270         }
1271     }
1272 #endif
1273 
1274     return entry;
1275 }
1276 
1277 /*===========================================================================*
1278  *                      magic_dsodesc_lookup_by_handle                       *
1279  *===========================================================================*/
1280 PUBLIC struct _magic_dsodesc* magic_dsodesc_lookup_by_handle(void *handle)
1281 {
1282     struct _magic_dsodesc* desc = NULL;
1283     struct _magic_dsodesc* dsodesc;
1284 
1285     /*
1286      * Scan all the descriptors and return the one matching the provided handle.
1287      * Note that there is no locking here. The caller has to explicitely call
1288      * MAGIC_DSODESC_LOCK/UNLOCK before/after invoking this function.
1289      */
1290     MAGIC_DSODESC_ITER(_magic_first_dsodesc, dsodesc,
1291         if(dsodesc->handle == handle) {
1292             desc = dsodesc;
1293             break;
1294         }
1295     );
1296 
1297     return desc;
1298 }
1299 
1300 /*===========================================================================*
1301  *                         magic_print_function                              *
1302  *===========================================================================*/
1303 PUBLIC void magic_print_function(struct _magic_function *function)
1304 {
1305     MAGIC_FUNCTION_PRINT(function, MAGIC_EXPAND_TYPE_STR);
1306 }
1307 
1308 /*===========================================================================*
1309  *                         magic_print_functions                             *
1310  *===========================================================================*/
1311 PUBLIC void magic_print_functions()
1312 {
1313     int i;
1314     struct _magic_function* function;
1315 
1316     _magic_printf("magic_print_functions: Printing %d entries\n", _magic_functions_num);
1317     for(i=0;i<_magic_functions_num;i++) {
1318         function = &_magic_functions[i];
1319         MAGIC_FUNCTION_PRINT(function, MAGIC_EXPAND_TYPE_STR);
1320         _magic_printf("\n");
1321     }
1322 }
1323 
1324 /*===========================================================================*
1325  *                           magic_print_type                                *
1326  *===========================================================================*/
1327 PUBLIC void magic_print_type(const struct _magic_type* type)
1328 {
1329     MAGIC_TYPE_PRINT(type, MAGIC_EXPAND_TYPE_STR);
1330 }
1331 
1332 /*===========================================================================*
1333  *                           magic_print_types                               *
1334  *===========================================================================*/
1335 PUBLIC void magic_print_types()
1336 {
1337     int i;
1338     struct _magic_type* type;
1339 
1340     _magic_printf("magic_print_types: Printing %d types\n", _magic_types_num);
1341     for(i=0;i<_magic_types_num;i++) {
1342         type = &_magic_types[i];
1343         MAGIC_TYPE_PRINT(type, MAGIC_EXPAND_TYPE_STR);
1344         _magic_printf("\n");
1345     }
1346 }
1347 
1348 /*===========================================================================*
1349  *                      magic_type_str_set_print_style                       *
1350  *===========================================================================*/
1351 PUBLIC void magic_type_str_set_print_style(const int style)
1352 {
1353     magic_type_str_print_style = style;
1354 }
1355 
1356 /*===========================================================================*
1357  *                      magic_type_str_get_print_style                       *
1358  *===========================================================================*/
1359 PUBLIC int magic_type_str_get_print_style()
1360 {
1361     return magic_type_str_print_style;
1362 }
1363 
1364 /*===========================================================================*
1365  *                       magic_type_get_nesting_level                        *
1366  *===========================================================================*/
1367 PRIVATE INLINE int magic_type_get_nesting_level(const struct _magic_type* type,
1368     int level)
1369 {
1370     int i;
1371     int nesting_level = -1;
1372 
1373     for(i=0;i<level;i++) {
1374         if(magic_nested_types[i] == type) {
1375             nesting_level = i;
1376             break;
1377         }
1378     }
1379 
1380     return nesting_level;
1381 }
1382 
1383 /*===========================================================================*
1384  *                            magic_type_str_print                           *
1385  *===========================================================================*/
1386 PUBLIC void magic_type_str_print(const struct _magic_type* type)
1387 {
1388     int num_contained_types;
1389     int is_empty_str = !type->type_str || !strcmp(type->type_str, "");
1390     int type_has_name = type->name && strcmp(type->name, "");
1391     int print_multi_names = (magic_type_str_print_style & MAGIC_TYPE_STR_PRINT_MULTI_NAMES) && MAGIC_TYPE_HAS_MULTI_NAMES(type);
1392     int print_ptr_name = (magic_type_str_print_style & MAGIC_TYPE_STR_PRINT_MULTI_NAMES) && !MAGIC_TYPE_HAS_MULTI_NAMES(type) && type_has_name;
1393     assert(magic_level < MAGIC_MAX_RECURSIVE_TYPES);
1394 
1395     if(magic_level == 0) {
1396         magic_counter = 0;
1397     }
1398     else if(magic_counter >= MAGIC_TYPE_STR_PRINT_MAX) {
1399         _magic_printf("%%");
1400         return;
1401     }
1402     else if(magic_level >= MAGIC_TYPE_STR_PRINT_MAX_LEVEL) {
1403         _magic_printf("%%");
1404         return;
1405     }
1406 
1407     if(MAGIC_TYPE_STR_PRINT_DEBUG) {
1408         _magic_printf("Entering level %d...\n", magic_level);
1409     }
1410 
1411     if(type->type_id == MAGIC_TYPE_OPAQUE) {
1412         _magic_printf("opaque");
1413         magic_counter += strlen("opaque");
1414         return;
1415     }
1416 
1417     num_contained_types = MAGIC_TYPE_NUM_CONTAINED_TYPES(type);
1418     if(num_contained_types == 0) {
1419         assert(!is_empty_str);
1420         if((magic_type_str_print_style & (MAGIC_TYPE_STR_PRINT_LLVM_TYPES|MAGIC_TYPE_STR_PRINT_SOURCE_TYPES)) == (MAGIC_TYPE_STR_PRINT_LLVM_TYPES|MAGIC_TYPE_STR_PRINT_SOURCE_TYPES)) {
1421             if(print_multi_names) {
1422                 _magic_printf("%s/", type->type_str);
1423                 magic_type_names_print(type);
1424                 magic_counter += strlen(type->type_str)+1+strlen(type->name)*type->num_names;
1425             }
1426             else {
1427                 _magic_printf("%s/%s", type->type_str, type->name);
1428                 magic_counter += strlen(type->type_str)+1+strlen(type->name);
1429             }
1430         }
1431         else if(magic_type_str_print_style & MAGIC_TYPE_STR_PRINT_LLVM_TYPES) {
1432             _magic_printf(type->type_str);
1433             magic_counter += strlen(type->type_str);
1434         }
1435         else if(magic_type_str_print_style & MAGIC_TYPE_STR_PRINT_SOURCE_TYPES) {
1436             if(print_multi_names) {
1437                 magic_type_names_print(type);
1438                 magic_counter += strlen(type->name)*type->num_names;
1439             }
1440             else {
1441                 _magic_printf(type->name);
1442                 magic_counter += strlen(type->name);
1443             }
1444         }
1445         return;
1446     }
1447 
1448     if(type->type_id == MAGIC_TYPE_POINTER) {
1449         int nesting_level = magic_type_get_nesting_level(type, magic_level);
1450         if(nesting_level >= 0) {
1451             _magic_printf("\\%d", magic_level - nesting_level);
1452             magic_counter += 2;
1453             return;
1454         }
1455     }
1456 
1457     magic_nested_types[magic_level] = type;
1458     magic_level++;
1459     if(type->type_id == MAGIC_TYPE_POINTER) {
1460         magic_type_str_print(type->contained_types[0]);
1461         _magic_printf("*");
1462         magic_counter += 1;
1463         if(print_multi_names) {
1464             _magic_printf("|");
1465             magic_type_names_print(type);
1466             magic_counter += 1+strlen(type->name)*type->num_names;
1467         }
1468         else if(print_ptr_name) {
1469             _magic_printf("|");
1470             _magic_printf("%s", type->name);
1471             magic_counter += 1+strlen(type->name);
1472         }
1473     }
1474     else if(type->type_id == MAGIC_TYPE_ARRAY || type->type_id == MAGIC_TYPE_VECTOR) {
1475         int num_elements = type->num_child_types;
1476         char start_sep = type->type_id == MAGIC_TYPE_ARRAY ? '[' : '<';
1477         char end_sep = type->type_id == MAGIC_TYPE_ARRAY ? ']' : '>';
1478         _magic_printf("%c", start_sep);
1479         magic_counter += 1;
1480         if(MAGIC_TYPE_FLAG(type, MAGIC_TYPE_VARSIZE)) {
1481             _magic_printf(" (V) ");
1482             magic_counter += 5;
1483         }
1484         if(num_elements) {
1485             _magic_printf("%d x ", num_elements);
1486             magic_counter += 5;
1487         }
1488         magic_type_str_print(type->contained_types[0]);
1489         _magic_printf("%c", end_sep);
1490         magic_counter += 1;
1491     }
1492     else if(type->type_id == MAGIC_TYPE_STRUCT || type->type_id == MAGIC_TYPE_UNION) {
1493         int i;
1494         int skip_struct = type->type_id == MAGIC_TYPE_STRUCT && (magic_type_str_print_style & MAGIC_TYPE_STR_PRINT_SKIP_STRUCTS);
1495         int skip_union = type->type_id == MAGIC_TYPE_UNION && (magic_type_str_print_style & MAGIC_TYPE_STR_PRINT_SKIP_UNIONS);
1496         _magic_printf("{ ");
1497         magic_counter += 2;
1498         if(type->type_id == MAGIC_TYPE_UNION) {
1499             _magic_printf("(U) ");
1500             magic_counter += 4;
1501         }
1502         if(print_multi_names) {
1503             _magic_printf("$");
1504             magic_type_names_print(type);
1505             _magic_printf(" ");
1506             magic_counter += 2 + strlen(type->name)*type->num_names;
1507         }
1508         else {
1509             _magic_printf("$%s ", strcmp(type->name, "") ? type->name : "ANONYMOUS");
1510             magic_counter += 2 + strlen(strcmp(type->name, "") ? type->name : "ANONYMOUS");
1511         }
1512         assert(type->member_names);
1513         if(!skip_struct && !skip_union) {
1514             for(i=0;i<num_contained_types;i++) {
1515                 if(i > 0) {
1516                     _magic_printf(", ");
1517                     magic_counter += 2;
1518                 }
1519                 if((magic_type_str_print_style & MAGIC_TYPE_STR_PRINT_MEMBER_NAMES)
1520                     && (!MAGIC_TYPE_STR_PRINT_MAX || magic_counter < MAGIC_TYPE_STR_PRINT_MAX)) {
1521                     assert(type->member_names[i] && strcmp(type->member_names[i], "") && "Invalid member name!");
1522                     _magic_printf("%s ", type->member_names[i]);
1523                     magic_counter += strlen(type->member_names[i])+1;
1524                 }
1525                 magic_type_str_print(type->contained_types[i]);
1526             }
1527         }
1528         _magic_printf(" }");
1529         magic_counter += 2;
1530    }
1531    else if(type->type_id == MAGIC_TYPE_FUNCTION) {
1532        int i;
1533        assert(num_contained_types > 0);
1534        magic_type_str_print(type->contained_types[0]);
1535        num_contained_types--;
1536        _magic_printf(" (");
1537        magic_counter += 2;
1538        for(i=0;i<num_contained_types;i++) {
1539            if(i > 0) {
1540                _magic_printf(", ");
1541                magic_counter += 2;
1542            }
1543            magic_type_str_print(type->contained_types[i+1]);
1544        }
1545        _magic_printf(")");
1546        magic_counter += 1;
1547    }
1548    else {
1549        _magic_printf("???[id=%d,child_types=%d,size=%zu]", type->type_id, type->num_child_types, type->size);
1550        magic_counter += 30;
1551    }
1552    magic_level--;
1553    if(MAGIC_TYPE_STR_PRINT_DEBUG) {
1554        _magic_printf("Exiting level %d...\n", magic_level);
1555    }
1556 }
1557 
1558 /*===========================================================================*
1559  *                         magic_type_values_print                           *
1560  *===========================================================================*/
1561 PUBLIC void magic_type_values_print(const struct _magic_type* type)
1562 {
1563     int i=0;
1564 
1565     if(!MAGIC_TYPE_HAS_VALUE_SET(type)) {
1566         return;
1567     }
1568     while(MAGIC_TYPE_HAS_VALUE(type, i)) {
1569         int value = MAGIC_TYPE_VALUE(type, i);
1570         _magic_printf("%s%d", (i==0 ? "" : ", "), value);
1571         i++;
1572     }
1573 }
1574 
1575 /*===========================================================================*
1576  *                         magic_type_names_print                            *
1577  *===========================================================================*/
1578 PUBLIC void magic_type_names_print(const struct _magic_type* type)
1579 {
1580     unsigned int i;
1581 
1582     for(i=0;i<type->num_names;i++) {
1583         _magic_printf("%s%s", (i==0 ? "" : "|"), type->names[i]);
1584     }
1585 }
1586 
1587 /*===========================================================================*
1588  *                       magic_type_comp_types_print                         *
1589  *===========================================================================*/
1590 PUBLIC void magic_type_comp_types_print(const struct _magic_type* type,
1591     int flags)
1592 {
1593     int num;
1594     int i=0;
1595     const struct _magic_type* comp_type;
1596 
1597     if(!MAGIC_TYPE_HAS_COMP_TYPES(type)) {
1598         return;
1599     }
1600     MAGIC_TYPE_NUM_COMP_TYPES(type, &num);
1601     _magic_printf("#%d", num);
1602     if(flags & MAGIC_SKIP_COMP_TYPES) {
1603         return;
1604     }
1605     flags &= ~MAGIC_EXPAND_TYPE_STR;
1606 
1607     MAGIC_TYPE_COMP_ITER(type, comp_type,
1608         _magic_printf("%s%d=", (i==0 ? ": " : ", "), i+1);
1609         MAGIC_TYPE_PRINT(comp_type, flags|MAGIC_SKIP_COMP_TYPES);
1610         i++;
1611     );
1612 }
1613 
1614 /*===========================================================================*
1615  *                     magic_type_str_print_from_target                      *
1616  *===========================================================================*/
1617 PUBLIC int magic_type_str_print_from_target(void* target)
1618 {
1619     int printed_types=0;
1620     int ret;
1621     ret = magic_type_target_walk(target, NULL, NULL,
1622         magic_type_str_print_cb, &printed_types);
1623     if(ret < 0) {
1624         return ret;
1625     }
1626     if(printed_types == 0) {
1627         _magic_printf("BAD OFFSET");
1628     }
1629     return printed_types;
1630 }
1631 
1632 /*===========================================================================*
1633  *                            magic_type_equals                              *
1634  *===========================================================================*/
1635 PUBLIC int magic_type_equals(const struct _magic_type* type, const struct _magic_type* other_type)
1636 {
1637     assert(magic_level < MAGIC_MAX_RECURSIVE_TYPES);
1638 
1639     if(type == other_type) {
1640         return TRUE;
1641     }
1642     if(type->type_id != other_type->type_id) {
1643         return FALSE;
1644     }
1645     if((type->flags & MAGIC_TYPE_EXTERNAL) || (other_type->flags & MAGIC_TYPE_EXTERNAL)) {
1646         int i, nesting_level;
1647         if(type->num_child_types == other_type->num_child_types) {
1648             int num_contained_types = MAGIC_TYPE_NUM_CONTAINED_TYPES(type);
1649             if(num_contained_types == 0) {
1650                 return !strcmp(type->type_str, other_type->type_str);
1651             }
1652             nesting_level = magic_type_get_nesting_level(type, magic_level);
1653             if(nesting_level >= 0) {
1654                 return (other_type == magic_nested_types2[nesting_level]);
1655             }
1656             magic_nested_types[magic_level] = type;
1657             magic_nested_types2[magic_level] = other_type;
1658             magic_level++;
1659             for(i=0;i<num_contained_types;i++) {
1660                 if(magic_type_equals(type->contained_types[i], other_type->contained_types[i]) == FALSE) {
1661                     magic_level--;
1662                     return FALSE;
1663                 }
1664             }
1665             magic_level--;
1666             return TRUE;
1667         }
1668     }
1669     return FALSE;
1670 }
1671 
1672 /*===========================================================================*
1673  *                           magic_type_compatible                           *
1674  *===========================================================================*/
1675 PUBLIC int magic_type_compatible(const struct _magic_type* type, const struct _magic_type* other_type, int flags)
1676 {
1677     int i, nesting_level, num_contained_types;
1678     assert(magic_level < MAGIC_MAX_RECURSIVE_TYPES);
1679 
1680     if(type == other_type) {
1681         return TRUE;
1682     }
1683 
1684     if(type->type_id != other_type->type_id) {
1685         return FALSE;
1686     }
1687 
1688     if(type->num_child_types != other_type->num_child_types) {
1689         return FALSE;
1690     }
1691 
1692     if(flags & MAGIC_TYPE_COMPARE_FLAGS) {
1693         if((type->flags & (~MAGIC_TYPE_IS_ROOT)) != (other_type->flags & (~MAGIC_TYPE_IS_ROOT))){
1694             return FALSE;
1695         }
1696     }
1697 
1698     if(flags & MAGIC_TYPE_COMPARE_VALUE_SET) {
1699         if(MAGIC_TYPE_HAS_VALUE_SET(type) != MAGIC_TYPE_HAS_VALUE_SET(other_type)){
1700             return FALSE;
1701         }
1702         if(MAGIC_TYPE_HAS_VALUE_SET(type)){
1703             i=0;
1704             while(MAGIC_TYPE_HAS_VALUE(type, i) && MAGIC_TYPE_HAS_VALUE(other_type, i)) {
1705                 if(MAGIC_TYPE_VALUE(type, i) != MAGIC_TYPE_VALUE(other_type, i)){
1706                     /* a value is different */
1707                     return FALSE;
1708                 }
1709                 i++;
1710             }
1711             if(MAGIC_TYPE_HAS_VALUE(type, i) || MAGIC_TYPE_HAS_VALUE(other_type, i)) {
1712                 return FALSE;
1713             }
1714         }
1715     }
1716 
1717     if(flags & MAGIC_TYPE_COMPARE_NAME) {
1718         if(strcmp(type->name, other_type->name)){
1719             return FALSE;
1720         }
1721     }
1722 
1723     if(flags & MAGIC_TYPE_COMPARE_NAMES) {
1724         if(type->num_names != other_type->num_names) {
1725             return FALSE;
1726         }
1727         if(type->num_names > 1) {
1728             for(i=0; (unsigned int)i<type->num_names; i++){
1729                 if(strcmp(type->names[i], other_type->names[i])) {
1730                     return FALSE;
1731                 }
1732             }
1733         }
1734     }
1735 
1736     num_contained_types = MAGIC_TYPE_NUM_CONTAINED_TYPES(type);
1737     if(num_contained_types == 0) {
1738         return type->size == other_type->size && !strcmp(type->type_str, other_type->type_str);
1739     }
1740 
1741     if(type->type_id == MAGIC_TYPE_STRUCT) {
1742         if(flags & MAGIC_TYPE_COMPARE_MEMBER_NAMES) {
1743             for(i=0; (unsigned int)i<type->num_child_types; i++){
1744                 if(strcmp(type->member_names[i], other_type->member_names[i])) {
1745                     return FALSE;
1746                 }
1747             }
1748         }
1749         if(flags & MAGIC_TYPE_COMPARE_MEMBER_OFFSETS) {
1750             for(i=0; (unsigned int)i<type->num_child_types; i++){
1751                 if(type->member_offsets[i] != other_type->member_offsets[i]) {
1752                     return FALSE;
1753                 }
1754             }
1755         }
1756     }
1757 
1758     nesting_level = magic_type_get_nesting_level(type, magic_level);
1759     if(nesting_level >= 0) {
1760         return (other_type == magic_nested_types2[nesting_level]);
1761     }
1762     magic_nested_types[magic_level] = type;
1763     magic_nested_types2[magic_level] = other_type;
1764     magic_level++;
1765     for(i=0;i<num_contained_types;i++) {
1766         if(!magic_type_compatible(type->contained_types[i], other_type->contained_types[i], flags)) {
1767             magic_level--;
1768             return FALSE;
1769         }
1770     }
1771     magic_level--;
1772     return TRUE;
1773 }
1774 
1775 /*===========================================================================*
1776  *                        magic_type_comp_compatible                         *
1777  *===========================================================================*/
1778 PUBLIC int magic_type_comp_compatible(const struct _magic_type* type, const struct _magic_type* other_type)
1779 {
1780     const struct _magic_type *comp_type;
1781 
1782     MAGIC_TYPE_COMP_ITER(type, comp_type,
1783         if(magic_type_compatible(comp_type, other_type, 0)) {
1784              return TRUE;
1785         }
1786     );
1787 
1788     return FALSE;
1789 }
1790 
1791 /*===========================================================================*
1792  *                          magic_type_ptr_is_text                           *
1793  *===========================================================================*/
1794 PUBLIC int magic_type_ptr_is_text(const struct _magic_type* ptr_type)
1795 {
1796     const struct _magic_type *comp_type;
1797 
1798     assert(ptr_type->type_id == MAGIC_TYPE_POINTER);
1799     if(ptr_type->contained_types[0]->type_id == MAGIC_TYPE_FUNCTION
1800         || MAGIC_TYPE_IS_VOID(ptr_type->contained_types[0])) {
1801         return TRUE;
1802     }
1803 
1804     MAGIC_TYPE_COMP_ITER(ptr_type, comp_type,
1805         if(comp_type->type_id == MAGIC_TYPE_FUNCTION
1806             || MAGIC_TYPE_IS_VOID(comp_type)) {
1807             return TRUE;
1808         }
1809     );
1810 
1811     return FALSE;
1812 }
1813 
1814 /*===========================================================================*
1815  *                          magic_type_ptr_is_data                           *
1816  *===========================================================================*/
1817 PUBLIC int magic_type_ptr_is_data(const struct _magic_type* ptr_type)
1818 {
1819     const struct _magic_type *comp_type;
1820 
1821     assert(ptr_type->type_id == MAGIC_TYPE_POINTER);
1822     if(ptr_type->contained_types[0]->type_id != MAGIC_TYPE_FUNCTION) {
1823         return TRUE;
1824     }
1825 
1826     MAGIC_TYPE_COMP_ITER(ptr_type, comp_type,
1827         if(comp_type->type_id != MAGIC_TYPE_FUNCTION) {
1828             return TRUE;
1829         }
1830     );
1831 
1832     return FALSE;
1833 }
1834 
1835 /*===========================================================================*
1836  *                    magic_type_alloc_needs_varsized_array                  *
1837  *===========================================================================*/
1838 PUBLIC int magic_type_alloc_needs_varsized_array(const struct _magic_type* type,
1839     size_t alloc_size, int *num_elements)
1840 {
1841     /* See if this type needs a var-sized array for the given allocation size */
1842     const struct _magic_type *array_type, *array_el_type;
1843     size_t array_offset, array_size;
1844     if(!MAGIC_TYPE_FLAG(type, MAGIC_TYPE_VARSIZE)) {
1845         return FALSE;
1846     }
1847     assert(type->type_id == MAGIC_TYPE_STRUCT);
1848 
1849     if(alloc_size <= type->size || type->num_child_types == 0) {
1850         return FALSE;
1851     }
1852     array_type = type->contained_types[type->num_child_types-1];
1853     if(array_type->type_id != MAGIC_TYPE_ARRAY) {
1854         return FALSE;
1855     }
1856     array_el_type = array_type->contained_types[0];
1857     array_offset = type->member_offsets[type->num_child_types-1]+array_type->num_child_types*array_el_type->size;
1858     array_size = alloc_size - array_offset;
1859     if(array_size == 0 || array_size % array_el_type->size != 0) {
1860         return FALSE;
1861     }
1862     if(num_elements) {
1863         *num_elements = 1+array_size/array_el_type->size;
1864     }
1865 
1866     return TRUE;
1867 }
1868 
1869 /*===========================================================================*
1870  *                     magic_type_alloc_get_varsized_array_size              *
1871  *===========================================================================*/
1872 PUBLIC size_t magic_type_alloc_get_varsized_array_size(const struct _magic_type* type,
1873     int num_elements)
1874 {
1875     /* Get the allocation size from the number of elements of the varsized array. */
1876     const struct _magic_type *array_type, *array_el_type;
1877     size_t array_offset;
1878     if(!MAGIC_TYPE_FLAG(type, MAGIC_TYPE_VARSIZE)) {
1879         return 0;
1880     }
1881     assert(type->type_id == MAGIC_TYPE_STRUCT);
1882 
1883     if(num_elements == 1) {
1884         return type->size;
1885     }
1886     array_type = type->contained_types[type->num_child_types-1];
1887     if(array_type->type_id != MAGIC_TYPE_ARRAY) {
1888         return 0;
1889     }
1890     array_el_type = array_type->contained_types[0];
1891     array_offset = type->member_offsets[type->num_child_types-1]+array_type->num_child_types*array_el_type->size;
1892     return array_offset + array_el_type->size*(num_elements-1);
1893 }
1894 
1895 /*===========================================================================*
1896  *                      magic_type_parse_varsized_array                      *
1897  *===========================================================================*/
1898 PUBLIC void magic_type_parse_varsized_array(const struct _magic_type *type,
1899     const struct _magic_type **sub_struct_type, const struct _magic_type **sub_array_type,
1900     size_t *sub_array_offset, size_t *sub_array_size)
1901 {
1902     /* Parse a var-sized array containing a variable-sized struct. */
1903     const struct _magic_type *_sub_struct_type, *_sub_array_type, *_sub_array_el_type;
1904     size_t _sub_array_offset, _sub_array_size;
1905 
1906     assert(type->type_id == MAGIC_TYPE_ARRAY && MAGIC_TYPE_FLAG(type, MAGIC_TYPE_DYNAMIC));
1907     _sub_struct_type = type->contained_types[0];
1908     assert(magic_type_alloc_needs_varsized_array(_sub_struct_type, type->size, NULL));
1909 
1910     _sub_array_type = _sub_struct_type->contained_types[_sub_struct_type->num_child_types-1];
1911     _sub_array_el_type = _sub_array_type->contained_types[0];
1912     _sub_array_offset = _sub_struct_type->member_offsets[_sub_struct_type->num_child_types-1]+_sub_array_type->num_child_types*_sub_array_el_type->size;
1913     _sub_array_size = type->size - _sub_array_offset;
1914 
1915     if(sub_struct_type) *sub_struct_type = _sub_struct_type;
1916     if(sub_array_type) *sub_array_type = _sub_array_type;
1917     if(sub_array_offset) *sub_array_offset = _sub_array_offset;
1918     if(sub_array_size) *sub_array_size = _sub_array_size;
1919 }
1920 
1921 /*===========================================================================*
1922  *                          magic_type_walk_flags                            *
1923  *===========================================================================*/
1924 PUBLIC int magic_type_walk_flags(const struct _magic_type* parent_type,
1925     unsigned parent_offset, int child_num,
1926     const struct _magic_type* type, unsigned offset,
1927     const unsigned min_offset, const unsigned max_offset,
1928     const magic_type_walk_cb_t cb, void* cb_args, int flags) {
1929     static THREAD_LOCAL int magic_depth = 0;
1930     int ret, status, action;
1931     ret = MAGIC_TYPE_WALK_CONTINUE;
1932 
1933     if(offset >= min_offset && offset <= max_offset) {
1934          ret = cb(parent_type, parent_offset, child_num, type, offset, magic_depth, cb_args);
1935     }
1936     else if(offset > max_offset) {
1937         ret = MAGIC_TYPE_WALK_STOP;
1938     }
1939     else if(offset+type->size <= min_offset) {
1940         ret = MAGIC_TYPE_WALK_SKIP_PATH;
1941     }
1942 
1943     /* The status code returned to the caller is propagated directly from the
1944      * callback only in case of ret<0 and ret == MAGIC_TYPE_WALK_STOP.
1945      * In all the other cases, we return 0 the caller.
1946      */
1947     status = ret < 0 ? ret : 0;
1948     action = ret < 0 ? MAGIC_TYPE_WALK_STOP : ret;
1949     switch(action) {
1950         case MAGIC_TYPE_WALK_STOP:
1951             status = status ? status : MAGIC_TYPE_WALK_STOP;
1952         break;
1953         case MAGIC_TYPE_WALK_SKIP_PATH:
1954             status = 0;
1955         break;
1956         case MAGIC_TYPE_WALK_CONTINUE:
1957             if(!MAGIC_TYPE_IS_WALKABLE(type)) {
1958                 status = 0;
1959             }
1960             else {
1961                 int i, num_child_types, start;
1962                 num_child_types = type->num_child_types;
1963                 start = 0;
1964                 if(type->type_id == MAGIC_TYPE_ARRAY || type->type_id == MAGIC_TYPE_VECTOR) {
1965                     if(!MAGIC_TYPE_FLAG(type, MAGIC_TYPE_VARSIZE) && offset < min_offset) {
1966                         /* Skip irrelevant array iterations. */
1967                         start = (min_offset-offset)/(type->contained_types[0]->size);
1968                     }
1969                 }
1970                 for(i=start;i<num_child_types;i++) {
1971                     const struct _magic_type *child_type;
1972                     unsigned child_offset;
1973                     magic_type_walk_step(type, i, &child_type, &child_offset, flags);
1974                     magic_depth++;
1975                     status = magic_type_walk_flags(type, offset, i, child_type, offset+child_offset, min_offset, max_offset, cb, cb_args, flags);
1976                     magic_depth--;
1977                     if(status < 0 || status == MAGIC_TYPE_WALK_STOP) {
1978                         break;
1979                     }
1980                 }
1981             }
1982         break;
1983         default:
1984             _magic_printf("magic_type_walk: unrecognized callback return code: %d, stopping type walk...\n", action);
1985             status = MAGIC_TYPE_WALK_STOP;
1986         break;
1987     }
1988     return status;
1989 }
1990 
1991 /*===========================================================================*
1992  *                          magic_type_target_walk                           *
1993  *===========================================================================*/
1994 PUBLIC int magic_type_target_walk(void *target,
1995     struct _magic_dsentry **trg_dsentry, struct _magic_dfunction **trg_dfunction,
1996     const magic_type_walk_cb_t cb, void *cb_args)
1997 {
1998     int ret;
1999     struct _magic_sentry *sentry = NULL;
2000     struct _magic_function *function = NULL;
2001     sentry = magic_sentry_lookup_by_range(target, magic_reentrant ? &magic_dsentry_buff : NULL);
2002     if (sentry == NULL) {
2003         function = magic_function_lookup_by_addr(target, magic_reentrant ? &magic_dfunction_buff : NULL);
2004         if (function == NULL) {
2005             /* No known entry found. */
2006             return MAGIC_ENOENT;
2007         }
2008         if (MAGIC_STATE_FLAG(function, MAGIC_STATE_ADDR_NOT_TAKEN)) {
2009             /* A function has been found, but it was not supposed to be a target. */
2010             return MAGIC_EBADENT;
2011         }
2012     }
2013     else if (MAGIC_STATE_FLAG(sentry, MAGIC_STATE_ADDR_NOT_TAKEN)) {
2014         /* An entry has been found, but it was not supposed to be a target. */
2015         return MAGIC_EBADENT;
2016     }
2017     assert(sentry || function);
2018     if (magic_reentrant) {
2019         if (sentry) {
2020             if (trg_dsentry) {
2021                 if (MAGIC_STATE_FLAG(sentry, MAGIC_STATE_DYNAMIC)) {
2022                     magic_copy_dsentry(MAGIC_DSENTRY_FROM_SENTRY(sentry), *trg_dsentry);
2023                 }
2024                 else {
2025                     memcpy(MAGIC_DSENTRY_TO_SENTRY(*trg_dsentry), sentry, sizeof(struct _magic_sentry));
2026                 }
2027             }
2028             if (trg_dfunction) {
2029                 *trg_dfunction = NULL;
2030             }
2031         }
2032         else {
2033             if (trg_dfunction) {
2034                 if (MAGIC_STATE_FLAG(function, MAGIC_STATE_DYNAMIC)) {
2035                     magic_copy_dfunction(MAGIC_DFUNCTION_FROM_FUNCTION(function), *trg_dfunction);
2036                 }
2037                 else {
2038                     memcpy(MAGIC_DFUNCTION_TO_FUNCTION(*trg_dfunction), function, sizeof(struct _magic_function));
2039                 }
2040             }
2041             if (trg_dsentry) {
2042                 *trg_dsentry = NULL;
2043             }
2044         }
2045     } else {
2046         /*
2047          * Just return the pointer to the target object.
2048          * NB!: Because the target objects can be static (i.e. sentries,
2049          * functions), the user MUST first check the flag
2050          * of the returned target element to see if it is a sentry
2051          * or function. Otherwise, he might end up accessing invalid
2052          * memory.
2053          */
2054         if (sentry) {
2055             if (trg_dsentry) {
2056                 *trg_dsentry = MAGIC_DSENTRY_FROM_SENTRY(sentry);
2057             }
2058             if (trg_dfunction) {
2059                 *trg_dfunction = NULL;
2060             }
2061         }
2062         else {
2063             if (trg_dfunction) {
2064                 *trg_dfunction = MAGIC_DFUNCTION_FROM_FUNCTION(function);
2065             }
2066             if (trg_dsentry) {
2067                 *trg_dsentry = NULL;
2068             }
2069         }
2070     }
2071 
2072     if (sentry) {
2073         ret = magic_type_walk_root_at_offset(sentry->type, (char *) target - (char *) sentry->address, cb, cb_args);
2074     } else {
2075         ret = magic_type_walk_root_at_offset(function->type, (char*) target - (char*) function->address, cb, cb_args);
2076     }
2077 
2078     return ret;
2079 }
2080 
2081 /*===========================================================================*
2082  *                      magic_type_walk_as_void_array                        *
2083  *===========================================================================*/
2084 PUBLIC int magic_type_walk_as_void_array(const struct _magic_type* parent_type,
2085     unsigned parent_offset, int child_num, const struct _magic_type* type,
2086     unsigned offset, const unsigned min_offset, const unsigned max_offset,
2087     const magic_type_walk_cb_t cb, void* cb_args)
2088 {
2089     struct _magic_type void_array_type;
2090     MAGIC_TYPE_VOID_ARRAY_GET_FROM_SIZE(&void_array_type, type->size);
2091     return magic_type_walk(parent_type, parent_offset, child_num, &void_array_type,
2092         offset, min_offset, max_offset, cb, cb_args);
2093 }
2094 
2095 /*===========================================================================*
2096  *                     magic_type_walk_as_ptrint_array                       *
2097  *===========================================================================*/
2098 PUBLIC int magic_type_walk_as_ptrint_array(const struct _magic_type* parent_type,
2099     unsigned parent_offset, int child_num, const struct _magic_type* type, void* offset_addr,
2100     unsigned offset, const unsigned min_offset, const unsigned max_offset,
2101     const magic_type_walk_cb_t cb, void* cb_args)
2102 {
2103     struct _magic_type ptrint_array_type;
2104     unsigned type_size = type->size;
2105     unsigned addr_diff = ((unsigned)offset_addr) % sizeof(void*);
2106     if(addr_diff > 0) {
2107         unsigned addr_off_by = sizeof(void*) - addr_diff;
2108         if(type_size <= addr_off_by) {
2109             return MAGIC_EBADWALK;
2110         }
2111         type_size -= addr_off_by;
2112         offset_addr = (void*)((unsigned)offset_addr + addr_off_by);
2113         offset += addr_off_by;
2114     }
2115     addr_diff = (((unsigned)offset_addr)+type_size) % sizeof(void*);
2116     if(addr_diff > 0) {
2117         unsigned addr_off_by = addr_diff;
2118         if(type_size <= addr_off_by) {
2119             return MAGIC_EBADWALK;
2120         }
2121         type_size -= addr_off_by;
2122     }
2123     MAGIC_TYPE_PTRINT_ARRAY_GET_FROM_SIZE(&ptrint_array_type, type_size);
2124     return magic_type_walk(parent_type, parent_offset, child_num, &ptrint_array_type,
2125         offset, min_offset, max_offset, cb, cb_args);
2126 }
2127 
2128 /*===========================================================================*
2129  *                         magic_type_str_print_cb                           *
2130  *===========================================================================*/
2131 PUBLIC int magic_type_str_print_cb(const struct _magic_type* parent_type,
2132     const unsigned parent_offset, int child_num,
2133     const struct _magic_type* type, const unsigned offset, int depth, void* cb_args)
2134 {
2135     int *printed_types = (int*) cb_args;
2136     if(printed_types) (*printed_types)++;
2137     magic_type_str_print(type);
2138     _magic_printf("; ");
2139     return MAGIC_TYPE_WALK_CONTINUE;
2140 }
2141 
2142 /*===========================================================================*
2143  *                            magic_type_count_cb                            *
2144  *===========================================================================*/
2145 PUBLIC int magic_type_count_cb(const struct _magic_type* parent_type,
2146     const unsigned parent_offset, int child_num,
2147     const struct _magic_type* type, const unsigned offset, int depth, void* cb_args)
2148 {
2149     int *type_counter = (int*) cb_args;
2150     if(type_counter) (*type_counter)++;
2151     return MAGIC_TYPE_WALK_CONTINUE;
2152 }
2153 
2154 /*===========================================================================*
2155  *                         magic_type_child_offset_cb                        *
2156  *===========================================================================*/
2157 PUBLIC int magic_type_child_offset_cb(const struct _magic_type* parent_type,
2158     const unsigned parent_offset, int child_num,
2159     const struct _magic_type* type, const unsigned offset, int depth, void* cb_args)
2160 {
2161     void **args_array = (void**) cb_args;
2162     int *my_child_num = (int*) args_array[0];
2163     unsigned *child_offset = (unsigned*) args_array[1];
2164 
2165     if(!parent_type) {
2166         return MAGIC_TYPE_WALK_CONTINUE;
2167     }
2168     if(child_num == *my_child_num) {
2169         *child_offset = offset;
2170         return MAGIC_TYPE_WALK_STOP;
2171     }
2172     return MAGIC_TYPE_WALK_SKIP_PATH;
2173 }
2174 
2175 /*===========================================================================*
2176  *                            magic_type_walk_step                           *
2177  *===========================================================================*/
2178 PUBLIC void magic_type_walk_step(const struct _magic_type *type,
2179     int child_num, const struct _magic_type **child_type, unsigned *child_offset,
2180     int walk_flags)
2181 {
2182     int type_id;
2183     struct _magic_type type_buff;
2184     if(type->type_id == MAGIC_TYPE_UNION && (walk_flags & MAGIC_TYPE_WALK_UNIONS_AS_VOID)) {
2185         MAGIC_TYPE_VOID_ARRAY_GET_FROM_SIZE(&type_buff, type->size);
2186         type = &type_buff;
2187     }
2188     type_id = type->type_id;
2189     if(type_id == MAGIC_TYPE_STRUCT || type_id == MAGIC_TYPE_UNION) {
2190         *child_type = type->contained_types[child_num];
2191         *child_offset = type->member_offsets[child_num];
2192     }
2193     else {
2194         assert(type_id == MAGIC_TYPE_ARRAY || type_id == MAGIC_TYPE_VECTOR);
2195         if(MAGIC_TYPE_FLAG(type, MAGIC_TYPE_VARSIZE) && child_num > 0) {
2196             const struct _magic_type *sub_array_type, *sub_array_el_type;
2197             size_t sub_array_offset;
2198             magic_type_parse_varsized_array(type, NULL, &sub_array_type, &sub_array_offset, NULL);
2199             sub_array_el_type = sub_array_type->contained_types[0];
2200             *child_type = sub_array_el_type;
2201             *child_offset = sub_array_offset + (child_num-1)*sub_array_el_type->size;
2202         }
2203         else {
2204             *child_type = type->contained_types[0];
2205             *child_offset = child_num*((*child_type)->size);
2206         }
2207     }
2208 }
2209 
2210 /*===========================================================================*
2211  *                            magic_type_get_size                            *
2212  *===========================================================================*/
2213 PUBLIC size_t magic_type_get_size(struct _magic_type *type, int flags)
2214 {
2215     size_t size;
2216     int i, num_contained_types;
2217 
2218     size = sizeof(type->size) +
2219            sizeof(type->num_child_types) + sizeof(type->contained_types) +
2220            sizeof(type->member_offsets) + sizeof(type->type_id) + sizeof(type->flags);
2221     num_contained_types = MAGIC_TYPE_NUM_CONTAINED_TYPES(type);
2222 
2223     if(num_contained_types > 0) {
2224         size += sizeof(*(type->contained_types))*num_contained_types;
2225     }
2226     if(type->type_id == MAGIC_TYPE_STRUCT) {
2227         size += sizeof(*(type->member_offsets))*num_contained_types;
2228         if(flags & MAGIC_SIZE_MEMBER_NAMES) {
2229             size += sizeof(*(type->member_names))*num_contained_types;
2230             for(i=0;i<num_contained_types;i++) {
2231                 size += strlen(type->member_names[i])+1;
2232             }
2233         }
2234     }
2235 
2236     if(flags & MAGIC_SIZE_VALUE_SET) {
2237         if(MAGIC_TYPE_HAS_VALUE_SET(type)) {
2238             int num;
2239             MAGIC_TYPE_NUM_VALUES(type, &num);
2240             size += sizeof(int)+(num+1);
2241         }
2242     }
2243     if(flags & MAGIC_SIZE_TYPE_NAMES) {
2244         size += sizeof(type->num_names) + sizeof(type->names) + sizeof(*(type->names))*(type->num_names);
2245         for(i=0;(unsigned int)i<type->num_names;i++) {
2246             size += strlen(type->names[i])+1;
2247         }
2248     }
2249     if(flags & MAGIC_SIZE_COMP_TYPES) {
2250         if(MAGIC_TYPE_HAS_COMP_TYPES(type)) {
2251             int num;
2252             MAGIC_TYPE_NUM_COMP_TYPES(type, &num);
2253             size += sizeof(*(type->compatible_types))*num;
2254         }
2255     }
2256 
2257     return size;
2258 }
2259 
2260 /*===========================================================================*
2261  *                            magic_types_get_size                           *
2262  *===========================================================================*/
2263 PUBLIC size_t magic_types_get_size(int flags)
2264 {
2265     size_t size;
2266     int i;
2267 
2268     size = 0;
2269     for(i=0;i<_magic_types_num;i++) {
2270         size += magic_type_get_size(&_magic_types[i], flags);
2271     }
2272 
2273     return size;
2274 }
2275 
2276 /*===========================================================================*
2277  *                          magic_function_get_size                          *
2278  *===========================================================================*/
2279 PUBLIC size_t magic_function_get_size(struct _magic_function *function, int flags)
2280 {
2281     size_t size;
2282 
2283     size = sizeof(function->type) + sizeof(function->flags) + sizeof(function->address);
2284 
2285     if(flags & MAGIC_SIZE_NAMES) {
2286         size += sizeof(function->name) + strlen(function->name)+1;
2287     }
2288 
2289     return size;
2290 }
2291 
2292 /*===========================================================================*
2293  *                          magic_functions_get_size                         *
2294  *===========================================================================*/
2295 PUBLIC size_t magic_functions_get_size(int flags)
2296 {
2297     size_t size;
2298     int i;
2299 
2300     size = 0;
2301     for(i=0;i<_magic_functions_num;i++) {
2302         size += magic_function_get_size(&_magic_functions[i], flags);
2303     }
2304 
2305     return size;
2306 }
2307 
2308 /*===========================================================================*
2309  *                         magic_dfunctions_get_size                         *
2310  *===========================================================================*/
2311 PUBLIC size_t magic_dfunctions_get_size(int flags)
2312 {
2313     size_t size;
2314     struct _magic_dfunction* dfunction;
2315     struct _magic_function* function;
2316 
2317     size = 0;
2318     MAGIC_DFUNCTION_FUNC_ITER(_magic_first_dfunction, dfunction, function,
2319         size += magic_function_get_size(function, flags);
2320     );
2321 
2322     return size;
2323 }
2324 
2325 /*===========================================================================*
2326  *                           magic_sentry_get_size                           *
2327  *===========================================================================*/
2328 PUBLIC size_t magic_sentry_get_size(struct _magic_sentry *sentry, int flags)
2329 {
2330     size_t size;
2331 
2332     size = sizeof(sentry->type) + sizeof(sentry->flags);
2333 
2334     if(MAGIC_SENTRY_IS_DSENTRY(sentry)) {
2335         struct _magic_dsentry *dsentry = MAGIC_DSENTRY_FROM_SENTRY(sentry);
2336         if(flags & MAGIC_SIZE_DSENTRY_NAMES) {
2337             size += sizeof(sentry->name) + strlen(sentry->name)+1;
2338             if(dsentry->parent_name) {
2339                 size += sizeof(dsentry->parent_name) + strlen(dsentry->parent_name)+1;
2340             }
2341         }
2342         if(sentry->type == &dsentry->type) {
2343             size += sizeof(dsentry->type.num_child_types);
2344         }
2345         size += sizeof(dsentry->next);
2346     }
2347     else {
2348         size += sizeof(sentry->address);
2349         if(flags & MAGIC_SIZE_NAMES) {
2350             size += sizeof(sentry->name) + strlen(sentry->name)+1;
2351         }
2352     }
2353 
2354     return size;
2355 }
2356 
2357 /*===========================================================================*
2358  *                           magic_sentries_get_size                         *
2359  *===========================================================================*/
2360 PUBLIC size_t magic_sentries_get_size(int flags)
2361 {
2362     size_t size;
2363     int i;
2364 
2365     size = 0;
2366     for(i=0;i<_magic_sentries_num;i++) {
2367         size += magic_sentry_get_size(&_magic_sentries[i], flags);
2368     }
2369 
2370     return size;
2371 }
2372 
2373 /*===========================================================================*
2374  *                          magic_dsentries_get_size                         *
2375  *===========================================================================*/
2376 PUBLIC size_t magic_dsentries_get_size(int flags)
2377 {
2378     size_t size;
2379     struct _magic_dsentry *prev_dsentry, *dsentry;
2380     struct _magic_sentry* sentry;
2381 
2382     size = 0;
2383     MAGIC_DSENTRY_ALIVE_ITER(_magic_first_dsentry, prev_dsentry, dsentry, sentry,
2384         if(!MAGIC_STATE_FLAG(sentry, MAGIC_STATE_OUT_OF_BAND)) {
2385             size += magic_sentry_get_size(sentry, flags);
2386         }
2387     );
2388 
2389     return size;
2390 }
2391 
2392 /*===========================================================================*
2393  *                           magic_dsindex_get_size                          *
2394  *===========================================================================*/
2395 PUBLIC size_t magic_dsindex_get_size(struct _magic_dsindex *dsindex, int flags)
2396 {
2397     size_t size;
2398 
2399     size = sizeof(dsindex->type) + sizeof(dsindex->flags);
2400 
2401     if(flags & MAGIC_SIZE_DSINDEX_NAMES) {
2402         size += sizeof(dsindex->parent_name) + strlen(dsindex->parent_name)+1;
2403         size += sizeof(dsindex->name) + strlen(dsindex->name)+1;
2404     }
2405 
2406     return size;
2407 }
2408 
2409 /*===========================================================================*
2410  *                          magic_dsindexes_get_size                         *
2411  *===========================================================================*/
2412 PUBLIC size_t magic_dsindexes_get_size(int flags)
2413 {
2414     size_t size;
2415     int i;
2416 
2417     size = 0;
2418     for(i=0;i<_magic_dsindexes_num;i++) {
2419         size += magic_dsindex_get_size(&_magic_dsindexes[i], flags);
2420     }
2421 
2422     return size;
2423 }
2424 
2425 /*===========================================================================*
2426  *                           magic_sodesc_get_size                           *
2427  *===========================================================================*/
2428 PUBLIC size_t magic_sodesc_get_size(struct _magic_sodesc *sodesc, int flags)
2429 {
2430     return sizeof(struct _magic_sodesc);
2431 }
2432 
2433 /*===========================================================================*
2434  *                           magic_sodescs_get_size                          *
2435  *===========================================================================*/
2436 PUBLIC size_t magic_sodescs_get_size(int flags)
2437 {
2438     size_t size;
2439     struct _magic_sodesc* sodesc;
2440 
2441     size = 0;
2442     MAGIC_SODESC_ITER(_magic_first_sodesc, sodesc,
2443         size += magic_sodesc_get_size(sodesc, flags);
2444     );
2445 
2446     return size;
2447 }
2448 
2449 /*===========================================================================*
2450  *                           magic_dsodesc_get_size                          *
2451  *===========================================================================*/
2452 PUBLIC size_t magic_dsodesc_get_size(struct _magic_dsodesc *dsodesc, int flags)
2453 {
2454     return sizeof(struct _magic_dsodesc);
2455 }
2456 
2457 /*===========================================================================*
2458  *                          magic_dsodescs_get_size                          *
2459  *===========================================================================*/
2460 PUBLIC size_t magic_dsodescs_get_size(int flags)
2461 {
2462     size_t size;
2463     struct _magic_dsodesc* dsodesc;
2464 
2465     size = 0;
2466     MAGIC_DSODESC_ITER(_magic_first_dsodesc, dsodesc,
2467         size += magic_dsodesc_get_size(dsodesc, flags);
2468     );
2469 
2470     return size;
2471 }
2472 
2473 /*===========================================================================*
2474  *                          magic_metadata_get_size                          *
2475  *===========================================================================*/
2476 PUBLIC size_t magic_metadata_get_size(int flags)
2477 {
2478     size_t size = 0;
2479 
2480     size += magic_types_get_size(flags);
2481     size += magic_functions_get_size(flags);
2482     size += magic_dfunctions_get_size(flags);
2483     size += magic_sentries_get_size(flags);
2484     size += magic_dsentries_get_size(flags);
2485     size += magic_dsindexes_get_size(flags);
2486     size += magic_dsodescs_get_size(flags);
2487 
2488     return size;
2489 }
2490 
2491 /*===========================================================================*
2492  *                       magic_sentries_data_get_size                        *
2493  *===========================================================================*/
2494 PUBLIC size_t magic_sentries_data_get_size(int flags)
2495 {
2496     size_t size;
2497     int i;
2498 
2499     size = 0;
2500     for(i=0;i<_magic_sentries_num;i++) {
2501         size += _magic_sentries[i].type->size;
2502     }
2503 
2504     return size;
2505 }
2506 
2507 /*===========================================================================*
2508  *                       magic_dsentries_data_get_size                       *
2509  *===========================================================================*/
2510 PUBLIC size_t magic_dsentries_data_get_size(int flags)
2511 {
2512     size_t size;
2513     struct _magic_dsentry *prev_dsentry, *dsentry;
2514     struct _magic_sentry* sentry;
2515 
2516     size = 0;
2517     MAGIC_DSENTRY_ALIVE_ITER(_magic_first_dsentry, prev_dsentry, dsentry, sentry,
2518         if(!MAGIC_STATE_FLAG(sentry, MAGIC_STATE_OUT_OF_BAND)) {
2519             size += sentry->type->size;
2520             if(MAGIC_STATE_FLAG(sentry, MAGIC_STATE_HEAP)) {
2521                 /* Assume a couple of words for malloc header. */
2522                 size += 2*sizeof(void*);
2523             }
2524         }
2525     );
2526 
2527     return size;
2528 }
2529 
2530 /*===========================================================================*
2531  *                         magic_other_data_get_size                         *
2532  *===========================================================================*/
2533 PUBLIC size_t magic_other_data_get_size(int flags)
2534 {
2535     size_t size = 0;
2536 
2537     MAGIC_DSENTRY_LOCK();
2538     magic_range_is_stack(NULL);
2539     MAGIC_DSENTRY_UNLOCK();
2540     size += MAGIC_RANGE_SIZE(magic_stack_range);
2541     size += MAGIC_RANGE_SIZE(magic_text_range);
2542 
2543     return size;
2544 }
2545 
2546 /*===========================================================================*
2547  *                            magic_data_get_size                            *
2548  *===========================================================================*/
2549 PUBLIC size_t magic_data_get_size(int flags)
2550 {
2551     size_t size = 0;
2552 
2553     size += magic_sentries_data_get_size(flags);
2554     size += magic_dsentries_data_get_size(flags);
2555     size += magic_other_data_get_size(flags);
2556 
2557     return size;
2558 }
2559 
2560 /*===========================================================================*
2561  *                           magic_print_size_stats                          *
2562  *===========================================================================*/
2563 PUBLIC void magic_print_size_stats(int flags)
2564 {
2565     size_t sentries_data_size, sentries_metadata_size;
2566     size_t dsentries_data_size, dsentries_metadata_size;
2567     size_t data_size, metadata_size;
2568     int dsentries_num;
2569     sentries_data_size = magic_sentries_data_get_size(flags);
2570     sentries_metadata_size = magic_sentries_get_size(flags);
2571     dsentries_data_size = magic_dsentries_data_get_size(flags);
2572     dsentries_metadata_size = magic_dsentries_get_size(flags);
2573     data_size = magic_data_get_size(flags);
2574     metadata_size = magic_metadata_get_size(flags);
2575     MAGIC_DSENTRY_NUM(_magic_first_dsentry, &dsentries_num);
2576     _magic_printf("--------------------------------------------------------\n");
2577     _magic_printf("magic_print_size_stats: Printing size stats:\n");
2578     _magic_printf("    - sentries:  # %6d, data %8d, metadata %8d, total %8d, ratio %.3f\n", _magic_sentries_num, sentries_data_size, sentries_metadata_size, sentries_data_size+sentries_metadata_size, ((double)sentries_metadata_size)/sentries_data_size);
2579     _magic_printf("    - dsentries: # %6d, data %8d, metadata %8d, total %8d, ratio %.3f\n", dsentries_num, dsentries_data_size, dsentries_metadata_size, dsentries_data_size+dsentries_metadata_size, ((double)dsentries_metadata_size)/dsentries_data_size);
2580     _magic_printf("    - other:     # %6d, data %8d\n", 2, magic_other_data_get_size(flags));
2581     _magic_printf("    - state all: # %6d, data %8d, metadata %8d, total %8d, ratio %.3f\n", _magic_sentries_num+dsentries_num, sentries_data_size+dsentries_data_size, metadata_size, sentries_data_size+dsentries_data_size+metadata_size, ((double)metadata_size)/(sentries_data_size+dsentries_data_size));
2582     _magic_printf("    - all:       # %6d, data %8d, metadata %8d, total %8d, ratio %.3f\n", _magic_sentries_num+dsentries_num+2, data_size, metadata_size, data_size+metadata_size, ((double)metadata_size)/data_size);
2583     _magic_printf("--------------------------------------------------------\n");
2584     _magic_printf("magic_print_size_stats: Printing metadata size breakdown:\n");
2585     _magic_printf("    - types:     # %6d, metadata %8d\n", _magic_types_num, magic_types_get_size(flags));
2586     _magic_printf("    - functions: # %6d, metadata %8d\n", _magic_functions_num, magic_functions_get_size(flags));
2587     _magic_printf("    - dfunctions # %6d, metadata %8d\n", 0, magic_dfunctions_get_size(flags));
2588     _magic_printf("    - sentries:  # %6d, metadata %8d\n", _magic_sentries_num, sentries_metadata_size);
2589     _magic_printf("    - dsentries: # %6d, metadata %8d\n", dsentries_num, dsentries_metadata_size);
2590     _magic_printf("    - dsindexes: # %6d, metadata %8d\n", _magic_dsindexes_num, magic_dsindexes_get_size(flags));
2591     _magic_printf("    - dsodescs:  # %6d, metadata %8d\n", 0, magic_dsodescs_get_size(flags));
2592     _magic_printf("--------------------------------------------------------\n");
2593 }
2594 
2595