Drop main() prototype. Syncs with NetBSD-8
[minix.git] / minix / lib / libmagicrt / magic.c
blob553b3d42771abb6dc781ee04e00f9d232ba2f28f
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
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;
18 #include <ncurses.h>
19 PUBLIC WINDOW *UNUSED(_____magic_instr_WINDOW_unused);
20 #endif
22 #include <netinet/in.h>
23 PUBLIC struct in6_addr *UNUSED(_____magic_instr_in6_addr_unused);
25 /* Magic printf. */
26 MAGIC_VAR printf_ptr_t _magic_printf = MAGIC_PRINTF_DEFAULT;
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;
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;
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;
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;
49 /* Magic vars references. */
50 MAGIC_VAR struct _magic_vars_t _magic_vars_buff = {
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 */
60 /* Runtime flags. */
61 0, /* no_mem_inst */
63 /* Magic type array. */
64 NULL, /* types */
65 0, /* types_num */
66 0, /* types_next_id */
68 /* Magic function array. */
69 NULL, /* functions */
70 0, /* functions_num */
71 0, /* functions_next_id */
73 /* Magic state entry array. */
74 NULL, /* sentries */
75 0, /* sentries_num */
76 0, /* sentries_str_num */
77 0, /* sentries_next_id */
79 /* Magic dynamic state index array. */
80 NULL, /* dsindexes */
81 0, /* dsindexes_num */
83 /* Magic dynamic state entry list. */
84 NULL, /* first_dsentry */
85 0, /* num_dead_sentries */
86 0, /* size_dead_dsentries */
88 /* Magic memory pool dynamic state entry list. */
89 NULL, /* first_mempool_dsentry */
91 /* Magic dynamic function list. */
92 NULL, /* first_dfunction */
93 NULL, /* last_dfunction */
94 0, /* dfunctions_num */
96 /* Magic SO library descriptor list. */
97 NULL, /* first_sodesc */
98 NULL, /* last_sodesc */
99 0, /* sodescs_num */
101 /* Magic DSO library descriptor list. */
102 NULL, /* first_dsodesc */
103 NULL, /* last_dsodesc */
104 0, /* dsodescs_num */
106 /* Magic stack-related variables. */
107 NULL, /* first_stack_dsentry */
108 NULL, /* last_stack_dsentry */
110 /* Magic memory ranges */
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] */
120 {0,0}, /* *sentry_range[2] */
121 {0,0}, /* *function_range[2] */
122 {0,0}, /* *dfunction_range[2] */
124 NULL, /* *heap_start */
125 NULL, /* *heap_end */
126 1, /* update_dsentry_ranges */
127 1, /* update_dfunction_ranges */
129 #ifdef __MINIX
130 { { NULL, 0 } }, /* unmap_mem */
131 #endif
133 NULL, /* sentry_rl_buff */
134 0, /* sentry_rl_buff_offset */
135 0, /* sentry_rl_buff_size */
136 NULL, /* sentry_rl_index */
138 NULL, /* sentry_hash_buff */
139 0, /* sentry_hash_buff_offset */
140 0, /* sentry_hash_buff_size */
141 NULL, /* sentry_hash_head */
143 NULL, /* function_hash_buff */
144 0, /* function_hash_buff_offset */
145 0, /* function_hash_buff_size */
146 NULL, /* function_hash_head */
148 0 /* fake_malloc */
151 PUBLIC struct _magic_vars_t *_magic_vars = &_magic_vars_buff;
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];
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;
164 /* Magic annotations. */
165 MAGIC_VAR VOLATILE int MAGIC_CALL_ANNOTATION_VAR;
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;
178 /* Magic out-of-band dsentries. */
179 PUBLIC struct _magic_obdsentry _magic_obdsentries[MAGIC_MAX_OBDSENTRIES];
181 /* Pool management data. */
182 PUBLIC struct _magic_mpdesc _magic_mpdescs[MAGIC_MAX_MEMPOOLS];
184 /* Magic page size. */
185 PUBLIC unsigned long magic_sys_pagesize = 0;
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;
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
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 */
224 PUBLIC struct _magic_dfunction magic_default_dfunction = {
225 MAGIC_DFUNCTION_MNUM,
227 { 0, "", NULL, MAGIC_STATE_DYNAMIC|MAGIC_STATE_TEXT|MAGIC_STATE_CONSTANT, NULL },
228 NULL,
229 NULL
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
236 /* Magic code reentrant flag. */
237 PRIVATE int magic_reentrant = 1;
239 /*===========================================================================*
240 * _magic_vars_addr *
241 *===========================================================================*/
242 void *_magic_vars_addr()
244 return _magic_vars;
247 /*===========================================================================*
248 * _magic_vars_size *
249 *===========================================================================*/
250 size_t _magic_vars_size()
252 return sizeof(struct _magic_vars_t);
255 /*===========================================================================*
256 * magic_null_printf *
257 *===========================================================================*/
258 PUBLIC int magic_null_printf(const char *format, ...)
260 return 0;
263 #ifndef __MINIX
264 /*===========================================================================*
265 * magic_err_printf *
266 *===========================================================================*/
267 PUBLIC int magic_err_printf(const char *format, ...)
269 va_list va;
270 int ret;
271 va_start(va, format);
272 ret = vfprintf(stderr, format, va);
273 va_end(va);
275 return ret;
277 #endif
279 /*===========================================================================*
280 * magic_set_printf *
281 *===========================================================================*/
282 PUBLIC void magic_set_printf(printf_ptr_t func_ptr)
284 assert(func_ptr);
285 _magic_printf = func_ptr;
288 /*===========================================================================*
289 * magic_get_printf *
290 *===========================================================================*/
291 PUBLIC printf_ptr_t magic_get_printf(void)
293 return _magic_printf;
296 /*===========================================================================*
297 * magic_reentrant_enable *
298 *===========================================================================*/
299 PUBLIC void magic_reentrant_enable(void)
301 magic_reentrant = 1;
303 /*===========================================================================*
304 * magic_reentrant_disable *
305 *===========================================================================*/
306 PUBLIC void magic_reentrant_disable(void)
308 magic_reentrant = 0;
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)
317 _magic_printf("Assertion '%s' failed in file %s, function %s(), line %d, pid %d\n",
318 assertion, file, function, line, getpid());
319 abort();
322 /*===========================================================================*
323 * magic_get_sys_pagesize *
324 *===========================================================================*/
325 PUBLIC unsigned long magic_get_sys_pagesize()
327 if(!magic_sys_pagesize) {
328 magic_sys_pagesize = SYS_PAGESIZE;
330 return magic_sys_pagesize;
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)
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;
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)
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;
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)
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;
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)
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;
385 /*===========================================================================*
386 * magic_types_init *
387 *===========================================================================*/
388 PRIVATE void magic_types_init()
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];
399 assert(MAGIC_VOID_PTR_TYPE);
400 assert(MAGIC_VOID_PTR_TYPE->size == sizeof(void*));
401 assert(MAGIC_VOID_TYPE->size == sizeof(char));
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;
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);
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);
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);
423 /*===========================================================================*
424 * magic_data_init *
425 *===========================================================================*/
426 MAGIC_FUNC void magic_data_init(void)
428 MAGIC_FUNC_BODY();
431 /*===========================================================================*
432 * magic_init *
433 *===========================================================================*/
434 PUBLIC void magic_init(void)
436 unsigned i;
438 if(magic_init_done || !_magic_enabled) {
439 return;
442 /* Initialize magic data structures first. */
443 magic_data_init();
445 /* Initialize asr support. */
446 magic_asr_init();
448 /* Initialize eval support. */
449 magic_eval_init();
451 /* Initialize magic obdsentries. */
452 memset(_magic_obdsentries, 0, MAGIC_MAX_OBDSENTRIES * sizeof(struct _magic_obdsentry));
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);
459 /* Initialize special types. */
460 magic_types_init();
462 /* Initialize magic ranges. */
463 magic_ranges_init();
465 /* Perform stack-related initialization. */
466 magic_stack_init();
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
473 /* Checks. */
474 assert(magic_check_sentries() && "Bad sentries!");
475 assert(magic_check_dsentries_safe() && "Bad dsentries!");
477 /* All done. */
478 magic_init_done = 1;
481 /*===========================================================================*
482 * magic_do_check_dfunction *
483 *===========================================================================*/
484 PRIVATE INLINE int magic_do_check_dfunction(struct _magic_dfunction *dfunction, int flags)
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;
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;
504 return TRUE;
507 /*===========================================================================*
508 * magic_check_dfunction *
509 *===========================================================================*/
510 PUBLIC int magic_check_dfunction(struct _magic_dfunction *dfunction, int flags)
512 int check;
513 check = magic_do_check_dfunction(dfunction, flags);
514 if(!check) {
515 return FALSE;
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;
524 #endif
526 return TRUE;
529 /*===========================================================================*
530 * magic_check_dfunctions *
531 *===========================================================================*/
532 PUBLIC int magic_check_dfunctions()
534 int magic_dfunctions_found = 0;
535 struct _magic_dfunction* dfunction = NULL;
536 struct _magic_function* function = NULL;
537 int ret, check = TRUE;
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;
544 magic_dfunctions_found++;
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;
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;
554 return check;
557 /*===========================================================================*
558 * magic_check_dfunctions_safe *
559 *===========================================================================*/
560 PUBLIC int magic_check_dfunctions_safe()
562 int ret;
563 MAGIC_DFUNCTION_LOCK();
564 ret = magic_check_dfunctions();
565 MAGIC_DFUNCTION_UNLOCK();
566 return ret;
569 /*===========================================================================*
570 * magic_print_dfunction *
571 *===========================================================================*/
572 PUBLIC void magic_print_dfunction(struct _magic_dfunction *dfunction)
574 MAGIC_DFUNCTION_PRINT(dfunction, MAGIC_EXPAND_TYPE_STR);
577 /*===========================================================================*
578 * magic_print_dfunctions *
579 *===========================================================================*/
580 PUBLIC void magic_print_dfunctions()
582 int magic_dfunctions_found = 0;
583 struct _magic_dfunction* dfunction;
584 struct _magic_function* function;
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++;
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);
597 /*===========================================================================*
598 * magic_print_dfunctions_safe *
599 *===========================================================================*/
600 PUBLIC void magic_print_dfunctions_safe()
602 MAGIC_DFUNCTION_LOCK();
603 magic_print_dfunctions();
604 MAGIC_DFUNCTION_UNLOCK();
607 /*===========================================================================*
608 * magic_copy_dfunction *
609 *===========================================================================*/
610 PUBLIC void magic_copy_dfunction(struct _magic_dfunction *dfunction,
611 struct _magic_dfunction *dst_dfunction)
613 /* Raw copy. */
614 memcpy(dst_dfunction, dfunction, sizeof(struct _magic_dfunction));
617 /*===========================================================================*
618 * magic_print_dsindex *
619 *===========================================================================*/
620 PUBLIC void magic_print_dsindex(struct _magic_dsindex *dsindex)
622 MAGIC_DSINDEX_PRINT(dsindex, MAGIC_EXPAND_TYPE_STR);
625 /*===========================================================================*
626 * magic_print_dsindexes *
627 *===========================================================================*/
628 PUBLIC void magic_print_dsindexes()
630 int i;
631 struct _magic_dsindex* dsindex;
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");
641 /*===========================================================================*
642 * magic_do_check_dsentry *
643 *===========================================================================*/
644 PRIVATE INLINE int magic_do_check_dsentry(struct _magic_dsentry *dsentry, int flags)
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;
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;
664 return TRUE;
667 /*===========================================================================*
668 * magic_check_dsentry *
669 *===========================================================================*/
670 PUBLIC int magic_check_dsentry(struct _magic_dsentry *dsentry, int flags)
672 #if MAGIC_CHECK_LEVEL >= 1
673 int check;
674 check = magic_do_check_dsentry(dsentry, flags);
675 if(!check) {
676 return FALSE;
678 #endif
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;
686 #endif
688 return TRUE;
691 /*===========================================================================*
692 * magic_check_dsentries *
693 *===========================================================================*/
694 PUBLIC int magic_check_dsentries()
696 struct _magic_dsentry *prev_dsentry, *dsentry;
697 struct _magic_sentry* sentry;
698 int ret, check = TRUE;
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;
706 return check;
709 /*===========================================================================*
710 * magic_check_dsentries_safe *
711 *===========================================================================*/
712 PUBLIC int magic_check_dsentries_safe()
714 int ret;
715 MAGIC_DSENTRY_LOCK();
716 ret = magic_check_dsentries();
717 MAGIC_DSENTRY_UNLOCK();
718 return ret;
721 /*===========================================================================*
722 * magic_print_dsentry *
723 *===========================================================================*/
724 PUBLIC void magic_print_dsentry(struct _magic_dsentry *dsentry)
726 MAGIC_DSENTRY_PRINT(dsentry, MAGIC_EXPAND_TYPE_STR);
729 /*===========================================================================*
730 * magic_print_dsentries *
731 *===========================================================================*/
732 PUBLIC void magic_print_dsentries()
734 struct _magic_dsentry *prev_dsentry, *dsentry;
735 struct _magic_sentry* sentry;
736 int magic_dsentries_num = 0;
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++;
744 _magic_printf("magic_print_dsentries: %d entries found\n", magic_dsentries_num);
747 /*===========================================================================*
748 * magic_print_dsentries_safe *
749 *===========================================================================*/
750 PUBLIC void magic_print_dsentries_safe()
752 MAGIC_DSENTRY_LOCK();
753 magic_print_dsentries();
754 MAGIC_DSENTRY_UNLOCK();
757 /*===========================================================================*
758 * magic_copy_dsentry *
759 *===========================================================================*/
760 PUBLIC void magic_copy_dsentry(struct _magic_dsentry *dsentry,
761 struct _magic_dsentry *dst_dsentry)
763 struct _magic_sentry *sentry;
765 /* Raw copy. */
766 memcpy(dst_dsentry, dsentry, sizeof(struct _magic_dsentry));
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;
778 /*===========================================================================*
779 * magic_print_sodesc *
780 *===========================================================================*/
781 PUBLIC void magic_print_sodesc(struct _magic_sodesc *sodesc)
783 MAGIC_SODESC_PRINT(sodesc);
786 /*===========================================================================*
787 * magic_print_sodescs *
788 *===========================================================================*/
789 PUBLIC void magic_print_sodescs()
791 int magic_sodescs_found = 0;
792 struct _magic_sodesc* sodesc;
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++;
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);
805 /*===========================================================================*
806 * magic_print_dsodesc *
807 *===========================================================================*/
808 PUBLIC void magic_print_dsodesc(struct _magic_dsodesc *dsodesc)
810 MAGIC_DSODESC_PRINT(dsodesc);
813 /*===========================================================================*
814 * magic_print_dsodescs *
815 *===========================================================================*/
816 PUBLIC void magic_print_dsodescs()
818 int magic_dsodescs_found = 0;
819 struct _magic_dsodesc* dsodesc;
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++;
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);
832 /*===========================================================================*
833 * magic_print_dsodescs_safe *
834 *===========================================================================*/
835 PUBLIC void magic_print_dsodescs_safe()
837 MAGIC_DSODESC_LOCK();
838 magic_print_dsodescs();
839 MAGIC_DSODESC_UNLOCK();
842 /*===========================================================================*
843 * magic_print_sections *
844 *===========================================================================*/
845 PUBLIC void magic_print_sections(void)
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);
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)
861 struct _magic_dsentry *prev_dsentry, *dsentry;
862 struct _magic_sentry* sentry;
863 struct _magic_sentry* entry = NULL;
864 void *start_address, *end_address;
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);
875 else {
876 entry = sentry;
878 break;
881 MAGIC_DSENTRY_UNLOCK();
883 return entry;
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)
892 int i;
893 struct _magic_dsindex* index = NULL;
894 assert(parent_name && name);
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;
905 return index;
908 /*===========================================================================*
909 * magic_dsentry_prev_lookup *
910 *===========================================================================*/
911 PUBLIC struct _magic_dsentry* magic_dsentry_prev_lookup(struct _magic_dsentry* dsentry)
913 struct _magic_dsentry *prev_dsentry, *it_dsentry;
914 struct _magic_sentry *sentry;
915 int found = 0;
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;
926 if(!found) {
927 return (struct _magic_dsentry*) MAGIC_ENOPTR;
929 return prev_dsentry;
930 #endif
933 /*===========================================================================*
934 * magic_mempool_dsentry_prev_lookup *
935 *===========================================================================*/
936 PUBLIC struct _magic_dsentry* magic_mempool_dsentry_prev_lookup(struct _magic_dsentry* dsentry)
938 struct _magic_dsentry *prev_dsentry, *it_dsentry;
939 struct _magic_sentry *sentry;
940 int found = 0;
942 MAGIC_DSENTRY_MEMPOOL_ITER(_magic_first_mempool_dsentry, prev_dsentry, it_dsentry, sentry,
943 if(dsentry == it_dsentry) {
944 found = 1;
945 break;
948 if(!found) {
949 return (struct _magic_dsentry*) MAGIC_ENOPTR;
951 return prev_dsentry;
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)
960 struct _magic_function* entry = NULL;
961 struct _magic_function* function;
962 struct _magic_dfunction* dfunction;
964 if(id <= 0) {
965 return NULL;
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];
973 #endif
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);
984 else {
985 entry = function;
987 break;
990 MAGIC_DFUNCTION_UNLOCK();
991 #endif
993 return entry;
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)
1002 int i;
1003 struct _magic_function *entry = NULL;
1004 struct _magic_function *function;
1005 struct _magic_dfunction *dfunction;
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);
1011 #endif
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;
1023 #endif
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);
1034 else {
1035 entry = function;
1037 break;
1041 MAGIC_DFUNCTION_UNLOCK();
1042 #endif
1044 return entry;
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)
1053 int i;
1054 struct _magic_function* entry = NULL;
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;
1066 #endif
1068 return entry;
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)
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;
1085 * **** START UTHASH SPECIFIC DEFINITIONS ****
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)
1092 * Since we have a limited buffer, we need to stop bucket expansion when
1093 * reaching a certain limit.
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; \
1105 } while(0);
1107 * **** FINISH UTHASH SPECIFIC DEFINITIONS ****
1109 HASH_ADD_PTR(*head, key, elem);
1111 * **** START UTHASH DEFINITION REMOVAL ****
1113 #undef uthash_malloc
1114 #undef uthash_free
1115 #undef uthash_expand_fyi
1117 * **** FINISH UTHASH DEFINITION REMOVAL ****
1121 /*===========================================================================*
1122 * magic_function_hash_build *
1123 *===========================================================================*/
1124 PUBLIC void magic_function_hash_build(void *buff, size_t buff_size)
1127 * XXX:
1128 * Warning: this implementation is thread unsafe and also makes
1129 * magic_function_lookup_by_addr thread unsafe!
1131 int i;
1132 struct _magic_dfunction *dfunction;
1133 struct _magic_function *function;
1134 struct _magic_function_hash *function_hash, *head;
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;
1141 head = NULL;
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);
1152 #endif
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);
1163 MAGIC_DFUNCTION_UNLOCK();
1164 #endif
1165 magic_function_hash_head = (void *)head;
1166 assert(magic_function_hash_head);
1169 /*===========================================================================*
1170 * magic_function_hash_destroy *
1171 *===========================================================================*/
1172 PUBLIC void magic_function_hash_destroy(void)
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;
1180 /*===========================================================================*
1181 * magic_function_hash_estimate_buff_size *
1182 *===========================================================================*/
1183 PUBLIC size_t magic_function_hash_estimate_buff_size(int functions_num)
1185 if (functions_num == 0) {
1186 functions_num = _magic_dfunctions_num;
1187 functions_num += _magic_functions_num;
1190 return (functions_num * sizeof(struct _magic_function_hash)) +
1191 MAGIC_FUNCTION_ADDR_HASH_OVERHEAD;
1194 /*===========================================================================*
1195 * magic_function_hash_alloc *
1196 *===========================================================================*/
1197 PUBLIC void* magic_function_hash_alloc(size_t size)
1199 void *addr;
1201 assert(magic_function_hash_buff);
1202 assert(magic_function_hash_buff_offset + size <=
1203 magic_function_hash_buff_size);
1205 addr = (char*) magic_function_hash_buff + magic_function_hash_buff_offset;
1206 magic_function_hash_buff_offset += size;
1208 return addr;
1211 /*===========================================================================*
1212 * magic_function_hash_dealloc *
1213 *===========================================================================*/
1214 PUBLIC void magic_function_hash_dealloc(UNUSED(void *object), UNUSED(size_t sz))
1216 return;
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)
1226 * Warning: this implementation is thread unsafe!
1228 struct _magic_function_hash *res, *head;
1229 head = (struct _magic_function_hash *) magic_function_hash_head;
1231 HASH_FIND_PTR(head, &addr, res);
1232 if (res == NULL)
1233 return NULL;
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);
1241 return res->function;
1244 /*===========================================================================*
1245 * magic_type_lookup_by_name *
1246 *===========================================================================*/
1247 PUBLIC struct _magic_type* magic_type_lookup_by_name(const char *name)
1249 int i;
1250 unsigned int j;
1251 struct _magic_type* entry = NULL;
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;
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;
1267 if (entry) {
1268 break;
1272 #endif
1274 return entry;
1277 /*===========================================================================*
1278 * magic_dsodesc_lookup_by_handle *
1279 *===========================================================================*/
1280 PUBLIC struct _magic_dsodesc* magic_dsodesc_lookup_by_handle(void *handle)
1282 struct _magic_dsodesc* desc = NULL;
1283 struct _magic_dsodesc* dsodesc;
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.
1290 MAGIC_DSODESC_ITER(_magic_first_dsodesc, dsodesc,
1291 if(dsodesc->handle == handle) {
1292 desc = dsodesc;
1293 break;
1297 return desc;
1300 /*===========================================================================*
1301 * magic_print_function *
1302 *===========================================================================*/
1303 PUBLIC void magic_print_function(struct _magic_function *function)
1305 MAGIC_FUNCTION_PRINT(function, MAGIC_EXPAND_TYPE_STR);
1308 /*===========================================================================*
1309 * magic_print_functions *
1310 *===========================================================================*/
1311 PUBLIC void magic_print_functions()
1313 int i;
1314 struct _magic_function* function;
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");
1324 /*===========================================================================*
1325 * magic_print_type *
1326 *===========================================================================*/
1327 PUBLIC void magic_print_type(const struct _magic_type* type)
1329 MAGIC_TYPE_PRINT(type, MAGIC_EXPAND_TYPE_STR);
1332 /*===========================================================================*
1333 * magic_print_types *
1334 *===========================================================================*/
1335 PUBLIC void magic_print_types()
1337 int i;
1338 struct _magic_type* type;
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");
1348 /*===========================================================================*
1349 * magic_type_str_set_print_style *
1350 *===========================================================================*/
1351 PUBLIC void magic_type_str_set_print_style(const int style)
1353 magic_type_str_print_style = style;
1356 /*===========================================================================*
1357 * magic_type_str_get_print_style *
1358 *===========================================================================*/
1359 PUBLIC int magic_type_str_get_print_style()
1361 return magic_type_str_print_style;
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)
1370 int i;
1371 int nesting_level = -1;
1373 for(i=0;i<level;i++) {
1374 if(magic_nested_types[i] == type) {
1375 nesting_level = i;
1376 break;
1380 return nesting_level;
1383 /*===========================================================================*
1384 * magic_type_str_print *
1385 *===========================================================================*/
1386 PUBLIC void magic_type_str_print(const struct _magic_type* type)
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);
1395 if(magic_level == 0) {
1396 magic_counter = 0;
1398 else if(magic_counter >= MAGIC_TYPE_STR_PRINT_MAX) {
1399 _magic_printf("%%");
1400 return;
1402 else if(magic_level >= MAGIC_TYPE_STR_PRINT_MAX_LEVEL) {
1403 _magic_printf("%%");
1404 return;
1407 if(MAGIC_TYPE_STR_PRINT_DEBUG) {
1408 _magic_printf("Entering level %d...\n", magic_level);
1411 if(type->type_id == MAGIC_TYPE_OPAQUE) {
1412 _magic_printf("opaque");
1413 magic_counter += strlen("opaque");
1414 return;
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;
1426 else {
1427 _magic_printf("%s/%s", type->type_str, type->name);
1428 magic_counter += strlen(type->type_str)+1+strlen(type->name);
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);
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;
1440 else {
1441 _magic_printf(type->name);
1442 magic_counter += strlen(type->name);
1445 return;
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;
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;
1468 else if(print_ptr_name) {
1469 _magic_printf("|");
1470 _magic_printf("%s", type->name);
1471 magic_counter += 1+strlen(type->name);
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;
1484 if(num_elements) {
1485 _magic_printf("%d x ", num_elements);
1486 magic_counter += 5;
1488 magic_type_str_print(type->contained_types[0]);
1489 _magic_printf("%c", end_sep);
1490 magic_counter += 1;
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;
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;
1508 else {
1509 _magic_printf("$%s ", strcmp(type->name, "") ? type->name : "ANONYMOUS");
1510 magic_counter += 2 + strlen(strcmp(type->name, "") ? type->name : "ANONYMOUS");
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;
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;
1525 magic_type_str_print(type->contained_types[i]);
1528 _magic_printf(" }");
1529 magic_counter += 2;
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;
1543 magic_type_str_print(type->contained_types[i+1]);
1545 _magic_printf(")");
1546 magic_counter += 1;
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;
1552 magic_level--;
1553 if(MAGIC_TYPE_STR_PRINT_DEBUG) {
1554 _magic_printf("Exiting level %d...\n", magic_level);
1558 /*===========================================================================*
1559 * magic_type_values_print *
1560 *===========================================================================*/
1561 PUBLIC void magic_type_values_print(const struct _magic_type* type)
1563 int i=0;
1565 if(!MAGIC_TYPE_HAS_VALUE_SET(type)) {
1566 return;
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++;
1575 /*===========================================================================*
1576 * magic_type_names_print *
1577 *===========================================================================*/
1578 PUBLIC void magic_type_names_print(const struct _magic_type* type)
1580 unsigned int i;
1582 for(i=0;i<type->num_names;i++) {
1583 _magic_printf("%s%s", (i==0 ? "" : "|"), type->names[i]);
1587 /*===========================================================================*
1588 * magic_type_comp_types_print *
1589 *===========================================================================*/
1590 PUBLIC void magic_type_comp_types_print(const struct _magic_type* type,
1591 int flags)
1593 int num;
1594 int i=0;
1595 const struct _magic_type* comp_type;
1597 if(!MAGIC_TYPE_HAS_COMP_TYPES(type)) {
1598 return;
1600 MAGIC_TYPE_NUM_COMP_TYPES(type, &num);
1601 _magic_printf("#%d", num);
1602 if(flags & MAGIC_SKIP_COMP_TYPES) {
1603 return;
1605 flags &= ~MAGIC_EXPAND_TYPE_STR;
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++;
1614 /*===========================================================================*
1615 * magic_type_str_print_from_target *
1616 *===========================================================================*/
1617 PUBLIC int magic_type_str_print_from_target(void* target)
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;
1626 if(printed_types == 0) {
1627 _magic_printf("BAD OFFSET");
1629 return printed_types;
1632 /*===========================================================================*
1633 * magic_type_equals *
1634 *===========================================================================*/
1635 PUBLIC int magic_type_equals(const struct _magic_type* type, const struct _magic_type* other_type)
1637 assert(magic_level < MAGIC_MAX_RECURSIVE_TYPES);
1639 if(type == other_type) {
1640 return TRUE;
1642 if(type->type_id != other_type->type_id) {
1643 return FALSE;
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);
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]);
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;
1665 magic_level--;
1666 return TRUE;
1669 return FALSE;
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)
1677 int i, nesting_level, num_contained_types;
1678 assert(magic_level < MAGIC_MAX_RECURSIVE_TYPES);
1680 if(type == other_type) {
1681 return TRUE;
1684 if(type->type_id != other_type->type_id) {
1685 return FALSE;
1688 if(type->num_child_types != other_type->num_child_types) {
1689 return FALSE;
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;
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;
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;
1709 i++;
1711 if(MAGIC_TYPE_HAS_VALUE(type, i) || MAGIC_TYPE_HAS_VALUE(other_type, i)) {
1712 return FALSE;
1717 if(flags & MAGIC_TYPE_COMPARE_NAME) {
1718 if(strcmp(type->name, other_type->name)){
1719 return FALSE;
1723 if(flags & MAGIC_TYPE_COMPARE_NAMES) {
1724 if(type->num_names != other_type->num_names) {
1725 return FALSE;
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;
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);
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;
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;
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]);
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;
1771 magic_level--;
1772 return TRUE;
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)
1780 const struct _magic_type *comp_type;
1782 MAGIC_TYPE_COMP_ITER(type, comp_type,
1783 if(magic_type_compatible(comp_type, other_type, 0)) {
1784 return TRUE;
1788 return FALSE;
1791 /*===========================================================================*
1792 * magic_type_ptr_is_text *
1793 *===========================================================================*/
1794 PUBLIC int magic_type_ptr_is_text(const struct _magic_type* ptr_type)
1796 const struct _magic_type *comp_type;
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;
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;
1811 return FALSE;
1814 /*===========================================================================*
1815 * magic_type_ptr_is_data *
1816 *===========================================================================*/
1817 PUBLIC int magic_type_ptr_is_data(const struct _magic_type* ptr_type)
1819 const struct _magic_type *comp_type;
1821 assert(ptr_type->type_id == MAGIC_TYPE_POINTER);
1822 if(ptr_type->contained_types[0]->type_id != MAGIC_TYPE_FUNCTION) {
1823 return TRUE;
1826 MAGIC_TYPE_COMP_ITER(ptr_type, comp_type,
1827 if(comp_type->type_id != MAGIC_TYPE_FUNCTION) {
1828 return TRUE;
1832 return FALSE;
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)
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;
1847 assert(type->type_id == MAGIC_TYPE_STRUCT);
1849 if(alloc_size <= type->size || type->num_child_types == 0) {
1850 return FALSE;
1852 array_type = type->contained_types[type->num_child_types-1];
1853 if(array_type->type_id != MAGIC_TYPE_ARRAY) {
1854 return FALSE;
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;
1862 if(num_elements) {
1863 *num_elements = 1+array_size/array_el_type->size;
1866 return TRUE;
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)
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;
1881 assert(type->type_id == MAGIC_TYPE_STRUCT);
1883 if(num_elements == 1) {
1884 return type->size;
1886 array_type = type->contained_types[type->num_child_types-1];
1887 if(array_type->type_id != MAGIC_TYPE_ARRAY) {
1888 return 0;
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);
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)
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;
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));
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;
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;
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;
1933 if(offset >= min_offset && offset <= max_offset) {
1934 ret = cb(parent_type, parent_offset, child_num, type, offset, magic_depth, cb_args);
1936 else if(offset > max_offset) {
1937 ret = MAGIC_TYPE_WALK_STOP;
1939 else if(offset+type->size <= min_offset) {
1940 ret = MAGIC_TYPE_WALK_SKIP_PATH;
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.
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;
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);
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;
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;
1988 return status;
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)
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;
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;
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;
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);
2024 else {
2025 memcpy(MAGIC_DSENTRY_TO_SENTRY(*trg_dsentry), sentry, sizeof(struct _magic_sentry));
2028 if (trg_dfunction) {
2029 *trg_dfunction = NULL;
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);
2037 else {
2038 memcpy(MAGIC_DFUNCTION_TO_FUNCTION(*trg_dfunction), function, sizeof(struct _magic_function));
2041 if (trg_dsentry) {
2042 *trg_dsentry = NULL;
2045 } else {
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.
2054 if (sentry) {
2055 if (trg_dsentry) {
2056 *trg_dsentry = MAGIC_DSENTRY_FROM_SENTRY(sentry);
2058 if (trg_dfunction) {
2059 *trg_dfunction = NULL;
2062 else {
2063 if (trg_dfunction) {
2064 *trg_dfunction = MAGIC_DFUNCTION_FROM_FUNCTION(function);
2066 if (trg_dsentry) {
2067 *trg_dsentry = NULL;
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);
2078 return ret;
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)
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);
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)
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;
2111 type_size -= addr_off_by;
2112 offset_addr = (void*)((unsigned)offset_addr + addr_off_by);
2113 offset += addr_off_by;
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;
2121 type_size -= addr_off_by;
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);
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)
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;
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)
2149 int *type_counter = (int*) cb_args;
2150 if(type_counter) (*type_counter)++;
2151 return MAGIC_TYPE_WALK_CONTINUE;
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)
2161 void **args_array = (void**) cb_args;
2162 int *my_child_num = (int*) args_array[0];
2163 unsigned *child_offset = (unsigned*) args_array[1];
2165 if(!parent_type) {
2166 return MAGIC_TYPE_WALK_CONTINUE;
2168 if(child_num == *my_child_num) {
2169 *child_offset = offset;
2170 return MAGIC_TYPE_WALK_STOP;
2172 return MAGIC_TYPE_WALK_SKIP_PATH;
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)
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;
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];
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;
2203 else {
2204 *child_type = type->contained_types[0];
2205 *child_offset = child_num*((*child_type)->size);
2210 /*===========================================================================*
2211 * magic_type_get_size *
2212 *===========================================================================*/
2213 PUBLIC size_t magic_type_get_size(struct _magic_type *type, int flags)
2215 size_t size;
2216 int i, num_contained_types;
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);
2223 if(num_contained_types > 0) {
2224 size += sizeof(*(type->contained_types))*num_contained_types;
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;
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);
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;
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;
2257 return size;
2260 /*===========================================================================*
2261 * magic_types_get_size *
2262 *===========================================================================*/
2263 PUBLIC size_t magic_types_get_size(int flags)
2265 size_t size;
2266 int i;
2268 size = 0;
2269 for(i=0;i<_magic_types_num;i++) {
2270 size += magic_type_get_size(&_magic_types[i], flags);
2273 return size;
2276 /*===========================================================================*
2277 * magic_function_get_size *
2278 *===========================================================================*/
2279 PUBLIC size_t magic_function_get_size(struct _magic_function *function, int flags)
2281 size_t size;
2283 size = sizeof(function->type) + sizeof(function->flags) + sizeof(function->address);
2285 if(flags & MAGIC_SIZE_NAMES) {
2286 size += sizeof(function->name) + strlen(function->name)+1;
2289 return size;
2292 /*===========================================================================*
2293 * magic_functions_get_size *
2294 *===========================================================================*/
2295 PUBLIC size_t magic_functions_get_size(int flags)
2297 size_t size;
2298 int i;
2300 size = 0;
2301 for(i=0;i<_magic_functions_num;i++) {
2302 size += magic_function_get_size(&_magic_functions[i], flags);
2305 return size;
2308 /*===========================================================================*
2309 * magic_dfunctions_get_size *
2310 *===========================================================================*/
2311 PUBLIC size_t magic_dfunctions_get_size(int flags)
2313 size_t size;
2314 struct _magic_dfunction* dfunction;
2315 struct _magic_function* function;
2317 size = 0;
2318 MAGIC_DFUNCTION_FUNC_ITER(_magic_first_dfunction, dfunction, function,
2319 size += magic_function_get_size(function, flags);
2322 return size;
2325 /*===========================================================================*
2326 * magic_sentry_get_size *
2327 *===========================================================================*/
2328 PUBLIC size_t magic_sentry_get_size(struct _magic_sentry *sentry, int flags)
2330 size_t size;
2332 size = sizeof(sentry->type) + sizeof(sentry->flags);
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;
2342 if(sentry->type == &dsentry->type) {
2343 size += sizeof(dsentry->type.num_child_types);
2345 size += sizeof(dsentry->next);
2347 else {
2348 size += sizeof(sentry->address);
2349 if(flags & MAGIC_SIZE_NAMES) {
2350 size += sizeof(sentry->name) + strlen(sentry->name)+1;
2354 return size;
2357 /*===========================================================================*
2358 * magic_sentries_get_size *
2359 *===========================================================================*/
2360 PUBLIC size_t magic_sentries_get_size(int flags)
2362 size_t size;
2363 int i;
2365 size = 0;
2366 for(i=0;i<_magic_sentries_num;i++) {
2367 size += magic_sentry_get_size(&_magic_sentries[i], flags);
2370 return size;
2373 /*===========================================================================*
2374 * magic_dsentries_get_size *
2375 *===========================================================================*/
2376 PUBLIC size_t magic_dsentries_get_size(int flags)
2378 size_t size;
2379 struct _magic_dsentry *prev_dsentry, *dsentry;
2380 struct _magic_sentry* sentry;
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);
2389 return size;
2392 /*===========================================================================*
2393 * magic_dsindex_get_size *
2394 *===========================================================================*/
2395 PUBLIC size_t magic_dsindex_get_size(struct _magic_dsindex *dsindex, int flags)
2397 size_t size;
2399 size = sizeof(dsindex->type) + sizeof(dsindex->flags);
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;
2406 return size;
2409 /*===========================================================================*
2410 * magic_dsindexes_get_size *
2411 *===========================================================================*/
2412 PUBLIC size_t magic_dsindexes_get_size(int flags)
2414 size_t size;
2415 int i;
2417 size = 0;
2418 for(i=0;i<_magic_dsindexes_num;i++) {
2419 size += magic_dsindex_get_size(&_magic_dsindexes[i], flags);
2422 return size;
2425 /*===========================================================================*
2426 * magic_sodesc_get_size *
2427 *===========================================================================*/
2428 PUBLIC size_t magic_sodesc_get_size(struct _magic_sodesc *sodesc, int flags)
2430 return sizeof(struct _magic_sodesc);
2433 /*===========================================================================*
2434 * magic_sodescs_get_size *
2435 *===========================================================================*/
2436 PUBLIC size_t magic_sodescs_get_size(int flags)
2438 size_t size;
2439 struct _magic_sodesc* sodesc;
2441 size = 0;
2442 MAGIC_SODESC_ITER(_magic_first_sodesc, sodesc,
2443 size += magic_sodesc_get_size(sodesc, flags);
2446 return size;
2449 /*===========================================================================*
2450 * magic_dsodesc_get_size *
2451 *===========================================================================*/
2452 PUBLIC size_t magic_dsodesc_get_size(struct _magic_dsodesc *dsodesc, int flags)
2454 return sizeof(struct _magic_dsodesc);
2457 /*===========================================================================*
2458 * magic_dsodescs_get_size *
2459 *===========================================================================*/
2460 PUBLIC size_t magic_dsodescs_get_size(int flags)
2462 size_t size;
2463 struct _magic_dsodesc* dsodesc;
2465 size = 0;
2466 MAGIC_DSODESC_ITER(_magic_first_dsodesc, dsodesc,
2467 size += magic_dsodesc_get_size(dsodesc, flags);
2470 return size;
2473 /*===========================================================================*
2474 * magic_metadata_get_size *
2475 *===========================================================================*/
2476 PUBLIC size_t magic_metadata_get_size(int flags)
2478 size_t size = 0;
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);
2488 return size;
2491 /*===========================================================================*
2492 * magic_sentries_data_get_size *
2493 *===========================================================================*/
2494 PUBLIC size_t magic_sentries_data_get_size(int flags)
2496 size_t size;
2497 int i;
2499 size = 0;
2500 for(i=0;i<_magic_sentries_num;i++) {
2501 size += _magic_sentries[i].type->size;
2504 return size;
2507 /*===========================================================================*
2508 * magic_dsentries_data_get_size *
2509 *===========================================================================*/
2510 PUBLIC size_t magic_dsentries_data_get_size(int flags)
2512 size_t size;
2513 struct _magic_dsentry *prev_dsentry, *dsentry;
2514 struct _magic_sentry* sentry;
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*);
2527 return size;
2530 /*===========================================================================*
2531 * magic_other_data_get_size *
2532 *===========================================================================*/
2533 PUBLIC size_t magic_other_data_get_size(int flags)
2535 size_t size = 0;
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);
2543 return size;
2546 /*===========================================================================*
2547 * magic_data_get_size *
2548 *===========================================================================*/
2549 PUBLIC size_t magic_data_get_size(int flags)
2551 size_t size = 0;
2553 size += magic_sentries_data_get_size(flags);
2554 size += magic_dsentries_data_get_size(flags);
2555 size += magic_other_data_get_size(flags);
2557 return size;
2560 /*===========================================================================*
2561 * magic_print_size_stats *
2562 *===========================================================================*/
2563 PUBLIC void magic_print_size_stats(int flags)
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");