--- /dev/null
+#ifndef _UTIL_STDLIB_H
+#define _UTIL_STDLIB_H
+
+#include "util_def.h"
+
+#include <string.h>
+
+typedef struct util_stdlib_s {
+ int id;
+ char *name;
+ unsigned long flags;
+} util_stdlib_t;
+
+typedef enum util_stdlib_id_e {
+ STDLIB_ACCEPT = 0,
+ STDLIB_ACCEPT4,
+ STDLIB_BIND,
+ STDLIB_BRK,
+ STDLIB_CALLOC,
+ STDLIB_EPOLL_CREATE,
+ STDLIB_EPOLL_CREATE1,
+ STDLIB_EPOLL_WAIT,
+ STDLIB_FREE,
+ STDLIB_GETSOCKOPT,
+ STDLIB_KILL,
+ STDLIB_LISTEN,
+ STDLIB_MALLOC,
+ STDLIB_MEMALIGN,
+ STDLIB_MMAP,
+ STDLIB_MMAP64,
+ STDLIB_MUNMAP,
+ STDLIB_POLL,
+ STDLIB_POSIX_MEMALIGN,
+ STDLIB_PPOLL,
+ STDLIB_PTHREAD_COND_WAIT,
+ STDLIB_PTHREAD_COND_TIMEDWAIT,
+ STDLIB_PTHREAD_JOIN,
+ STDLIB_READ,
+ STDLIB_REALLOC,
+ STDLIB_RECV,
+ STDLIB_RECVFROM,
+ STDLIB_RECVMSG,
+ STDLIB_SBRK,
+ STDLIB_SELECT,
+ STDLIB_SEMOP,
+ STDLIB_SEMTIMEDOP,
+ STDLIB_SETSOCKOPT,
+ STDLIB_SHMAT,
+ STDLIB_SHMDT,
+ STDLIB_SIGSUSPEND,
+ STDLIB_SIGTIMEDWAIT,
+ STDLIB_SIGWAITINFO,
+ STDLIB_SLEEP,
+ STDLIB_SOCKET,
+ STDLIB_USLEEP,
+ STDLIB_VALLOC,
+ STDLIB_WAITPID,
+ __NUM_STDLIBS_IDS
+} util_stdlib_id_t;
+
+typedef enum util_stdlib_flag_e {
+ STLIB_BLOCK_EXT = 0,
+ STLIB_BLOCK_INT,
+ __NUM_STDLIBS_FLAGS
+} util_stdlib_flag_t;
+#define _UTIL_STLIB_FLAGS_STR "ei"
+
+#define _UTIL_STLIB_FLAG(F) (1 << (F))
+#define _UTIL_STLIB_BLOCK_MASK \
+ (_UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)|_UTIL_STLIB_FLAG(STLIB_BLOCK_INT))
+
+#define _UTIL_STLIB_FLAGS_STR_BUFF_SIZE (__NUM_STDLIBS_FLAGS+1)
+#define _UTIL_STLIB_FLAG_C(F, E) \
+ (((F) & _UTIL_STLIB_FLAG(E)) ? _UTIL_STLIB_FLAGS_STR[E] : '-')
+
+#define _UTIL_STDLIB_DEF(ID, N, F) { (ID), (N), (F) }
+#define _UTIL_STDLIBS_INITIALIZER { \
+ _UTIL_STDLIB_DEF(STDLIB_ACCEPT, "accept", _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)), \
+ _UTIL_STDLIB_DEF(STDLIB_ACCEPT4, "accept4", _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)), \
+ _UTIL_STDLIB_DEF(STDLIB_BIND, "bind", 0), \
+ _UTIL_STDLIB_DEF(STDLIB_BRK, "brk", 0), \
+ _UTIL_STDLIB_DEF(STDLIB_CALLOC, "calloc", 0), \
+ _UTIL_STDLIB_DEF(STDLIB_EPOLL_CREATE, "epoll_create", 0), \
+ _UTIL_STDLIB_DEF(STDLIB_EPOLL_CREATE1, "epoll_create1", 0), \
+ _UTIL_STDLIB_DEF(STDLIB_EPOLL_WAIT, "epoll_wait", _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)), \
+ _UTIL_STDLIB_DEF(STDLIB_FREE, "free", 0), \
+ _UTIL_STDLIB_DEF(STDLIB_GETSOCKOPT, "getsockopt", 0), \
+ _UTIL_STDLIB_DEF(STDLIB_KILL, "kill", 0), \
+ _UTIL_STDLIB_DEF(STDLIB_LISTEN, "listen", 0), \
+ _UTIL_STDLIB_DEF(STDLIB_MALLOC, "malloc", 0), \
+ _UTIL_STDLIB_DEF(STDLIB_MEMALIGN, "memalign", 0), \
+ _UTIL_STDLIB_DEF(STDLIB_MMAP, "mmap", 0), \
+ _UTIL_STDLIB_DEF(STDLIB_MMAP64, "mmap64", 0), \
+ _UTIL_STDLIB_DEF(STDLIB_MUNMAP, "munmap", 0), \
+ _UTIL_STDLIB_DEF(STDLIB_POLL, "poll", _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)), \
+ _UTIL_STDLIB_DEF(STDLIB_POSIX_MEMALIGN, "posix_memalign", 0), \
+ _UTIL_STDLIB_DEF(STDLIB_PPOLL, "ppoll", _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)), \
+ _UTIL_STDLIB_DEF(STDLIB_PTHREAD_COND_WAIT, "pthread_cond_wait", _UTIL_STLIB_FLAG(STLIB_BLOCK_INT)), \
+ _UTIL_STDLIB_DEF(STDLIB_PTHREAD_COND_TIMEDWAIT, "pthread_cond_timedwait", _UTIL_STLIB_FLAG(STLIB_BLOCK_INT)), \
+ _UTIL_STDLIB_DEF(STDLIB_PTHREAD_JOIN, "pthread_join", _UTIL_STLIB_FLAG(STLIB_BLOCK_INT)), \
+ _UTIL_STDLIB_DEF(STDLIB_READ, "read", _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)), \
+ _UTIL_STDLIB_DEF(STDLIB_REALLOC, "realloc", 0), \
+ _UTIL_STDLIB_DEF(STDLIB_RECV, "recv", _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)), \
+ _UTIL_STDLIB_DEF(STDLIB_RECVFROM, "recvfrom", _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)), \
+ _UTIL_STDLIB_DEF(STDLIB_RECVMSG, "recvsmg", _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)), \
+ _UTIL_STDLIB_DEF(STDLIB_SBRK, "sbrk", 0), \
+ _UTIL_STDLIB_DEF(STDLIB_SELECT, "select", _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)), \
+ _UTIL_STDLIB_DEF(STDLIB_SEMOP, "semop", _UTIL_STLIB_FLAG(STLIB_BLOCK_INT)), \
+ _UTIL_STDLIB_DEF(STDLIB_SEMTIMEDOP, "semtimedop", _UTIL_STLIB_FLAG(STLIB_BLOCK_INT)), \
+ _UTIL_STDLIB_DEF(STDLIB_SETSOCKOPT, "setsockopt", 0), \
+ _UTIL_STDLIB_DEF(STDLIB_SHMAT, "shmat", 0), \
+ _UTIL_STDLIB_DEF(STDLIB_SHMDT, "shmdt", 0), \
+ _UTIL_STDLIB_DEF(STDLIB_SIGSUSPEND, "sigsuspend", _UTIL_STLIB_FLAG(STLIB_BLOCK_INT)), \
+ _UTIL_STDLIB_DEF(STDLIB_SIGTIMEDWAIT, "sigtimedwait", _UTIL_STLIB_FLAG(STLIB_BLOCK_INT)), \
+ _UTIL_STDLIB_DEF(STDLIB_SIGWAITINFO, "sigwaitinfo", _UTIL_STLIB_FLAG(STLIB_BLOCK_INT)), \
+ _UTIL_STDLIB_DEF(STDLIB_SLEEP, "sleep", _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)), \
+ _UTIL_STDLIB_DEF(STDLIB_SOCKET, "socket", 0), \
+ _UTIL_STDLIB_DEF(STDLIB_USLEEP, "usleep", _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)), \
+ _UTIL_STDLIB_DEF(STDLIB_VALLOC, "valloc", 0), \
+ _UTIL_STDLIB_DEF(STDLIB_WAITPID, "waitpid", _UTIL_STLIB_FLAG(STLIB_BLOCK_INT)) \
+}
+
+static inline util_stdlib_t* util_stdlib_lookup_by_name(const char *name, util_stdlib_t *stlib_arr)
+{
+ int i;
+ for (i=0;i<__NUM_STDLIBS_IDS;i++) {
+ if (!strcmp(name, stlib_arr[i].name)) {
+ return &stlib_arr[i];
+ }
+ }
+
+ return NULL;
+}
+
+static inline char* util_stdlib_flags_to_str(unsigned long flags,
+ char* buffer)
+{
+ int i;
+ for(i=0;i<__NUM_STDLIBS_FLAGS;i++) {
+ buffer[i] = _UTIL_STLIB_FLAG_C(flags, i);
+ }
+ buffer[i] = '\0';
+
+ return buffer;
+}
+
+#endif /* _UTIL_STDLIB_H */
+
--- /dev/null
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+
+#ifndef __USE_GNU
+#define __USE_GNU 1
+#endif
+
+#ifndef UNIX_PATH_MAX
+#define UNIX_PATH_MAX 108
+#endif
+
+#ifndef PAGE_SIZE
+#define PAGE_SIZE 4096
+#endif
+
+#ifndef MIN_MMAP_ADDR
+#define MIN_MMAP_ADDR ((void*)(PAGE_SIZE*100))
+#endif
+
+#ifndef _UTIL_PRINTF
+#define _UTIL_PRINTF printf
+#endif
+
+#ifndef _UTIL_PTHREAD_CREATE
+#define _UTIL_PTHREAD_CREATE pthread_create
+#endif
+
+#ifndef _UTIL_PTHREAD_JOIN
+#define _UTIL_PTHREAD_JOIN pthread_join
+#endif
+
+#ifndef _UTIL_PTHREAD_CANCEL
+#define _UTIL_PTHREAD_CANCEL pthread_cancel
+#endif
+
+#ifndef _UTIL_PTHREAD_SIGMASK
+#define _UTIL_PTHREAD_SIGMASK pthread_sigmask
+#endif
+
+#ifndef _UTIL_MALLOC
+#define _UTIL_MALLOC malloc
+#endif
+
+#ifndef _UTIL_CALLOC
+#define _UTIL_CALLOC calloc
+#endif
+
+#ifndef _UTIL_FREE
+#define _UTIL_FREE free
+#endif
+
--- /dev/null
+#ifndef _MAGIC_COMMON_H
+#define _MAGIC_COMMON_H
+
+/* Magic constants. */
+#define MAGIC_PREFIX magic_
+#define MAGIC_PREFIX_STR "magic_"
+#define MAGIC_ASR_PREFIX magic_asr_
+#define MAGIC_ASR_PREFIX_STR "magic_asr_"
+#define MAGIC_EVAL_FUNC_PREFIX "me_"
+#define MAGIC_ANON_MEMBER_PREFIX "magic.anon"
+#define MAGIC_STRINGREF_HAS_MAGIC_HIDDEN_PREFIX(S) \
+ ((S).startswith(MAGIC_HIDDEN_ARRAY_PREFIX) \
+ || (S).startswith(MAGIC_HIDDEN_STR_PREFIX))
+
+#define MAGIC_VOID_PTR _____magic_instr_void_ptr
+#define MAGIC_VOID_PTR_NAME "_____magic_instr_void_ptr"
+#define MAGIC_VOID_ARRAY _____magic_instr_void_arr
+#define MAGIC_VOID_ARRAY_NAME "_____magic_instr_void_arr"
+
+#define MAGIC_VOID_PTR_TYPE _magic_void_ptr_type_ptr
+#define MAGIC_VOID_PTR_TYPE_ID 1
+#define MAGIC_VOID_PTR_INT_CAST_TYPE _magic_void_ptr_int_cast_type_ptr
+#define MAGIC_VOID_PTR_INT_CAST_TYPE_ID 2
+#define MAGIC_VOID_ARRAY_TYPE _magic_void_array_type_ptr
+#define MAGIC_VOID_ARRAY_TYPE_ID 3
+#define MAGIC_PTRINT_TYPE _magic_ptrint_type_ptr
+#define MAGIC_PTRINT_TYPE_ID 4
+#define MAGIC_PTRINT_ARRAY_TYPE _magic_ptrint_array_type_ptr
+#define MAGIC_PTRINT_ARRAY_TYPE_ID 5
+#define MAGIC_VOID_TYPE (MAGIC_VOID_PTR_TYPE->contained_types[0])
+
+#ifdef __MINIX
+#define GLOBAL_VARS_IN_SECTION 1
+#else
+#define GLOBAL_VARS_IN_SECTION 0
+#endif
+#define GLOBAL_VARS_SECTION_PREFIX ".gvars"
+#define GLOBAL_VARS_SECTION_DATA GLOBAL_VARS_SECTION_PREFIX
+#define GLOBAL_VARS_SECTION_RO (GLOBAL_VARS_SECTION_PREFIX "_ro")
+
+#define MAGIC_LLVM_METADATA_SECTION "llvm.metadata"
+#define MAGIC_DEFAULT_EXT_LIB_SECTION_REGEX "^.lib.*"
+#define MAGIC_STATIC_FUNCTIONS_SECTION "magic_functions"
+
+#define MAGIC_STATIC_VARS_SECTION_PREFIX "magic_data"
+#define MAGIC_STATIC_VARS_SECTION_DATA MAGIC_STATIC_VARS_SECTION_PREFIX
+#define MAGIC_STATIC_VARS_SECTION_RO (MAGIC_STATIC_VARS_SECTION_PREFIX "_ro")
+
+#define MAGIC_SHADOW_VARS_SECTION_PREFIX "magic_shadow_data"
+#define MAGIC_SHADOW_VARS_SECTION_DATA MAGIC_SHADOW_VARS_SECTION_PREFIX
+#define MAGIC_SHADOW_VARS_SECTION_RO (MAGIC_SHADOW_VARS_SECTION_PREFIX "_ro")
+
+#define UNBL_SECTION_PREFIX "unblockify"
+#define MAGIC_SHADOW_VAR_PREFIX ".magic_shadow_"
+#define MAGIC_HIDDEN_ARRAY_PREFIX ".arr.magic"
+#define MAGIC_HIDDEN_STR_PREFIX ".str.magic"
+
+/* Magic configuration. */
+#ifndef MAGIC_OUTPUT_CTL
+#define MAGIC_OUTPUT_CTL 0
+#endif
+/* 0=disabled, 1=force no debug output, 2=force no output (for perf. testing).*/
+#define MAGIC_CHECK_LEVEL 1
+/* 2=extra checks, 1=standard checks, 0=no checks (for perf. testing). */
+#define MAGIC_FLATTEN_FUNCTION_ARGS 1
+#define MAGIC_CHECK_INVARIANTS 1
+#define MAGIC_SHRINK_TYPE_STR 1
+#define MAGIC_MAX_NAME_LEN 64
+#define MAGIC_MAX_TYPE_STR_LEN 256
+#define MAGIC_MAX_RECURSIVE_TYPES 1024
+#define MAGIC_TYPE_STR_PRINT_MAX 5000
+#define MAGIC_TYPE_STR_PRINT_MAX_LEVEL 10
+#define MAGIC_MAX_DEAD_DSENTRIES 10
+#define MAGIC_MAX_DEAD_DSENTRIES_SIZE (1024 * 4 * 10)
+#define MAGIC_NAMED_ALLOC_USE_DBG_INFO 0
+/* 1=for more verbose dsentry naming. */
+#define MAGIC_FORCE_ALLOC_EXT_NAMES 0
+/* 1=to force external names for allocations made inside library functions. */
+#define MAGIC_ABORT_ON_UNSUPPORTED_LOCAL_EXTERNAL_TYPE 0
+/* 0=to resort to void* type when a local external type is not supported. */
+#ifndef MAGIC_MEM_USAGE_OUTPUT_CTL
+#define MAGIC_MEM_USAGE_OUTPUT_CTL 0
+#endif
+/* 0=disabled, 1=use call site info 2=use stacktrace */
+
+#define MAGIC_INSTRUMENT_MEM_FUNCS_ASR_ONLY 0
+#define MAGIC_INSTRUMENT_MEM_CUSTOM_WRAPPERS 1
+#define MAGIC_INSTRUMENT_MEM_FUNCS 1
+#define MAGIC_INSTRUMENT_STACK 1
+#define MAGIC_FORCE_RAW_UNIONS 0
+#define MAGIC_FORCE_RAW_BITFIELDS 0
+#define MAGIC_FORCE_DYN_MEM_ZERO_INIT 0
+/* 1=for accurate dsentry analysis. */
+#define MAGIC_INDEX_DYN_LIBS 1
+#define MAGIC_USE_DYN_MEM_WRAPPERS 1
+#define MAGIC_USE_DYN_DL_WRAPPERS 1
+#define MAGIC_ALLOW_DYN_MEM_WRAPPER_NESTING 1
+
+/* qprof-related settings */
+#ifdef __MINIX
+#define MAGIC_USE_QPROF_INSTRUMENTATION 0
+#else
+#define MAGIC_USE_QPROF_INSTRUMENTATION 1
+#endif
+#define MAGIC_DEEPEST_LL_LOOP_HOOK magic_deepest_ll_loop
+#define MAGIC_DEEPEST_LL_LIB_HOOK magic_deepest_ll_lib
+#define MAGIC_DEEPEST_LL_LOOP_HOOK_NAME "magic_deepest_ll_loop"
+#define MAGIC_DEEPEST_LL_LIB_HOOK_NAME "magic_deepest_ll_lib"
+#define MAGIC_NUM_LL_TASK_CLASSES magic_num_ll_task_classes
+#define MAGIC_NUM_LL_BLOCK_EXT_TASK_CLASSES magic_num_ll_block_ext_task_classes
+#define MAGIC_NUM_LL_BLOCK_INT_TASK_CLASSES magic_num_ll_block_int_task_classes
+#define MAGIC_NUM_LL_BLOCK_EXT_LIBS magic_num_ll_block_ext_libs
+#define MAGIC_NUM_LL_BLOCK_INT_LIBS magic_num_ll_block_int_libs
+#define MAGIC_NUM_LL_TASK_CLASSES_NAME "magic_num_ll_task_classes"
+#define MAGIC_NUM_LL_BLOCK_EXT_TASK_CLASSES_NAME "magic_num_ll_block_ext_task_classes"
+#define MAGIC_NUM_LL_BLOCK_INT_TASK_CLASSES_NAME "magic_num_ll_block_int_task_classes"
+#define MAGIC_NUM_LL_BLOCK_EXT_LIBS_NAME "magic_num_ll_block_ext_libs"
+#define MAGIC_NUM_LL_BLOCK_INT_LIBS_NAME "magic_num_ll_block_int_libs"
+
+#define MAGIC_THREAD_SAFE 1
+#define MAGIC_FORCE_LOCKS 0
+#define MAGIC_LOOKUP_SENTRY 1
+#define MAGIC_LOOKUP_DSENTRY 1
+#define MAGIC_LOOKUP_FUNCTION 1
+#define MAGIC_LOOKUP_DFUNCTION 1
+#define MAGIC_LOOKUP_TYPE 1
+#define MAGIC_LOOKUP_SENTRY_ALLOW_RANGE_INDEX 1
+#define MAGIC_LOOKUP_SENTRY_ALLOW_NAME_HASH 1
+#define MAGIC_LOOKUP_FUNCTION_ALLOW_ADDR_HASH 1
+
+#define MAGIC_INDEX_INT_CAST 1
+#define MAGIC_INDEX_FUN_PTR_INT_CAST 1
+#define MAGIC_INDEX_STR_PTR_INT_CAST 1
+#define MAGIC_INDEX_VOID_PTR_INT_CAST 1
+#define MAGIC_INDEX_OTH_PTR_INT_CAST 1
+
+#define MAGIC_INDEX_BIT_CAST 1
+#define MAGIC_INDEX_TRANSITIVE_BIT_CASTS 0
+#define MAGIC_INDEX_FUN_PTR_BIT_CAST 1
+#define MAGIC_INDEX_STR_PTR_BIT_CAST 1
+#define MAGIC_INDEX_VOID_PTR_BIT_CAST 0
+#define MAGIC_INDEX_OTH_PTR_BIT_CAST 1
+
+#ifdef __MINIX
+#define MAGIC_SKIP_TOVOID_PTR_BIT_CAST 0
+#else
+#define MAGIC_SKIP_TOVOID_PTR_BIT_CAST 1
+#endif
+
+#define MAGIC_COMPACT_COMP_TYPES 0
+
+#define MAGIC_OFF_BY_N_PROTECTION_N 0
+
+#define MAGIC_VARSIZED_STRUCTS_SUPPORT 1
+
+#define MAGIC_ALLOW_DEAD_DSENTRIES_DEFAULT 0
+
+#define MAGIC_WALK_UNIONS_AS_VOID_ARRAYS_DEFAULT 1
+
+#define MAGIC_DEBUG_SELECT(D,ND) (MAGIC_OUTPUT_CTL>=1 ? (ND) : (D))
+#define MAGIC_OUTPUT_SELECT(D,ND,NO) \
+ (MAGIC_OUTPUT_CTL>=2 ? (NO) : MAGIC_DEBUG_SELECT(D,ND))
+#define MAGIC_DEBUG_SET(D) MAGIC_DEBUG_SELECT(D,0)
+
+#define MAGIC_ENABLED "_magic_enabled"
+
+#define MAGIC_ARRAY_NAME "_magic_sentries_array"
+#define MAGIC_TYPE_ARRAY_NAME "_magic_types_array"
+#define MAGIC_FUNC_ARRAY_NAME "_magic_functions_array"
+#define MAGIC_DSINDEX_ARRAY_NAME "_magic_dsindexes_array"
+
+#define MAGIC_ROOT_VAR_NAME "_magic_vars_buff"
+#define MAGIC_RSTRUCT_FIELD_ASR_SEED "asr_seed"
+#define MAGIC_RSTRUCT_FIELD_ASR_HEAP_MAP_DO_PERMUTATE "asr_heap_map_do_permutate"
+#define MAGIC_RSTRUCT_FIELD_ASR_HEAP_MAX_OFFSET "asr_heap_max_offset"
+#define MAGIC_RSTRUCT_FIELD_ASR_HEAP_MAX_PADDING "asr_heap_max_padding"
+#define MAGIC_RSTRUCT_FIELD_ASR_MAP_MAX_OFFSET_PAGES "asr_map_max_offset_pages"
+#define MAGIC_RSTRUCT_FIELD_ASR_MAP_MAX_PADDING_PAGES "asr_map_max_padding_pages"
+#define MAGIC_RSTRUCT_FIELD_TYPES "types"
+#define MAGIC_RSTRUCT_FIELD_TYPES_NUM "types_num"
+#define MAGIC_RSTRUCT_FIELD_TYPES_NEXT_ID "types_next_id"
+#define MAGIC_RSTRUCT_FIELD_FUNCTIONS "functions"
+#define MAGIC_RSTRUCT_FIELD_FUNCTIONS_NUM "functions_num"
+#define MAGIC_RSTRUCT_FIELD_FUNCTIONS_NEXT_ID "functions_next_id"
+#define MAGIC_RSTRUCT_FIELD_SENTRIES "sentries"
+#define MAGIC_RSTRUCT_FIELD_SENTRIES_NUM "sentries_num"
+#define MAGIC_RSTRUCT_FIELD_SENTRIES_STR_NUM "sentries_str_num"
+#define MAGIC_RSTRUCT_FIELD_SENTRIES_NEXT_ID "sentries_next_id"
+#define MAGIC_RSTRUCT_FIELD_DSINDEXES "dsindexes"
+#define MAGIC_RSTRUCT_FIELD_DSINDEXES_NUM "dsindexes_num"
+#define MAGIC_RSTRUCT_FIELD_FIRST_DSENTRY "first_dsentry"
+#define MAGIC_RSTRUCT_FIELDS \
+ MAGIC_RSTRUCT_FIELD_ASR_SEED, \
+ MAGIC_RSTRUCT_FIELD_ASR_HEAP_MAP_DO_PERMUTATE, \
+ MAGIC_RSTRUCT_FIELD_ASR_HEAP_MAX_OFFSET, \
+ MAGIC_RSTRUCT_FIELD_ASR_HEAP_MAX_PADDING, \
+ MAGIC_RSTRUCT_FIELD_ASR_MAP_MAX_OFFSET_PAGES, \
+ MAGIC_RSTRUCT_FIELD_ASR_MAP_MAX_PADDING_PAGES, \
+ MAGIC_RSTRUCT_FIELD_TYPES, \
+ MAGIC_RSTRUCT_FIELD_TYPES_NUM, \
+ MAGIC_RSTRUCT_FIELD_TYPES_NEXT_ID, \
+ MAGIC_RSTRUCT_FIELD_FUNCTIONS, \
+ MAGIC_RSTRUCT_FIELD_FUNCTIONS_NUM, \
+ MAGIC_RSTRUCT_FIELD_FUNCTIONS_NEXT_ID, \
+ MAGIC_RSTRUCT_FIELD_SENTRIES, \
+ MAGIC_RSTRUCT_FIELD_SENTRIES_NUM, \
+ MAGIC_RSTRUCT_FIELD_SENTRIES_STR_NUM, \
+ MAGIC_RSTRUCT_FIELD_SENTRIES_NEXT_ID, \
+ MAGIC_RSTRUCT_FIELD_DSINDEXES, \
+ MAGIC_RSTRUCT_FIELD_DSINDEXES_NUM, \
+ MAGIC_RSTRUCT_FIELD_FIRST_DSENTRY
+
+#define MAGIC_ENTRY_POINT "main"
+#define MAGIC_INIT_FUNC_NAME "magic_init"
+#define MAGIC_DATA_INIT_FUNC_NAME "magic_data_init"
+
+#define MAGIC_STACK_DSENTRIES_CREATE_FUNC_NAME "magic_stack_dsentries_create"
+#define MAGIC_STACK_DSENTRIES_DESTROY_FUNC_NAME "magic_stack_dsentries_destroy"
+
+#define MAGIC_GET_PAGE_SIZE_FUNC_NAME "magic_get_sys_pagesize"
+
+#define MAGIC_VOID_PTR_TYPE_PTR_NAME "_magic_void_ptr_type_ptr"
+
+#define MAGIC_ALLOC_NAME_SUFFIX "#"
+#define MAGIC_ALLOC_NAME_SEP "%"
+#define MAGIC_ALLOC_NONAME "%UNKNOWN"
+#define MAGIC_ALLOC_EXT_NAME "%EXT"
+#define MAGIC_ALLOC_EXT_PARENT_NAME "%EXT_PARENT"
+#define MAGIC_ALLOC_RET_ADDR_NAME "%RET_ADDR"
+#define MAGIC_ALLOC_INITIAL_STACK_NAME "%INITIAL_STACK_AREA"
+#define MAGIC_OBDSENTRY_DEFAULT_PARENT_NAME "%OUT_OF_BAND_PARENT"
+#define MAGIC_DSENTRY_DATA_SEGMENT_NAME "%LIB_DATA_SEGMENT"
+#define MAGIC_DSENTRY_ABS_NAME_SEP "~"
+#define MAGIC_SELEMENT_SEP "/"
+#define MAGIC_NAME_INVALID "%INVALID"
+
+#define MAGIC_SSTRUCT_FIELD_ID "id"
+#define MAGIC_SSTRUCT_FIELD_NAME "name"
+#define MAGIC_SSTRUCT_FIELD_TYPE "type"
+#define MAGIC_SSTRUCT_FIELD_FLAGS "flags"
+#define MAGIC_SSTRUCT_FIELD_ADDRESS "address"
+#define MAGIC_SSTRUCT_FIELD_SHADOW_ADDRESS "shadow_address"
+#define MAGIC_SSTRUCT_FIELDS \
+ MAGIC_SSTRUCT_FIELD_ID, \
+ MAGIC_SSTRUCT_FIELD_NAME, \
+ MAGIC_SSTRUCT_FIELD_TYPE, \
+ MAGIC_SSTRUCT_FIELD_FLAGS, \
+ MAGIC_SSTRUCT_FIELD_ADDRESS, \
+ MAGIC_SSTRUCT_FIELD_SHADOW_ADDRESS
+
+#define MAGIC_TSTRUCT_FIELD_ID "id"
+#define MAGIC_TSTRUCT_FIELD_NAME "name"
+#define MAGIC_TSTRUCT_FIELD_NAMES "names"
+#define MAGIC_TSTRUCT_FIELD_NUM_NAMES "num_names"
+#define MAGIC_TSTRUCT_FIELD_TYPE_STR "type_str"
+#define MAGIC_TSTRUCT_FIELD_SIZE "size"
+#define MAGIC_TSTRUCT_FIELD_NUM_CHILD_TYPES "num_child_types"
+#define MAGIC_TSTRUCT_FIELD_CONTAINED_TYPES "contained_types"
+#define MAGIC_TSTRUCT_FIELD_COMPATIBLE_TYPES "compatible_types"
+#define MAGIC_TSTRUCT_FIELD_MEMBER_NAMES "member_names"
+#define MAGIC_TSTRUCT_FIELD_MEMBER_OFFSETS "member_offsets"
+#define MAGIC_TSTRUCT_FIELD_VALUE_SET "value_set"
+#define MAGIC_TSTRUCT_FIELD_TYPE_ID "type_id"
+#define MAGIC_TSTRUCT_FIELD_FLAGS "flags"
+#define MAGIC_TSTRUCT_FIELD_BIT_WIDTH "bit_width"
+#define MAGIC_TSTRUCT_FIELDS \
+ MAGIC_TSTRUCT_FIELD_ID, \
+ MAGIC_TSTRUCT_FIELD_NAME, \
+ MAGIC_TSTRUCT_FIELD_NAMES, \
+ MAGIC_TSTRUCT_FIELD_NUM_NAMES, \
+ MAGIC_TSTRUCT_FIELD_TYPE_STR, \
+ MAGIC_TSTRUCT_FIELD_SIZE, \
+ MAGIC_TSTRUCT_FIELD_NUM_CHILD_TYPES, \
+ MAGIC_TSTRUCT_FIELD_CONTAINED_TYPES, \
+ MAGIC_TSTRUCT_FIELD_COMPATIBLE_TYPES, \
+ MAGIC_TSTRUCT_FIELD_MEMBER_NAMES, \
+ MAGIC_TSTRUCT_FIELD_MEMBER_OFFSETS, \
+ MAGIC_TSTRUCT_FIELD_VALUE_SET, \
+ MAGIC_TSTRUCT_FIELD_TYPE_ID, \
+ MAGIC_TSTRUCT_FIELD_FLAGS, \
+ MAGIC_TSTRUCT_FIELD_BIT_WIDTH
+
+#define MAGIC_FSTRUCT_FIELD_ID "id"
+#define MAGIC_FSTRUCT_FIELD_NAME "name"
+#define MAGIC_FSTRUCT_FIELD_TYPE "type"
+#define MAGIC_FSTRUCT_FIELD_FLAGS "flags"
+#define MAGIC_FSTRUCT_FIELD_ADDRESS "address"
+#define MAGIC_FSTRUCT_FIELDS \
+ MAGIC_FSTRUCT_FIELD_ID, \
+ MAGIC_FSTRUCT_FIELD_NAME, \
+ MAGIC_FSTRUCT_FIELD_TYPE, \
+ MAGIC_FSTRUCT_FIELD_FLAGS, \
+ MAGIC_FSTRUCT_FIELD_ADDRESS
+
+#define MAGIC_DSTRUCT_FIELD_TYPE "type"
+#define MAGIC_DSTRUCT_FIELD_NAME "name"
+#define MAGIC_DSTRUCT_FIELD_PARENT_NAME "parent_name"
+#define MAGIC_DSTRUCT_FIELD_FLAGS "flags"
+#define MAGIC_DSTRUCT_FIELDS \
+ MAGIC_DSTRUCT_FIELD_TYPE, \
+ MAGIC_DSTRUCT_FIELD_NAME, \
+ MAGIC_DSTRUCT_FIELD_PARENT_NAME, \
+ MAGIC_DSTRUCT_FIELD_FLAGS
+
+#define MAGIC_TYPE_ISUNION 0x01
+#define MAGIC_TYPE_ISPADDED 0x02
+
+/* Type IDs. */
+#define MAGIC_TYPE_VOID 1
+#define MAGIC_TYPE_FLOAT 2
+#define MAGIC_TYPE_INTEGER 3
+#define MAGIC_TYPE_FUNCTION 4
+#define MAGIC_TYPE_ARRAY 5
+#define MAGIC_TYPE_ENUM 6
+#define MAGIC_TYPE_VECTOR 7
+#define MAGIC_TYPE_UNION 8
+#define MAGIC_TYPE_STRUCT 9
+#define MAGIC_TYPE_POINTER 10
+#define MAGIC_TYPE_OPAQUE 11
+
+/* Type flags. */
+#define MAGIC_TYPE_EXTERNAL 0x001
+#define MAGIC_TYPE_IS_ROOT 0x002
+#define MAGIC_TYPE_DYNAMIC 0x004
+#define MAGIC_TYPE_INT_CAST 0x008
+#define MAGIC_TYPE_STRICT_VALUE_SET 0x010
+#define MAGIC_TYPE_VARSIZE 0x020
+#define MAGIC_TYPE_UNSIGNED 0x040
+#define MAGIC_TYPE_NO_INNER_PTRS 0x080
+
+/* State flags for sentries and functions. */
+#define MAGIC_STATE_DIRTY 0x00000001
+#define MAGIC_STATE_CONSTANT 0x00000002
+#define MAGIC_STATE_DYNAMIC 0x00000004
+#define MAGIC_STATE_DETACHED 0x00000008
+#define MAGIC_STATE_DATA 0x00000010
+#define MAGIC_STATE_HEAP 0x00000020
+#define MAGIC_STATE_MAP 0x00000040
+#define MAGIC_STATE_SHM 0x00000080
+#define MAGIC_STATE_STACK 0x00000100
+#define MAGIC_STATE_TEXT 0x00000200
+/* All libraries. */
+#define MAGIC_STATE_LIB 0x00000400
+/* Dynamically linked libraries. */
+#define MAGIC_STATE_LIB_SO 0x00000800
+/* Dynamically loaded libraries. */
+#define MAGIC_STATE_LIB_DSO 0x00001000
+#define MAGIC_STATE_ADDR_NOT_TAKEN 0x00002000
+#define MAGIC_STATE_EXT 0x00004000
+#define MAGIC_STATE_OUT_OF_BAND 0x00008000
+#define MAGIC_STATE_STRING 0x00010000
+#define MAGIC_STATE_NAMED_STRING 0x00020000
+#define MAGIC_STATE_MODE_R 0x00040000
+#define MAGIC_STATE_MODE_W 0x00080000
+#define MAGIC_STATE_MODE_X 0x00100000
+#define MAGIC_STATE_THREAD_LOCAL 0x00200000
+#define MAGIC_STATE_MEMPOOL 0x00400000
+#define MAGIC_STATE_MEMBLOCK 0x00800000
+#define MAGIC_STATE_EXTERNAL 0x01000000
+#define MAGIC_STATE_TYPE_SIZE_MISMATCH 0x02000000
+#define MAGIC_STATE_IMMUTABLE 0x04000000
+#define MAGIC_STATE_INIT 0x08000000
+#define MAGIC_STATE_DIRTY_PAGE 0x10000000
+/* Skip char* and void* entries in arrays */
+#define MAGIC_STATE_SKIP_BYTE_INDICES 0x20000000
+
+#define MAGIC_STATE_ANNOTATION_MASK \
+ (MAGIC_STATE_MODE_R | MAGIC_STATE_MODE_W | MAGIC_STATE_MODE_X)
+
+#define MAGIC_ASR_FLAG_INIT 0x40000
+
+#define MAGIC_STATE_EXTF_MASK 0xFF000000
+#define MAGIC_STATE_EXTF_SHIFT 24
+
+#define MAGIC_STATE_FLAG(E,F) (((E)->flags & (F)) != 0)
+#define MAGIC_STATE_FLAGS(E,F) (((E)->flags & (F)) == (F))
+#define MAGIC_STATE_FLAGS_REGION(F) \
+ ((F) & (MAGIC_STATE_DATA | MAGIC_STATE_HEAP | MAGIC_STATE_MAP \
+ | MAGIC_STATE_SHM | MAGIC_STATE_STACK | MAGIC_STATE_TEXT))
+#define MAGIC_STATE_FLAGS_LIBSPEC(F) \
+ ((F) & (MAGIC_STATE_LIB | MAGIC_STATE_LIB_SO | MAGIC_STATE_LIB_DSO))
+#define MAGIC_STATE_REGION(E) MAGIC_STATE_FLAGS_REGION((E)->flags)
+#define MAGIC_STATE_LIBSPEC(E) MAGIC_STATE_FLAGS_LIBSPEC((E)->flags)
+#define MAGIC_STATE_FLAGS_REGION_C(F) \
+ (((F) & MAGIC_STATE_DATA) ? 'D' : ((F) & MAGIC_STATE_HEAP) ? 'H' \
+ : ((F) & MAGIC_STATE_SHM) ? 'X' : ((F) & MAGIC_STATE_MAP) ? 'M' \
+ : ((F) & MAGIC_STATE_STACK) ? 'S' : ((F) & MAGIC_STATE_TEXT) ? 'T' : '?')
+#define MAGIC_STATE_FLAGS_LIBSPEC_C(F) \
+ (((F) & MAGIC_STATE_LIB) ? (((F) & MAGIC_STATE_LIB_SO) ? 'l' \
+ : ((F) & MAGIC_STATE_LIB_DSO) ? 'o' : 'L') : '0')
+#define MAGIC_STATE_REGION_C(E) MAGIC_STATE_FLAGS_REGION_C((E)->flags)
+#define MAGIC_STATE_LIBSPEC_C(E) MAGIC_STATE_FLAGS_LIBSPEC_C((E)->flags)
+
+#define MAGIC_STATE_IS_EXTF(F) (((F) & MAGIC_STATE_EXTF_MASK) == (F))
+#define MAGIC_STATE_FLAGS_TO_EXTF(F) \
+ (((F) & MAGIC_STATE_EXTF_MASK) >> MAGIC_STATE_EXTF_SHIFT)
+#define MAGIC_STATE_FLAGS_TO_NONEXTF(F) ((F) & (~MAGIC_STATE_EXTF_MASK))
+#define MAGIC_STATE_EXTF_TO_FLAGS(F) \
+ (((F) << MAGIC_STATE_EXTF_SHIFT) & MAGIC_STATE_EXTF_MASK)
+#define MAGIC_STATE_EXTF_FLAG(E,F) (MAGIC_STATE_EXTF_GET(E,F) != 0)
+#define MAGIC_STATE_EXTF_GET(E,F) \
+ ((MAGIC_STATE_FLAGS_TO_EXTF((E)->flags) & (F)))
+#define MAGIC_STATE_EXTF_ADD(E,F) \
+ ((E)->flags |= MAGIC_STATE_EXTF_TO_FLAGS(F))
+#define MAGIC_STATE_EXTF_DEL(E,F) \
+ ((E)->flags &= ~MAGIC_STATE_EXTF_TO_FLAGS(F))
+#define MAGIC_STATE_EXTF_SET(E,F) \
+ do { \
+ MAGIC_STATE_EXTF_CLEAR(E); \
+ (E)->flags |= MAGIC_STATE_EXTF_TO_FLAGS(F); \
+ } while(0)
+#define MAGIC_STATE_EXTF_CLEAR(E) ((E)->flags &= ~MAGIC_STATE_EXTF_MASK)
+
+/* Annotations. */
+#define MAGIC_CALL_ANNOTATION_VAR _magic_call_annotation_var
+#define MAGIC_CALL_ANNOTATION_VAR_NAME "_magic_call_annotation_var"
+#define MAGIC_CALL_ANNOTATE(C, VALUE) \
+ do { C; MAGIC_CALL_ANNOTATION_VAR = VALUE; } while(0)
+#define MAGIC_CALL_MEM_SKIP_INSTRUMENTATION 0x01
+
+#define MAGIC_VAR_ANNOTATION_PREFIX_NAME "_magic_var_annotation_"
+
+#define MAGIC_VAR_ANNOTATE(T,V,A) \
+T V; \
+volatile int _magic_var_annotation_ ## V = A
+#define MAGIC_VAR_INIT_ANNOTATE(T,V,I,A) \
+T V = I; \
+volatile int _magic_var_annotation_ ## V = A
+
+#define MAGIC_MEMCPY_FUNC_NAME "memcpy"
+#define MAGIC_MALLOC_FUNC_NAME "malloc"
+
+/* Magic memory pool management functions. */
+#define MAGIC_MEMPOOL_BLOCK_ALLOC_TEMPLATE_FUNC_NAME \
+ "mempool_block_alloc_template"
+
+/* Wrapper functions. */
+#define MAGIC_MEMPOOL_CREATE_FUNCS \
+ __X(magic_mempool_create_begin), __X(magic_mempool_create_end)
+#define MAGIC_MEMPOOL_DESTROY_FUNCS \
+ __X(magic_mempool_destroy_begin), __X(magic_mempool_destroy_end)
+#define MAGIC_MEMPOOL_MGMT_FUNCS \
+ __X(magic_mempool_mgmt_begin), __X(magic_mempool_mgmt_end)
+#define MAGIC_MEMPOOL_RESET_FUNCS \
+ __X(magic_mempool_reset_begin), __X(magic_mempool_mgmt_end)
+#define MAGIC_MEMPOOL_FUNCS \
+ MAGIC_MEMPOOL_CREATE_FUNCS, \
+ MAGIC_MEMPOOL_DESTROY_FUNCS, \
+ MAGIC_MEMPOOL_MGMT_FUNCS, \
+ MAGIC_MEMPOOL_RESET_FUNCS
+
+#define MAGIC_MEMPOOL_CREATE_FUNC_NAMES MAGIC_MEMPOOL_CREATE_FUNCS, ""
+#define MAGIC_MEMPOOL_DESTROY_FUNC_NAMES MAGIC_MEMPOOL_DESTROY_FUNCS, ""
+#define MAGIC_MEMPOOL_MGMT_FUNC_NAMES MAGIC_MEMPOOL_MGMT_FUNCS, ""
+#define MAGIC_MEMPOOL_RESET_FUNC_NAMES MAGIC_MEMPOOL_RESET_FUNCS, ""
+#define MAGIC_MEMPOOL_FUNC_NAMES MAGIC_MEMPOOL_FUNCS, ""
+
+/* Flags for inlining wrapper calls. */
+#define MAGIC_PRE_HOOK_SIMPLE_CALL 0x0001
+#define MAGIC_PRE_HOOK_FORWARDING_CALL 0x0002
+#define MAGIC_POST_HOOK_SIMPLE_CALL 0x0004
+#define MAGIC_POST_HOOK_FORWARDING_CALL 0x0008
+#define MAGIC_PRE_HOOK_DEBUG 0x0010
+#define MAGIC_POST_HOOK_DEBUG 0x0020
+#define MAGIC_PRE_HOOK_FLAGS_MASK \
+ (MAGIC_PRE_HOOK_SIMPLE_CALL | MAGIC_PRE_HOOK_FORWARDING_CALL)
+#define MAGIC_POST_HOOK_FLAGS_MASK \
+ (MAGIC_POST_HOOK_SIMPLE_CALL | MAGIC_POST_HOOK_FORWARDING_CALL)
+#define MAGIC_HOOK_DEBUG_MASK \
+ (MAGIC_PRE_HOOK_DEBUG | MAGIC_POST_HOOK_DEBUG)
+
+#if (MAGIC_MEM_USAGE_OUTPUT_CTL == 1)
+#define MAGIC_MEMPOOL_CREATE_FUNC_FLAGS MAGIC_PRE_HOOK_SIMPLE_CALL | MAGIC_POST_HOOK_FORWARDING_CALL | MAGIC_PRE_HOOK_DEBUG
+#else
+#define MAGIC_MEMPOOL_CREATE_FUNC_FLAGS MAGIC_PRE_HOOK_SIMPLE_CALL | MAGIC_POST_HOOK_FORWARDING_CALL
+#endif
+#define MAGIC_MEMPOOL_DESTROY_FUNC_FLAGS \
+ MAGIC_PRE_HOOK_FORWARDING_CALL | MAGIC_POST_HOOK_SIMPLE_CALL
+#define MAGIC_MEMPOOL_MGMT_FUNC_FLAGS \
+ MAGIC_PRE_HOOK_FORWARDING_CALL | MAGIC_POST_HOOK_SIMPLE_CALL
+#define MAGIC_MEMPOOL_RESET_FUNC_FLAGS \
+ MAGIC_PRE_HOOK_FORWARDING_CALL | MAGIC_POST_HOOK_SIMPLE_CALL
+#define MAGIC_MEMPOOL_FUNC_FLAGS \
+ MAGIC_MEMPOOL_CREATE_FUNC_FLAGS, \
+ MAGIC_MEMPOOL_DESTROY_FUNC_FLAGS, \
+ MAGIC_MEMPOOL_MGMT_FUNC_FLAGS, \
+ MAGIC_MEMPOOL_RESET_FUNC_FLAGS
+
+#define MAGIC_CHECKPOINT_ENABLED "_magic_checkpoint_enabled"
+#define MAGIC_CHECKPOINT_FUNC_NAME "sef_receive_status"
+
+#define MAGIC_SHADOW_FUNC_PREFIX "llvm_shadow"
+
+#define MAGIC_LAZY_CHECKPOINT_ENABLED "_magic_lazy_checkpoint_enabled"
+#define MAGIC_LAZY_CHECKPOINT_CLEARDF_FUNC_NAME "sef_receive_status"
+
+#define MAGIC_LAZY_CHECKPOINT_SHADOW_TAG "llvm_shadow"
+
+/* Magic memory functions. */
+#define MAGIC_MEMA_FUNCS \
+ __X(malloc), __X(calloc), __X(realloc), \
+ __X(posix_memalign), __X(valloc), __X(memalign), \
+ __X(mmap), \
+ __X(brk), __X(sbrk), \
+ __X(shmat), \
+ __X(mmap64)
+#define MAGIC_MEMA_FUNC_ALLOC_FLAGS \
+ MAGIC_STATE_HEAP, MAGIC_STATE_HEAP, MAGIC_STATE_HEAP, \
+ MAGIC_STATE_HEAP, MAGIC_STATE_HEAP, MAGIC_STATE_HEAP, \
+ MAGIC_STATE_MAP, \
+ MAGIC_STATE_HEAP, MAGIC_STATE_HEAP, \
+ MAGIC_STATE_SHM, \
+ MAGIC_STATE_MAP
+
+#ifdef __MINIX
+#define MAGIC_MEMA_EXTRA_FUNCS , __X(vm_map_cacheblock)
+#define MAGIC_MEMA_EXTRA_FUNC_ALLOC_FLAGS , MAGIC_STATE_MAP
+#else
+#define MAGIC_MEMA_EXTRA_FUNCS
+#define MAGIC_MEMA_EXTRA_FUNC_ALLOC_FLAGS
+#endif
+
+#define MAGIC_MEMD_FUNCS \
+ __X(free), __X(munmap), __X(shmdt)
+#define MAGIC_MEMD_FUNC_ALLOC_FLAGS \
+ 0, 0, 0
+
+#define MAGIC_MEM_FUNCS MAGIC_MEMA_FUNCS MAGIC_MEMA_EXTRA_FUNCS, MAGIC_MEMD_FUNCS
+#define MAGIC_MEM_UNS_FUNCS \
+ __X(mmap2), __X(remap_file_pages), __X(mremap)
+#define MAGIC_MEM_FUNC_ALLOC_FLAGS \
+ MAGIC_MEMA_FUNC_ALLOC_FLAGS MAGIC_MEMA_EXTRA_FUNC_ALLOC_FLAGS, MAGIC_MEMD_FUNC_ALLOC_FLAGS
+
+#define MAGIC_DL_FUNCS \
+ __X(dlopen), __X(dlclose)
+
+#define MAGIC_MEMA_FUNC_NAMES MAGIC_MEMA_FUNCS MAGIC_MEMA_EXTRA_FUNCS, ""
+#define MAGIC_MEMD_FUNC_NAMES MAGIC_MEMD_FUNCS, ""
+#define MAGIC_MEM_FUNC_NAMES MAGIC_MEM_FUNCS, ""
+#define MAGIC_DL_FUNC_NAMES MAGIC_DL_FUNCS, ""
+
+#if MAGIC_INSTRUMENT_MEM_FUNCS_ASR_ONLY
+#define MAGIC_MEM_PREFIX_STRS MAGIC_ASR_PREFIX_STR, MAGIC_PREFIX_STR, ""
+#else
+#define MAGIC_MEM_PREFIX_STRS MAGIC_PREFIX_STR, ""
+#endif
+
+#endif /* _MAGIC_COMMON_H */
+
-#include "pass_hello.h"
+#include <pass.h>
#include <stdlib.h>
using namespace llvm;
+++ /dev/null
-#ifndef _PASS_HELLO_H
-#define _PASS_HELLO_H
-
-#if LLVM_VERSION >= 33
-#define ATTRIBUTE_SET_TY AttributeSet
-#include <llvm/IR/Function.h>
-#include <llvm/IR/Module.h>
-#include <llvm/IR/Instructions.h>
-#include <llvm/IR/Type.h>
-#include <llvm/IR/Constants.h>
-#include <llvm/IR/Intrinsics.h>
-#include <llvm/IR/DerivedTypes.h>
-#include <llvm/IR/LLVMContext.h>
-#include <llvm/IR/IntrinsicInst.h>
-#include <llvm/IR/DataLayout.h>
-#include <llvm/IR/IRBuilder.h>
-#include <llvm/Support/raw_ostream.h>
-#else /* LLVM_VERSION < 33 */
-#define ATTRIBUTE_SET_TY AttrListPtr
-#include <llvm/Function.h>
-#include <llvm/Module.h>
-#include <llvm/Instructions.h>
-#include <llvm/Type.h>
-#include <llvm/Constants.h>
-#include <llvm/Intrinsics.h>
-#include <llvm/DerivedTypes.h>
-#include <llvm/LLVMContext.h>
-#include <llvm/IntrinsicInst.h>
-#endif /* LLVM_VERSION >= 33 */
-
-#if LLVM_VERSION >= 32
-#define DATA_LAYOUT_TY DataLayout
-#define ATTRIBUTE_SET_RET_IDX ATTRIBUTE_SET_TY::ReturnIndex
-#define ATTRIBUTE_SET_FN_IDX ATTRIBUTE_SET_TY::FunctionIndex
-#include <llvm/DebugInfo.h>
-#if LLVM_VERSION == 32
-#include <llvm/DataLayout.h>
-#include <llvm/IRBuilder.h>
-#endif
-#else /* LLVM_VERSION < 32 */
-#define DATA_LAYOUT_TY TargetData
-#define ATTRIBUTE_SET_RET_IDX 0
-#define ATTRIBUTE_SET_FN_IDX (~0U)
-#include <llvm/Target/TargetData.h>
-#include <llvm/Analysis/DebugInfo.h>
-#include <llvm/Support/IRBuilder.h>
-#endif /* LLVM_VERSION >= 32 */
-
-#if LLVM_VERSION >= 31
-/* XXX Check. */
-#define CONSTANT_ARRAY_INITIALIZER_TY ConstantDataArray
-
-#else /* LLVM_VERSION < 31 */
-#define CONSTANT_ARRAY_INITIALIZER_TY ConstantArray
-#endif /* LLVM_VERSION >= 31 */
-
-#if LLVM_VERSION >= 30
-#define BASE_PARSER parser
-
-#define TYPECONST
-#else /* LLVM_VERSION < 30 */
-#define BASE_PARSER basic_parser
-
-#define TYPECONST const
-#endif /* LLVM_VERSION >= 30 */
-
-#if LLVM_VERSION >= 29
-#define VALUE_TO_VALUE_MAP_TY ValueToValueMapTy
-#else /* LLVM_VERSION < 29 */
-#define VALUE_TO_VALUE_MAP_TY ValueMap<const Value*, Value*>
-#endif /* LLVM_VERSION >= 29 */
-
-#define ZERO_CONSTANT_INT(M) ConstantInt::get((M).getContext(), APInt(32, 0, 10))
-#define VOID_PTR_TY(M) PointerType::get(IntegerType::get((M).getContext(), 8), 0)
-#define VOID_PTR_PTR_TY(M) PointerType::get(PointerType::get(IntegerType::get((M).getContext(), 8), 0), 0)
-
-#define DEBUG_LLVM_DEBUG_API 0
-
-typedef enum PassUtilLinkageTypeE {
- PASS_UTIL_LINKAGE_NONE = 0,
- PASS_UTIL_LINKAGE_WEAK,
- PASS_UTIL_LINKAGE_COMMON,
- PASS_UTIL_LINKAGE_EXTERNAL,
- PASS_UTIL_LINKAGE_EXTERNAL_WEAK,
- PASS_UTIL_LINKAGE_WEAK_POINTER,
- PASS_UTIL_LINKAGE_PRIVATE,
- __NUM_PASS_UTIL_LINKAGE_TYPES
- /* Values here should only be appended at the end, external components (e.g., scripts) may be relying on them.*/
-} PassUtilLinkageType;
-
-#define PASS_UTIL_LINKAGE_TYPE_STRINGS \
- "NONE", \
- "WEAK", \
- "COMMON", \
- "EXTERNAL", \
- "EXTERNAL_WEAK", \
- "WEAK_POINTER", \
- "PRIVATE"
-
-typedef enum PassUtilPropE {
- PASS_UTIL_PROP_NONE,
- PASS_UTIL_PROP_NOINLINE,
- PASS_UTIL_PROP_USED,
- PASS_UTIL_PROP_PRESERVE,
- __NUM_PASS_UTIL_PROPS
-} PassUtilProp;
-
-#define PASS_UTIL_FLAG(F) (1 << F)
-
-#define PASS_COMMON_INIT_ONCE() \
- Module *PassUtil::M = NULL; \
-
-using namespace llvm;
-
-namespace llvm {
-
-class PassUtil {
- public:
- static Constant* getGetElementPtrConstant(Constant *constant, std::vector<Value*> &indexes);
- static CallInst* createCallInstruction(Value *F, std::vector<Value*> &args, const Twine &NameStr="", Instruction *InsertBefore=0);
- static CallInst* createCallInstruction(Value *F, std::vector<Value*> &args, const Twine &NameStr="", BasicBlock *InsertAtEnd=0);
- static FunctionType* getFunctionType(TYPECONST Type* Result, std::vector<TYPECONST Type*> &argsTy, bool isVarArg=false);
- static Constant* getStringConstantArray(Module &M, const std::string &string);
- static GlobalVariable* getStringGlobalVariable(Module &M, const std::string &string, const std::string &varName, const std::string &varSection = "", Constant **getElementPtrExpr=NULL, bool cacheable=false);
- private:
- static Module *M;
-};
-
-inline Constant* PassUtil::getGetElementPtrConstant(Constant *constant, std::vector<Value*> &indexes) {
-#if LLVM_VERSION >= 30
- ArrayRef<Value*> ref(indexes);
- return ConstantExpr::getGetElementPtr(constant, ref);
-#else
- return ConstantExpr::getGetElementPtr(constant, &indexes[0], indexes.size());
-#endif
-}
-
-inline CallInst* PassUtil::createCallInstruction(Value *F, std::vector<Value*> &args, const Twine &NameStr, Instruction *InsertBefore) {
-#if LLVM_VERSION >= 30
- ArrayRef<Value*> ref(args);
- return CallInst::Create(F, ref, NameStr, InsertBefore);
-#else
- return CallInst::Create(F, args.begin(), args.end(), NameStr, InsertBefore);
-#endif
-}
-
-inline CallInst* PassUtil::createCallInstruction(Value *F, std::vector<Value*> &args, const Twine &NameStr, BasicBlock *InsertAtEnd) {
-#if LLVM_VERSION >= 30
- ArrayRef<Value*> ref(args);
- return CallInst::Create(F, ref, NameStr, InsertAtEnd);
-#else
- return CallInst::Create(F, args.begin(), args.end(), NameStr, InsertAtEnd);
-#endif
-}
-
-inline FunctionType* PassUtil::getFunctionType(TYPECONST Type* Result, std::vector<TYPECONST Type*> &argsTy, bool isVarArg)
-{
-#if LLVM_VERSION >= 30
- ArrayRef<TYPECONST Type*> ref(argsTy);
- return FunctionType::get(Result, ref, isVarArg);
-#else
- return FunctionType::get(Result, argsTy, isVarArg);
-#endif
-}
-
-
-inline Constant* PassUtil::getStringConstantArray(Module &M, const std::string &string)
-{
- std::vector<Constant*> elements;
- elements.reserve(string.size() + 1);
- for (unsigned i = 0; i < string.size(); ++i)
- elements.push_back(ConstantInt::get(Type::getInt8Ty(M.getContext()), string[i]));
-
- // Add a null terminator to the string...
- elements.push_back(ConstantInt::get(Type::getInt8Ty(M.getContext()), 0));
-
- ArrayType *ATy = ArrayType::get(Type::getInt8Ty(M.getContext()), elements.size());
- return ConstantArray::get(ATy, elements);
-}
-
-inline GlobalVariable* PassUtil::getStringGlobalVariable(Module &M, const std::string &string, const std::string &varName, const std::string &varSection, Constant **getElementPtrExpr, bool cacheable)
-{
- static std::map<std::string, GlobalVariable*> stringCache;
- std::map<std::string, GlobalVariable*>::iterator stringCacheIt;
- std::string stringCacheKey;
- GlobalVariable *strGV = NULL;
-
- if (cacheable) {
- stringCacheKey = string + "~!~!" + varName + "~!~!" + varSection;
- stringCacheIt = stringCache.find(stringCacheKey);
- if (stringCacheIt != stringCache.end()) {
- strGV = stringCacheIt->second;
- cacheable = false;
- }
- }
-
- if (!strGV) {
- //create a constant internal string reference
- Constant *stringValue = PassUtil::getStringConstantArray(M, string);
-
- //create the global variable, cache it, and record it in the module
- strGV = new GlobalVariable(M, stringValue->getType(), true,
- GlobalValue::InternalLinkage, stringValue, varName);
- if (varSection.compare("")) {
- strGV->setSection(varSection);
- }
- }
- if (getElementPtrExpr) {
- std::vector<Value*> strConstantIndices;
- strConstantIndices.push_back(ZERO_CONSTANT_INT(M));
- strConstantIndices.push_back(ZERO_CONSTANT_INT(M));
- *getElementPtrExpr = PassUtil::getGetElementPtrConstant(strGV, strConstantIndices);
- }
-
- if (cacheable) {
- stringCache.insert(std::pair<std::string, GlobalVariable*>(stringCacheKey, strGV));
- }
-
- return strGV;
-}
-
-}
-
-#endif /* _PASS_HELLO_H */
--- /dev/null
+#ifndef _PASS_COMMON_H
+#define _PASS_COMMON_H
+
+#if LLVM_VERSION >= 33
+#define ATTRIBUTE_SET_TY AttributeSet
+#include <llvm/IR/Function.h>
+#include <llvm/IR/Module.h>
+#include <llvm/IR/Instructions.h>
+#include <llvm/IR/Type.h>
+#include <llvm/IR/Constants.h>
+#include <llvm/IR/Intrinsics.h>
+#include <llvm/IR/DerivedTypes.h>
+#include <llvm/IR/LLVMContext.h>
+#include <llvm/IR/IntrinsicInst.h>
+#include <llvm/IR/DataLayout.h>
+#include <llvm/IR/IRBuilder.h>
+#else /* LLVM_VERSION < 33 */
+#define ATTRIBUTE_SET_TY AttrListPtr
+#include <llvm/Function.h>
+#include <llvm/Module.h>
+#include <llvm/Instructions.h>
+#include <llvm/Type.h>
+#include <llvm/Constants.h>
+#include <llvm/Intrinsics.h>
+#include <llvm/DerivedTypes.h>
+#include <llvm/LLVMContext.h>
+#include <llvm/IntrinsicInst.h>
+#endif /* LLVM_VERSION >= 33 */
+
+#if LLVM_VERSION >= 32
+#define DATA_LAYOUT_TY DataLayout
+#define ATTRIBUTE_SET_RET_IDX ATTRIBUTE_SET_TY::ReturnIndex
+#define ATTRIBUTE_SET_FN_IDX ATTRIBUTE_SET_TY::FunctionIndex
+#include <llvm/DebugInfo.h>
+#if LLVM_VERSION == 32
+#include <llvm/DataLayout.h>
+#include <llvm/IRBuilder.h>
+#endif
+#else /* LLVM_VERSION < 32 */
+#define DATA_LAYOUT_TY TargetData
+#define ATTRIBUTE_SET_RET_IDX 0
+#define ATTRIBUTE_SET_FN_IDX (~0U)
+#include <llvm/Target/TargetData.h>
+#include <llvm/Analysis/DebugInfo.h>
+#include <llvm/Support/IRBuilder.h>
+#endif /* LLVM_VERSION >= 32 */
+
+#if LLVM_VERSION >= 31
+/* XXX Check. */
+#define CONSTANT_ARRAY_INITIALIZER_TY ConstantDataArray
+
+#else /* LLVM_VERSION < 31 */
+#define CONSTANT_ARRAY_INITIALIZER_TY ConstantArray
+#endif /* LLVM_VERSION >= 31 */
+
+#if LLVM_VERSION >= 30
+#define BASE_PARSER parser
+
+#define TYPECONST
+#else /* LLVM_VERSION < 30 */
+#define BASE_PARSER basic_parser
+
+#define TYPECONST const
+#endif /* LLVM_VERSION >= 30 */
+
+#if LLVM_VERSION >= 29
+#define VALUE_TO_VALUE_MAP_TY ValueToValueMapTy
+#else /* LLVM_VERSION < 29 */
+#define VALUE_TO_VALUE_MAP_TY ValueMap<const Value*, Value*>
+#endif /* LLVM_VERSION >= 29 */
+
+#define ZERO_CONSTANT_INT(M) ConstantInt::get((M).getContext(), APInt(32, 0, 10))
+#define VOID_PTR_TY(M) PointerType::get(IntegerType::get((M).getContext(), 8), 0)
+#define VOID_PTR_PTR_TY(M) PointerType::get(PointerType::get(IntegerType::get((M).getContext(), 8), 0), 0)
+
+#define FOREACH_FUNC(M, F, B) do { \
+ Module::FunctionListType &__FL = (M).getFunctionList(); \
+ for (Module::iterator __MI = __FL.begin(); __MI != __FL.end(); ++__MI) { \
+ const Function *F = __MI; \
+ if (F->isIntrinsic()) \
+ continue; \
+ B \
+ } \
+} while(0)
+
+#define FOREACH_FUNC_INS(F, I, B) do { \
+ for (Function::const_iterator __FI = F->begin(), __FE = F->end(); __FI != __FE; ++__FI) { \
+ for (BasicBlock::const_iterator __BI = __FI->begin(), BE = __FI->end(); __BI != BE; ++__BI) { \
+ Instruction *I = (Instruction*) ((unsigned long) &(*__BI)); \
+ B \
+ } \
+ } \
+} while(0)
+
+#define FOREACH_FUNC_CS(F, CS, B) do { \
+ FOREACH_FUNC_INS(F, I, \
+ CallSite CS = PassUtil::getCallSiteFromInstruction(I); \
+ if (!CS.getInstruction()) \
+ continue; \
+ B \
+ ); \
+} while(0)
+
+#define DEBUG_LLVM_DEBUG_API 0
+
+typedef enum PassUtilLinkageTypeE {
+ PASS_UTIL_LINKAGE_NONE = 0,
+ PASS_UTIL_LINKAGE_WEAK,
+ PASS_UTIL_LINKAGE_COMMON,
+ PASS_UTIL_LINKAGE_EXTERNAL,
+ PASS_UTIL_LINKAGE_EXTERNAL_WEAK,
+ PASS_UTIL_LINKAGE_WEAK_POINTER,
+ PASS_UTIL_LINKAGE_PRIVATE,
+ __NUM_PASS_UTIL_LINKAGE_TYPES
+ /* Values here should only be appended at the end, external components (e.g., scripts) may be relying on them.*/
+} PassUtilLinkageType;
+
+#define PASS_UTIL_LINKAGE_TYPE_STRINGS \
+ "NONE", \
+ "WEAK", \
+ "COMMON", \
+ "EXTERNAL", \
+ "EXTERNAL_WEAK", \
+ "WEAK_POINTER", \
+ "PRIVATE"
+
+typedef enum PassUtilPropE {
+ PASS_UTIL_PROP_NONE,
+ PASS_UTIL_PROP_NOINLINE,
+ PASS_UTIL_PROP_USED,
+ PASS_UTIL_PROP_PRESERVE,
+ __NUM_PASS_UTIL_PROPS
+} PassUtilProp;
+
+#define PASS_UTIL_FLAG(F) (1 << F)
+
+#define PASS_COMMON_INIT_ONCE() \
+ Module *PassUtil::M = NULL; \
+
+using namespace llvm;
+
+namespace llvm {
+
+class PassUtil {
+ public:
+ static void writeTypeSymbolic(raw_string_ostream &OS, TYPECONST Type *type, const Module *M);
+ static const std::string getTypeDescription(TYPECONST Type* type);
+ static Value *findDbgGlobalDeclare(GlobalVariable *V);
+ static Value *findDbgSubprogramDeclare(const Function *F);
+ static void getDbgLocationInfoRelPath(const std::string &baseDir, const std::string &filename, const std::string &directory, std::string &relPath);
+ static void getDbgLocationInfo(DIDescriptor &DID, const std::string &baseDir, std::string *filename, std::string *directory, std::string *relPath);
+ static bool getInstrDbgLocationInfo(Instruction *I, const std::string &baseDir, std::string *filename, std::string *directory, std::string *relPath, unsigned int *lineNum, bool expand=true);
+ static unsigned getDbgSubrangeNumElements(const DISubrange &subrange);
+ static bool isDbgVectorTy(const DIType &type);
+ static DIType getDITypeDerivedFrom(const DIDerivedType &type);
+ static bool isOpaqueTy(TYPECONST Type *type);
+ static Constant* getGetElementPtrConstant(Constant *constant, std::vector<Value*> &indexes);
+ static GetElementPtrInst* createGetElementPtrInstruction(Value *ptr, std::vector<Value*> &indexes, const Twine &NameStr="", Instruction *InsertBefore=0);
+ static GetElementPtrInst* createGetElementPtrInstruction(Value *ptr, std::vector<Value*> &indexes, const Twine &NameStr="", BasicBlock *InsertAtEnd=0);
+ static CallInst* createCallInstruction(Value *F, std::vector<Value*> &args, const Twine &NameStr="", Instruction *InsertBefore=0);
+ static CallInst* createCallInstruction(Value *F, std::vector<Value*> &args, const Twine &NameStr="", BasicBlock *InsertAtEnd=0);
+ static Function* getIntrinsicFunction(Module &M, Intrinsic::ID id, TYPECONST Type** types=NULL, unsigned size=0);
+ static FunctionType* getFunctionType(TYPECONST Type* Result, std::vector<TYPECONST Type*> &argsTy, bool isVarArg=false);
+ static Function* setFunctionProperties(Function *F, unsigned long properties);
+ static Function* createFunctionWeakPtrWrapper(Module &M, StringRef Name, FunctionType *Ty);
+ static Function* getOrInsertFunction(Module &M, StringRef Name, FunctionType *Ty, PassUtilLinkageType insertLinkage, unsigned long properties);
+ static PassUtilLinkageType getFunctionPassUtilLinkageType(Function *F);
+ static std::string getPassUtilLinkageTypeString(PassUtilLinkageType linkageType);
+ static void getFunctionEntryExits(Function *F, BasicBlock **entryBlock, std::vector<BasicBlock*> *exitBlocks);
+ static bool isReturnedValue(Function *F, Value *V);
+ static CallSite getCallSiteFromInstruction(Instruction *I);
+ static CallSite getCallSiteFromUser(User *U);
+ static void getFunctionsInDirectBUCallgraph(Function* F, std::set<Function*> &funcs);
+ static void getAllocaInfo(Function *F, Instruction **allocaInsertionPoint, Instruction **firstNonAllocaInst);
+ static Constant* getStringConstantArray(Module &M, const std::string &string);
+ static GlobalVariable* getStringGlobalVariable(Module &M, const std::string &string, const std::string &varName = ".str.pu", const std::string &varSection = "", Constant **getElementPtrExpr=NULL, bool cacheable=false);
+ static ATTRIBUTE_SET_TY remapCallSiteAttributes(CallSite &CS, int argOffset);
+ static void parseStringListOpt(std::vector<std::string> &vector, const std::string &string, const std::string &separator = ":");
+ static void parseStringPairListOpt(std::set<std::pair<std::string, std::string> > &set, const std::string &string, const std::string &listSeparator = ":", const std::string &pairSeparator = ";");
+ static void parseRegexListOpt(std::vector<Regex*> &list, const std::string &string);
+ static bool matchRegexes(std::string string, std::vector<Regex*> ®exes);
+ static void setModule(Module *M);
+ static void getModuleName(Module &M, std::string *fullName, std::string *dirName, std::string *baseName);
+ static unsigned long getTypeHash(TYPECONST Type* type, unsigned maxLevel=11);
+ private:
+ static Module *M;
+};
+
+inline void PassUtil::writeTypeSymbolic(raw_string_ostream &OS, TYPECONST Type *type, const Module *M) {
+#if LLVM_VERSION >= 30
+ /* XXX Check. */
+ type->print(OS);
+ return;
+#else
+ return WriteTypeSymbolic(OS, type, M);
+#endif
+}
+
+inline const std::string PassUtil::getTypeDescription(TYPECONST Type* type) {
+ std::string string;
+#if LLVM_VERSION >= 30
+ /* XXX Check. */
+ raw_string_ostream ostream(string);
+ type->print(ostream);
+ ostream.flush();
+#else
+ string = type->getDescription();
+#endif
+
+ return string;
+}
+
+inline Value *PassUtil::findDbgGlobalDeclare(GlobalVariable *V) {
+#if LLVM_VERSION >= 30
+ const Module *M = V->getParent();
+ NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.cu");
+ if (!NMD)
+ return 0;
+
+ for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
+ DICompileUnit CU(NMD->getOperand(i));
+ DIArray GVs = CU.getGlobalVariables();
+ for (unsigned i = 0, e = GVs.getNumElements(); i != e; ++i) {
+ DIDescriptor DIG(GVs.getElement(i));
+ if (DIGlobalVariable(DIG).getGlobal() == V)
+ return DIG;
+ }
+ }
+ return 0;
+#else
+ const Module *M = V->getParent();
+ NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.gv");
+ if (!NMD)
+ return 0;
+
+ for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
+ DIDescriptor DIG(cast<MDNode>(NMD->getOperand(i)));
+ if (!DIG.isGlobalVariable())
+ continue;
+ if (DIGlobalVariable(DIG).getGlobal() == V)
+ return DIG;
+ }
+ return 0;
+#endif
+}
+
+inline Value *PassUtil::findDbgSubprogramDeclare(const Function *V) {
+#if LLVM_VERSION >= 30
+ const Module *M = V->getParent();
+ NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.cu");
+ if (!NMD)
+ return 0;
+
+ for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
+ DICompileUnit CU(NMD->getOperand(i));
+ DIArray SPs = CU.getSubprograms();
+ for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) {
+ DISubprogram DIS(SPs.getElement(i));
+ if (DIS.getFunction() == V) {
+ return DIS;
+ }
+ }
+ }
+ return 0;
+#else
+ const Module *M = V->getParent();
+ NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.sp");
+ if (!NMD)
+ return 0;
+
+ for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
+ DIDescriptor DIG(cast<MDNode>(NMD->getOperand(i)));
+ if (!DIG.isSubprogram())
+ continue;
+ if (DISubprogram(DIG).getFunction() == V)
+ return DIG;
+ }
+ return 0;
+#endif
+}
+
+inline void PassUtil::getDbgLocationInfoRelPath(const std::string &baseDir, const std::string &filename, const std::string &directory, std::string &relPath) {
+ StringRef directoryRef(directory);
+ std::pair<StringRef, StringRef> stringPair = directoryRef.split(baseDir);
+ relPath = (stringPair.second.compare("") ? stringPair.second.str() : stringPair.first.str()) + "/" + filename;
+#if DEBUG_LLVM_DEBUG_API
+ errs() << " - getDbgLocationInfoRelPath: Location Info is: " << directory << " | " << filename << " | " << relPath << "\n";
+#endif
+}
+
+inline void PassUtil::getDbgLocationInfo(DIDescriptor &DID, const std::string &baseDir, std::string *filename, std::string *directory, std::string *relPath) {
+ StringRef _directory;
+ StringRef _filename;
+ if (DID.isGlobalVariable()) {
+#if LLVM_VERSION >= 30
+ _directory = ((DIGlobalVariable*)&DID)->getDirectory();
+ _filename = ((DIGlobalVariable*)&DID)->getFilename();
+#else
+ _directory = ((DIGlobalVariable*)&DID)->getCompileUnit().getDirectory();
+ _filename = ((DIGlobalVariable*)&DID)->getCompileUnit().getFilename();
+#endif
+#if DEBUG_LLVM_DEBUG_API
+ errs() << "DIGlobalVariable name is: " << ((DIGlobalVariable*)&DID)->getName() << "\n";
+#endif
+ }
+ else if (DID.isSubprogram()) {
+ _directory = ((DISubprogram*)&DID)->getDirectory();
+ _filename = ((DISubprogram*)&DID)->getFilename();
+#if DEBUG_LLVM_DEBUG_API
+ errs() << "DISubprogram name is: " << ((DISubprogram*)&DID)->getName() << "\n";
+#endif
+ }
+ else {
+ DIScope DIS;
+ assert (DID.isVariable());
+ DIS = ((DIVariable*)&DID)->getContext();
+ if (DIS.isSubprogram()) {
+ _directory = ((DISubprogram*)&DIS)->getDirectory();
+ _filename = ((DISubprogram*)&DIS)->getFilename();
+#if DEBUG_LLVM_DEBUG_API
+ errs() << "DIVariable (SP) name is: " << ((DIVariable*)&DID)->getName() << "\n";
+#endif
+ }
+ else if (DIS.isLexicalBlock()) {
+ _directory = ((DILexicalBlock*)&DIS)->getDirectory();
+ _filename = ((DILexicalBlock*)&DIS)->getFilename();
+#if DEBUG_LLVM_DEBUG_API
+ errs() << "DIVariable (LB) name is: " << ((DIVariable*)&DID)->getName() << "\n";
+#endif
+ }
+ else {
+#if LLVM_VERSION >= 30
+ assert(DIS.isLexicalBlockFile());
+ _directory = ((DILexicalBlockFile*)&DIS)->getDirectory();
+ _filename = ((DILexicalBlockFile*)&DIS)->getFilename();
+#if DEBUG_LLVM_DEBUG_API
+ errs() << "DIVariable (LBF) name is: " << ((DIVariable*)&DID)->getName() << "\n";
+#endif
+#else
+ assert(0 && "Unexpected DIScope instance!");
+#endif
+ }
+ }
+ if (filename) {
+ *filename = _filename;
+ }
+ if (directory) {
+ *directory = _directory;
+ }
+ if (relPath) {
+ getDbgLocationInfoRelPath(baseDir, _filename, _directory, *relPath);
+ }
+}
+
+inline bool PassUtil::getInstrDbgLocationInfo(Instruction *I, const std::string &baseDir, std::string *filename, std::string *directory, std::string *relPath, unsigned int *lineNum, bool expand) {
+ BasicBlock::iterator BI = I;
+ MDNode *N = BI->getMetadata("dbg");
+ if (!N && !expand) {
+ return false;
+ }
+ while(!N) {
+ if (BI->isTerminator()) {
+ BranchInst *BInst = dyn_cast<BranchInst>(BI);
+ if (BInst && BInst->isUnconditional()) {
+ BI = BInst->getSuccessor(0)->front();
+ N = BI->getMetadata("dbg");
+ continue;
+ }
+ return false;
+ }
+ BI++;
+ N = BI->getMetadata("dbg");
+ }
+
+ DILocation DIL(N);
+ StringRef _directory = DIL.getDirectory();
+ StringRef _filename = DIL.getFilename();
+ if (filename) {
+ *filename = _filename;
+ }
+ if (directory) {
+ *directory = _directory;
+ }
+ if (relPath) {
+ getDbgLocationInfoRelPath(baseDir, _filename, _directory, *relPath);
+ }
+ if (lineNum) {
+ *lineNum = DIL.getLineNumber();
+ }
+
+ return true;
+}
+
+inline unsigned PassUtil::getDbgSubrangeNumElements(const DISubrange &subrange) {
+#if LLVM_VERSION >= 33
+ const unsigned numElements = (unsigned) subrange.getCount();
+#else
+ const unsigned low = (unsigned) subrange.getLo();
+ const unsigned high = (unsigned) subrange.getHi();
+ const unsigned numElements = high - low + 1;
+#endif
+
+ return numElements;
+}
+
+inline bool PassUtil::isDbgVectorTy(const DIType &type) {
+#if LLVM_VERSION >= 33
+ return type.isVector();
+#else
+ return type.getTag() == dwarf::DW_TAG_vector_type;
+#endif
+}
+
+inline DIType PassUtil::getDITypeDerivedFrom(const DIDerivedType &type) {
+#if LLVM_VERSION >= 34
+ static DITypeIdentifierMap TypeIdentifierMap;
+ static bool TypeMapInitialized = false;
+ if (!TypeMapInitialized) {
+ assert(PassUtil::M && "Set module first!");
+ if (NamedMDNode *CU_Nodes = PassUtil::M->getNamedMetadata("llvm.dbg.cu")) {
+ TypeIdentifierMap = generateDITypeIdentifierMap(CU_Nodes);
+ TypeMapInitialized = true;
+ }
+ }
+ return type.getTypeDerivedFrom().resolve(TypeIdentifierMap);
+#else
+ return type.getTypeDerivedFrom();
+#endif
+}
+
+inline bool PassUtil::isOpaqueTy(TYPECONST Type *type) {
+#if LLVM_VERSION >= 30
+ return type->isStructTy() && (((TYPECONST StructType*)type)->isOpaque() || type->getNumContainedTypes() == 0);
+#else
+ return type->isOpaqueTy();
+#endif
+}
+
+inline Constant* PassUtil::getGetElementPtrConstant(Constant *constant, std::vector<Value*> &indexes) {
+#if LLVM_VERSION >= 30
+ ArrayRef<Value*> ref(indexes);
+ return ConstantExpr::getGetElementPtr(constant, ref);
+#else
+ return ConstantExpr::getGetElementPtr(constant, &indexes[0], indexes.size());
+#endif
+}
+
+inline GetElementPtrInst* PassUtil::createGetElementPtrInstruction(Value *ptr, std::vector<Value*> &indexes, const Twine &NameStr, Instruction *InsertBefore) {
+#if LLVM_VERSION >= 30
+ ArrayRef<Value*> ref(indexes);
+ return GetElementPtrInst::Create(ptr, ref, NameStr, InsertBefore);
+#else
+ return GetElementPtrInst::Create(ptr, indexes.begin(), indexes.end(), NameStr, InsertBefore);
+#endif
+}
+
+inline GetElementPtrInst* PassUtil::createGetElementPtrInstruction(Value *ptr, std::vector<Value*> &indexes, const Twine &NameStr, BasicBlock *InsertAtEnd) {
+#if LLVM_VERSION >= 30
+ ArrayRef<Value*> ref(indexes);
+ return GetElementPtrInst::Create(ptr, ref, NameStr, InsertAtEnd);
+#else
+ return GetElementPtrInst::Create(ptr, indexes.begin(), indexes.end(), NameStr, InsertAtEnd);
+#endif
+}
+
+inline CallInst* PassUtil::createCallInstruction(Value *F, std::vector<Value*> &args, const Twine &NameStr, Instruction *InsertBefore) {
+#if LLVM_VERSION >= 30
+ ArrayRef<Value*> ref(args);
+ return CallInst::Create(F, ref, NameStr, InsertBefore);
+#else
+ return CallInst::Create(F, args.begin(), args.end(), NameStr, InsertBefore);
+#endif
+}
+
+inline CallInst* PassUtil::createCallInstruction(Value *F, std::vector<Value*> &args, const Twine &NameStr, BasicBlock *InsertAtEnd) {
+#if LLVM_VERSION >= 30
+ ArrayRef<Value*> ref(args);
+ return CallInst::Create(F, ref, NameStr, InsertAtEnd);
+#else
+ return CallInst::Create(F, args.begin(), args.end(), NameStr, InsertAtEnd);
+#endif
+}
+
+inline Function* PassUtil::getIntrinsicFunction(Module &M, Intrinsic::ID id, TYPECONST Type** types, unsigned size) {
+#if LLVM_VERSION >= 30
+ std::vector<TYPECONST Type*> typeVector;
+ for(unsigned i=0;i<size;i++) {
+ typeVector.push_back(types[i]);
+ }
+ ArrayRef<TYPECONST Type*> ref(typeVector);
+ return Intrinsic::getDeclaration(&M, id, ref);
+#else
+ return Intrinsic::getDeclaration(&M, id, types, size);
+#endif
+}
+
+inline FunctionType* PassUtil::getFunctionType(TYPECONST Type* Result, std::vector<TYPECONST Type*> &argsTy, bool isVarArg)
+{
+#if LLVM_VERSION >= 30
+ ArrayRef<TYPECONST Type*> ref(argsTy);
+ return FunctionType::get(Result, ref, isVarArg);
+#else
+ return FunctionType::get(Result, argsTy, isVarArg);
+#endif
+}
+
+inline Function* PassUtil::setFunctionProperties(Function *F, unsigned long props)
+{
+ assert(F);
+ bool preserve = props & (PASS_UTIL_FLAG(PASS_UTIL_PROP_NOINLINE)|PASS_UTIL_FLAG(PASS_UTIL_PROP_USED)|PASS_UTIL_FLAG(PASS_UTIL_PROP_PRESERVE));
+
+ if (F->isDeclaration()) {
+ return F;
+ }
+ if (preserve) {
+ Instruction *I;
+ getAllocaInfo(F, NULL, &I);
+ assert(I);
+
+ /* Add a volatile store to a new global variable to preserve it. */
+ PointerType* voidPointerTy = PointerType::get(IntegerType::get(F->getContext(), 8), 0);
+ GlobalVariable* volatileVar = new GlobalVariable(*F->getParent(),
+ voidPointerTy, false, GlobalValue::CommonLinkage,
+ 0, F->getName() + "_llvm_propvar");
+ volatileVar->setInitializer(ConstantPointerNull::get(voidPointerTy));
+ new StoreInst(ConstantExpr::getCast(Instruction::BitCast, F, voidPointerTy), volatileVar, true, I);
+ }
+ return F;
+}
+
+inline Function* PassUtil::createFunctionWeakPtrWrapper(Module &M, StringRef Name, FunctionType *Ty)
+{
+ unsigned i;
+ Function *F = getOrInsertFunction(M, Name.str() + "_llvm_weakptrwrapper" , Ty, PASS_UTIL_LINKAGE_COMMON, 0);
+ TYPECONST Type *RetTy = Ty->getReturnType();
+ PointerType *FPtrTy = PointerType::get(Ty, 0);
+ Constant *FPtrNull = Constant::getNullValue(FPtrTy);
+
+ /* Create the global function pointer variable. */
+ GlobalVariable* weakPtrVar = new GlobalVariable(M, FPtrTy, false,
+ GlobalValue::CommonLinkage, 0, Name);
+ weakPtrVar->setInitializer(FPtrNull);
+
+ /* Create the wrapper function body. */
+ F->dropAllReferences();
+ BasicBlock* entryBB = BasicBlock::Create(M.getContext(), "entry",F,0);
+ BasicBlock* weakPtrOverridenBB = BasicBlock::Create(M.getContext(), "have." + Name.str(),F,0);
+ BasicBlock* endBB = BasicBlock::Create(M.getContext(), "end",F,0);
+ AllocaInst* retval = NULL;
+
+ /* Parse arguments. */
+ std::vector<AllocaInst*> argsAllocaInsts;
+ for (Function::arg_iterator args = F->arg_begin(); args != F->arg_end(); args++) {
+ Value *argValue = args;
+ AllocaInst *allocaInst = new AllocaInst(argValue->getType(), ".llvm.pu.args", entryBB);
+ argsAllocaInsts.push_back(allocaInst);
+ }
+ if (!RetTy->isVoidTy()) {
+ retval = new AllocaInst(RetTy, "retval", entryBB);
+ }
+ i=0;
+ for (Function::arg_iterator args = F->arg_begin(); args != F->arg_end(); args++, i++) {
+ Value *argValue = args;
+ AllocaInst *allocaInst = argsAllocaInsts[i];
+ new StoreInst(argValue, allocaInst, true, entryBB);
+ }
+ if (retval) {
+ new StoreInst(Constant::getNullValue(RetTy), retval, true, entryBB);
+ }
+
+ /* Build entry block. */
+ LoadInst* weakPtr = new LoadInst(weakPtrVar, "", true, entryBB);
+ ICmpInst* cmpInst = new ICmpInst(*entryBB, ICmpInst::ICMP_NE, weakPtr, FPtrNull, "");
+ BranchInst::Create(weakPtrOverridenBB, endBB, cmpInst, entryBB);
+
+ /* Build weakPtrOverriden block, only executed with a non-NULL weakPtr */
+ std::vector<Value*> weakPtrCallParams;
+ i=0;
+ for (Function::arg_iterator args = F->arg_begin(); args != F->arg_end(); args++, i++) {
+ AllocaInst *allocaInst = argsAllocaInsts[i];
+ weakPtrCallParams.push_back(new LoadInst(allocaInst, "", true, weakPtrOverridenBB));
+ }
+ weakPtr = new LoadInst(weakPtrVar, "", true, weakPtrOverridenBB);
+ CallInst* weakPtrCall = createCallInstruction(weakPtr, weakPtrCallParams, "", weakPtrOverridenBB);
+ weakPtrCall->setCallingConv(CallingConv::C);
+
+ if (retval) {
+ new StoreInst(weakPtrCall, retval, false, weakPtrOverridenBB);
+ }
+ BranchInst::Create(endBB, weakPtrOverridenBB);
+
+ /* Build end block. */
+ if (!retval) {
+ ReturnInst::Create(M.getContext(), endBB);
+ }
+ else {
+ LoadInst* retvalValue = new LoadInst(retval, "", false, endBB);
+ ReturnInst::Create(M.getContext(), retvalValue, endBB);
+ }
+ return F;
+}
+
+inline Function* PassUtil::getOrInsertFunction(Module &M, StringRef Name, FunctionType *Ty, PassUtilLinkageType insertLinkage, unsigned long properties)
+{
+ static std::map<std::string, Function *> functionMap;
+ std::map<std::string, Function *>::iterator functionMapIt;
+ Function *F = NULL;
+ bool needsEmptyBody = true;
+ bool needsProperties = true;
+ bool needsIncludsion = true;
+
+ functionMapIt = functionMap.find(Name);
+ if (functionMapIt != functionMap.end()) {
+ return functionMapIt->second;
+ }
+ F = M.getFunction(Name);
+
+ if (F) {
+ /* If the function exists, check the type and return it. */
+ if (F->getFunctionType() != Ty) {
+ return NULL;
+ }
+ functionMap.insert(std::pair<std::string, Function *>(Name, F));
+ setFunctionProperties(F, properties);
+ return F;
+ }
+
+ /* Has the user requested creation of the function otherwise? */
+ if (insertLinkage == PASS_UTIL_LINKAGE_NONE) {
+ return NULL;
+ }
+ switch(insertLinkage) {
+ case PASS_UTIL_LINKAGE_WEAK:
+ /* Create empty function that can optionally be overriden at link time*/
+ F = Function::Create(Ty, GlobalVariable::WeakAnyLinkage, Name);
+ break;
+ case PASS_UTIL_LINKAGE_COMMON:
+ /* Creates empty function, non overridable. */
+ F = Function::Create(Ty, GlobalVariable::InternalLinkage, Name);
+ break;
+ case PASS_UTIL_LINKAGE_EXTERNAL:
+ /* Creates function declaration that must be defined at link time. */
+ F = Function::Create(Ty, GlobalVariable::ExternalLinkage, Name);
+ needsEmptyBody = false;
+ break;
+ case PASS_UTIL_LINKAGE_EXTERNAL_WEAK:
+ /* Creates weak function declaration that can optionally be defined
+ * at link time (if undefined the linker will emit a NULL symbol).
+ */
+ F = Function::Create(Ty, GlobalVariable::ExternalWeakLinkage, Name);
+ needsEmptyBody = false;
+ break;
+ case PASS_UTIL_LINKAGE_WEAK_POINTER:
+ /* Creates function pointer initialized to NULL that can optionally
+ * be initialized at runtime. Invocations are wrapped to ensure that
+ * indirect call is performed on a NULL pointer. This is to emulate
+ * Mac OS' weak_pointer attribute, which allows weak symbols to be
+ * overriden in LD_PRELOADED libraries at runtime.
+ */
+ F = PassUtil::createFunctionWeakPtrWrapper(M, Name, Ty);
+ needsProperties = false;
+ needsIncludsion = false;
+ break;
+ default:
+ return NULL;
+ break;
+ }
+ if (needsIncludsion) {
+ M.getFunctionList().push_back(F);
+ }
+ if (needsEmptyBody) {
+ BasicBlock* block = BasicBlock::Create(M.getContext(), "entry", F);
+ IRBuilder<> builder(block);
+ TYPECONST Type *RetTy = Ty->getReturnType();
+ if (RetTy->isVoidTy()) {
+ builder.CreateRetVoid();
+ }
+ else {
+ builder.CreateRet(Constant::getNullValue(RetTy));
+ }
+ }
+ functionMap.insert(std::pair<std::string, Function *>(Name, F));
+ if (needsProperties) {
+ setFunctionProperties(F, properties);
+ }
+ return F;
+}
+
+inline PassUtilLinkageType PassUtil::getFunctionPassUtilLinkageType(Function *F)
+{
+ if (F->isDeclaration()) {
+ return PASS_UTIL_LINKAGE_EXTERNAL;
+ }
+ if (F->hasInternalLinkage()) {
+ return PASS_UTIL_LINKAGE_PRIVATE;
+ }
+ return PASS_UTIL_LINKAGE_COMMON;
+}
+
+inline std::string PassUtil::getPassUtilLinkageTypeString(PassUtilLinkageType linkageType)
+{
+ const char *strArray[] = { PASS_UTIL_LINKAGE_TYPE_STRINGS };
+ std::string str(strArray[linkageType]);
+ return str;
+}
+
+inline void PassUtil::getFunctionEntryExits(Function *F, BasicBlock **entryBlock, std::vector<BasicBlock*> *exitBlocks)
+{
+ if (entryBlock) {
+ *entryBlock = &F->front();
+ }
+ if (exitBlocks) {
+ for(Function::iterator I = F->begin(), E = F->end(); I != E; ++I) {
+ if (isa<ReturnInst>(I->getTerminator()) || isa<UnreachableInst>(I->getTerminator()))
+ exitBlocks->push_back(I);
+ }
+ }
+}
+
+inline bool PassUtil::isReturnedValue(Function *F, Value *V)
+{
+ std::vector<BasicBlock*> exitBlocks;
+ PassUtil::getFunctionEntryExits(F, NULL, &exitBlocks);
+ for (unsigned i=0;i<exitBlocks.size();i++) {
+ Instruction *I = exitBlocks[i]->getTerminator();
+ ReturnInst *RI = dyn_cast<ReturnInst>(I);
+ if (RI && RI->getReturnValue()) {
+ Value *RV = RI->getReturnValue();
+ if (RV == V) {
+ return true;
+ }
+ if (LoadInst *LI = dyn_cast<LoadInst>(RV)) {
+ if (LI->getPointerOperand() == V) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+inline CallSite PassUtil::getCallSiteFromInstruction(Instruction *I)
+{
+ return getCallSiteFromUser(I);
+}
+
+inline CallSite PassUtil::getCallSiteFromUser(User *U)
+{
+ CallSite CS(U->stripPointerCasts());
+ CallSite emptyCS;
+ Instruction *I = CS.getInstruction();
+ if (!I)
+ return emptyCS;
+ if (isa<CallInst>(I) && dyn_cast<CallInst>(I)->isInlineAsm())
+ return emptyCS;
+ Function *F = CS.getCalledFunction();
+ if (F && F->isIntrinsic())
+ return emptyCS;
+ return CS;
+}
+
+inline void PassUtil::getFunctionsInDirectBUCallgraph(Function* F, std::set<Function*> &funcs) {
+ if (funcs.find(F) != funcs.end())
+ return;
+ funcs.insert(F);
+ FOREACH_FUNC_CS(F, CS,
+ if (!CS.getCalledFunction())
+ continue;
+ getFunctionsInDirectBUCallgraph(CS.getCalledFunction(), funcs);
+ );
+}
+
+inline void PassUtil::getAllocaInfo(Function *F, Instruction **allocaInsertionPoint, Instruction **firstNonAllocaInst)
+{
+ assert(!F->isDeclaration());
+ BasicBlock::iterator allocaIP = F->front().begin();
+ while (isa<AllocaInst>(allocaIP)) ++allocaIP;
+ BasicBlock::iterator firstNonAI = allocaIP;
+ if (firstNonAI->getName().equals("alloca point")) {
+ firstNonAI++;
+ }
+ if(allocaInsertionPoint) {
+ *allocaInsertionPoint = allocaIP;
+ }
+ if(firstNonAllocaInst) {
+ *firstNonAllocaInst = firstNonAI;
+ }
+}
+
+inline Constant* PassUtil::getStringConstantArray(Module &M, const std::string &string)
+{
+ std::vector<Constant*> elements;
+ elements.reserve(string.size() + 1);
+ for (unsigned i = 0; i < string.size(); ++i)
+ elements.push_back(ConstantInt::get(Type::getInt8Ty(M.getContext()), string[i]));
+
+ // Add a null terminator to the string...
+ elements.push_back(ConstantInt::get(Type::getInt8Ty(M.getContext()), 0));
+
+ ArrayType *ATy = ArrayType::get(Type::getInt8Ty(M.getContext()), elements.size());
+ return ConstantArray::get(ATy, elements);
+}
+
+inline GlobalVariable* PassUtil::getStringGlobalVariable(Module &M, const std::string &string, const std::string &varName, const std::string &varSection, Constant **getElementPtrExpr, bool cacheable)
+{
+ static std::map<std::string, GlobalVariable*> stringCache;
+ std::map<std::string, GlobalVariable*>::iterator stringCacheIt;
+ std::string stringCacheKey;
+ GlobalVariable *strGV = NULL;
+
+ if (cacheable) {
+ stringCacheKey = string + "~!~!" + varName + "~!~!" + varSection;
+ stringCacheIt = stringCache.find(stringCacheKey);
+ if (stringCacheIt != stringCache.end()) {
+ strGV = stringCacheIt->second;
+ cacheable = false;
+ }
+ }
+
+ if (!strGV) {
+ //create a constant internal string reference
+ Constant *stringValue = PassUtil::getStringConstantArray(M, string);
+
+ //create the global variable, cache it, and record it in the module
+ strGV = new GlobalVariable(M, stringValue->getType(), true,
+ GlobalValue::InternalLinkage, stringValue, varName);
+ if (varSection.compare("")) {
+ strGV->setSection(varSection);
+ }
+ }
+ if (getElementPtrExpr) {
+ std::vector<Value*> strConstantIndices;
+ strConstantIndices.push_back(ZERO_CONSTANT_INT(M));
+ strConstantIndices.push_back(ZERO_CONSTANT_INT(M));
+ *getElementPtrExpr = PassUtil::getGetElementPtrConstant(strGV, strConstantIndices);
+ }
+
+ if (cacheable) {
+ stringCache.insert(std::pair<std::string, GlobalVariable*>(stringCacheKey, strGV));
+ }
+
+ return strGV;
+}
+
+inline ATTRIBUTE_SET_TY PassUtil::remapCallSiteAttributes(CallSite &CS, int argOffset)
+{
+ ATTRIBUTE_SET_TY Attrs = CS.getAttributes();
+ ATTRIBUTE_SET_TY NewAttrs;
+#if LLVM_VERSION >= 33
+ Instruction *I = CS.getInstruction();
+ NewAttrs.addAttributes(I->getContext(), ATTRIBUTE_SET_RET_IDX, Attrs.getRetAttributes());
+ NewAttrs.addAttributes(I->getContext(), ATTRIBUTE_SET_FN_IDX, Attrs.getFnAttributes());
+ for (unsigned i=1;i<=CS.arg_size();i++) {
+ NewAttrs.addAttributes(I->getContext(), i+argOffset, Attrs.getParamAttributes(i));
+ }
+#elif LLVM_VERSION == 32
+ Instruction *I = CS.getInstruction();
+ NewAttrs.addAttr(I->getContext(), ATTRIBUTE_SET_RET_IDX, Attrs.getRetAttributes());
+ NewAttrs.addAttr(I->getContext(), ATTRIBUTE_SET_FN_IDX, Attrs.getFnAttributes());
+ for (unsigned i=1;i<=CS.arg_size();i++) {
+ NewAttrs.addAttr(I->getContext(), i+argOffset, Attrs.getParamAttributes(i));
+ }
+#else
+ NewAttrs.addAttr(ATTRIBUTE_SET_RET_IDX, Attrs.getRetAttributes());
+ NewAttrs.addAttr(ATTRIBUTE_SET_FN_IDX, Attrs.getFnAttributes());
+ for (unsigned i=1;i<=CS.arg_size();i++) {
+ NewAttrs.addAttr(i+argOffset, Attrs.getParamAttributes(i));
+ }
+#endif
+
+ return NewAttrs;
+}
+
+inline void PassUtil::parseStringListOpt(std::vector<std::string> &list, const std::string &string, const std::string &separator)
+{
+ if(string.compare("")) {
+ SmallVector< StringRef, 8 > vector;
+ StringRef sref(string);
+ sref.split(vector, separator, -1, false);
+ list.insert(list.end(), vector.begin(), vector.end());
+ }
+}
+
+inline void PassUtil::parseStringPairListOpt(std::set<std::pair<std::string, std::string> > &set, const std::string &string, const std::string &listSeparator, const std::string &pairSeparator)
+{
+ if(string.compare("")) {
+ SmallVector< StringRef, 8 > vector;
+ StringRef sref(string);
+ sref.split(vector, listSeparator, -1, false);
+ SmallVector< StringRef, 8 > parts;
+ while(!vector.empty()) {
+ StringRef token = vector.pop_back_val();
+ parts.clear();
+ token.split(parts, pairSeparator, -1, false);
+ assert(parts.size() == 2 && "Two tokens were expected.");
+ set.insert(std::pair<std::string, std::string>(parts.front(), parts.back()));
+ }
+ }
+}
+
+inline void PassUtil::parseRegexListOpt(std::vector<Regex*> &list, const std::string &string)
+{
+ std::vector<std::string> stringList;
+ std::vector<std::string>::iterator it;
+ PassUtil::parseStringListOpt(stringList, string);
+
+ for (it = stringList.begin(); it != stringList.end(); ++it) {
+ Regex* regex = new Regex(*it, 0);
+ std::string error;
+ assert(regex->isValid(error));
+ list.push_back(regex);
+ }
+}
+
+inline bool PassUtil::matchRegexes(std::string string, std::vector<Regex*> ®exes)
+{
+ for (std::vector<Regex*>::iterator it = regexes.begin(); it != regexes.end(); ++it) {
+ Regex *regex = *it;
+ if(regex->match(string, NULL)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+inline void PassUtil::setModule(Module *M)
+{
+ PassUtil::M = M;
+}
+
+inline void PassUtil::getModuleName(Module &M, std::string *fullName, std::string *dirName, std::string *baseName)
+{
+ std::string _fullName, _dirName, _baseName;
+ _fullName = M.getModuleIdentifier();
+ SmallVector< StringRef, 8 > vector;
+ StringRef fullNameRef(_fullName);
+ fullNameRef.split(vector, "/", -1, false);
+ if (vector.size() > 1) {
+ _baseName = vector.pop_back_val();
+ for (unsigned i=0;i<vector.size();i++) {
+ _dirName.append("/");
+ _dirName.append(vector[i]);
+ }
+ }
+ else {
+ _baseName = _fullName;
+ _dirName = "/";
+ }
+ vector.clear();
+ StringRef baseNameRef(_baseName);
+ baseNameRef.split(vector, ".", -1, false);
+ if (vector.size() > 1) {
+ _baseName = vector[0];
+ }
+ if (fullName)
+ *fullName = _fullName;
+ if (dirName)
+ *dirName = _dirName;
+ if (baseName)
+ *baseName = _baseName;
+}
+
+inline unsigned long PassUtil::getTypeHash(TYPECONST Type* type, unsigned maxLevel)
+{
+ static std::vector<TYPECONST Type*> nestedTypes;
+ static unsigned level = 0;
+ static unsigned counter;
+ unsigned long hash = 7;
+ if(level == 0) {
+ counter = 0;
+ }
+ unsigned numContainedTypes = type->getNumContainedTypes();
+ unsigned nestedIndex = 0;
+ for(unsigned i=0;i<nestedTypes.size();i++) {
+ if(type == nestedTypes[i]) {
+ nestedIndex = i+1;
+ break;
+ }
+ }
+ hash = (13*hash) ^ level;
+ hash = (13*hash) ^ counter++;
+ hash = (13*hash) ^ type->getTypeID();
+ hash = (13*hash) ^ nestedIndex;
+ if(TYPECONST IntegerType *intType = dyn_cast<IntegerType>(type)) {
+ hash = (13*hash) ^ intType->getBitWidth();
+ }
+ else if(TYPECONST PointerType *ptrType = dyn_cast<PointerType>(type)) {
+ hash = (13*hash) ^ ptrType->getElementType()->getTypeID();
+ }
+ if(nestedIndex > 0 || level >= maxLevel) {
+ return hash;
+ }
+ if(numContainedTypes == 0) {
+ return hash;
+ }
+ level++;
+ nestedTypes.push_back(type);
+ hash = (13*hash) ^ numContainedTypes;
+ for(unsigned i=0;i<numContainedTypes;i++) {
+ hash = (13*hash) ^ getTypeHash(type->getContainedType(i), maxLevel);
+ }
+ nestedTypes.pop_back();
+ level--;
+
+ return hash;
+}
+
+}
+
+#endif /* _PASS_COMMON_H */
--- /dev/null
+#ifndef _QPROF_COMMON_H
+#define _QPROF_COMMON_H
+
+#include <cstdlib>
+#include <common/util/stdlib.h>
+
+#define QPROF_SEP ","
+#define QPROF_SEP2 ":"
+#define QPROF_SEP3 "|"
+
+#define QPROF_DECLARE_LL_SITESTACKS_OPT(P, VAR) \
+ static cl::opt<std::string> \
+ VAR(#P "-ll-sitestacks", \
+ cl::desc("Specify all the long-lived sitestacks on a per-task basis in qprof format"), \
+ cl::init(""), cl::NotHidden, cl::ValueRequired)
+
+#define QPROF_DECLARE_DEEPEST_LL_LOOPS_OPT(P, VAR) \
+ static cl::opt<std::string> \
+ VAR(#P "-deepest-ll-loops", \
+ cl::desc("Specify all the deepest long-lived loops on a per-task basis in qprof format"), \
+ cl::init(""), cl::NotHidden, cl::ValueRequired)
+
+#define QPROF_DECLARE_DEEPEST_LL_LIBS_OPT(P, VAR) \
+ static cl::opt<std::string> \
+ VAR(#P "-deepest-ll-libs", \
+ cl::desc("Specify all the deepest long-lived loop lib calls on a per-task basis in qprof format"), \
+ cl::init(""), cl::NotHidden, cl::ValueRequired)
+
+#define QPROF_DECLARE_TASK_CLASSES_OPT(P, VAR) \
+ static cl::opt<std::string> \
+ VAR(#P "-task-classes", \
+ cl::desc("Specify all the task classes in qprof format"), \
+ cl::init(""), cl::NotHidden, cl::ValueRequired)
+
+#define QPROF_DECLARE_ALL_OPTS(P, VAR1, VAR2, VAR3, VAR4) \
+ QPROF_DECLARE_LL_SITESTACKS_OPT(P, VAR1); \
+ QPROF_DECLARE_DEEPEST_LL_LOOPS_OPT(P, VAR2); \
+ QPROF_DECLARE_DEEPEST_LL_LIBS_OPT(P, VAR3); \
+ QPROF_DECLARE_TASK_CLASSES_OPT(P, VAR4) \
+
+using namespace llvm;
+
+namespace llvm {
+
+class QProfSite {
+ public:
+ static QProfSite* get(Module &M, int taskClassID, int taskSiteID, std::string moduleName, int lineNum, std::string functionName, std::string siteName, std::string siteFuncName, int siteDepth, int lib, unsigned long libFlags, bool refreshSite=true);
+ static QProfSite* getFromString(Module &M, int taskClassID, int taskSiteID, std::string &siteString, bool refreshSite=true);
+ static std::vector<QProfSite*> getFromSitesString(Module &M, std::string &sitesString, bool refreshSites=true);
+
+ void refresh(Module &M);
+ std::string toString();
+ bool isLoop();
+ bool isFunction();
+ bool isCallsite();
+ bool isLibCallsite();
+ bool equals(QProfSite *other);
+
+ int taskClassID;
+ int taskSiteID;
+ std::string moduleName;
+ int lineNum;
+ std::string functionName;
+ std::string siteName;
+ std::string siteFuncName;
+ unsigned long libFlags;
+ Function *function;
+ Function *siteFunction;
+ Instruction *siteInstruction;
+ private:
+ QProfSite() {}
+
+ int siteDepth;
+ int lib;
+};
+
+class QProfConf {
+ public:
+ static QProfConf* get(Module &M, std::string *llSitestacks, std::string *deepestLLLoops, std::string *deepestLLLibs, std::string *taskClasses, bool refreshSites=true);
+
+ std::map<int, std::vector<QProfSite*> > getTaskClassLLSitestacks();
+ std::map<int, QProfSite*> getTaskClassDeepestLLLoops();
+ std::map<int, std::vector<QProfSite*> > getTaskClassDeepestLLLibs();
+ int getNumTaskClasses();
+ int getNumLLTaskClasses();
+ int getNumLLBlockExtTaskClasses();
+ int getNumLLBlockIntTaskClasses();
+ int getNumLLBlockExtLibs();
+ int getNumLLBlockIntLibs();
+
+ std::vector<QProfSite*> getLLFunctions();
+ std::vector<QProfSite*> getDeepestLLLoops();
+ std::vector<QProfSite*> getDeepestLLLibs();
+ bool lookupTaskClassLibFlags(int taskClassID, int *libFlags);
+ void mergeTaskClassLLSitestacks(int taskClassID, int otherTaskClassID);
+ void mergeTaskClassDeepestLLLoops(int taskClassID, int otherTaskClassID);
+ void mergeTaskClassDeepestLLLibs(int taskClassID, int otherTaskClassID);
+ void mergeTaskClassPair(int taskClassID, int otherTaskClassID);
+ void mergeAllTaskClassesWithSameDeepestLLLoops();
+ void print(raw_ostream &O);
+ void printSiteList(raw_ostream &O, std::vector<QProfSite*> &list);
+
+ private:
+ QProfConf() {}
+
+ static std::map<int, std::vector<QProfSite*> > parseTaskClassSiteList(Module &M, std::string &str, bool refreshSites=true);
+ static std::map<int, QProfSite*> parseTaskClassSite(Module &M, std::string &str, bool refreshSites=true);
+ static std::vector<int> parseIntList(std::string &str);
+
+ std::map<int, std::vector<QProfSite*> > taskClassLLSitestacks;
+ std::map<int, QProfSite*> taskClassDeepestLLLoops;
+ std::map<int, std::vector<QProfSite*> > taskClassDeepestLLLibs;
+ int numTaskClasses;
+ int numLLTaskClasses;
+ int numLLBlockExtTaskClasses;
+ int numLLBlockIntTaskClasses;
+ int numLLBlockExtLibs;
+ int numLLBlockIntLibs;
+};
+
+static int stringRefToInt(StringRef &ref)
+{
+ return atoi(ref.str().c_str());
+}
+
+inline QProfSite* QProfSite::get(Module &M, int taskClassID, int taskSiteID,
+ std::string moduleName, int lineNum, std::string functionName,
+ std::string siteName, std::string siteFuncName, int siteDepth, int lib,
+ unsigned long libFlags, bool refreshSite)
+{
+ QProfSite *site = new QProfSite();
+ site->taskClassID = taskClassID;
+ site->taskSiteID = taskSiteID;
+ site->moduleName = moduleName;
+ site->lineNum = lineNum;
+ site->functionName = functionName;
+ site->siteName = siteName;
+ site->siteFuncName = siteFuncName;
+ site->siteDepth = siteDepth;
+ site->lib = lib;
+ site->libFlags = libFlags;
+ site->function = NULL;
+ site->siteFunction = NULL;
+ site->siteInstruction = NULL;
+ if (refreshSite) {
+ site->refresh(M);
+ }
+
+ return site;
+}
+
+inline QProfSite* QProfSite::getFromString(Module &M, int taskClassID, int taskSiteID,
+ std::string &siteString, bool refreshSite)
+{
+ StringRef ref(siteString);
+ SmallVector< StringRef, 3 > tokenVector;
+ if (!siteString.compare("")) {
+ return NULL;
+ }
+ ref.split(tokenVector, QPROF_SEP3);
+ assert(tokenVector.size() == 8);
+ return get(M, taskClassID, taskSiteID, tokenVector[0], stringRefToInt(tokenVector[1]),
+ tokenVector[2], tokenVector[3], tokenVector[4],
+ stringRefToInt(tokenVector[5]), stringRefToInt(tokenVector[6]),
+ stringRefToInt(tokenVector[7]), refreshSite);
+}
+
+inline std::vector<QProfSite*> QProfSite::getFromSitesString(Module &M,
+ std::string &sitesString, bool refreshSites)
+{
+ unsigned i;
+ int taskClassID;
+ std::vector<QProfSite*> sites;
+ StringRef ref(sitesString);
+ SmallVector< StringRef, 3 > tokenVector;
+ if (!sitesString.compare("")) {
+ return sites;
+ }
+ ref.split(tokenVector, QPROF_SEP2);
+ assert(tokenVector.size() > 1);
+ taskClassID = stringRefToInt(tokenVector[0]);
+ for (i=1;i<tokenVector.size();i++) {
+ std::string token = tokenVector[i].str();
+ QProfSite *site = QProfSite::getFromString(M, taskClassID, i, token,
+ refreshSites);
+ sites.push_back(site);
+ }
+ return sites;
+}
+
+inline void QProfSite::refresh(Module &M)
+{
+ BasicBlock *siteBB = NULL;
+ function = NULL;
+ siteFunction = NULL;
+ siteInstruction = NULL;
+ function = M.getFunction(functionName);
+ siteFunction = M.getFunction(siteFuncName);
+ if (!siteFunction) {
+ errs() << "Function " << siteFuncName << " not found. Invalid qprof profiling data?\n";
+ }
+ assert(siteFunction);
+ for (Function::iterator BB = siteFunction->begin(),
+ e = siteFunction->end(); BB != e; ++BB) {
+ if (!BB->getName().compare(siteName)) {
+ siteBB = BB;
+ break;
+ }
+ }
+ assert(siteBB);
+ if (isCallsite()) {
+ for (BasicBlock::iterator it = siteBB->begin(); it != siteBB->end(); ++it) {
+ CallSite CS(it);
+ if (CS.getInstruction() && CS.getCalledFunction() == function) {
+ siteInstruction = it;
+ break;
+ }
+ }
+ assert(siteInstruction && "Invalid qprof callsite?");
+ }
+ else {
+ siteInstruction = &siteBB->front();
+ }
+}
+
+inline std::string QProfSite::toString()
+{
+ std::string str;
+ raw_string_ostream ostream(str);
+ ostream << taskClassID << QPROF_SEP3 << taskSiteID << QPROF_SEP3 << moduleName << QPROF_SEP3 << lineNum << QPROF_SEP3 << functionName << QPROF_SEP3 << siteName << QPROF_SEP3 << siteFuncName << QPROF_SEP3 << siteDepth << QPROF_SEP3 << lib << QPROF_SEP3 << libFlags;
+ ostream.flush();
+ return str;
+}
+
+inline bool QProfSite::isLoop()
+{
+ return siteDepth > 0;
+}
+
+inline bool QProfSite::isFunction()
+{
+ return !isLoop() && !isCallsite();
+}
+
+inline bool QProfSite::isCallsite()
+{
+ return isLibCallsite();
+}
+
+inline bool QProfSite::isLibCallsite()
+{
+ return lib != 0;
+}
+
+inline bool QProfSite::equals(QProfSite *other)
+{
+ if (lineNum != other->lineNum) {
+ return false;
+ }
+ if (libFlags != other->libFlags) {
+ return false;
+ }
+ if (moduleName.compare(other->moduleName)) {
+ return false;
+ }
+ if (functionName.compare(other->functionName)) {
+ return false;
+ }
+ if (siteName.compare(other->siteName)) {
+ return false;
+ }
+ if (siteFuncName.compare(other->siteFuncName)) {
+ return false;
+ }
+ return true;
+}
+
+inline QProfConf* QProfConf::get(Module &M, std::string *llSitestacks,
+ std::string *deepestLLLoops, std::string *deepestLLLibs,
+ std::string *taskClasses, bool refreshSites)
+{
+ std::vector<int> intValues;
+ QProfConf *conf = new QProfConf();
+ if (llSitestacks) {
+ conf->taskClassLLSitestacks = parseTaskClassSiteList(M,
+ *llSitestacks, refreshSites);
+ }
+ if (deepestLLLoops) {
+ conf->taskClassDeepestLLLoops = parseTaskClassSite(M,
+ *deepestLLLoops, refreshSites);
+ }
+ if (deepestLLLibs) {
+ conf->taskClassDeepestLLLibs = parseTaskClassSiteList(M,
+ *deepestLLLibs, refreshSites);
+ }
+ if (taskClasses) {
+ intValues = parseIntList(*taskClasses);
+ }
+ if (intValues.size() > 0) {
+ assert(intValues.size() == 6);
+ conf->numTaskClasses = intValues[0];
+ conf->numLLTaskClasses = intValues[1];
+ conf->numLLBlockExtTaskClasses = intValues[2];
+ conf->numLLBlockIntTaskClasses = intValues[3];
+ conf->numLLBlockExtLibs = intValues[4];
+ conf->numLLBlockIntLibs = intValues[5];
+ }
+ else {
+ conf->numTaskClasses = 0;
+ conf->numLLTaskClasses = 0;
+ conf->numLLBlockExtTaskClasses = 0;
+ conf->numLLBlockIntTaskClasses = 0;
+ conf->numLLBlockExtLibs = 0;
+ conf->numLLBlockIntLibs = 0;
+ }
+
+ return conf;
+}
+
+inline std::map<int, std::vector<QProfSite*> > QProfConf::getTaskClassLLSitestacks()
+{
+ return taskClassLLSitestacks;
+}
+
+inline std::map<int, QProfSite*> QProfConf::getTaskClassDeepestLLLoops()
+{
+ return taskClassDeepestLLLoops;
+}
+
+inline std::map<int, std::vector<QProfSite*> > QProfConf::getTaskClassDeepestLLLibs()
+{
+ return taskClassDeepestLLLibs;
+}
+
+inline int QProfConf::getNumTaskClasses()
+{
+ return numTaskClasses;
+}
+
+inline int QProfConf::getNumLLTaskClasses()
+{
+ return numLLTaskClasses;
+}
+
+inline int QProfConf::getNumLLBlockExtTaskClasses()
+{
+ return numLLBlockExtTaskClasses;
+}
+
+inline int QProfConf::getNumLLBlockIntTaskClasses()
+{
+ return numLLBlockIntTaskClasses;
+}
+
+inline int QProfConf::getNumLLBlockExtLibs()
+{
+ return numLLBlockExtLibs;
+}
+
+inline int QProfConf::getNumLLBlockIntLibs()
+{
+ return numLLBlockIntLibs;
+}
+
+inline std::vector<QProfSite*> QProfConf::getLLFunctions()
+{
+ std::vector<QProfSite*> sites;
+ std::map<int, std::vector<QProfSite*> >::iterator it;
+ it = taskClassLLSitestacks.begin();
+ for (; it != taskClassLLSitestacks.end(); it++) {
+ std::vector<QProfSite*> *siteVector = &it->second;
+ for (unsigned i=0;i<siteVector->size();i++) {
+ QProfSite* site = (*siteVector)[i];
+ if (site->isFunction()) {
+ sites.push_back((*siteVector)[i]);
+ }
+ }
+ }
+ return sites;
+}
+
+inline std::vector<QProfSite*> QProfConf::getDeepestLLLoops()
+{
+ std::vector<QProfSite*> sites;
+ std::map<int, QProfSite*>::iterator it;
+ it = taskClassDeepestLLLoops.begin();
+ for (; it != taskClassDeepestLLLoops.end(); it++) {
+ sites.push_back(it->second);
+ }
+ return sites;
+}
+
+inline std::vector<QProfSite*> QProfConf::getDeepestLLLibs()
+{
+ std::vector<QProfSite*> sites;
+ std::map<int, std::vector<QProfSite*> >::iterator it;
+ it = taskClassDeepestLLLibs.begin();
+ for (; it != taskClassDeepestLLLibs.end(); it++) {
+ std::vector<QProfSite*> *siteVector = &it->second;
+ for (unsigned i=0;i<siteVector->size();i++) {
+ sites.push_back((*siteVector)[i]);
+ }
+ }
+ return sites;
+}
+
+inline bool QProfConf::lookupTaskClassLibFlags(int taskClassID, int *libFlags)
+{
+ bool found = false;
+ std::vector<QProfSite*> deepestLLLibs = getDeepestLLLibs();
+
+ *libFlags = 0;
+ for (unsigned i=0;i<deepestLLLibs.size();i++) {
+ QProfSite *site = deepestLLLibs[i];
+ if (site->taskClassID == taskClassID) {
+ *libFlags |= site->libFlags;
+ found = true;
+ }
+ }
+ return found;
+}
+
+inline void QProfConf::mergeTaskClassLLSitestacks(int taskClassID, int otherTaskClassID)
+{
+ size_t erased = taskClassLLSitestacks.erase(otherTaskClassID);
+ assert(erased == 1);
+}
+
+inline void QProfConf::mergeTaskClassDeepestLLLoops(int taskClassID, int otherTaskClassID)
+{
+ size_t erased = taskClassDeepestLLLoops.erase(otherTaskClassID);
+ assert(erased == 1);
+}
+
+inline void QProfConf::mergeTaskClassDeepestLLLibs(int taskClassID, int otherTaskClassID)
+{
+ size_t erased = taskClassDeepestLLLibs.erase(otherTaskClassID);
+ assert(erased == 1);
+}
+
+inline void QProfConf::mergeTaskClassPair(int taskClassID,
+ int otherTaskClassID)
+{
+ int libFlags;
+ mergeTaskClassLLSitestacks(taskClassID, otherTaskClassID);
+ mergeTaskClassDeepestLLLoops(taskClassID, otherTaskClassID);
+ mergeTaskClassDeepestLLLibs(taskClassID, otherTaskClassID);
+
+ numTaskClasses--;
+ if (lookupTaskClassLibFlags(taskClassID, &libFlags)) {
+ numLLTaskClasses--;
+ if (libFlags & _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)) {
+ numLLBlockExtTaskClasses--;
+ }
+ else {
+ numLLBlockIntTaskClasses--;
+ }
+ }
+}
+
+inline void QProfConf::mergeAllTaskClassesWithSameDeepestLLLoops()
+{
+ std::vector<QProfSite*> deepestLLLoops = getDeepestLLLoops();
+ std::vector<std::pair<QProfSite*, QProfSite*> > loopPairs;
+
+ for (unsigned i=0;i<deepestLLLoops.size();i++) {
+ QProfSite *site = deepestLLLoops[i];
+ for (unsigned j=0;j<i;j++) {
+ if (site->equals(deepestLLLoops[j])) {
+ loopPairs.push_back(std::pair<QProfSite*, QProfSite*>(site, deepestLLLoops[j]));
+ }
+ }
+ }
+ for (unsigned i=0;i<loopPairs.size();i++) {
+ int taskClassID = loopPairs[i].first->taskClassID;
+ int otherTaskClassID = loopPairs[i].second->taskClassID;
+ mergeTaskClassPair(taskClassID, otherTaskClassID);
+ }
+}
+
+inline void QProfConf::print(raw_ostream &O)
+{
+ std::vector<QProfSite*> list;
+ O << "*** QProfConf:\n";
+ O << " - numTaskClasses=" << getNumTaskClasses() << "\n";
+ O << " - numLLTaskClasses=" << getNumLLTaskClasses() << "\n";
+ O << " - numLLBlockExtTaskClasses=" << getNumLLBlockExtTaskClasses() << "\n";
+ O << " - numLLBlockIntTaskClasses=" << getNumLLBlockIntTaskClasses() << "\n";
+ O << " - numLLBlockExtLibs=" << getNumLLBlockExtLibs() << "\n";
+ O << " - numLLBlockIntLibs=" << getNumLLBlockIntLibs() << "\n";
+ list = getLLFunctions();
+ O << " - LLFunctions="; printSiteList(O, list); O << "\n";
+ list = getDeepestLLLoops();
+ O << " - deepestLLLoops="; printSiteList(O, list); O << "\n";
+ list = getDeepestLLLibs();
+ O << " - deepestLLLibs="; printSiteList(O, list); O << "\n";
+}
+
+inline void QProfConf::printSiteList(raw_ostream &O, std::vector<QProfSite*> &list)
+{
+ for (std::vector<QProfSite*>::iterator it = list.begin(); it != list.end(); it++) {
+ QProfSite* site = *it;
+ if (it != list.begin()) {
+ O << ", ";
+ }
+ O << "{ ";
+ O << site->toString();
+ O << " }";
+ }
+}
+
+inline std::map<int, std::vector<QProfSite*> > QProfConf::parseTaskClassSiteList(Module &M,
+ std::string &str, bool refreshSites)
+{
+ std::map<int, std::vector<QProfSite*> > siteListMap;
+ StringRef ref(str);
+ SmallVector< StringRef, 3 > tokenVector;
+ if (!str.compare("")) {
+ return siteListMap;
+ }
+ ref.split(tokenVector, QPROF_SEP);
+ for (unsigned i=0;i<tokenVector.size();i++) {
+ std::string token = tokenVector[i].str();
+ std::vector<QProfSite*> sites = QProfSite::getFromSitesString(M,
+ token, refreshSites);
+ if (sites.size() > 0) {
+ int taskClassID = sites[0]->taskClassID;
+ siteListMap.insert(std::pair<int, std::vector<QProfSite*> >(taskClassID,
+ sites));
+ }
+ }
+ return siteListMap;
+}
+
+inline std::map<int, QProfSite*> QProfConf::parseTaskClassSite(Module &M,
+ std::string &str, bool refreshSites)
+{
+ std::map<int, std::vector<QProfSite*> >::iterator it;
+ std::map<int, std::vector<QProfSite*> > siteListMap =
+ parseTaskClassSiteList(M, str, refreshSites);
+ std::map<int, QProfSite*> siteMap;
+ for (it=siteListMap.begin();it!=siteListMap.end();it++) {
+ std::vector<QProfSite*> list = it->second;
+ assert(list.size() == 1);
+ siteMap.insert(std::pair<int, QProfSite*>(it->first, list[0]));
+ }
+
+ return siteMap;
+}
+
+inline std::vector<int> QProfConf::parseIntList(std::string &str)
+{
+ std::vector<int> intValues;
+ StringRef ref(str);
+ SmallVector< StringRef, 3 > tokenVector;
+ if (!str.compare("")) {
+ return intValues;
+ }
+ ref.split(tokenVector, QPROF_SEP);
+ for (unsigned i=0;i<tokenVector.size();i++) {
+ intValues.push_back(stringRefToInt(tokenVector[i]));
+ }
+
+ return intValues;
+}
+
+}
+
+#endif /* _QPROF_COMMON_H */
--- /dev/null
+#ifndef MAGIC_CTLAZY_CHECKPOINT_PASS_H
+#define MAGIC_CTLAZY_CHECKPOINT_PASS_H
+
+#include <magic/magic.h>
+#include <magic/MagicPass.h>
+#include <magic/support/VariableRefs.h>
+
+using namespace llvm;
+
+namespace llvm {
+
+#define magicCTLazyCheckpointPassLog(M) DEBUG(dbgs() << "MagicCTLazyCheckpointPass: " << M << "\n")
+
+class MagicCTLazyCheckpointPass : public FunctionPass {
+
+ public:
+ static char ID;
+
+ MagicCTLazyCheckpointPass();
+
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const;
+ virtual bool runOnFunction(Function &F);
+
+ private:
+ AliasAnalysis *AA;
+
+ bool instructionModifiesVar(Module &M, Instruction *inst, GlobalVariable* var);
+};
+
+}
+
+#endif
--- /dev/null
+#ifndef MAGIC_CHECKPOINT_PASS_H
+#define MAGIC_CHECKPOINT_PASS_H
+
+#include <magic/magic.h>
+#include <magic/MagicPass.h>
+
+using namespace llvm;
+
+namespace llvm {
+
+#define magicCheckpointPassLog(M) DEBUG(dbgs() << "MagicCheckpointPass: " << M << "\n")
+
+class MagicCheckpointPass : public ModulePass {
+
+ public:
+ static char ID;
+
+ MagicCheckpointPass();
+
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const;
+ virtual bool runOnModule(Module &M);
+
+ private:
+ MagicPass *MP;
+};
+
+}
+
+#endif
--- /dev/null
+#ifndef MAGIC_LTLAZY_CHECKPOINT_PASS_H
+#define MAGIC_LTLAZY_CHECKPOINT_PASS_H
+
+#include <magic/magic.h>
+#include <magic/MagicPass.h>
+
+using namespace llvm;
+
+namespace llvm {
+
+#define magicLTLazyCheckpointPassLog(M) DEBUG(dbgs() << "MagicLTLazyCheckpointPass: " << M << "\n")
+
+class MagicLTLazyCheckpointPass : public FunctionPass {
+
+ public:
+ static char ID;
+
+ MagicLTLazyCheckpointPass();
+
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const;
+ virtual bool runOnFunction(Function &F);
+
+ private:
+ MagicPass *MP;
+};
+
+}
+
+#endif
--- /dev/null
+#ifndef MAGIC_PASS_H
+
+#define MAGIC_PASS_H
+
+#include <pass.h>
+#include <magic/magic.h>
+#include <magic/support/Backports.h>
+#include <magic/support/MagicUtil.h>
+#include <magic/support/SmartType.h>
+#include <magic/support/TypeInfo.h>
+#include <magic/support/MagicDebugFunction.h>
+#include <magic/support/MagicMemFunction.h>
+#include <magic/support/MagicMmapCtlFunction.h>
+
+#if MAGIC_USE_QPROF_INSTRUMENTATION
+#include <common/qprof_common.h>
+#endif
+
+using namespace llvm;
+
+namespace llvm {
+
+#define magicPassLog(M) DEBUG(dbgs() << "MagicPass: " << M << "\n")
+#define magicPassErr(M) errs() << "MagicPass: " << M << "\n"
+
+class MagicPass : public ModulePass {
+
+ public:
+ static char ID;
+
+ MagicPass();
+
+ std::vector<GlobalVariable*> getGlobalVariables() const;
+ std::vector<int> getGlobalVariableSizes() const;
+ std::vector<GlobalVariable*> getShadowGlobalVariables() const;
+ std::vector<Function*> getFunctions() const;
+ GlobalVariable* getMagicArray() const;
+ GlobalVariable* getMagicTypeArray() const;
+ GlobalVariable* getMagicFunctionArray() const;
+ GlobalVariable* getMagicDsindexArray() const;
+
+ virtual bool runOnModule(Module &M);
+
+ private:
+ std::vector<GlobalVariable*> globalVariables;
+ std::set<GlobalVariable*> globalVariablesWithAddressTaken;
+ std::vector<int> globalVariableSizes;
+ std::vector<GlobalVariable*> shadowGlobalVariables;
+ std::vector<Function*> functions;
+ std::vector<TypeInfo*> globalTypeInfos;
+ std::map<GlobalValue*, TypeInfo*> globalParentMap;
+ std::map<GlobalValue*, TypeInfo*>::iterator parentMapIt;
+ std::map<std::string, GlobalVariable*> stringOwnerMap;
+ std::map<std::string, GlobalVariable*>::iterator stringOwnerMapIt;
+ std::map<GlobalVariable*, std::string> stringOwnerInvertedMap;
+ std::map<GlobalVariable*, std::string>::iterator stringOwnerInvertedMapIt;
+
+ GlobalVariable* magicArray;
+ GlobalVariable* magicTypeArray;
+ GlobalVariable* magicFunctionArray;
+ GlobalVariable* magicDsindexArray;
+
+ std::vector<std::string> libPathRegexes;
+ std::vector<std::string> voidTypeAliases;
+ std::set<std::string> voidTypeAliasesSet;
+ std::vector<std::string> mmFuncPrefixes;
+ std::set<std::pair<std::string, std::string> > mmFuncPairs;
+ std::vector<std::string> mmPoolFunctions;
+ std::vector<std::string> mmapCtlFunctions;
+ std::set<std::string>::iterator stringSetIt;
+ std::set<Function*> brkFunctions;
+ std::set<Function*> sbrkFunctions;
+ std::vector<Regex*> magicDataSectionRegexes;
+ std::vector<Regex*> magicFunctionSectionRegexes;
+ std::vector<Regex*> extLibSectionRegexes;
+
+#if MAGIC_USE_QPROF_INSTRUMENTATION
+ QProfConf *qprofConf;
+#endif
+
+ void qprofInstrumentationInit(Module &M);
+ void qprofInstrumentationApply(Module &M);
+ bool checkPointerVariableIndexes(TYPECONST Type* type, std::vector<int> &ptrVarIndexes, unsigned offset=0);
+ void findPointerVariables(Function* function, Value *value, std::vector<Value*> &ptrVars, std::vector<std::vector<int> > &ptrVarIndexes, Value *parent = NULL, bool isUser=false);
+ TypeInfo* typeInfoFromPointerVariables(Module &M, TypeInfo *voidPtrTypeInfo, std::vector<Value*> &ptrVars, std::vector<std::vector<int> > &ptrVarIndexes, std::string &allocName);
+ TypeInfo* getAllocTypeInfo(Module &M, TypeInfo *voidPtrTypeInfo, const CallSite &CS, std::string &allocName, std::string &allocParentName);
+ TypeInfo* fillTypeInfos(TypeInfo &sourceTypeInfo, std::vector<TypeInfo*> &typeInfos);
+ TypeInfo* fillExternalTypeInfos(TYPECONST Type* sourceType, GlobalValue *parent, std::vector<TypeInfo*> &typeInfos);
+ void printInterestingTypes(TYPECONST TypeInfo *aTypeInfo);
+ unsigned getMaxRecursiveSequenceLength(TYPECONST TypeInfo *aTypeInfo);
+ FunctionType* getFunctionType(TYPECONST FunctionType *baseType, std::vector<unsigned> selectedArgs);
+ bool isCompatibleMagicMemFuncType(TYPECONST FunctionType *type, TYPECONST FunctionType* magicType);
+ void indexCasts(Module &M, User *U, std::vector<TYPECONST Type*> &intCastTypes, std::vector<int> &intCastValues, std::map<TYPECONST Type*, std::set<TYPECONST Type*> > &bitcastMap);
+
+ void fillStackInstrumentedFunctions(std::vector<Function*> &stackIntrumentedFuncs, Function *deepestLLFunction);
+ void indexLocalTypeInfos(Module &M, Function *F, std::map<AllocaInst*, std::pair<TypeInfo*, std::string> > &localMap);
+ void addMagicStackDsentryFuncCalls(Module &M, Function *insertCallsInFunc, Function *localsFromFunc, Function *dsentryCreateFunc, Function *dsentryDestroyFunc, TYPECONST StructType *dsentryStructType, std::map<AllocaInst*, std::pair<TypeInfo*, std::string> > localTypeInfoMap, std::map<TypeInfo*, Constant*> &magicArrayTypePtrMap, TypeInfo *voidPtrTypeInfo, std::vector<TypeInfo*> &typeInfoList, std::vector<std::pair<std::string, std::string> > &namesList, std::vector<int> &flagsList);
+ bool isExtLibrary(GlobalValue *GV, DIDescriptor *DID);
+ bool isMagicGV(Module &M, GlobalVariable *GV);
+ bool isMagicFunction(Module &M, Function *F);
+};
+
+inline std::vector<GlobalVariable*> MagicPass::getGlobalVariables() const {
+ return globalVariables;
+}
+
+inline std::vector<int> MagicPass::getGlobalVariableSizes() const {
+ return globalVariableSizes;
+}
+
+inline std::vector<GlobalVariable*> MagicPass::getShadowGlobalVariables() const {
+ return shadowGlobalVariables;
+}
+
+inline std::vector<Function*> MagicPass::getFunctions() const {
+ return functions;
+}
+
+inline GlobalVariable* MagicPass::getMagicArray() const {
+ return magicArray;
+}
+
+inline GlobalVariable* MagicPass::getMagicTypeArray() const {
+ return magicTypeArray;
+}
+
+inline GlobalVariable* MagicPass::getMagicFunctionArray() const {
+ return magicFunctionArray;
+}
+
+inline GlobalVariable* MagicPass::getMagicDsindexArray() const {
+ return magicDsindexArray;
+}
+
+}
+
+#endif
--- /dev/null
+#ifndef _MAGIC_PASS_H
+#define _MAGIC_PASS_H
+
+#include <pass.h>
+#include <magic_common.h>
+
+#define MAGIC_FORCE_ALIGN 0
+#define MAGIC_FORCE_INLINING 0
+
+#endif /* _MAGIC_PASS_H */
+
--- /dev/null
+#ifndef BACKPORTS_H
+#define BACKPORTS_H
+
+#include <pass.h>
+
+using namespace llvm;
+
+namespace llvm {
+
+class Backports {
+ public:
+
+ //From DbgInfoPrinter.cpp (LLVM 2.9)
+ static Value *findDbgGlobalDeclare(GlobalVariable *V);
+ static Value *findDbgSubprogramDeclare(Function *V);
+ static const DbgDeclareInst *findDbgDeclare(const Value *V);
+
+ //From Local.cpp (LLVM 2.9)
+ static DbgDeclareInst *FindAllocaDbgDeclare(Value *V);
+};
+
+}
+
+#endif
--- /dev/null
+#ifndef BIT_FIELD_AGGREGATION_H
+#define BIT_FIELD_AGGREGATION_H
+
+#include <magic/support/EDIType.h>
+#include <magic/support/TypeUtil.h>
+
+using namespace llvm;
+
+namespace llvm {
+
+#define BitFieldAggregationErr(M) errs() << "BitFieldAggregation: " << M << "\n"
+
+#define BFA_NAME_PREFIX "__BFA__"
+
+class BitFieldAggregation {
+ public:
+ BitFieldAggregation(TYPECONST Type* type, std::vector<EDIType> EDITypes, unsigned typeIndex, unsigned EDITypeIndex, std::vector<DIDerivedType> members, unsigned counter);
+ BitFieldAggregation();
+ void init(TYPECONST Type* type, std::vector<EDIType> EDITypes, unsigned typeIndex, unsigned EDITypeIndex, std::vector<DIDerivedType> members, unsigned counter);
+
+ const std::string getDescription() const;
+
+ unsigned getTypeIndex() const;
+ unsigned getEDITypeIndex() const;
+ std::string getName() const;
+ std::vector<DIDerivedType> getMembers() const;
+
+ unsigned getSize() const;
+ TYPECONST Type *getType() const;
+ std::vector<EDIType> getEDITypes() const;
+ unsigned getRepresentativeEDITypeIndex() const;
+
+ void print(raw_ostream &OS) const;
+
+ static bool getBitFieldAggregations(TYPECONST Type *type, const EDIType *aEDIType, std::vector<BitFieldAggregation> &bfas, bool returnOnError=false);
+ static bool hasBitFields(TYPECONST Type *type, const EDIType *aEDIType);
+ static bool isBitField(TYPECONST Type *type, const EDIType *aEDIType, unsigned memberIdx);
+
+ private:
+ TYPECONST Type *type;
+ std::vector<EDIType> EDITypes;
+ unsigned typeIndex;
+ unsigned EDITypeIndex;
+ std::string name;
+ std::vector<DIDerivedType> members;
+ unsigned size;
+
+ static std::string bfaNamePrefix;
+
+ static BitFieldAggregation* getBitFieldAggregation(TYPECONST Type *type, const EDIType *aEDIType, bool returnOnError, unsigned typeIndex, unsigned EDITypeIndex, unsigned lastTypeIndex, unsigned lastEDITypeIndex, unsigned counter);
+};
+
+inline raw_ostream &operator<<(raw_ostream &OS, const BitFieldAggregation &bfa) {
+ bfa.print(OS);
+ return OS;
+}
+
+inline unsigned BitFieldAggregation::getTypeIndex() const {
+ return typeIndex;
+}
+
+inline unsigned BitFieldAggregation::getEDITypeIndex() const {
+ return EDITypeIndex;
+}
+
+inline std::string BitFieldAggregation::getName() const {
+ return name;
+}
+
+inline std::vector<DIDerivedType> BitFieldAggregation::getMembers() const {
+ return members;
+}
+
+inline unsigned BitFieldAggregation::getSize() const {
+ return size;
+}
+
+inline TYPECONST Type *BitFieldAggregation::getType() const {
+ return type;
+}
+
+inline std::vector<EDIType> BitFieldAggregation::getEDITypes() const {
+ return EDITypes;
+}
+
+inline unsigned BitFieldAggregation::getRepresentativeEDITypeIndex() const {
+ return EDITypeIndex;
+}
+
+inline void BitFieldAggregation::print(raw_ostream &OS) const {
+ OS << getDescription();
+}
+
+inline bool BitFieldAggregation::hasBitFields(TYPECONST Type *type, const EDIType *aEDIType) {
+ if(!aEDIType->isStructTy()) {
+ return false;
+ }
+ unsigned numContainedTypes = aEDIType->getNumContainedTypes();
+ for(unsigned i=0;i<numContainedTypes;i++) {
+ if (isBitField(type, aEDIType, i)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+inline bool BitFieldAggregation::isBitField(TYPECONST Type *type, const EDIType *aEDIType, unsigned memberIdx) {
+ const DIDerivedType subDIType = aEDIType->getMember(memberIdx);
+ unsigned EDITypeBits = subDIType.getSizeInBits();
+ const DIType aDIType = PassUtil::getDITypeDerivedFrom(subDIType);
+ unsigned EDITypeOriginalBits = aDIType.getSizeInBits();
+ return (EDITypeBits>0 && EDITypeOriginalBits>0 && EDITypeBits != EDITypeOriginalBits);
+}
+
+}
+
+#endif
--- /dev/null
+#ifndef EDITYPE_H
+#define EDITYPE_H
+
+#include <pass.h>
+
+using namespace llvm;
+
+namespace llvm {
+
+#define EDITypeLog(M) DEBUG(dbgs() << "EDIType: " << M << "\n")
+#define EDITypeErr(M) errs() << "EDIType: " << M << "\n"
+
+#define EDIType_assert(X) do { \
+ if(!(X)) { \
+ errs() << "Assertion failed, dumping object...\n"; \
+ errs() << *this; \
+ } \
+ assert(X); \
+ } while(0)
+
+class EDIType {
+ public:
+ EDIType(const MDNode *N, bool norm=true, bool checkOpaqueTypes=true);
+ EDIType(bool norm=false, bool checkOpaqueTypes=false);
+ EDIType(const DIType aDIType, bool norm=true, bool checkOpaqueTypes=true);
+
+ bool operator == (const EDIType& aEDIType) const;
+
+ static const bool NORMALIZE = true;
+ static const bool DO_NOT_NORMALIZE = false;
+ static const bool CHECK_OPAQUE_TYPES = true;
+ static const bool DO_NOT_CHECK_OPAQUE_TYPES = false;
+
+ const std::string getDescription(int skipUnions=0, int skipStructs=0, int allowMultiNames=0) const;
+ const EDIType& getContainedType(unsigned i, bool norm=true) const;
+ unsigned getNumContainedTypes() const;
+ const DIDerivedType& getMember(unsigned i) const;
+ bool isUnionOrStructTy(bool isStruct=true, bool isUnion=true) const;
+ bool hasInnerPointers() const;
+ DIArray getTypeArray() const;
+ const EDIType* getTopStructType(unsigned index) const;
+
+ unsigned getNumElements() const;
+ unsigned getNumDimensions() const;
+ void setCurrentDimension(unsigned dimension);
+ unsigned getCurrentDimension() const;
+ const DIType *getDIType() const;
+ StringRef getName() const;
+ std::vector<StringRef> getNames() const;
+ StringRef getNamesString() const;
+ std::vector<unsigned> getEnumValues() const;
+ unsigned getTag()const;
+ EDIType getTypeDerivedFrom() const;
+ bool isType() const;
+ bool isBasicType() const;
+ bool isDerivedType() const;
+ bool isCompositeType() const;
+ bool isPrimitiveType() const;
+ bool isAggregateType() const;
+ bool isVoidTy() const;
+ bool isComplexFloatingPointTy() const;
+ bool isFloatingPointTy() const;
+ bool isCharTy() const;
+ bool isIntTy() const;
+ bool isBoolTy() const;
+ bool isIntegerTy() const;
+ bool isFunctionTy() const;
+ bool isArrayTy() const;
+ bool isEnumTy() const;
+ bool isVectorTy() const;
+ bool isUnionTy() const;
+ bool isStructTy() const;
+ bool isPointerTy() const;
+ bool isOpaqueTy() const;
+
+ void print(raw_ostream &OS) const;
+ void printDescription(raw_ostream &OS, int skipUnions=0, int skipStructs=0, int allowMultiNames=0) const;
+ bool equals(const EDIType *other) const;
+
+ static std::string lookupTypedefName(std::string &name);
+ static std::string lookupUnionMemberName(TYPECONST Type* type);
+ static const EDIType* getStructEDITypeByName(std::string &name);
+ static void setModule(Module *M);
+ static void writeTypeSymbolic(raw_string_ostream &OS, TYPECONST Type *type, const Module *M);
+
+ private:
+ DIType aDIType;
+ unsigned currentDimension;
+ bool checkOpaqueTypes;
+ StringRef myName;
+ std::vector<StringRef> myNames;
+ static StringRef voidName;
+ static Module *module;
+ static DebugInfoFinder DIFinder;
+
+ void init(bool norm, bool checkOpaqueTypes);
+ void normalize();
+ void normalizeTypedef();
+};
+
+inline raw_ostream &operator<<(raw_ostream &OS, const EDIType &aEDIType) {
+ aEDIType.print(OS);
+ return OS;
+}
+
+inline unsigned EDIType::getNumElements() const {
+ if(!isArrayTy() && !isVectorTy()) {
+ return 1;
+ }
+ const DIArray aDIArray = getTypeArray();
+ const DIDescriptor aDIDescriptor = aDIArray.getElement(currentDimension);
+ assert(aDIDescriptor.getTag() == dwarf::DW_TAG_subrange_type);
+
+ return PassUtil::getDbgSubrangeNumElements((DISubrange)aDIDescriptor);
+}
+
+inline unsigned EDIType::getNumDimensions() const {
+ return isArrayTy() || isVectorTy() ? getTypeArray().getNumElements() : 1;
+}
+
+inline void EDIType::setCurrentDimension(unsigned dimension) {
+ assert(dimension < getNumDimensions());
+ this->currentDimension = dimension;
+}
+
+inline unsigned EDIType::getCurrentDimension() const {
+ return currentDimension;
+}
+
+inline const DIType *EDIType::getDIType() const {
+ return &aDIType;
+}
+
+inline StringRef EDIType::getName() const {
+ return myName;
+}
+
+inline std::vector<StringRef> EDIType::getNames() const {
+ return myNames;
+}
+
+inline StringRef EDIType::getNamesString() const {
+ std::string string;
+ raw_string_ostream ostream(string);
+ for(unsigned i=0;i<myNames.size();i++) {
+ if(i>0) ostream << "|";
+ ostream << myNames[i];
+ }
+ ostream.flush();
+ return string;
+}
+
+inline std::vector<unsigned> EDIType::getEnumValues() const {
+ assert(isEnumTy());
+ std::vector<unsigned> enumValues;
+ DIArray aDIArray = getTypeArray();
+ unsigned numValues = aDIArray.getNumElements();
+ for(unsigned i=0;i<numValues;i++) {
+ DIDescriptor aDIDescriptor = aDIArray.getElement(i);
+ assert(aDIDescriptor.getTag() == dwarf::DW_TAG_enumerator);
+ const unsigned value = (unsigned) ((DIEnumerator)aDIDescriptor).getEnumValue();
+ enumValues.push_back(value);
+ }
+ return enumValues;
+}
+
+inline unsigned EDIType::getTag()const {
+ return aDIType.getTag();
+}
+
+inline EDIType EDIType::getTypeDerivedFrom() const {
+ EDIType_assert(isDerivedType() || isCompositeType());
+ EDIType subType(PassUtil::getDITypeDerivedFrom((const DIDerivedType)aDIType));
+ return subType;
+}
+
+inline bool EDIType::isType() const {
+ return aDIType.isType() || isVoidTy();
+}
+
+inline bool EDIType::isBasicType() const {
+ return aDIType.isBasicType();
+}
+
+inline bool EDIType::isDerivedType() const {
+ return aDIType.isDerivedType() && !aDIType.isCompositeType();
+}
+
+inline bool EDIType::isCompositeType() const {
+ return aDIType.isCompositeType();
+}
+
+inline bool EDIType::isPrimitiveType() const {
+ return (isVoidTy() || isFloatingPointTy());
+}
+
+inline bool EDIType::isAggregateType() const {
+ return isUnionOrStructTy() || isArrayTy() || isVectorTy();
+}
+
+inline bool EDIType::isVoidTy() const {
+ return !aDIType.isValid(); //xxx we should keep track of this to spot all the i8* = void*
+}
+
+inline bool EDIType::isComplexFloatingPointTy() const {
+ if(!isBasicType()) return false;
+ return (((DIBasicType)aDIType).getEncoding() == dwarf::DW_ATE_complex_float);
+}
+
+inline bool EDIType::isFloatingPointTy() const {
+ if(!isBasicType()) return false;
+ return EDIType::isComplexFloatingPointTy() || (((DIBasicType)aDIType).getEncoding() == dwarf::DW_ATE_float);
+}
+
+inline bool EDIType::isCharTy() const {
+ if(!isBasicType()) return false;
+ return (((DIBasicType)aDIType).getEncoding() == dwarf::DW_ATE_signed_char ||
+ ((DIBasicType)aDIType).getEncoding() == dwarf::DW_ATE_unsigned_char);
+}
+
+inline bool EDIType::isIntTy() const {
+ if(!isBasicType()) return false;
+ return (((DIBasicType)aDIType).getEncoding() == dwarf::DW_ATE_signed ||
+ ((DIBasicType)aDIType).getEncoding() == dwarf::DW_ATE_unsigned);
+}
+
+inline bool EDIType::isBoolTy() const {
+ if(!isBasicType()) return false;
+ return (((DIBasicType)aDIType).getEncoding() == dwarf::DW_ATE_boolean);
+}
+
+inline bool EDIType::isIntegerTy() const {
+ return (isCharTy() || isIntTy() || isBoolTy());
+}
+
+inline bool EDIType::isFunctionTy() const {
+ return (getTag() == dwarf::DW_TAG_subroutine_type && !isOpaqueTy());
+}
+
+inline bool EDIType::isArrayTy() const {
+ return (getTag() == dwarf::DW_TAG_array_type && !isOpaqueTy());
+}
+
+inline bool EDIType::isEnumTy() const {
+ return (getTag() == dwarf::DW_TAG_enumeration_type && !isOpaqueTy());
+}
+
+inline bool EDIType::isVectorTy() const {
+ return (PassUtil::isDbgVectorTy(aDIType) && !isOpaqueTy());
+}
+
+inline bool EDIType::isUnionTy() const {
+ return isUnionOrStructTy(false, true);
+}
+
+inline bool EDIType::isStructTy() const {
+ return isUnionOrStructTy(true, false);
+}
+
+inline bool EDIType::isPointerTy() const {
+ return (getTag() == dwarf::DW_TAG_pointer_type);
+}
+
+inline bool EDIType::isOpaqueTy() const {
+ return (isCompositeType() && getTypeArray().getNumElements() == 0);
+}
+
+inline void EDIType::writeTypeSymbolic(raw_string_ostream &OS, TYPECONST Type *type, const Module *M) {
+ return PassUtil::writeTypeSymbolic(OS, type, M);
+}
+
+}
+
+#endif
--- /dev/null
+#ifndef MAGIC_DEBUG_FUNCTION_H_
+#define MAGIC_DEBUG_FUNCTION_H_
+
+#include <pass.h>
+
+#define NUM_DEBUG_ARGS 1
+
+using namespace llvm;
+
+namespace llvm {
+
+class MagicDebugFunction {
+public:
+ MagicDebugFunction(Function *function);
+
+ Function* getFunction() const;
+ void addHooks(std::pair<Function*, Function*> hooks, unsigned flags, std::vector<unsigned> argsMapping, std::vector<Value*> trailingArgs);
+ void fixCalls(Module &M, const std::string &baseDir="");
+
+ void print(raw_ostream &OS) const;
+ void printDescription(raw_ostream &OS) const;
+ const std::string getDescription() const;
+ static bool inlineHookCalls(Function* function, std::pair<Function*, Function*> hooks, unsigned flags, std::vector<unsigned> argsMapping,
+ std::vector<Value*> trailingArgs);
+ Function* getDebugFunction(Module &M);
+
+private:
+ Function *function;
+
+ std::pair<Function*, Function*> hooks;
+ unsigned flags;
+ std::vector<unsigned> argsMapping;
+ std::vector<Value*> trailingArgs;
+
+ Function* getDebugClone(Function* function, const Twine wrapperName, TYPECONST Type* debugArgType);
+};
+
+inline raw_ostream &operator<<(raw_ostream &OS, const MagicDebugFunction &aMagicDebugFunction) {
+ aMagicDebugFunction.print(OS);
+ return OS;
+}
+
+inline void MagicDebugFunction::print(raw_ostream &OS) const {
+ OS << getDescription();
+}
+
+inline void MagicDebugFunction::printDescription(raw_ostream &OS) const {
+ OS << "[ function = ";
+ OS << function->getName() << "(" << TypeUtil::getDescription(function->getFunctionType()) << ") ]";
+}
+
+inline const std::string MagicDebugFunction::getDescription() const {
+ std::string string;
+ raw_string_ostream ostream(string);
+ printDescription(ostream);
+ ostream.flush();
+ return string;
+}
+
+inline Function* MagicDebugFunction::getDebugClone(Function* function, const Twine wrapperName, TYPECONST Type* debugArgType) {
+ Function* wrapper;
+ std::vector<TYPECONST Type*> ArgTypes;
+ VALUE_TO_VALUE_MAP_TY VMap;
+
+ // Build arg types for wrapper
+ ArgTypes.push_back(debugArgType);
+ Function::const_arg_iterator E = function->arg_end();
+ for (Function::const_arg_iterator I = function->arg_begin(); I != E; ++I)
+ ArgTypes.push_back(I->getType());
+
+ // Create a new function type...
+ FunctionType *FTy = FunctionType::get(function->getFunctionType()->getReturnType(), ArgTypes, function->getFunctionType()->isVarArg());
+
+ // Create the wrapper
+ wrapper = Function::Create(FTy, function->getLinkage(), wrapperName, function->getParent());
+
+ // Loop over the arguments, copying the names of the mapped arguments over...
+ Function::arg_iterator DestI = wrapper->arg_begin();
+ Value *magicTypeValue = DestI;
+ magicTypeValue->setName("cs_info");
+ DestI++;
+ for (Function::const_arg_iterator I = function->arg_begin(), E = function->arg_end(); I != E; ++I) {
+ DestI->setName(I->getName());
+ VMap[I] = DestI++;
+ }
+
+ SmallVector<ReturnInst*, 8> Returns; // Ignore returns cloned...
+ CloneFunctionInto(wrapper, function, VMap, false, Returns, "", NULL);
+ return wrapper;
+}
+
+inline MagicDebugFunction::MagicDebugFunction(Function *function) {
+ this->function = function;
+}
+
+inline void MagicDebugFunction::addHooks(std::pair<Function*, Function*> aHooks, unsigned aFlags, std::vector<unsigned> aArgsMapping,
+ std::vector<Value*> aTrailingArgs) {
+ hooks = aHooks;
+ flags = aFlags;
+ trailingArgs = aTrailingArgs;
+ argsMapping = aArgsMapping;
+}
+
+inline Function* MagicDebugFunction::getFunction() const {
+ return function;
+}
+
+inline Function* MagicDebugFunction::getDebugFunction(Module &M) {
+ PointerType* PointerTy = PointerType::get(IntegerType::get((&M)->getContext(), 8), 0);
+ Function* debugFunction = MagicDebugFunction::getDebugClone(function, "debug_magic_" + function->getName(), PointerTy);
+ bool ret = MagicDebugFunction::inlineHookCalls(debugFunction, hooks, flags, argsMapping, trailingArgs);
+ if (ret) {
+ return debugFunction;
+ } else {
+ return NULL;
+ }
+}
+
+inline void MagicDebugFunction::fixCalls(Module &M, const std::string &baseDir) {
+ PointerType* PointerTy = PointerType::get(IntegerType::get((&M)->getContext(), 8), 0);
+ Function* debugFunction = MagicDebugFunction::getDebugClone(function, "debug_magic_" + function->getName(), PointerTy);
+ bool ret = MagicDebugFunction::inlineHookCalls(debugFunction, hooks, flags, argsMapping, trailingArgs);
+ assert(ret && "Unable to inline the calls to the hook functions.");
+
+ std::vector<User*> Users(function->use_begin(), function->use_end());
+ std::vector<Value*> EqPointers;
+ while (!Users.empty()) {
+ User *U = Users.back();
+ Users.pop_back();
+
+ if (Instruction * I = dyn_cast<Instruction>(U)) {
+ CallSite CS = MagicUtil::getCallSiteFromInstruction(I);
+ if (CS.getInstruction()
+ && (MagicUtil::getCalledFunctionFromCS(CS) == function
+ || std::find(EqPointers.begin(), EqPointers.end(), CS.getCalledValue()) != EqPointers.end())) {
+ Function *parentFunction = CS.getInstruction()->getParent()->getParent();
+ StringRef callParentName = MagicUtil::getFunctionSourceName(M, parentFunction, NULL, baseDir);
+ //extend function name with debug information
+ if (MDNode *N = I->getMetadata("dbg")) {
+ DILocation Loc(N);
+ std::string string;
+ raw_string_ostream ostream(string);
+ ostream << callParentName << MAGIC_ALLOC_NAME_SEP << Loc.getFilename() << MAGIC_ALLOC_NAME_SEP << Loc.getLineNumber();
+ ostream.flush();
+ callParentName = string;
+ }
+ Value* callParentNameValue = MagicUtil::getArrayPtr(M, MagicUtil::getStringRef(M, callParentName));
+ std::vector<Value*> debugArgs;
+ debugArgs.push_back(callParentNameValue);
+ debugArgs.insert(debugArgs.end(), CS.arg_begin(), CS.arg_end());
+ CallInst* newInst = MagicUtil::createCallInstruction(debugFunction, debugArgs, "", I);
+ newInst->takeName(I);
+ MagicUtil::replaceCallInst(I, newInst, 1);
+ }
+ } else if (GlobalValue * GV = dyn_cast<GlobalValue>(U)) {
+ Users.insert(Users.end(), GV->use_begin(), GV->use_end());
+ EqPointers.push_back(GV);
+ } else if (ConstantExpr * CE = dyn_cast<ConstantExpr>(U)) {
+ if (CE->isCast()) {
+ Users.insert(Users.end(), CE->use_begin(), CE->use_end());
+ EqPointers.push_back(CE);
+ }
+ }
+ }
+}
+
+}
+
+// inlines calls to the pre and post hooks and returns true if the inlining succeeded, false otherwise
+inline bool MagicDebugFunction::inlineHookCalls(Function* function, std::pair<Function*, Function*> hooks, unsigned flags,
+ std::vector<unsigned> argsMapping, std::vector<Value*> trailingArgs) {
+ std::vector<Value*> emptyArgs;
+ std::vector<unsigned> emptyMapping;
+ std::vector<unsigned> debugEmptyMapping;
+ std::vector<unsigned> debugArgsMapping;
+
+ // debug version of the function, argument mapping has to be adjusted
+ if (flags & MAGIC_HOOK_DEBUG_MASK) {
+ // re-adjusted the index of the arguments (do not re-adjust return value)
+ for (unsigned i = 0; i < argsMapping.size(); i++) {
+ if (argsMapping[i] > 0) {
+ argsMapping[i] += NUM_DEBUG_ARGS;
+ }
+ }
+ // first come the debug argument
+ for (unsigned i = 1; i <= NUM_DEBUG_ARGS; i++) {
+ debugEmptyMapping.push_back(i);
+ debugArgsMapping.push_back(i);
+ }
+ debugArgsMapping.insert(debugArgsMapping.end(), argsMapping.begin(), argsMapping.end());
+ }
+
+ if (hooks.first != NULL) {
+ // inline first hook call at the beginning of the function, according to the flag
+ switch (flags & MAGIC_PRE_HOOK_FLAGS_MASK) {
+ case MAGIC_PRE_HOOK_SIMPLE_CALL:
+ MagicUtil::inlinePreHookForwardingCall(function, hooks.first, (flags & MAGIC_PRE_HOOK_DEBUG) ? debugEmptyMapping : emptyMapping,
+ emptyArgs);
+ break;
+ case MAGIC_PRE_HOOK_FORWARDING_CALL:
+ MagicUtil::inlinePreHookForwardingCall(function, hooks.first, (flags & MAGIC_PRE_HOOK_DEBUG) ? debugArgsMapping : argsMapping,
+ trailingArgs);
+ break;
+ default:
+ // unknown flag
+ return false;
+ }
+ }
+
+ if (hooks.second != NULL) {
+ // inline the second wrapper call at the end of the function, according to the flag
+ switch (flags & MAGIC_POST_HOOK_FLAGS_MASK) {
+ case MAGIC_POST_HOOK_SIMPLE_CALL:
+ MagicUtil::inlinePostHookForwardingCall(function, hooks.second, (flags & MAGIC_POST_HOOK_DEBUG) ? debugEmptyMapping : emptyMapping,
+ emptyArgs);
+ break;
+ case MAGIC_POST_HOOK_FORWARDING_CALL:
+ MagicUtil::inlinePostHookForwardingCall(function, hooks.second, (flags & MAGIC_POST_HOOK_DEBUG) ? debugArgsMapping : argsMapping,
+ trailingArgs);
+ break;
+ default:
+ // unknown flag
+ return false;
+ }
+ }
+
+ return true;
+}
+
+#endif /* MAGIC_DEBUG_FUNCTION_H_ */
--- /dev/null
+#ifndef MAGIC_MEM_FUNCTION_H
+#define MAGIC_MEM_FUNCTION_H
+
+#include <pass.h>
+#include <magic/support/TypeInfo.h>
+
+#define NUM_MAGIC_ARGS 3
+
+using namespace llvm;
+
+namespace llvm {
+
+class MagicMemFunction {
+public:
+ MagicMemFunction(Module &M, Function *function, Function *wrapper, bool isDealloc, int allocFlags);
+
+ Function* getFunction() const;
+ Function* getWrapper() const;
+ bool isDeallocFunction() const;
+ int getAllocFlags() const;
+ Instruction* getInstruction() const;
+ Function* getInstructionParent() const;
+ TypeInfo* getInstructionTypeInfo() const;
+ Value* getInstructionTypeValue() const;
+ bool hasInstructionType() const;
+ std::vector<MagicMemFunction> getInstructionDeps() const;
+
+ void setInstruction(Instruction* I);
+ void setInstructionTypeInfo(TypeInfo* aTypeInfo, std::string &allocName, std::string &allocParentName);
+ void setInstructionTypeValue(Value* typeValue, Value* allocNameValue, Value* allocParentNameValue);
+ void addInstructionDep(MagicMemFunction &function);
+ void replaceInstruction(std::map<TypeInfo*, Constant*> &magicArrayTypePtrMap, TypeInfo *voidPtrTypeInfo);
+
+ void print(raw_ostream &OS) const;
+ void printDescription(raw_ostream &OS) const;
+ const std::string getDescription() const;
+
+ static int getMemFunctionPointerParam(Function* function, std::set<Function*> &brkFunctions, TypeInfo *voidPtrTypeInfo);
+ static Function* getCustomWrapper(Function* function, Function* stdFunction, Function* stdWrapper, std::vector<unsigned> argMapping,
+ bool isDealloc);
+ static bool isCustomWrapper(Function *function);
+
+private:
+ Module *module;
+ Function *function;
+ Function *wrapper;
+ bool isDealloc;
+ int allocFlags;
+ Instruction *instruction;
+ TypeInfo* aTypeInfo;
+ std::string allocName;
+ std::string allocParentName;
+ Value* typeValue;
+ Value* allocNameValue;
+ Value* allocParentNameValue;
+ std::vector<MagicMemFunction> instructionDeps;
+
+ void buildWrapper(std::map<TypeInfo*, Constant*> &magicArrayTypePtrMap, TypeInfo *voidPtrTypeInfo);
+
+ static Function *lastAllocWrapper;
+ static std::map<std::string, Function*> allocWrapperCache;
+ static std::set<Function*> customWrapperSet;
+};
+
+inline raw_ostream &operator<<(raw_ostream &OS, const MagicMemFunction &aMagicMemFunction) {
+ aMagicMemFunction.print(OS);
+ return OS;
+}
+
+inline void MagicMemFunction::print(raw_ostream &OS) const {
+ OS << getDescription();
+}
+
+inline void MagicMemFunction::printDescription(raw_ostream &OS) const {
+ OS << "[ function = ";
+ OS << function->getName() << "(" << TypeUtil::getDescription(function->getFunctionType()) << ")";
+ OS << ", wrapper = ";
+ if (wrapper) {
+ OS << wrapper->getName() << "(" << TypeUtil::getDescription(wrapper->getFunctionType()) << ")";
+ } else
+ OS << "NULL";
+ OS << ", isDeallocFunction = ";
+ OS << isDealloc;
+ OS << ", instruction = ";
+ if (instruction)
+ instruction->print(OS);
+ else
+ OS << "NULL";
+ OS << ", typeInfo = ";
+ if (aTypeInfo)
+ OS << aTypeInfo->getDescription();
+ else
+ OS << "NULL";
+ OS << ", allocName = ";
+ OS << allocName;
+ OS << ", allocParentName = ";
+ OS << allocParentName;
+ OS << ", typeValue = ";
+ if (typeValue)
+ typeValue->print(OS);
+ else
+ OS << "NULL";
+ OS << ", allocNameValue = ";
+ if (allocNameValue)
+ allocNameValue->print(OS);
+ else
+ OS << "NULL";
+ OS << ", allocParentNameValue = ";
+ if (allocParentNameValue)
+ allocParentNameValue->print(OS);
+ else
+ OS << "NULL";
+ OS << ", instructionDeps = {";
+ for (unsigned i = 0; i < instructionDeps.size(); i++) {
+ if (i > 0) {
+ OS << ", ";
+ }
+ instructionDeps[i].print(OS);
+ }
+ OS << "}]";
+}
+
+inline const std::string MagicMemFunction::getDescription() const {
+ std::string string;
+ raw_string_ostream ostream(string);
+ printDescription(ostream);
+ ostream.flush();
+ return string;
+}
+
+inline MagicMemFunction::MagicMemFunction(Module &M, Function *function, Function *wrapper, bool isDealloc, int allocFlags) {
+ this->module = &M;
+ this->function = function;
+ this->wrapper = wrapper;
+ this->isDealloc = isDealloc;
+ this->allocFlags = allocFlags;
+ this->instruction = NULL;
+ this->aTypeInfo = NULL;
+ this->allocName = "";
+ this->allocParentName = "";
+ this->typeValue = NULL;
+ this->allocNameValue = NULL;
+ this->allocParentNameValue = NULL;
+ assert(function);
+ if (wrapper && !isDealloc) {
+ lastAllocWrapper = wrapper;
+ }
+ if (isDealloc) {
+ assert(!allocFlags);
+ }
+}
+
+inline Function* MagicMemFunction::getFunction() const {
+ return function;
+}
+
+inline Function* MagicMemFunction::getWrapper() const {
+ return wrapper;
+}
+
+inline bool MagicMemFunction::isDeallocFunction() const {
+ return isDealloc;
+}
+
+inline int MagicMemFunction::getAllocFlags() const {
+ return allocFlags;
+}
+
+inline Instruction* MagicMemFunction::getInstruction() const {
+ return instruction;
+}
+
+inline Function* MagicMemFunction::getInstructionParent() const {
+ if (!instruction) {
+ return NULL;
+ }
+ return instruction->getParent()->getParent();
+}
+
+inline TypeInfo* MagicMemFunction::getInstructionTypeInfo() const {
+ return aTypeInfo;
+}
+
+inline Value* MagicMemFunction::getInstructionTypeValue() const {
+ return typeValue;
+}
+
+inline bool MagicMemFunction::hasInstructionType() const {
+ return aTypeInfo || typeValue;
+}
+
+inline std::vector<MagicMemFunction> MagicMemFunction::getInstructionDeps() const {
+ return instructionDeps;
+}
+
+inline void MagicMemFunction::setInstruction(Instruction* I) {
+ this->instruction = I;
+ assert(isa<CallInst>(instruction) || isa<InvokeInst>(instruction));
+}
+
+inline void MagicMemFunction::setInstructionTypeInfo(TypeInfo* aTypeInfo, std::string &allocName, std::string &allocParentName) {
+ this->aTypeInfo = aTypeInfo;
+ this->allocName = allocName;
+ this->allocParentName = allocParentName;
+}
+
+inline void MagicMemFunction::setInstructionTypeValue(Value* typeValue, Value* allocNameValue, Value* allocParentNameValue) {
+ this->typeValue = typeValue;
+ this->allocNameValue = allocNameValue;
+ this->allocParentNameValue = allocParentNameValue;
+}
+
+inline void MagicMemFunction::addInstructionDep(MagicMemFunction &function) {
+ assert(wrapper == NULL && "Dependencies are resolved at wrapper building time, so wrapper has to be NULL!");
+ instructionDeps.push_back(function);
+ allocFlags |= function.getAllocFlags();
+}
+
+inline void MagicMemFunction::replaceInstruction(std::map<TypeInfo*, Constant*> &magicArrayTypePtrMap, TypeInfo *voidPtrTypeInfo) {
+ Instruction *I = getInstruction();
+ assert(I);
+ CallSite CS = MagicUtil::getCallSiteFromInstruction(I);
+ std::vector<Value*> magicMemArgs;
+ unsigned numMagicArgs = 0;
+ //if we do not have a wrapper, build one
+ if (!wrapper) {
+ buildWrapper(magicArrayTypePtrMap, voidPtrTypeInfo);
+ }
+ //inject magic args
+ if (!isDeallocFunction()) {
+ std::map<TypeInfo*, Constant*>::iterator it;
+ if (!typeValue) {
+ assert(aTypeInfo);
+ if (aTypeInfo == voidPtrTypeInfo->getContainedType(0)) {
+ typeValue = ConstantPointerNull::get((TYPECONST PointerType*) (wrapper->arg_begin()->getType()));
+ } else {
+ it = magicArrayTypePtrMap.find(aTypeInfo);
+ assert(it != magicArrayTypePtrMap.end());
+ typeValue = it->second;
+ }
+ assert(allocName.compare(""));
+ assert(allocParentName.compare(""));
+ allocNameValue = MagicUtil::getArrayPtr(*module, MagicUtil::getStringRef(*module, allocName));
+ allocParentNameValue = MagicUtil::getArrayPtr(*module, MagicUtil::getStringRef(*module, allocParentName));
+ }
+ magicMemArgs.push_back(typeValue);
+ magicMemArgs.push_back(allocNameValue);
+ magicMemArgs.push_back(allocParentNameValue);
+ numMagicArgs = NUM_MAGIC_ARGS;
+ }
+ //push other args
+ unsigned arg_size = MagicUtil::getCalledFunctionFromCS(CS)->getFunctionType()->getNumContainedTypes() - 1;
+ for (unsigned i = 0; i < arg_size; i++) {
+ Value *arg = CS.getArgument(i);
+ TYPECONST Type* wArgType = wrapper->getFunctionType()->getContainedType(i + numMagicArgs + 1);
+ if (arg->getType() != wArgType) {
+ if (arg->getType()->isPointerTy()) {
+ assert(wArgType->isPointerTy());
+ arg = CastInst::CreatePointerCast(arg, wArgType, "WrapperCast", I);
+ }
+ else {
+ assert(arg->getType()->isIntegerTy());
+ assert(wArgType->isIntegerTy());
+ arg = CastInst::CreateIntegerCast(arg, wArgType, false, "WrapperCast", I);
+ }
+ }
+ magicMemArgs.push_back(arg);
+ }
+ //replace function with wrapper
+ CallInst* newInst = MagicUtil::createCallInstruction(wrapper, magicMemArgs, "", I);
+ newInst->takeName(I);
+ MagicUtil::replaceCallInst(I, newInst, NUM_MAGIC_ARGS);
+}
+
+inline int MagicMemFunction::getMemFunctionPointerParam(Function* function, std::set<Function*> &brkFunctions, TypeInfo *voidPtrTypeInfo) {
+ TYPECONST Type *type = function->getReturnType();
+ if (type == voidPtrTypeInfo->getType()) {
+ return 0;
+ } else if (brkFunctions.find(function) != brkFunctions.end()) {
+ return 1;
+ } else {
+ unsigned i;
+ for (i = 1; i < function->getFunctionType()->getNumContainedTypes(); i++) {
+ type = function->getFunctionType()->getContainedType(i);
+ if (type->isPointerTy() && type->getContainedType(0) == voidPtrTypeInfo->getType()) {
+ return i;
+ }
+ }
+ }
+
+ return -1;
+}
+
+inline void MagicMemFunction::buildWrapper(std::map<TypeInfo*, Constant*> &magicArrayTypePtrMap, TypeInfo *voidPtrTypeInfo) {
+ assert(!isDeallocFunction());
+ assert(lastAllocWrapper);
+ std::vector<TYPECONST Type*> ArgTypes;
+ VALUE_TO_VALUE_MAP_TY VMap;
+
+ std::map<std::string, Function*>::iterator allocWrapperCacheIt;
+
+ // See if the wrapper is in cache, otherwise create a new wrapper using function cloning
+ allocWrapperCacheIt = allocWrapperCache.find(function->getName());
+ if (allocWrapperCacheIt != allocWrapperCache.end()) {
+ wrapper = allocWrapperCacheIt->second;
+ return;
+ }
+
+ // Build arg types for wrapper
+ Function::const_arg_iterator E = lastAllocWrapper->arg_begin();
+ for (unsigned i = 0; i < NUM_MAGIC_ARGS; i++)
+ E++;
+ for (Function::const_arg_iterator I = lastAllocWrapper->arg_begin(); I != E; ++I)
+ ArgTypes.push_back(I->getType());
+ E = function->arg_end();
+ for (Function::const_arg_iterator I = function->arg_begin(); I != E; ++I)
+ ArgTypes.push_back(I->getType());
+
+ // Create a new function type...
+ FunctionType *FTy = FunctionType::get(function->getFunctionType()->getReturnType(), ArgTypes, function->getFunctionType()->isVarArg());
+
+ // Create the wrapper
+ wrapper = Function::Create(FTy, function->getLinkage(), "magic_" + function->getName(), function->getParent());
+
+ // Loop over the arguments, copying the names of the mapped arguments over...
+ Function::arg_iterator DestI = wrapper->arg_begin();
+ Value *magicTypeValue = DestI;
+ magicTypeValue->setName("magic_type");
+ DestI++;
+ Value *magicNameValue = DestI;
+ magicNameValue->setName("magic_name");
+ DestI++;
+ Value *magicParentNameValue = DestI;
+ magicParentNameValue->setName("magic_parent_name");
+ DestI++;
+ for (Function::const_arg_iterator I = function->arg_begin(), E = function->arg_end(); I != E; ++I) {
+ DestI->setName(I->getName());
+ VMap[I] = DestI++;
+ }
+
+ SmallVector<ReturnInst*, 8> Returns; // Ignore returns cloned...
+ CloneFunctionInto(wrapper, function, VMap, false, Returns, "", NULL);
+
+ allocWrapperCache.insert(std::pair<std::string, Function*>(function->getName(), wrapper));
+
+ // Create a mapping between the function instruction pointers and the wrapper instruction pointers
+ std::vector<Instruction *> wrapperInstructionDeps;
+ for (unsigned i = 0; i < instructionDeps.size(); i++) {
+ Instruction *instruction = instructionDeps[i].getInstruction();
+ Instruction *wrapperInstruction = NULL;
+ unsigned instructionOffset = 0;
+ for (inst_iterator I = inst_begin(function), E = inst_end(function); I != E; ++I, instructionOffset++) {
+ if (instruction == &(*I)) {
+ break;
+ }
+ }
+ assert(instructionOffset > 0);
+ for (inst_iterator I = inst_begin(wrapper), E = inst_end(wrapper); I != E; ++I, instructionOffset--) {
+ if (instructionOffset == 0) {
+ wrapperInstruction = &(*I);
+ break;
+ }
+ }
+ assert(wrapperInstruction);
+ wrapperInstructionDeps.push_back(wrapperInstruction);
+ }
+
+ // Forward magic type argument to any dependent instruction and replace it
+ for (unsigned i = 0; i < wrapperInstructionDeps.size(); i++) {
+ instructionDeps[i].setInstruction(wrapperInstructionDeps[i]);
+ instructionDeps[i].setInstructionTypeValue(magicTypeValue, magicNameValue, magicParentNameValue);
+ instructionDeps[i].replaceInstruction(magicArrayTypePtrMap, voidPtrTypeInfo);
+ }
+}
+
+inline Function* MagicMemFunction::getCustomWrapper(Function* function, Function* stdFunction, Function* stdWrapper, std::vector<unsigned> argMapping,
+ bool isDealloc) {
+ Function* wrapper;
+ std::vector<TYPECONST Type*> ArgTypes;
+ VALUE_TO_VALUE_MAP_TY VMap;
+
+ // Build arg types for wrapper
+ // add magic arguments
+ if (!isDealloc) {
+ Function::const_arg_iterator E = stdWrapper->arg_begin();
+ for (unsigned i = 0; i < NUM_MAGIC_ARGS; i++)
+ E++;
+ for (Function::const_arg_iterator I = stdWrapper->arg_begin(); I != E; ++I) {
+ ArgTypes.push_back(I->getType());
+ }
+ }
+ // add original function arguments
+ for (Function::const_arg_iterator I = function->arg_begin(), E = function->arg_end(); I != E; ++I) {
+ ArgTypes.push_back(I->getType());
+ }
+
+ // Create a new function type...
+ FunctionType *FTy = FunctionType::get(stdWrapper->getFunctionType()->getReturnType(), ArgTypes, function->getFunctionType()->isVarArg());
+
+ // Create the wrapper
+ wrapper = Function::Create(FTy, function->getLinkage(), "magic_" + function->getName(), function->getParent());
+
+ // Loop over the arguments, copying the names of the mapped arguments over...
+ Function::arg_iterator DestI = wrapper->arg_begin();
+ std::vector<Value*> wrapperArgs;
+ if (!isDealloc) {
+ std::string magicArgs[] = { "magic_type", "magic_name", "magic_parent_name" };
+ for (unsigned i = 0; i < NUM_MAGIC_ARGS; i++) {
+ DestI->setName(magicArgs[i]);
+ wrapperArgs.push_back(DestI);
+ DestI++;
+ }
+ }
+ for (Function::const_arg_iterator I = function->arg_begin(), E = function->arg_end(); I != E; ++I) {
+ DestI->setName(I->getName());
+ wrapperArgs.push_back(DestI);
+ DestI++;
+ }
+
+ // map the arguments of the standard wrapper to the arguments of the new custom wrapper
+ if ((!isDealloc) || argMapping.size()) {
+ Function::const_arg_iterator W = stdWrapper->arg_begin();
+ if (!isDealloc) {
+ // magic arguments are in the same position
+ for (unsigned i = 0; i < NUM_MAGIC_ARGS; i++) {
+ VMap[W] = wrapperArgs[i];
+ W++;
+ }
+ }
+ // map the selected arguments of the custom wrapper using the mapping provided as input
+ unsigned argOffset = isDealloc ? 0 : NUM_MAGIC_ARGS;
+ for (unsigned i = 0; i < argMapping.size(); i++) {
+ VMap[W] = wrapperArgs[argOffset + argMapping[i] - 1];
+ W++;
+ }
+ }
+
+ SmallVector<ReturnInst*, 8> Returns; // Ignore returns cloned...
+ CloneFunctionInto(wrapper, stdWrapper, VMap, false, Returns, "", NULL);
+
+ // check whether some of the arguments of the custom wrapper need to be casted
+ // in order to match the basic wrapper implementation
+ Instruction *FirstInst = MagicUtil::getFirstNonAllocaInst(wrapper);
+ Function::const_arg_iterator W = stdWrapper->arg_begin();
+ unsigned argOffset = 0;
+ if (!isDealloc) {
+ argOffset = NUM_MAGIC_ARGS;
+ // skip the magic arguments, they are always the same
+ for (unsigned i = 0; i < NUM_MAGIC_ARGS; i++) {
+ W++;
+ }
+ }
+ for (unsigned i = 0; i < argMapping.size(); i++) {
+ TYPECONST Type* StdParamType = W->getType();
+ Value* ParamValue = wrapperArgs[argOffset + argMapping[i] - 1];
+ TYPECONST Type* ParamType = ParamValue->getType();
+ if (!MagicUtil::isCompatibleType(ParamType, StdParamType)) {
+ assert(CastInst::isCastable(ParamType, StdParamType) && "The type of the parameter of the custom wrapper "
+ "cannot be casted to the type of the basic wrapper to which it is corresponding.");
+ Instruction::CastOps CastOpCode = CastInst::getCastOpcode(ParamValue, false, StdParamType, false);
+ Instruction *ParamCastInst = CastInst::Create(CastOpCode, ParamValue, StdParamType, "", FirstInst);
+
+ for (Value::use_iterator it = ParamValue->use_begin(); it != ParamValue->use_end(); it++) {
+ if (Constant * C = dyn_cast<Constant>(*it)) {
+ if (!isa<GlobalValue>(C)) {
+ C->replaceUsesOfWith(ParamValue, ParamCastInst);
+ continue;
+ }
+ }
+ Instruction *I = dyn_cast<Instruction>(*it);
+ if (I && (I != ParamCastInst)) {
+ // replace all uses, except for the calls to the wrapped function
+ CallInst *CI = dyn_cast<CallInst>(I);
+ if (CI && (CI->getCalledFunction() == function)) {
+ continue;
+ }
+ I->replaceUsesOfWith(ParamValue, ParamCastInst);
+ }
+ }
+ }
+ W++;
+ }
+
+ // replace the call(s) to the standard function with calls to our function
+ for (Function::iterator BI = wrapper->getBasicBlockList().begin(), BE = wrapper->getBasicBlockList().end(); BI != BE; ++BI) {
+ unsigned pos = 0;
+ unsigned bbSize = BI->getInstList().size();
+ while (pos < bbSize) {
+ BasicBlock::iterator it = BI->getInstList().begin();
+ for (unsigned i = 0; i < pos; i++) {
+ it++;
+ }
+ Instruction *inst = &(*it);
+ // find the calls to the standard function
+ CallInst *callInst = dyn_cast<CallInst>(inst);
+ if (callInst && callInst->getCalledFunction() && (callInst->getCalledFunction()->getFunctionType() == stdFunction->getFunctionType())
+ && (!callInst->getCalledFunction()->getName().compare(stdFunction->getName()))) {
+ CallSite CS = MagicUtil::getCallSiteFromInstruction(callInst);
+ unsigned numStdParams = stdFunction->getFunctionType()->getNumParams();
+ unsigned numParams = function->getFunctionType()->getNumParams();
+ // construct the parameter array
+ std::vector<Value*> callArgs(numParams, NULL);
+ // first add the arguments that are common to the custom and standard function
+ // add casts where necessary
+ for (unsigned i = 0; i < numStdParams; i++) {
+ Value *argValue = CS.getArgument(i);
+ TYPECONST Type* paramType = function->getFunctionType()->getParamType(i);
+ TYPECONST Type* argType = argValue->getType();
+ if (paramType != argType) {
+ assert(CastInst::isCastable(argType, paramType) && "The value of the argument cannot be "
+ "casted to the parameter type required by the function to be called.");
+ Instruction::CastOps opcode = CastInst::getCastOpcode(argValue, false, paramType, false);
+ argValue = CastInst::Create(opcode, argValue, paramType, "", callInst);
+ }
+ callArgs[argMapping[i] - 1] = argValue;
+ }
+ // the other arguments are just forwarded from the wrapper's argument list
+ // skip the magic arguments of the wrapper from the beginning of the argument list
+ unsigned argOffset = isDealloc ? 0 : NUM_MAGIC_ARGS;
+ for (unsigned i = argOffset; i < wrapper->getFunctionType()->getNumParams(); i++) {
+ if (callArgs[i - argOffset] == NULL) {
+ Value* arg = wrapperArgs[i];
+ callArgs[i - argOffset] = arg;
+ }
+ }
+
+ CallInst* newCallInst = MagicUtil::createCallInstruction(function, callArgs, "", callInst);
+ newCallInst->takeName(callInst);
+ MagicUtil::replaceCallInst(callInst, newCallInst, argOffset);
+ }
+ pos++;
+ }
+ }
+
+ customWrapperSet.insert(wrapper);
+ return wrapper;
+}
+
+inline bool MagicMemFunction::isCustomWrapper(Function *function)
+{
+ return customWrapperSet.find(function) != customWrapperSet.end();
+}
+
+}
+
+#endif
+
--- /dev/null
+#ifndef MAGIC_MMAP_CTL_FUNCTION_H
+#define MAGIC_MMAP_CTL_FUNCTION_H
+
+#include <pass.h>
+#include <magic/support/TypeInfo.h>
+
+using namespace llvm;
+
+namespace llvm {
+
+class MagicMmapCtlFunction {
+ public:
+ MagicMmapCtlFunction(Function *function, PointerType *voidPointerType, std::string &ptrArgName, std::string &lenArgName);
+
+ Function* getFunction() const;
+ void fixCalls(Module &M, Function *magicGetPageSizeFunc) const;
+
+ void print(raw_ostream &OS) const;
+ void printDescription(raw_ostream &OS) const;
+ const std::string getDescription() const;
+
+ private:
+ Function *function;
+ int ptrArg;
+ int lenArg;
+};
+
+inline raw_ostream &operator<<(raw_ostream &OS, const MagicMmapCtlFunction &aMagicMmapCtlFunction) {
+ aMagicMmapCtlFunction.print(OS);
+ return OS;
+}
+
+inline void MagicMmapCtlFunction::print(raw_ostream &OS) const {
+ OS << getDescription();
+}
+
+inline void MagicMmapCtlFunction::printDescription(raw_ostream &OS) const {
+ OS << "[ function = "; OS << function->getName() << "(" << TypeUtil::getDescription(function->getFunctionType()) << ")"
+ << ", ptr arg = "; OS << ptrArg
+ << ", len arg = "; OS << lenArg
+ << "]";
+}
+
+inline const std::string MagicMmapCtlFunction::getDescription() const {
+ std::string string;
+ raw_string_ostream ostream(string);
+ printDescription(ostream);
+ ostream.flush();
+ return string;
+}
+
+inline MagicMmapCtlFunction::MagicMmapCtlFunction(Function *function, PointerType *voidPointerType, std::string &ptrArgName, std::string &lenArgName) {
+ this->function = function;
+ this->ptrArg = -1;
+ this->lenArg = -1;
+ bool lookupPtrArg = ptrArgName.compare("");
+ bool lookupLenArg = lenArgName.compare("");
+ assert((lookupPtrArg || lookupLenArg) && "No valid argument name specified!");
+ unsigned i=0;
+ for (Function::arg_iterator it = function->arg_begin(), E = function->arg_end();
+ it != E; ++it) {
+ std::string argName = it->getName();
+ if(lookupPtrArg && !argName.compare(ptrArgName)) {
+ this->ptrArg = i;
+ }
+ else if(lookupLenArg && !argName.compare(lenArgName)) {
+ this->lenArg = i;
+ }
+ i++;
+ }
+ if(this->ptrArg >= 0) {
+ assert(function->getFunctionType()->getContainedType(this->ptrArg+1) == voidPointerType && "Invalid ptr argument specified!");
+ }
+ else {
+ assert(!lookupPtrArg && "Invalid ptr argument name specified!");
+ }
+ if(this->lenArg >= 0) {
+ assert(isa<IntegerType>(function->getFunctionType()->getContainedType(this->lenArg+1)) && "Invalid len argument specified!");
+ }
+ else {
+ assert(!lookupLenArg && "Invalid len argument name specified!");
+ }
+}
+
+inline Function* MagicMmapCtlFunction::getFunction() const {
+ return function;
+}
+
+/* This assumes in-band metadata of 1 page before every mmapped region. */
+inline void MagicMmapCtlFunction::fixCalls(Module &M, Function *magicGetPageSizeFunc) const {
+ std::vector<User*> Users(function->use_begin(), function->use_end());
+ while (!Users.empty()) {
+ User *U = Users.back();
+ Users.pop_back();
+
+ if (Instruction *I = dyn_cast<Instruction>(U)) {
+ Function *parent = I->getParent()->getParent();
+ if(parent->getName().startswith("magic") || parent->getName().startswith("_magic")) {
+ continue;
+ }
+ CallSite CS = MagicUtil::getCallSiteFromInstruction(I);
+
+ std::vector<Value*> args;
+ CallInst* magicGetPageSizeCall = MagicUtil::createCallInstruction(magicGetPageSizeFunc, args, "", I);
+ magicGetPageSizeCall->setCallingConv(CallingConv::C);
+ magicGetPageSizeCall->setTailCall(false);
+ TYPECONST IntegerType *type = dyn_cast<IntegerType>(magicGetPageSizeCall->getType());
+ assert(type);
+
+ if(this->ptrArg >= 0) {
+ Value *ptrValue = CS.getArgument(this->ptrArg);
+ BinaryOperator* negativePageSize = BinaryOperator::Create(Instruction::Sub, ConstantInt::get(M.getContext(), APInt(type->getBitWidth(), 0)), magicGetPageSizeCall, "", I);
+ GetElementPtrInst* ptrValueWithOffset = GetElementPtrInst::Create(ptrValue, negativePageSize, "", I);
+
+ CS.setArgument(this->ptrArg, ptrValueWithOffset);
+ }
+ if(this->lenArg >= 0) {
+ Value *lenValue = CS.getArgument(this->lenArg);
+ BinaryOperator* lenValuePlusPageSize = BinaryOperator::Create(Instruction::Add, lenValue, magicGetPageSizeCall, "", I);
+
+ CS.setArgument(this->lenArg, lenValuePlusPageSize);
+ }
+ }
+ }
+}
+
+}
+
+#endif
+
--- /dev/null
+#ifndef MAGIC_UTIL_H
+#define MAGIC_UTIL_H
+
+#include <magic/magic.h>
+#include <magic/support/SmartType.h>
+#include <cxxabi.h>
+
+using namespace llvm;
+
+namespace llvm {
+
+#define magicUtilLog(M) DEBUG(dbgs() << "MagicUtil: " << M << "\n")
+
+class MagicUtil {
+ public:
+ static StringRef getGVSourceName(Module &M, GlobalVariable *GV, DIGlobalVariable **DIGVP=NULL, const std::string &baseDir="");
+ static StringRef getLVSourceName(Module &M, AllocaInst *V, DIVariable **DIVP=NULL);
+ static StringRef getFunctionSourceName(Module &M, Function *F, DISubprogram **DISP=NULL, const std::string &baseDir="");
+ static void putStringRefCache(Module &M, const std::string &str, GlobalVariable *GV);
+ static Constant* getGetElementPtrConstant(Constant *constant, std::vector<Value*> &indexes);
+ static GetElementPtrInst* createGetElementPtrInstruction(Value *ptr, std::vector<Value*> &indexes, const Twine &NameStr="", Instruction *InsertBefore=0);
+ static GetElementPtrInst* createGetElementPtrInstruction(Value *ptr, std::vector<Value*> &indexes, const Twine &NameStr="", BasicBlock *InsertAtEnd=0);
+ static CallInst* createCallInstruction(Value *F, std::vector<Value*> &args, const Twine &NameStr="", Instruction *InsertBefore=0);
+ static CallInst* createCallInstruction(Value *F, std::vector<Value*> &args, const Twine &NameStr="", BasicBlock *InsertAtEnd=0);
+ static Function* getIntrinsicFunction(Module &M, Intrinsic::ID id, TYPECONST Type** types=NULL, unsigned size=0);
+ static GlobalVariable *getStringRef(Module &M, const std::string &str);
+ static GlobalVariable *getIntArrayRef(Module &M, unsigned arrSize, std::vector<int> *arr, bool isConstant=true);
+ static GlobalVariable *getStringArrayRef(Module &M, unsigned arrSize, std::vector<std::string> *arr, bool isConstant=true);
+ static GlobalVariable *getGenericArrayRef(Module &M, std::vector<Constant*> &arrayElems, bool isConstant=true);
+ static GlobalVariable *getMagicTypePtrArrayRef(Module &M, Instruction *InsertBefore, std::vector<Value*> &globalTypeIndexes, GlobalVariable *magicTypeArray);
+ static GlobalVariable* getExportedIntGlobalVar(Module &M, std::string name, int value, bool isConstant=true);
+ static GlobalVariable* getShadowRef(Module &M, GlobalVariable *GV);
+ static Value* getMagicStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* array, Value* arrayIndex, const std::string &structFieldName, std::string *structFieldNames);
+ static Value* getMagicSStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* magicArray, Value* magicArrayIndex, const std::string &structFieldName);
+ static Value* getMagicTStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* magicTypeArray, Value* magicTypeArrayIndex, const std::string &structFieldName);
+ static Value* getMagicFStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* magicFunctionArray, Value* magicFunctionArrayIndex, const std::string &structFieldName);
+ static Value* getMagicRStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* magicVar, const std::string &structFieldName);
+ static Value* getMagicDStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* magicDsindexArray, Value* magicDsindexArrayIndex, const std::string &structFieldName);
+ static Constant* getArrayPtr(Module &M, GlobalVariable* array);
+ static void insertMemcpyInst(Module &M, Instruction *InsertBefore, Value *Dst, Value *Src, Value *Len, unsigned Align);
+ static void insertCopyInst(Module &M, Instruction *InsertBefore, GlobalVariable *GV, GlobalVariable *SGV, int GVSize, bool forceMemcpy);
+ static Function* getCalledFunctionFromCS(const CallSite &CS);
+ static void replaceCallInst(Instruction *originalInst, CallInst *newInst, int argOffset=0, bool removeUnusedFunction=true);
+ static std::vector<Function*> getGlobalVariablesShadowFunctions(Module &M, std::vector<GlobalVariable*> globalVariables, std::vector<GlobalVariable*> shadowGlobalVariables, std::vector<int> globalVariableSizes, GlobalVariable* magicArray, int magicArraySize, bool forceShadow, bool setDirtyFlag);
+ static Function* getGlobalVariableShadowFunction(Module &M, GlobalVariable* GV, GlobalVariable* SGV, int GVSize, GlobalVariable* magicArray, int magicArrayIndex, bool forceShadow, bool setDirtyFlag);
+ static void insertGlobalVariableCleanDirtyFlag(Module &M, GlobalVariable* GV, GlobalVariable* magicArray, int magicArrayIndex, Instruction *InsertBefore);
+ static void insertShadowTag(Module &M, GlobalVariable *GV, Instruction *InsertBefore);
+ static bool isShadowTag(Instruction *inst);
+ static GlobalVariable* getGlobalVariableFromShadowTag(Instruction *inst, std::vector<Instruction*> &instructionsToRemove);
+ static void cleanupShadowTag(Module &M, std::vector<Instruction*> &instructionsToRemove);
+ static bool hasAddressTaken(const GlobalValue *GV, bool includeMembers=true);
+ static bool lookupValueSet(const GlobalVariable *GV, std::vector<int> &valueSet);
+ static Value* getStringOwner(GlobalVariable *GV);
+ static Instruction* getFirstNonAllocaInst(Function* F, bool skipAllocaPoint=true);
+ static void setGlobalVariableSection(GlobalVariable *GV, const std::string §ion);
+ static bool getCallAnnotation(Module &M, const CallSite &CS, int *annotation);
+ static bool getVarAnnotation(Module &M, const GlobalVariable *GV, int *annotation);
+ static CallSite getCallSiteFromInstruction(Instruction *I);
+ static AllocaInst* getAllocaInstFromArgument(Argument *argument);
+ static Function* getMangledFunction(Module &M, StringRef functionName);
+ static Function* getFunction(Module &M, StringRef functionName);
+ static bool isCompatibleType(const Type* type1, const Type* type2);
+ static void inlinePreHookForwardingCall(Function* function, Function* preHookFunction, std::vector<unsigned> argsMapping, std::vector<Value*> trailingArgs);
+ static void inlinePostHookForwardingCall(Function* function, Function* postHookFunction, std::vector<unsigned> mapping, std::vector<Value*> trailingArgs);
+ static int getPointerIndirectionLevel(const Type* type);
+ static Value* getFunctionParam(Function* function, unsigned index);
+ static bool isLocalConstant(Module &M, GlobalVariable *GV);
+};
+
+}
+
+#endif
--- /dev/null
+#ifndef SMART_TYPE_H
+#define SMART_TYPE_H
+
+#include <pass.h>
+#include <magic/support/Backports.h>
+#include <magic/support/EDIType.h>
+#include <magic/support/TypeUtil.h>
+#include <magic/support/BitFieldAggregation.h>
+
+using namespace llvm;
+
+namespace llvm {
+
+#define SmartTypeLog(M) DEBUG(dbgs() << "SmartType: " << M << "\n")
+#define SmartTypeErr(M) errs() << "SmartType: " << M << "\n"
+
+#if HAVE_EXCEPTIONS
+#define THROW(E) throw E
+#define TRY(B) try{ B }
+#define CATCH(E, B) catch(E){ B }
+#else
+#define THROW(E) assert(0 && "throw: Exceptions disabled")
+#define TRY(B) assert(0 && "try: Exceptions disabled");
+#define CATCH(E, B) assert(0 && "catch: Exceptions disabled");
+#endif
+
+#define SmartType_assert(X) do { \
+ if(!(X)) { \
+ if(useExceptions) { \
+ THROW(std::exception()); \
+ } \
+ errs() << "Assertion failed, dumping object...\n"; \
+ errs() << "Name is: " << this->aEDIType.getName() << "\n"; \
+ errs() << *this; \
+ } \
+ assert(X); \
+ } while(0)
+
+class SmartType {
+ public:
+ SmartType(const SmartType& et);
+ SmartType(TYPECONST Type *type, const DIType *aDIType, bool useExceptions=false, bool forceRawTypeRepresentation=false);
+ SmartType(TYPECONST Type *type, const EDIType *aEDIType, bool useExceptions=false, bool forceRawTypeRepresentation=false);
+ ~SmartType();
+
+ SmartType& operator=(const SmartType& et);
+ void cloneFrom(const SmartType& et);
+
+ const std::string getDescription() const;
+ const SmartType* getContainedType(unsigned i) const;
+ unsigned getNumContainedTypes() const;
+ const DIDerivedType& getMember(unsigned i) const;
+ unsigned getUnionMemberIdx() const;
+ const SmartType* getTopStructType(unsigned index) const;
+
+ TYPECONST Type *getType() const;
+ const EDIType *getEDIType() const;
+ bool isTypeConsistent() const;
+ bool hasInnerPointers() const;
+ bool isVoidTy() const;
+ bool isPrimitiveTy() const;
+ bool isAggregateType() const;
+ bool isFunctionTy() const;
+ bool isStructTy() const;
+ bool isArrayTy() const;
+ bool isPointerTy() const;
+ bool isOpaqueTy() const;
+ bool isPaddedTy() const;
+ unsigned getNumElements() const;
+ bool isUseExceptions() const;
+
+ void verify() const;
+ bool verifyTy() const;
+ void print(raw_ostream &OS) const;
+ bool equals(const SmartType* other, bool isDebug=false) const;
+ bool hasRawTypeRepresentation() const;
+
+ static const SmartType* getSmartTypeFromGV(Module &M, GlobalVariable *GV, DIGlobalVariable *DIG = NULL);
+ static const SmartType* getSmartTypeFromLV(Module &M, AllocaInst *AI, DIVariable *DIV = NULL);
+ static const SmartType* getSmartTypeFromFunction(Module &M, Function *F, DISubprogram *DIS = NULL);
+ static const SmartType* getStructSmartTypeByName(Module &M, GlobalVariable* GV, std::string &name, bool isUnion=false);
+ static std::vector<const SmartType*>* getTopStructSmartTypes(Module &M, GlobalVariable* GV);
+ static bool isTypeConsistent(TYPECONST Type *type, const EDIType *aEDIType, bool useBfas=true, int *weakConsistencyLevel=NULL);
+
+ private:
+ TYPECONST Type *type;
+ EDIType aEDIType;
+ bool hasExplicitContainedEDITypes;
+ bool isInconsistent;
+ std::vector<EDIType*> explicitContainedEDITypes;
+ std::vector<BitFieldAggregation> bfas;
+ bool useExceptions;
+ bool rawTypeRepresentation;
+ unsigned unionMemberIdx;
+ static std::vector<TYPECONST Type*> equalsNestedTypes;
+ static bool forceRawUnions;
+ static bool forceRawBitfields;
+
+ void init(TYPECONST Type *type, const EDIType *aEDIType, bool useExceptions, bool forceRawTypeRepresentation);
+ void normalize();
+ void flattenFunctionTy();
+ int flattenFunctionArgs(TYPECONST Type *type, const EDIType *aEDIType, unsigned nextContainedType);
+ bool isTy(bool isTyType, bool isTyEDIType, const char* source) const;
+
+ static unsigned getBFAFreeIdx(unsigned i, const std::vector<BitFieldAggregation> &inputBfas);
+ static bool isRawTypeConsistent(TYPECONST Type *type, const EDIType *aEDIType);
+ static bool isTypeConsistent2(TYPECONST Type *type, const EDIType *aEDIType);
+ static bool isTypeConsistent2(std::vector<TYPECONST Type*> &nestedTypes, std::vector<const EDIType*> &nestedEDITypes, const SmartType *aSmartType);
+};
+
+inline raw_ostream &operator<<(raw_ostream &OS, const SmartType &aSmartType) {
+ aSmartType.print(OS);
+ return OS;
+}
+
+inline TYPECONST Type *SmartType::getType() const {
+ return type;
+}
+
+inline const EDIType *SmartType::getEDIType() const {
+ return &aEDIType;
+}
+
+inline bool SmartType::isTypeConsistent() const {
+ if(isInconsistent) {
+ return false;
+ }
+ if(isFunctionTy() || hasRawTypeRepresentation()) {
+ return true;
+ }
+ return isTypeConsistent(type, &aEDIType);
+}
+
+inline bool SmartType::hasInnerPointers() const {
+ return aEDIType.hasInnerPointers();
+}
+
+inline bool SmartType::isVoidTy() const {
+ return isTy(type->isVoidTy(), aEDIType.isVoidTy(), "isVoidTy");
+}
+
+inline bool SmartType::isPrimitiveTy() const {
+ if(aEDIType.isComplexFloatingPointTy()) {
+ assert(type->isStructTy());
+ return true;
+ }
+ return isTy(type->isPrimitiveType(), aEDIType.isPrimitiveType(), "isPrimitiveTy");
+}
+
+inline bool SmartType::isAggregateType() const {
+ return isTy(type->isAggregateType(), aEDIType.isAggregateType(), "isAggregateType");
+}
+
+inline bool SmartType::isFunctionTy() const {
+ if(isOpaqueTy()) {
+ return false;
+ }
+ return isTy(type->isFunctionTy(), aEDIType.isFunctionTy(), "isFunctionTy");
+}
+
+inline bool SmartType::isStructTy() const {
+ if(aEDIType.isComplexFloatingPointTy()) {
+ assert(type->isStructTy());
+ return false;
+ }
+ if(aEDIType.isArrayTy() && TypeUtil::isArrayAsStructTy(type)) {
+ return false;
+ }
+ if(isOpaqueTy()) {
+ return false;
+ }
+ return isTy(type->isStructTy(), aEDIType.isUnionOrStructTy(), "isStructTy");
+}
+
+inline bool SmartType::isArrayTy() const {
+ if(aEDIType.isArrayTy() && TypeUtil::isArrayAsStructTy(type)) {
+ return true;
+ }
+ if (hasRawTypeRepresentation()) { // only possible for structs and bitfields
+ return false;
+ }
+ return isTy(type->isArrayTy(), aEDIType.isArrayTy(), "isArrayTy");
+}
+
+inline bool SmartType::isPointerTy() const {
+ return isTy(type->isPointerTy(), aEDIType.isPointerTy(), "isPointerTy");
+}
+
+inline bool SmartType::isOpaqueTy() const {
+ return TypeUtil::isOpaqueTy(type) || aEDIType.isOpaqueTy();
+}
+
+inline bool SmartType::isPaddedTy() const {
+ if(!isAggregateType() || hasRawTypeRepresentation()) {
+ return false;
+ }
+ return TypeUtil::isPaddedType(type);
+}
+
+inline unsigned SmartType::getNumElements() const {
+ if(!isArrayTy()) {
+ return 0;
+ }
+ unsigned EDINumElements = aEDIType.getNumElements();
+ unsigned numElements;
+ if(type->isArrayTy()) {
+ numElements = ((ArrayType*)type)->getNumElements();
+ }
+ else {
+ assert(type->isStructTy());
+ numElements = type->getNumContainedTypes();
+ }
+ if(numElements == 0) {
+ assert(EDINumElements <= 1 || EDINumElements==UINT_MAX);
+ return 0;
+ }
+ assert(numElements == EDINumElements);
+ return numElements;
+}
+
+inline bool SmartType::isUseExceptions() const {
+ return useExceptions;
+}
+
+inline bool SmartType::verifyTy() const {
+ if(isVoidTy()) return true;
+ if(isPrimitiveTy()) return true;
+ if(isAggregateType()) return true;
+ if(isFunctionTy()) return true;
+ if(isStructTy()) return true;
+ if(isArrayTy()) return true;
+ if(isPointerTy()) return true;
+ if(isOpaqueTy()) return true;
+
+ return false;
+}
+
+inline bool SmartType::hasRawTypeRepresentation() const {
+ return rawTypeRepresentation;
+}
+
+}
+
+#endif
--- /dev/null
+#ifndef TYPE_INFO_H
+#define TYPE_INFO_H
+
+#include <magic/magic.h>
+#include <magic_common.h>
+#include <magic/support/SmartType.h>
+#include <magic/support/TypeUtil.h>
+
+using namespace llvm;
+
+#define TypeInfoErr(M) errs() << "TypeInfo: " << M << "\n"
+
+#define FUNCTIONS_USE_HASH_TYPE_STRINGS 1
+#define ROOT_TYPES_HAVE_TYPE_STRINGS 0
+#define DEBUG_CAST_LOOKUPS 0
+
+#define TYPEINFO_PERSISTENT 0x01
+
+namespace llvm {
+
+class TypeInfo {
+ public:
+ TypeInfo(const SmartType *aSmartType, int persistent=0);
+ TypeInfo(TYPECONST FunctionType *FT, int persistent=0);
+ TypeInfo(TYPECONST PointerType *PT, int persistent=0);
+ TypeInfo(TYPECONST ArrayType *AT, int persistent=0);
+ TypeInfo(TYPECONST IntegerType *IT, int persistent=0);
+ TypeInfo(TYPECONST StructType *OpaqueST, int persistent=0);
+ void init(int persistent);
+
+ const SmartType *getSmartType() const;
+ TYPECONST Type *getType() const;
+ unsigned getNumContainedTypes() const;
+ unsigned getNumChildTypes() const;
+ TypeInfo *getContainedType(unsigned i) const;
+ std::vector<GlobalValue*> getParents() const;
+ std::string getTypeString() const;
+ std::string getDescription() const;
+ std::string getVerboseDescription() const;
+ std::string getName() const;
+ std::vector<std::string> getNames() const;
+ std::string getNamesString() const;
+ std::vector<std::string> getMemberNames() const;
+ std::vector<int> getValueSet() const;
+ std::vector<TypeInfo*> getCastTypes() const;
+ unsigned getTypeID() const;
+ unsigned getFlags() const;
+ unsigned getBitWidth() const;
+ bool equals(TYPECONST TypeInfo *other) const;
+ bool hasRawTypeRepresentation() const;
+
+ std::string formatMemberName(const std::string &memberName, unsigned &numAnonMembers);
+ void setValueSet(const std::vector<int> &valueSet);
+ void setContainedTypes(const std::vector<TypeInfo*> &containedTypes);
+ void addParent(GlobalValue* parent);
+ void addParents(const std::vector<GlobalValue*> &parents);
+ bool removeParent(GlobalValue* parent);
+ bool removeAllParents();
+ void setPersistent();
+ bool splitByParentValueSet(std::vector<TypeInfo*> &splitTypeInfos, std::set<GlobalVariable*> &globalVariablesWithAddressTaken);
+
+ static unsigned getMaxNameLength();
+ static unsigned getMaxTypeStringLength();
+ static void setIntCastTypes(std::map<TYPECONST Type*, std::set<int> > &intCastTypes);
+ static void setBitCastTypes(std::map<TYPECONST Type*, std::set<TYPECONST Type*> > &bitCastTypes);
+
+ private:
+ const SmartType *aSmartType;
+ TYPECONST Type *aType;
+ bool forceTypeDescription;
+ mutable std::string typeDescription;
+ std::string name;
+ std::vector<std::string> names;
+ std::vector<std::string> memberNames;
+ std::vector<int> valueSet;
+ std::vector<TypeInfo*> containedTypes;
+ std::vector<GlobalValue*> parents;
+ unsigned bitWidth;
+ unsigned typeID;
+ unsigned numElements;
+ unsigned flags;
+ static unsigned maxNameLength;
+ static unsigned maxTypeStringLength;
+ static std::map<TYPECONST Type*, std::set<int> > intCastTypes;
+ static std::map<TYPECONST Type*, std::set<TYPECONST Type*> > bitCastTypes;
+ static std::map<TYPECONST Type*, std::set<TypeInfo*> > typeMap;
+
+ TypeInfo() {}
+};
+
+inline TypeInfo::TypeInfo(const SmartType *aSmartType, int persistent) {
+ unsigned i;
+ assert(aSmartType);
+ this->aSmartType = aSmartType;
+ this->aType = aSmartType->getType();
+ bool rawTypeRepresentation = aSmartType->hasRawTypeRepresentation();
+ forceTypeDescription = aSmartType->isFunctionTy();
+ name = aSmartType->getEDIType()->getName();
+ std::vector<StringRef> nameRefs = aSmartType->getEDIType()->getNames();
+ for(i=0;i<nameRefs.size();i++) {
+ if(nameRefs[i].size() > maxNameLength) {
+ maxNameLength = nameRefs[i].size();
+ }
+ names.push_back(nameRefs[i]);
+ }
+ if(aSmartType->isStructTy()) {
+ if(!rawTypeRepresentation) {
+ const EDIType* aEDIType = aSmartType->getEDIType();
+ unsigned numContainedTypes = aSmartType->getNumContainedTypes();
+ unsigned numAnonMembers = 0;
+ if(aEDIType->isUnionTy()) {
+ assert(numContainedTypes == 1);
+ i=aSmartType->getUnionMemberIdx();
+ const DIDerivedType subDIType = aSmartType->getMember(i);
+ memberNames.push_back(formatMemberName(subDIType.getName(), numAnonMembers));
+ }
+ else {
+ assert(aEDIType->isStructTy());
+ i=0;
+ for(;i<numContainedTypes;i++) {
+ const DIDerivedType subDIType = aSmartType->getMember(i);
+ memberNames.push_back(formatMemberName(subDIType.getName(), numAnonMembers));
+ }
+ }
+ }
+ else {
+ memberNames.push_back("raw");
+ }
+ }
+ if(aSmartType->getEDIType()->isEnumTy()) {
+ std::vector<unsigned> enumValues = aSmartType->getEDIType()->getEnumValues();
+ valueSet.push_back(enumValues.size()); //push length as the first value
+ for(unsigned i=0;i<enumValues.size();i++) {
+ valueSet.push_back((int)enumValues[i]);
+ }
+ }
+ bitWidth = TypeUtil::typeToBits(aSmartType->getType());
+ const EDIType *aEDIType = aSmartType->getEDIType();
+ typeID = 0;
+ flags = 0;
+ if(aSmartType->isOpaqueTy()) {
+ typeID = MAGIC_TYPE_OPAQUE;
+ }
+ else if(aEDIType->isVoidTy()) {
+ typeID = MAGIC_TYPE_VOID;
+ }
+ else if(aSmartType->isFunctionTy()) {
+ typeID = MAGIC_TYPE_FUNCTION;
+ }
+ else if(aSmartType->isStructTy()) {
+ if(aEDIType->isUnionTy()) {
+ typeID = MAGIC_TYPE_UNION;
+ }
+ else if(aEDIType->isStructTy()) {
+ typeID = MAGIC_TYPE_STRUCT;
+#if MAGIC_VARSIZED_STRUCTS_SUPPORT
+ if(!rawTypeRepresentation) {
+ assert(this->aType->getNumContainedTypes() > 0);
+ TYPECONST Type *lastSubType = this->aType->getContainedType(this->aType->getNumContainedTypes()-1);
+ if(lastSubType->isArrayTy() && ((ArrayType*)lastSubType)->getNumElements() <= 1) {
+ flags |= MAGIC_TYPE_VARSIZE;
+ }
+ }
+#endif
+ }
+ }
+ else if(aSmartType->isPointerTy()) {
+ typeID = MAGIC_TYPE_POINTER;
+ }
+ else if(aSmartType->isArrayTy()) {
+ typeID = MAGIC_TYPE_ARRAY;
+ }
+ else if(aEDIType->isFloatingPointTy()) {
+ typeID = MAGIC_TYPE_FLOAT;
+ }
+ else if(aEDIType->isIntegerTy()) {
+ typeID = MAGIC_TYPE_INTEGER;
+ }
+ else if(aEDIType->isEnumTy()) {
+ typeID = MAGIC_TYPE_ENUM;
+ }
+ else if(aEDIType->isVectorTy()) {
+ typeID = MAGIC_TYPE_VECTOR;
+ }
+ assert(typeID);
+ if(typeID == MAGIC_TYPE_INTEGER || typeID == MAGIC_TYPE_ENUM) {
+ if(getNamesString().find("unsigned") != std::string::npos) {
+ flags |= MAGIC_TYPE_UNSIGNED;
+ }
+ }
+ numElements = aSmartType->getNumElements();
+ init(persistent);
+}
+
+inline TypeInfo::TypeInfo(TYPECONST FunctionType *FT, int persistent) {
+ assert(FT);
+ aSmartType = NULL;
+ aType = FT;
+ forceTypeDescription = true;
+ bitWidth = 0;
+ typeID = MAGIC_TYPE_FUNCTION;
+ numElements = 0;
+ flags = MAGIC_TYPE_EXTERNAL;
+ init(persistent);
+}
+
+inline TypeInfo::TypeInfo(TYPECONST PointerType *PT, int persistent) {
+ assert(PT);
+ aSmartType = NULL;
+ aType = PT;
+ forceTypeDescription = false;
+ bitWidth = 0;
+ typeID = MAGIC_TYPE_POINTER;
+ numElements = 0;
+ flags = MAGIC_TYPE_EXTERNAL;
+ init(persistent);
+}
+
+inline TypeInfo::TypeInfo(TYPECONST ArrayType *AT, int persistent) {
+ assert(AT);
+ aSmartType = NULL;
+ aType = AT;
+ forceTypeDescription = false;
+ bitWidth = 0;
+ typeID = MAGIC_TYPE_ARRAY;
+ numElements = AT->getNumElements();
+ flags = MAGIC_TYPE_EXTERNAL;
+ init(persistent);
+}
+
+inline TypeInfo::TypeInfo(TYPECONST IntegerType *IT, int persistent) {
+ assert(IT);
+ aSmartType = NULL;
+ aType = IT;
+ forceTypeDescription = true;
+ bitWidth = IT->getBitWidth();
+ typeID = MAGIC_TYPE_INTEGER;
+ numElements = 0;
+ flags = MAGIC_TYPE_EXTERNAL;
+ init(persistent);
+}
+
+inline TypeInfo::TypeInfo(TYPECONST StructType *OpaqueST, int persistent) {
+ assert(OpaqueST);
+ assert(TypeUtil::isOpaqueTy(OpaqueST));
+ aSmartType = NULL;
+ aType = OpaqueST;
+ forceTypeDescription = true;
+ bitWidth = 0;
+ typeID = MAGIC_TYPE_OPAQUE;
+ numElements = 0;
+ flags = MAGIC_TYPE_EXTERNAL;
+ init(persistent);
+}
+
+inline void TypeInfo::init(int persistent) {
+ std::map<TYPECONST Type*, std::set<int> >::iterator intCastTypesIt;
+ //set persistent if necessary
+ if(persistent) {
+ setPersistent();
+ }
+ //initialize value set for pointers casted to int
+ if(aType->isPointerTy()) {
+ intCastTypesIt = intCastTypes.find(aType);
+ if(intCastTypesIt != intCastTypes.end()) {
+ std::set<int> &pointerValues = intCastTypesIt->second;
+ assert(pointerValues.size() > 0);
+ flags |= MAGIC_TYPE_INT_CAST;
+ if(pointerValues.size() > 1 || *(pointerValues.begin()) != 0) {
+ valueSet.push_back(pointerValues.size()); //push length as the first value
+ for(std::set<int>::iterator it=pointerValues.begin() ; it != pointerValues.end(); it++) {
+ assert(*it != 0);
+ valueSet.push_back(*it);
+ }
+ }
+ }
+ }
+ //adjust flags
+ bool hasInnerPointers = aSmartType ? aSmartType->hasInnerPointers() : TypeUtil::hasInnerPointers(aType);
+ if(!hasInnerPointers) {
+ flags |= MAGIC_TYPE_NO_INNER_PTRS;
+ }
+}
+
+inline const SmartType *TypeInfo::getSmartType() const {
+ return aSmartType;
+}
+
+inline TYPECONST Type *TypeInfo::getType() const {
+ return aType;
+}
+
+inline unsigned TypeInfo::getNumContainedTypes() const {
+ return containedTypes.size();
+}
+
+inline unsigned TypeInfo::getNumChildTypes() const {
+ return typeID == MAGIC_TYPE_ARRAY ? numElements : containedTypes.size();
+}
+
+inline TypeInfo *TypeInfo::getContainedType(unsigned i) const {
+ assert(i<containedTypes.size());
+ return containedTypes[i];
+}
+
+inline std::vector<GlobalValue*> TypeInfo::getParents() const {
+ return parents;
+}
+
+inline std::string TypeInfo::getTypeString() const {
+ std::string typeString = forceTypeDescription || aType->getNumContainedTypes() == 0 ? getDescription() : "";
+ if(MAGIC_SHRINK_TYPE_STR && typeString.size() > MAGIC_MAX_TYPE_STR_LEN) {
+ typeString = typeString.substr(0, MAGIC_MAX_TYPE_STR_LEN-3) + "...";
+ }
+ if(typeString.size() > maxTypeStringLength) {
+ maxTypeStringLength = typeString.size();
+ }
+ return typeString;
+}
+
+inline std::string TypeInfo::getDescription() const {
+ if(typeDescription.size() == 0) {
+ if(aType->isFunctionTy() && FUNCTIONS_USE_HASH_TYPE_STRINGS) {
+ unsigned hash = TypeUtil::getHash(aType);
+ raw_string_ostream ostream(typeDescription);
+ ostream << "hash_" << hash;
+ ostream.flush();
+ }
+ else {
+ typeDescription = TypeUtil::getDescription(aType);
+ }
+ }
+ return typeDescription;
+}
+
+inline std::string TypeInfo::getVerboseDescription() const {
+ return aSmartType ? aSmartType->getDescription() : getDescription();
+}
+
+inline std::string TypeInfo::getName() const {
+ return name;
+}
+
+inline std::vector<std::string> TypeInfo::getNames() const {
+ return names;
+}
+
+inline std::string TypeInfo::getNamesString() const {
+ std::string string;
+ raw_string_ostream ostream(string);
+ for(unsigned i=0;i<names.size();i++) {
+ if(i>0) ostream << "|";
+ ostream << names[i];
+ }
+ ostream.flush();
+ return string;
+}
+
+inline std::vector<std::string> TypeInfo::getMemberNames() const {
+ for(unsigned i=0;i<memberNames.size();i++) {
+ if(memberNames[i].size() > maxNameLength) {
+ maxNameLength = memberNames[i].size();
+ }
+ }
+ return memberNames;
+}
+
+inline std::vector<int> TypeInfo::getValueSet() const {
+ return valueSet;
+}
+
+inline std::vector<TypeInfo*> TypeInfo::getCastTypes() const {
+ std::vector<TypeInfo*> castTypes;
+ std::map<TYPECONST Type*, std::set<TYPECONST Type*> >::iterator bitCastTypesIt;
+ std::map<TYPECONST Type*, std::set<TypeInfo*> >::iterator typeMapIt;
+ if(!aType->isPointerTy()) {
+ return castTypes;
+ }
+ //XXX to-do: match only original struct name during lookup by looking at the original bitcast instruction
+ //the following lookups do not distinguish between struct x = {18} and struct y = {i8}
+ //the number of false positives generated seems to be fairly small, anyway
+ bitCastTypesIt = bitCastTypes.find(aType);
+ if(bitCastTypesIt == bitCastTypes.end()) {
+ return castTypes;
+ }
+ std::set<TYPECONST Type*> bitCastSet = bitCastTypesIt->second;
+#if MAGIC_INDEX_TRANSITIVE_BIT_CASTS
+ std::vector<TYPECONST Type*> bitCasts;
+ for(std::set<TYPECONST Type*>::iterator it=bitCastSet.begin();it!=bitCastSet.end();it++) {
+ bitCasts.push_back(*it);
+ }
+ while(!bitCasts.empty()) {
+ TYPECONST Type* bcType = bitCasts.front();
+ bitCasts.erase(bitCasts.begin());
+ bitCastTypesIt = bitCastTypes.find(bcType);
+ if(bitCastTypesIt != bitCastTypes.end()) {
+ std::set<TYPECONST Type*> set = bitCastTypesIt->second;
+ for(std::set<TYPECONST Type*>::iterator it=set.begin();it!=set.end();it++) {
+ unsigned bitCastSetSize = bitCastSet.size();
+ TYPECONST Type *newBcType = *it;
+ if(newBcType == aType) {
+ continue;
+ }
+ bitCastSet.insert(newBcType);
+ if(bitCastSet.size() != bitCastSetSize) {
+ bitCasts.push_back(newBcType);
+ }
+ }
+ }
+ }
+#endif
+
+#if DEBUG_CAST_LOOKUPS
+ if(aType->getContainedType(0)->isStructTy()) {
+ TypeInfoErr("--- type is struct* " << getContainedType(0)->getName());
+ }
+ else if(aType->getContainedType(0)->isPointerTy() && aType->getContainedType(0)->getContainedType(0)->isStructTy()) {
+ TypeInfoErr("--- type is struct** " << getContainedType(0)->getContainedType(0)->getName());
+ }
+ else {
+ TypeInfoErr("--- type is " << getDescription());
+ }
+#endif
+
+ for(std::set<TYPECONST Type*>::iterator it=bitCastSet.begin();it!=bitCastSet.end();it++) {
+ TYPECONST Type* type = *it;
+ assert(type->isPointerTy());
+ typeMapIt = typeMap.find(type->getContainedType(0));
+ if(typeMapIt == typeMap.end()) {
+
+#if DEBUG_CAST_LOOKUPS
+ TypeInfoErr("*** cast target type not found: " << TypeUtil::getDescription(type->getContainedType(0)));
+#endif
+
+ continue;
+ }
+ std::set<TypeInfo*> *typeInfoSet = &(typeMapIt->second);
+ for(std::set<TypeInfo*>::iterator it2=typeInfoSet->begin();it2!=typeInfoSet->end();it2++) {
+ TypeInfo* typeInfo = *it2;
+ assert(typeInfo->getType() != getType()->getContainedType(0));
+
+#if DEBUG_CAST_LOOKUPS
+ if(typeInfo->getType()->isStructTy()) {
+ TypeInfoErr(">>> cast target type info is struct " << typeInfo->getName());
+ }
+ else if(typeInfo->getType()->isPointerTy() && typeInfo->getType()->getContainedType(0)->isStructTy()) {
+ TypeInfoErr(">>> cast target type info is struct* " << typeInfo->getContainedType(0)->getName());
+ }
+ else {
+ TypeInfoErr(">>> cast target type info is " << typeInfo->getDescription());
+ }
+#endif
+ castTypes.push_back(typeInfo);
+
+#if MAGIC_COMPACT_COMP_TYPES
+ /* This is safe as long as we check for compatible (LLVM) types at runtime. */
+ break;
+#endif
+ }
+ }
+ if(castTypes.size() > 0) { //push delimiter
+ castTypes.push_back(NULL);
+ }
+ return castTypes;
+}
+
+inline unsigned TypeInfo::getTypeID() const {
+ return typeID;
+}
+
+inline unsigned TypeInfo::getFlags() const {
+ return flags;
+}
+
+inline unsigned TypeInfo::getBitWidth() const {
+ return bitWidth;
+}
+
+inline bool TypeInfo::equals(TYPECONST TypeInfo *other) const {
+ if(aSmartType && other->getSmartType()) {
+ return aSmartType->equals(other->getSmartType());
+ }
+ return (flags & (~MAGIC_TYPE_IS_ROOT)) == (other->getFlags() & (~MAGIC_TYPE_IS_ROOT))
+ && !getDescription().compare(other->getDescription());
+}
+
+inline bool TypeInfo::hasRawTypeRepresentation() const {
+ return aSmartType && aSmartType->hasRawTypeRepresentation();
+}
+
+inline std::string TypeInfo::formatMemberName(const std::string &memberName, unsigned &numAnonMembers) {
+ if (memberName.compare("")) {
+ return memberName;
+ }
+ std::string name(memberName);
+ raw_string_ostream ostream(name);
+ ostream << MAGIC_ANON_MEMBER_PREFIX << "." << (numAnonMembers+1);
+ ostream.flush();
+ numAnonMembers++;
+
+ return name;
+}
+
+inline void TypeInfo::setValueSet(const std::vector<int> &valueSet) {
+ this->valueSet = valueSet;
+}
+
+inline void TypeInfo::setContainedTypes(const std::vector<TypeInfo*> &containedTypes) {
+ this->containedTypes = containedTypes;
+}
+
+inline void TypeInfo::addParent(GlobalValue* parent) {
+ assert((typeID == MAGIC_TYPE_FUNCTION && dyn_cast<Function>(parent))
+ || (typeID != MAGIC_TYPE_FUNCTION && dyn_cast<GlobalVariable>(parent)));
+ this->parents.push_back(parent);
+ flags |= MAGIC_TYPE_IS_ROOT;
+
+#if ROOT_TYPES_HAVE_TYPE_STRINGS
+ forceTypeDescription = true;
+#endif
+}
+
+inline void TypeInfo::addParents(const std::vector<GlobalValue*> &parents) {
+ for(unsigned i=0;i<parents.size();i++) {
+ addParent(parents[i]);
+ }
+}
+
+inline bool TypeInfo::removeParent(GlobalValue* parent)
+{
+ std::vector<GlobalValue*> originalParents = this->parents;
+ this->parents.clear();
+ for(unsigned i=0;i<originalParents.size();i++) {
+ if(originalParents[i] != parent) {
+ this->parents.push_back(originalParents[i]);
+ }
+ }
+ int sizeDiff = originalParents.size() - this->parents.size();
+ assert(sizeDiff == 0 || sizeDiff == 1);
+ return (sizeDiff == 1);
+}
+
+inline bool TypeInfo::removeAllParents()
+{
+ if(this->parents.size() > 0) {
+ this->parents.clear();
+ return true;
+ }
+ return false;
+}
+
+inline void TypeInfo::setPersistent() {
+ std::map<TYPECONST Type*, std::set<TypeInfo*> >::iterator typeMapIt;
+ typeMapIt = typeMap.find(aType);
+ if(typeMapIt == typeMap.end()) {
+ std::set<TypeInfo*> set;
+ set.insert(this);
+ typeMap.insert(std::pair<TYPECONST Type*, std::set<TypeInfo*> >(aType, set));
+ }
+ else {
+ std::set<TypeInfo*> *set;
+ set = &(typeMapIt->second);
+ set->insert(this);
+ }
+}
+
+inline bool TypeInfo::splitByParentValueSet(std::vector<TypeInfo*> &splitTypeInfos, std::set<GlobalVariable*> &globalVariablesWithAddressTaken) {
+ std::map<std::vector<int>, std::vector<GlobalVariable*> > valueSetMap;
+ std::map<std::vector<int>, std::vector<GlobalVariable*> >::iterator valueSetMapIt;
+ std::vector<int> valueSet;
+ splitTypeInfos.push_back(this);
+ if(!isa<IntegerType>(aType)) {
+ return false;
+ }
+ assert(valueSet.size() == 0);
+ for(unsigned i=0;i<parents.size();i++) {
+ if(GlobalVariable *GV = dyn_cast<GlobalVariable>(parents[i])) {
+ bool hasAddressTaken = globalVariablesWithAddressTaken.find(GV) != globalVariablesWithAddressTaken.end();
+ if(hasAddressTaken) {
+ continue;
+ }
+ valueSet.clear();
+ bool valueSetFound = MagicUtil::lookupValueSet(GV, valueSet);
+ if(!valueSetFound) {
+ continue;
+ }
+ valueSetMapIt = valueSetMap.find(valueSet);
+ if(valueSetMapIt == valueSetMap.end()) {
+ std::vector<GlobalVariable*> vector;
+ valueSetMap.insert(std::pair<std::vector<int>, std::vector<GlobalVariable*> >(valueSet, vector));
+ valueSetMapIt = valueSetMap.find(valueSet);
+ assert(valueSetMapIt != valueSetMap.end());
+ }
+ std::vector<GlobalVariable*> *globalsVector = &valueSetMapIt->second;
+ globalsVector->push_back(GV);
+ }
+ }
+ if(valueSetMap.size() == 0) {
+ return false;
+ }
+ for(valueSetMapIt = valueSetMap.begin(); valueSetMapIt!=valueSetMap.end(); valueSetMapIt++) {
+ const std::vector<int> &values = valueSetMapIt->first;
+ const std::vector<GlobalVariable*> &globalVariables = valueSetMapIt->second;
+ TypeInfo *aTypeInfo = new TypeInfo(*this);
+ aTypeInfo->setValueSet(values);
+ aTypeInfo->removeAllParents();
+ for(unsigned i=0;i<globalVariables.size();i++) {
+ GlobalVariable* GV = globalVariables[i];
+ bool parentRemoved = this->removeParent(GV);
+ assert(parentRemoved);
+ aTypeInfo->addParent(GV);
+ }
+ splitTypeInfos.push_back(aTypeInfo);
+ }
+ return true;
+}
+
+inline unsigned TypeInfo::getMaxNameLength() {
+ return TypeInfo::maxNameLength;
+}
+
+inline unsigned TypeInfo::getMaxTypeStringLength() {
+ return TypeInfo::maxTypeStringLength;
+}
+
+inline void TypeInfo::setIntCastTypes(std::map<TYPECONST Type*, std::set<int> > &intCastTypes) {
+ TypeInfo::intCastTypes = intCastTypes;
+}
+
+inline void TypeInfo::setBitCastTypes(std::map<TYPECONST Type*, std::set<TYPECONST Type*> > &bitCastTypes) {
+ TypeInfo::bitCastTypes = bitCastTypes;
+}
+
+}
+
+#endif
--- /dev/null
+#ifndef TYPE_UTIL_H
+#define TYPE_UTIL_H
+
+#include <pass.h>
+#include <magic/support/EDIType.h>
+
+using namespace llvm;
+
+namespace llvm {
+
+#define TypeUtilLog(M) DEBUG(dbgs() << "TypeUtil: " << M << "\n")
+
+class TypeUtil {
+ public:
+ static int VERBOSE_LEVEL;
+ static int PRINT_SKIP_UNIONS;
+ static int PRINT_SKIP_STRUCTS;
+ static int PRINT_USE_BUILTIN_PRINTING;
+ static int PRINT_MULTI_NAMES;
+ static const unsigned TYPE_STRUCT = 0x01;
+ static const unsigned TYPE_UNION = 0x02;
+ static const unsigned TYPE_ANONYMOUS = 0x04;
+ static const unsigned TYPE_UNNAMED = 0x08;
+
+ static bool isPaddedType(TYPECONST Type *type);
+
+ static TYPECONST Type* lookupTopStructType(TYPECONST Type *type, unsigned index);
+ static void parseTopStructTypes(Module &M, TYPECONST Type *type, std::vector<std::string> *names, std::vector<unsigned> *flags);
+ static int findTopStructTypeIndex(Module &M, TYPECONST Type *type, std::string &name, unsigned flagsToAccept);
+ static TYPECONST Type* getRecursiveElementType(TYPECONST Type *type);
+ static TYPECONST Type* getArrayFreePointerType(TYPECONST Type *type);
+ static bool hasInnerPointers(TYPECONST Type *type);
+ static bool isArrayAsStructTy(TYPECONST Type *type);
+ static bool isOpaqueTy(TYPECONST Type *type);
+
+ static unsigned getHash(TYPECONST Type* type);
+ static const std::string getDescription(TYPECONST Type* type, size_t max_chars = 0, size_t max_levels = 0);
+ static const std::string getDescription(const EDIType* aEDIType);
+ static const std::string getDescription(TYPECONST Type* type, const EDIType* aEDIType, size_t max_chars = 0, size_t max_levels = 0);
+ static const std::string getFormattedDescription(std::string &description);
+ static void printFormattedTypeString(raw_ostream &OS, std::string &typeStr, int start, int length);
+ static void printTypeString(raw_ostream &OS, TYPECONST Type* type, size_t max_chars = 0, size_t max_levels = 0);
+ static unsigned typeToBits(TYPECONST Type *type);
+};
+
+inline bool TypeUtil::isOpaqueTy(TYPECONST Type *type) {
+ return PassUtil::isOpaqueTy(type);
+}
+
+}
+
+#endif
--- /dev/null
+#ifndef VARIABLE_REFS_H
+#define VARIABLE_REFS_H
+
+#include <pass.h>
+
+using namespace llvm;
+
+namespace llvm {
+
+class VariableRefs {
+ public:
+ VariableRefs();
+
+ bool isUnnecessaryInstruction(Instruction* inst) const;
+ Instruction* getInstruction() const;
+ bool isInstructionInEntryBlock() const;
+
+ void addInstruction(Instruction* inst);
+ void clear();
+
+ private:
+ Instruction* instruction;
+ bool instructionInEntryBlock;
+
+ void setFunctionEntryInstruction(Function* function);
+};
+
+}
+
+#endif
#ifndef _PASS_H
#define _PASS_H
-#import <set>
-#import <map>
+#include <set>
+#include <map>
#include <llvm/Pass.h>
#include <llvm/Support/raw_ostream.h>
--- /dev/null
+#include <magic/MagicPass.h>
+
+using namespace llvm;
+
+PASS_COMMON_INIT_ONCE();
+
+// command-line arguments
+static cl::opt<std::string>
+DLLFName("magic-dll-function",
+ cl::desc("Specify the name of the deepest long-lived function whose stack "
+ "needs to be instrumented"),
+ cl::init(MAGIC_ENTRY_POINT), cl::NotHidden, cl::ValueRequired);
+
+static cl::opt<std::string>
+LibPathRegex("magic-lib-path-regex",
+ cl::desc("Specify all the colon-separated path regexes that identify directories containing "
+ "libraries. Deprecated. Use -magic-ext-lib-sections instead."),
+ cl::init(""), cl::NotHidden, cl::ValueRequired);
+
+static cl::opt<std::string>
+VoidTypeAlias("magic-void-alias",
+ cl::desc("Specify all the colon-separated type names that are to be treated as void, typically "
+ "used in custom memory management implementations"),
+ cl::init(""), cl::NotHidden, cl::ValueRequired);
+
+static cl::opt<std::string>
+MMFuncPrefix("magic-mmfunc-prefix",
+ cl::desc("Specify all the colon-separated prefixes that are to be used when extracting "
+ "memory management functions used in custom memory management implementations"),
+ cl::init(""), cl::NotHidden, cl::ValueRequired);
+
+static cl::opt<std::string>
+MMFuncPair("magic-mmfunc-pair",
+ cl::desc("Specify all the colon-separated pairs of malloc/free style memory management functions "
+ "used in custom memory management implementations. Each function is to be listed together "
+ "with a number indicating which of the input parameters is the one corresponding to its "
+ "malloc(size)/free(pointer) counterpart. Example: "
+ "\"my_smart_alloc/3;my_smart_free/3:my_custom_alloc/2;my_custom_free/1\". "
+ "The counter for arguments starts from 1."),
+ cl::init(""), cl::NotHidden, cl::ValueRequired);
+
+static cl::opt<std::string>
+MMPoolFunc("magic-mm-poolfunc",
+ cl::desc("Specify a pool memory management set of functions for creating pools, destroying pools, "
+ "managing the pool buffers, reseting (reusing) pools and allocating memory blocks from the pool. "
+ "All the functions are to be listed together with a number indicating which of the input parameters"
+ "(numbering starts at 1) corresponds to the pool object. For the creation function, the pool object "
+ "can be the return value (specify 0 for return value). The block allocation function additionally "
+ "requires the number of the parameter denoting the size. Separate sets of functions using ':' and "
+ "separate multiple functions of the same type using ';'. "
+ "Example: \"my_pool_block_alloc/1/2:my_pool_create/0:my_pool_destroy/1:my_pool_alloc/1;"
+ "another_pool_alloc/1;my_pool_free/1:my_pool_reset/1\"."
+ "If there are no additional management functions, skip them. "
+ "Example: \"pool_block_alloc/1/2:pool_create:pool_destroy/1\"."),
+ cl::init(""), cl::NotHidden, cl::ValueRequired);
+
+static cl::opt<bool>
+EnablePoolMemReuse("magic-mpool-enable-reuse",
+ cl::desc("Enable memory reuse across pools."),
+ cl::init(false), cl::NotHidden);
+
+static cl::opt<std::string>
+MMAPCtlFunction("magic-mmap-ctlfunc",
+ cl::desc("Specify all the colon-separated mmap control functions that change low-level properties"
+ "of memory-mapped memory regions taking the start address as an argument"),
+ cl::init(""), cl::NotHidden, cl::ValueRequired);
+
+static cl::opt<std::string>
+MagicDataSections("magic-data-sections",
+ cl::desc("Specify all the colon-separated magic data section regexes not to instrument"),
+ cl::init("^" MAGIC_STATIC_VARS_SECTION_PREFIX ".*$:^" UNBL_SECTION_PREFIX ".*$"), cl::NotHidden, cl::ValueRequired);
+
+static cl::opt<std::string>
+MagicFunctionSections("magic-function-sections",
+ cl::desc("Specify all the colon-separated magic function section regexes not to instrument"),
+ cl::init("^" MAGIC_STATIC_FUNCTIONS_SECTION ".*$:^" UNBL_SECTION_PREFIX ".*$"), cl::NotHidden, cl::ValueRequired);
+
+static cl::opt<std::string>
+ExtLibSections("magic-ext-lib-sections",
+ cl::desc("Specify all the colon-separated external lib section regexes"),
+ cl::init(MAGIC_DEFAULT_EXT_LIB_SECTION_REGEX), cl::NotHidden, cl::ValueRequired);
+
+static cl::opt<std::string>
+baseBuildDir("magic-base-build-dir",
+ cl::desc("Specify the base build directory from which the pass derives relative directories for debug symbols"),
+ cl::init(""), cl::NotHidden, cl::ValueRequired);
+
+static cl::opt<bool>
+EnableShadowing("magic-enable-shadowing",
+ cl::desc("Enable state shadowing"),
+ cl::init(false), cl::NotHidden);
+
+static cl::opt<bool>
+SkipAll("magic-skip-all",
+ cl::desc("Exit immediately"),
+ cl::init(false), cl::NotHidden);
+
+#if MAGIC_USE_QPROF_INSTRUMENTATION
+QPROF_DECLARE_ALL_OPTS(magic,
+ magicLLSitestacks,
+ magicDeepestLLLoops,
+ magicDeepestLLLibs,
+ magicTaskClasses
+);
+#endif
+
+#define DEBUG_TYPE_INFOS 0
+#define DEBUG_FILL_TYPE_INFOS 0
+#define DEBUG_FILL_EXT_TYPE_INFOS 0
+#define DEBUG_ALLOC_LEVEL 0
+#define DEBUG_ALLOC_BAD_TYPES 0
+#define DEBUG_CASTS 0
+#define DEBUG_DUPLICATED_TYPE_INFOS 0
+#define DEBUG_VALUE_SET 0
+#define DEBUG_QPROF 0
+
+namespace llvm {
+
+//===----------------------------------------------------------------------===//
+// Constructors, destructor, and operators
+//===----------------------------------------------------------------------===//
+
+MagicPass::MagicPass() : ModulePass(ID) {}
+
+unsigned TypeInfo::maxNameLength = 0;
+unsigned TypeInfo::maxTypeStringLength = 0;
+std::map<TYPECONST Type*, std::set<int> > TypeInfo::intCastTypes;
+std::map<TYPECONST Type*, std::set<TYPECONST Type*> > TypeInfo::bitCastTypes;
+std::map<TYPECONST Type*, std::set<TypeInfo*> > TypeInfo::typeMap;
+
+bool SmartType::forceRawUnions = MAGIC_FORCE_RAW_UNIONS;
+bool SmartType::forceRawBitfields = MAGIC_FORCE_RAW_BITFIELDS;
+
+Function *MagicMemFunction::lastAllocWrapper = NULL;
+std::map<std::string, Function*> MagicMemFunction::allocWrapperCache;
+std::set<Function*> MagicMemFunction::customWrapperSet;
+
+//===----------------------------------------------------------------------===//
+// Public methods
+//===----------------------------------------------------------------------===//
+
+bool MagicPass::runOnModule(Module &M) {
+ unsigned i;
+
+ if (SkipAll) {
+ return false;
+ }
+
+ magicPassLog("Running...");
+ EDIType::setModule(&M);
+ PassUtil::setModule(&M);
+
+ // initialize qprof instrumentation
+ qprofInstrumentationInit(M);
+
+ //look up magic entry point function
+ Function *magicEntryPointFunc = M.getFunction(MAGIC_ENTRY_POINT);
+ if( !magicEntryPointFunc ){
+ //if no valid entry point, we are not compiling a valid program, skip pass
+ magicPassLog("Error: no " << MAGIC_ENTRY_POINT << "() found");
+ return false;
+ }
+
+ //look up magic enabled variable
+ GlobalVariable* magicEnabled = M.getNamedGlobal(MAGIC_ENABLED);
+ if(!magicEnabled) {
+ magicPassErr("Error: no " << MAGIC_ENABLED << " variable found");
+ exit(1);
+ }
+
+ //look up magic root variable
+ GlobalVariable* magicRootVar = M.getNamedGlobal(MAGIC_ROOT_VAR_NAME);
+ if(!magicRootVar) {
+ magicPassErr("Error: no " << MAGIC_ROOT_VAR_NAME << " variable found");
+ exit(1);
+ }
+
+ //look up magic data init function and get the last instruction to add stuff in it
+ Function *magicDataInitFunc = M.getFunction(MAGIC_DATA_INIT_FUNC_NAME);
+ if(!magicDataInitFunc){
+ magicPassErr("Error: no " << MAGIC_DATA_INIT_FUNC_NAME << "() found");
+ exit(1);
+ }
+ Instruction *magicArrayBuildFuncInst = magicDataInitFunc->back().getTerminator();
+
+ //look up pointer to magic array and magic struct type
+ Value* magicArrayPtr = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_SENTRIES);
+ if(!magicArrayPtr) {
+ magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_SENTRIES << " field found");
+ exit(1);
+ }
+ TYPECONST StructType* magicStructType = (TYPECONST StructType*) ((TYPECONST PointerType*)((TYPECONST PointerType*)magicArrayPtr->getType())->getElementType())->getElementType();
+
+ //look up pointer to magic array size
+ Value *magicArraySize = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_SENTRIES_NUM);
+ if(!magicArraySize) {
+ magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_SENTRIES_NUM << " field found");
+ exit(1);
+ }
+
+ //look up pointer to magic array string size
+ Value *magicArrayStrSize = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_SENTRIES_STR_NUM);
+ if(!magicArrayStrSize) {
+ magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_SENTRIES_STR_NUM << " field found");
+ exit(1);
+ }
+
+ //look up pointer to magic next id
+ Value *magicNextId = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_SENTRIES_NEXT_ID);
+ if(!magicNextId) {
+ magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_SENTRIES_NEXT_ID << " field found");
+ exit(1);
+ }
+
+ //look up pointer to magic dsindex array and magic dsindex struct type
+ Value* magicDsindexArrayPtr = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_DSINDEXES);
+ if(!magicDsindexArrayPtr) {
+ magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_DSINDEXES << " field found");
+ exit(1);
+ }
+ TYPECONST StructType* magicDsindexStructType = (TYPECONST StructType*) ((TYPECONST PointerType*)((TYPECONST PointerType*)magicDsindexArrayPtr->getType())->getElementType())->getElementType();
+
+ //look up pointer to magic dsindex array size
+ Value *magicDsindexArraySize = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_DSINDEXES_NUM);
+ if(!magicDsindexArraySize) {
+ magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_DSINDEXES_NUM << " field found");
+ exit(1);
+ }
+
+ //look up pointer to magic type array and magic type struct type
+ Value *magicTypeArrayPtr = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_TYPES);
+ if(!magicTypeArrayPtr) {
+ magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_TYPES << " field found");
+ exit(1);
+ }
+ TYPECONST StructType* magicTypeStructType = (TYPECONST StructType*) ((TYPECONST PointerType*)((TYPECONST PointerType*)magicTypeArrayPtr->getType())->getElementType())->getElementType();
+
+ //look up pointer to magic type array size
+ Value *magicTypeArraySize = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_TYPES_NUM);
+ if(!magicTypeArraySize) {
+ magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_TYPES_NUM << " field found");
+ exit(1);
+ }
+
+ //look up pointer to magic type next id
+ Value *magicTypeNextId = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_TYPES_NEXT_ID);
+ if(!magicTypeNextId) {
+ magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_TYPES_NEXT_ID << " field found");
+ exit(1);
+ }
+
+ //look up pointer to magic function array and magic function struct type
+ Value *magicFunctionArrayPtr = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_FUNCTIONS);
+ if(!magicFunctionArrayPtr) {
+ magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_FUNCTIONS << " field found");
+ exit(1);
+ }
+ TYPECONST StructType* magicFunctionStructType = (TYPECONST StructType*) ((TYPECONST PointerType*)((TYPECONST PointerType*)magicFunctionArrayPtr->getType())->getElementType())->getElementType();
+
+ //look up pointer to magic function array size
+ Value *magicFunctionArraySize = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_FUNCTIONS_NUM);
+ if(!magicFunctionArraySize) {
+ magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_FUNCTIONS_NUM << " field found");
+ exit(1);
+ }
+
+ //look up pointer to magic function next id
+ Value *magicFunctionNextId = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_FUNCTIONS_NEXT_ID);
+ if(!magicFunctionNextId) {
+ magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_FUNCTIONS_NEXT_ID << " field found");
+ exit(1);
+ }
+
+ //look up magic dsentry struct type
+ Value *magicFirstDsentyPtr = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_FIRST_DSENTRY);
+ if(!magicFirstDsentyPtr) {
+ magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_FIRST_DSENTRY << " field found");
+ exit(1);
+ }
+ TYPECONST StructType* magicDsentryStructType = (TYPECONST StructType*) ((TYPECONST PointerType*)((TYPECONST PointerType*)magicFirstDsentyPtr->getType())->getElementType())->getElementType();
+
+ //look up magic init function
+ Function *magicInitFunc = M.getFunction(MAGIC_INIT_FUNC_NAME);
+ if( !magicInitFunc ){
+ magicPassErr("Error: no " << MAGIC_INIT_FUNC_NAME << "() found");
+ exit(1);
+ }
+
+ //look up magic dsentry stack functions
+ Function *magicStackDsentryCreateFunc = M.getFunction(MAGIC_STACK_DSENTRIES_CREATE_FUNC_NAME);
+ if (!magicStackDsentryCreateFunc) {
+ magicPassErr("Error: no " << MAGIC_STACK_DSENTRIES_CREATE_FUNC_NAME << "() found");
+ exit(1);
+ }
+ Function *magicStackDsentryDestroyFunc = M.getFunction(MAGIC_STACK_DSENTRIES_DESTROY_FUNC_NAME);
+ if (!magicStackDsentryDestroyFunc) {
+ magicPassErr("Error: no " << MAGIC_STACK_DSENTRIES_DESTROY_FUNC_NAME << "() found");
+ exit(1);
+ }
+
+ //look up deepest long-lived function
+ Function *deepestLLFunction = M.getFunction(DLLFName);
+ if (!deepestLLFunction) {
+ magicPassErr("Error: no " << DLLFName << "() found");
+ exit(1);
+ }
+
+ //lookup magic get page size function
+ Function *magicGetPageSizeFunc = M.getFunction(MAGIC_GET_PAGE_SIZE_FUNC_NAME);
+ if(!magicGetPageSizeFunc){
+ magicPassErr("Error: no " << MAGIC_GET_PAGE_SIZE_FUNC_NAME << "() found");
+ exit(1);
+ }
+
+ //look up magic void pointer
+ GlobalVariable *magicVoidPtr = M.getNamedGlobal(MAGIC_VOID_PTR_NAME);
+ if(!magicVoidPtr) {
+ magicPassErr("Error: no " << MAGIC_VOID_PTR_NAME << "variable found");
+ exit(1);
+ }
+ assert(!isMagicGV(M, magicVoidPtr));
+
+ //look up magic void array
+ GlobalVariable *magicVoidArr = M.getNamedGlobal(MAGIC_VOID_ARRAY_NAME);
+ if(!magicVoidArr) {
+ magicPassErr("Error: no " << MAGIC_VOID_ARRAY_NAME << "variable found");
+ exit(1);
+ }
+ assert(!isMagicGV(M, magicVoidArr));
+
+ //look up magic void * type pointer
+ GlobalVariable *magicVoidPtrTypePtr = M.getNamedGlobal(MAGIC_VOID_PTR_TYPE_PTR_NAME);
+ if(!magicVoidPtrTypePtr) {
+ magicPassErr("Error: no " << MAGIC_VOID_PTR_TYPE_PTR_NAME << "variable found");
+ exit(1);
+ }
+
+ //determine lib path regexes
+ PassUtil::parseStringListOpt(libPathRegexes, LibPathRegex);
+
+ //determine void type aliases
+ PassUtil::parseStringListOpt(voidTypeAliases, VoidTypeAlias);
+ std::copy( voidTypeAliases.begin(), voidTypeAliases.end(), std::inserter( voidTypeAliasesSet, voidTypeAliasesSet.end() ) );
+
+ //determine mm function prefixes
+ PassUtil::parseStringListOpt(mmFuncPrefixes, MMFuncPrefix);
+
+ //determine custom malloc/free style custom mm functions
+ PassUtil::parseStringPairListOpt(mmFuncPairs, MMFuncPair);
+
+ //determine the pool management sets of functions
+ PassUtil::parseStringListOpt(mmPoolFunctions, MMPoolFunc);
+
+ //determine mmap ctl functions
+ PassUtil::parseStringListOpt(mmapCtlFunctions, MMAPCtlFunction);
+
+ //determine magic data section regexes
+ PassUtil::parseRegexListOpt(magicDataSectionRegexes, MagicDataSections);
+
+ //determine magic function section regexes
+ PassUtil::parseRegexListOpt(magicFunctionSectionRegexes, MagicFunctionSections);
+
+ //determine magic ext lib section regexes
+ PassUtil::parseRegexListOpt(extLibSectionRegexes, ExtLibSections);
+
+ //look up inttoptr type casts
+ Module::GlobalListType &globalList = M.getGlobalList();
+ Module::FunctionListType &functionList = M.getFunctionList();
+ std::vector<TYPECONST Type*> intCastTypes;
+ std::vector<int> intCastValues;
+ std::map<TYPECONST Type*, std::set<TYPECONST Type*> > bitCastMap;
+ for (Module::iterator it = functionList.begin(); it != functionList.end(); ++it) {
+ Function *F = it;
+ if(isMagicFunction(M, F)) {
+ continue;
+ }
+ for (inst_iterator I2 = inst_begin(F), E2 = inst_end(F); I2 != E2; ++I2) {
+ indexCasts(M, &(*I2), intCastTypes, intCastValues, bitCastMap);
+ }
+ }
+ for (Module::global_iterator it = globalList.begin(); it != globalList.end(); ++it) {
+ GlobalVariable *GV = it;
+ StringRef GVName = GV->getName();
+ if(isMagicGV(M, GV) || GVName.startswith(".str") || GVName.startswith(".arr") || GVName.startswith("C.")) {
+ continue;
+ }
+ if(GV->hasInitializer()) {
+ indexCasts(M, GV->getInitializer(), intCastTypes, intCastValues, bitCastMap);
+ }
+ }
+
+ //index and set cast maps
+ std::map<TYPECONST Type*, std::set<int> > intCastMap;
+ std::map<TYPECONST Type*, std::set<int> >::iterator intCastMapIt;
+ for(i=0;i<intCastTypes.size();i++) {
+ TYPECONST Type* type = intCastTypes[i];
+ int value = intCastValues[i];
+ intCastMapIt = intCastMap.find(type);
+ if(intCastMapIt == intCastMap.end()) {
+ std::set<int> valueSet;
+ intCastMap.insert(std::pair<TYPECONST Type*, std::set<int> >(type, valueSet));
+ intCastMapIt = intCastMap.find(type);
+ }
+ assert(intCastMapIt != intCastMap.end());
+ std::set<int> *setPtr = &(intCastMapIt->second);
+ if(setPtr->size() == 1 && *(setPtr->begin()) == 0) {
+ continue;
+ }
+ if(value == 0) {
+ setPtr->clear();
+ }
+ setPtr->insert(value);
+ }
+ TypeInfo::setIntCastTypes(intCastMap);
+ TypeInfo::setBitCastTypes(bitCastMap);
+
+#if MAGIC_INSTRUMENT_MEM_FUNCS
+ //look up magic memory functions and corresponding wrappers
+ #define __X(P) #P
+ std::string magicMemFuncNames[] = { MAGIC_MEM_FUNC_NAMES };
+ std::string magicMemDeallocFuncNames[] = { MAGIC_MEMD_FUNC_NAMES };
+ #undef __X
+ int magicMemFuncAllocFlags[] = { MAGIC_MEM_FUNC_ALLOC_FLAGS };
+ std::string magicMemPrefixes[] = { MAGIC_MEM_PREFIX_STRS };
+ std::vector<std::string> llvmCallPrefixes;
+ for (std::vector<std::string>::iterator it = mmFuncPrefixes.begin(); it != mmFuncPrefixes.end(); ++it) {
+ llvmCallPrefixes.push_back(*it);
+ }
+ llvmCallPrefixes.push_back("");
+ llvmCallPrefixes.push_back("\01"); //llvm uses odd prefixes for some functions, sometimes (e.g. mmap64)
+ std::vector<MagicMemFunction> magicMemFunctions;
+ std::set<Function*> originalMagicMemFunctions;
+ for(i=0;magicMemFuncNames[i].compare("");i++) {
+ int allocFlags = magicMemFuncAllocFlags[i];
+ for(unsigned j=0;j<llvmCallPrefixes.size();j++) {
+ Function *f = M.getFunction(llvmCallPrefixes[j] + magicMemFuncNames[i]);
+ if(!f) {
+ continue;
+ }
+ TYPECONST FunctionType *fType = f->getFunctionType();
+ if(fType->getNumParams() == 0 && fType->isVarArg()) {
+ //missing function prototype, i.e. no realistic caller. Skip.
+ continue;
+ }
+ if(!magicMemFuncNames[i].compare("brk")) {
+ brkFunctions.insert(f);
+ }
+ if(!magicMemFuncNames[i].compare("sbrk")) {
+ sbrkFunctions.insert(f);
+ }
+ std::string wName, wName2;
+ Function *w = NULL, *w2 = NULL;
+ for(unsigned k=0;magicMemPrefixes[k].compare("");k++) {
+ wName = magicMemPrefixes[k] + magicMemFuncNames[i];
+ w = M.getFunction(wName);
+ if(w) {
+ wName2 = wName + "_";
+ break;
+ }
+ }
+ if(!w) {
+ magicPassErr("Error: no wrapper function found for " << magicMemFuncNames[i] << "()");
+ exit(1);
+ }
+ while(!isCompatibleMagicMemFuncType(f->getFunctionType(), w->getFunctionType()) && (w2 = M.getFunction(wName2))) {
+ w = w2;
+ wName2.append("_");
+ }
+ if(!isCompatibleMagicMemFuncType(f->getFunctionType(), w->getFunctionType())) {
+ magicPassErr("Error: wrapper function with incompatible type " << wName << "() found");
+ magicPassErr(TypeUtil::getDescription(f->getFunctionType(), MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL) << " != " << TypeUtil::getDescription(w->getFunctionType(), MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL));
+ exit(1);
+ }
+ bool isDeallocFunction = false;
+ for(unsigned j=0;magicMemDeallocFuncNames[j].compare("");j++) {
+ if(!magicMemDeallocFuncNames[j].compare(magicMemFuncNames[i])) {
+ isDeallocFunction = true;
+ break;
+ }
+ }
+ MagicMemFunction memFunction(M, f, w, isDeallocFunction, allocFlags);
+ magicMemFunctions.push_back(memFunction);
+ originalMagicMemFunctions.insert(f);
+
+#if DEBUG_ALLOC_LEVEL >= 1
+ magicPassErr("Memory management function/wrapper found: " << f->getName() << "()/" << w->getName() << "()");
+#endif
+ }
+ }
+
+ //look up custom memory management functions and build the corresponding wrappers
+ int stdAllocFlags = 0;
+ Function *stdAllocFunc, *stdAllocWrapperFunc;
+ stdAllocFunc = M.getFunction(MAGIC_MALLOC_FUNC_NAME);
+ assert(stdAllocFunc && "Could not find the standard allocation function.");
+ for(i=0;magicMemFuncNames[i].compare("");i++) {
+ if (!magicMemFuncNames[i].compare(MAGIC_MALLOC_FUNC_NAME)) {
+ stdAllocFlags = magicMemFuncAllocFlags[i];
+ break;
+ }
+ }
+ assert(magicMemFuncNames[i].compare("") && "Could not find the flags for the standard allocation function.");
+ std::string wName;
+ for(i=0;magicMemPrefixes[i].compare("");i++) {
+ wName = magicMemPrefixes[i] + MAGIC_MALLOC_FUNC_NAME;
+ stdAllocWrapperFunc = M.getFunction(wName);
+ if (stdAllocWrapperFunc) {
+ break;
+ }
+ }
+ assert(stdAllocWrapperFunc && "Could not find a wrapper for the standard allocation function.");
+ for (std::set<std::pair<std::string, std::string> >::iterator it = mmFuncPairs.begin(); it != mmFuncPairs.end(); ++it) {
+ std::vector<std::string> allocTokens;
+ PassUtil::parseStringListOpt(allocTokens, (*it).first, "/");
+ assert((allocTokens.size() == stdAllocFunc->getFunctionType()->getNumParams() + 1) && "Bad option format, format is: customFuncName/stdFuncArg1Mapping/.../stdFuncArgNMapping");
+
+ // build custom wrapper for the allocation function
+ Function *allocFunction = MagicUtil::getFunction(M, allocTokens[0]);
+ if (!allocFunction) {
+ continue;
+ }
+ std::vector<unsigned> allocArgMapping;
+ int param;
+ for (unsigned i = 0; i < stdAllocFunc->getFunctionType()->getNumParams(); i++) {
+ int ret = StringRef(allocTokens[i + 1]).getAsInteger(10, param);
+ assert(!ret && "Bad option format, format is: customFuncName/stdFuncArg1Mapping/.../stdFuncArgNMapping");
+ assert(param > 0 && "The numbering of function parameters starts from 1.");
+ allocArgMapping.push_back(param);
+ }
+ FunctionType *allocFuncType = getFunctionType(allocFunction->getFunctionType(), allocArgMapping);
+ if(!isCompatibleMagicMemFuncType(allocFuncType, stdAllocWrapperFunc->getFunctionType())) {
+ magicPassErr("Error: standard wrapper function " << stdAllocWrapperFunc->getName() << " has incompatible type.");
+ magicPassErr(TypeUtil::getDescription(allocFuncType, MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL) << " != " << TypeUtil::getDescription(stdAllocWrapperFunc->getFunctionType(), MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL));
+ exit(1);
+ }
+ Function *allocWrapper = MagicMemFunction::getCustomWrapper(allocFunction, stdAllocFunc, stdAllocWrapperFunc, allocArgMapping, false);
+
+ // register the wrapper
+ MagicMemFunction memFunctionAlloc(M, allocFunction, allocWrapper, false, stdAllocFlags);
+ magicMemFunctions.push_back(memFunctionAlloc);
+ originalMagicMemFunctions.insert(allocFunction);
+#if DEBUG_ALLOC_LEVEL >= 1
+ magicPassErr("Allocation function/custom wrapper added: " << allocFunction->getName() << "()/" << allocWrapper->getName() << "()");
+#endif
+ }
+
+ //lookup memory pool management functions and add the corresponding wrapper calls
+ int mempoolAllocFlags = MAGIC_STATE_HEAP;
+ Function *mempoolBlockAllocTemplate, *mempoolBlockAllocTemplateWrapper;
+ mempoolBlockAllocTemplate = MagicUtil::getFunction(M, MAGIC_MEMPOOL_BLOCK_ALLOC_TEMPLATE_FUNC_NAME);
+ assert(mempoolBlockAllocTemplate && "Could not find the pool block allocation template function.");
+ for(i = 0; magicMemPrefixes[i].compare(""); i++) {
+ wName = magicMemPrefixes[i] + MAGIC_MEMPOOL_BLOCK_ALLOC_TEMPLATE_FUNC_NAME;
+ mempoolBlockAllocTemplateWrapper = MagicUtil::getFunction(M, wName);
+ if (mempoolBlockAllocTemplateWrapper) {
+ break;
+ }
+ }
+ assert(mempoolBlockAllocTemplateWrapper && "Could not find a wrapper for the pool block allocation template function.");
+#define __X(P) #P
+ // C++11 Initializer Lists are not yet supported as of Clang 3.0 ...
+ std::pair<std::string, std::string> magicMempoolFuncNames[] = {
+ std::pair<std::string, std::string>(MAGIC_MEMPOOL_CREATE_FUNCS),
+ std::pair<std::string, std::string>(MAGIC_MEMPOOL_DESTROY_FUNCS),
+ std::pair<std::string, std::string>(MAGIC_MEMPOOL_MGMT_FUNCS),
+ std::pair<std::string, std::string>(MAGIC_MEMPOOL_RESET_FUNCS)
+ };
+#undef __X
+ int magicMempoolFuncFlags[] = { MAGIC_MEMPOOL_FUNC_FLAGS };
+ unsigned numMagicMempoolFuncPairs = sizeof(magicMempoolFuncNames) / sizeof(magicMempoolFuncNames[0]);
+ std::vector<std::pair<Function*, Function*> > magicMempoolFuncs(numMagicMempoolFuncPairs, std::pair<Function*, Function*>());
+ for (i = 0; i < numMagicMempoolFuncPairs; i++) {
+ magicMempoolFuncs[i].first = MagicUtil::getFunction(M, magicMempoolFuncNames[i].first);
+ if (!magicMempoolFuncs[i].first) {
+ magicPassErr("Could not find one of the memory pool wrapper functions: " + magicMempoolFuncNames[i].first);
+ exit(1);
+ }
+ magicMempoolFuncs[i].second = MagicUtil::getFunction(M, magicMempoolFuncNames[i].second);
+ if (!magicMempoolFuncs[i].second) {
+ magicPassErr("Could not find one of the memory pool wrapper functions: " + magicMempoolFuncNames[i].second);
+ exit(1);
+ }
+ }
+
+ std::vector<MagicDebugFunction> magicDebugFunctions;
+ if (mmPoolFunctions.size()) {
+ assert(mmPoolFunctions.size() >= 3 && mmPoolFunctions.size() <= 5 &&
+ "Specify at least 3 and at most 5 of the pool management types of functions: block alloc,pool create,pool destroy,pool management functions,pool reset functions.");
+ std::vector<std::string>::iterator mmPoolFuncsIt = mmPoolFunctions.begin();
+ std::vector<MagicMemFunction> mempoolMagicMemFunctions;
+
+ // memory pool block allocation functions
+ std::vector<std::string> mempoolBlockAllocFuncs;
+ PassUtil::parseStringListOpt(mempoolBlockAllocFuncs, *(mmPoolFuncsIt++), ";");
+
+ for (std::vector<std::string>::iterator funcIt = mempoolBlockAllocFuncs.begin(); funcIt != mempoolBlockAllocFuncs.end(); ++funcIt) {
+ std::vector<std::string> funcTokens;
+ PassUtil::parseStringListOpt(funcTokens, *funcIt, "/");
+ assert(funcTokens.size() == 3 && "Bad option format, format is: block_alloc_func/pool_ptr_arg_number/size_arg_number");
+ Function* blockAllocFunc = MagicUtil::getFunction(M, funcTokens[0]);
+ if (!blockAllocFunc) {
+ magicPassErr("Memory pool block allocation function not found - " + funcTokens[0] + ". Skipping instrumentation!");
+ mempoolMagicMemFunctions.clear();
+ break;
+ }
+ std::vector<unsigned> argMapping;
+ unsigned param;
+ for (unsigned i = 1; i < funcTokens.size(); i++) {
+ assert(!StringRef(funcTokens[i]).getAsInteger(10, param) && "Bad option format, format is: block_alloc_func/pool_ptr_arg_number/size_arg_number");
+ assert(param > 0 && param <= blockAllocFunc->getFunctionType()->getNumParams()
+ && "Bad option format. The function parameter number is not valid.");
+ argMapping.push_back(param);
+ }
+ FunctionType *blockAllocFuncType = getFunctionType(mempoolBlockAllocTemplate->getFunctionType(), argMapping);
+ if(!isCompatibleMagicMemFuncType(blockAllocFuncType, mempoolBlockAllocTemplateWrapper->getFunctionType())) {
+ magicPassErr("Error: standard wrapper function " << mempoolBlockAllocTemplateWrapper->getName() << " has incompatible type.");
+ magicPassErr(TypeUtil::getDescription(blockAllocFuncType, MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL) << " != " << TypeUtil::getDescription(mempoolBlockAllocTemplateWrapper->getFunctionType(), MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL));
+ exit(1);
+ }
+ Function *blockAllocWrapper = MagicMemFunction::getCustomWrapper(blockAllocFunc, mempoolBlockAllocTemplate, mempoolBlockAllocTemplateWrapper, argMapping, false);
+ MagicMemFunction memFunctionBlockAlloc(M, blockAllocFunc, blockAllocWrapper, false, mempoolAllocFlags);
+ mempoolMagicMemFunctions.push_back(memFunctionBlockAlloc);
+ }
+ if (!mempoolMagicMemFunctions.empty()) { // only if the block allocation functions have been successfully processed
+ // continue with the rest of the memory pool management functions, which do not require a magic wrapper
+ std::vector<std::vector<Function*> >::iterator magicMempoolFuncIt;
+ std::vector<std::vector<int> >::iterator magicMempoolFuncFlagsIt;
+ for (unsigned magicMempoolFuncIndex = 1; mmPoolFuncsIt != mmPoolFunctions.end(); ++mmPoolFuncsIt, ++magicMempoolFuncIndex) {
+ std::vector<std::string> mempoolMgmtFuncs;
+ PassUtil::parseStringListOpt(mempoolMgmtFuncs, *mmPoolFuncsIt, ";");
+ for (std::vector<std::string>::iterator funcIt = mempoolMgmtFuncs.begin(); funcIt != mempoolMgmtFuncs.end(); ++funcIt) {
+ std::vector<std::string> funcTokens;
+ PassUtil::parseStringListOpt(funcTokens, *funcIt, "/");
+ assert(funcTokens.size() == 2 && "Bad option format, format is: mempool_mgmt_func/pool_ptr_arg_number");
+ Function* mempoolMgmtFunc = MagicUtil::getFunction(M, funcTokens[0]);
+ assert(mempoolMgmtFunc && "Bad memory pool configuration, instrumentation aborted!");
+ std::vector<unsigned> argMapping;
+ unsigned param;
+ for (unsigned i = 1; i < funcTokens.size(); i++) {
+ assert(!StringRef(funcTokens[i]).getAsInteger(10, param) && "Bad option format, format is: mempool_mgmt_func/pool_ptr_arg_number");
+ assert(param <= mempoolMgmtFunc->getFunctionType()->getNumParams() &&
+ "Bad option format. The function parameter number is not valid.");
+ argMapping.push_back(param);
+ }
+ std::vector<Value*> trailingArgs;
+ if (magicMempoolFuncIndex == 1) { // pool create funcs
+ TYPECONST Type* poolType = mempoolMgmtFunc->getFunctionType()->getContainedType(argMapping[0]);
+ int level = MagicUtil::getPointerIndirectionLevel(poolType);
+ trailingArgs.push_back(ConstantInt::get(Type::getInt32Ty(M.getContext()), (level > 1)));
+ } else if (magicMempoolFuncIndex == 2) { // pool destroy funcs
+ trailingArgs.push_back(ConstantInt::get(Type::getInt32Ty(M.getContext()), (EnablePoolMemReuse ? 1 : 0)));
+ }
+ if (magicMempoolFuncFlags[magicMempoolFuncIndex - 1] & MAGIC_HOOK_DEBUG_MASK) {
+ MagicDebugFunction magicDebugFunction(mempoolMgmtFunc);
+ magicDebugFunction.addHooks(magicMempoolFuncs[magicMempoolFuncIndex - 1], magicMempoolFuncFlags[magicMempoolFuncIndex - 1], argMapping, trailingArgs);
+ magicDebugFunctions.push_back(magicDebugFunction);
+ } else {
+ bool ret = MagicDebugFunction::inlineHookCalls(mempoolMgmtFunc,
+ magicMempoolFuncs[magicMempoolFuncIndex - 1], magicMempoolFuncFlags[magicMempoolFuncIndex - 1], argMapping, trailingArgs);
+ if (!ret) {
+ magicPassErr("Unable to inline wrapper function calls for " + funcTokens[0]);
+ exit(1);
+ }
+ }
+ }
+ }
+ for (std::vector<MagicMemFunction>::iterator magicIt = mempoolMagicMemFunctions.begin(); magicIt != mempoolMagicMemFunctions.end(); ++magicIt) {
+ magicMemFunctions.push_back(*magicIt);
+ originalMagicMemFunctions.insert(magicIt->getFunction());
+ }
+ }
+ }
+
+ //lookup mmap ctl functions whose call arguments need to be fixed
+ std::vector<MagicMmapCtlFunction> magicMmapCtlFunctions;
+ for (std::vector<std::string>::iterator it = mmapCtlFunctions.begin(); it != mmapCtlFunctions.end(); ++it) {
+ std::vector<std::string> tokens;
+ tokens.clear();
+ PassUtil::parseStringListOpt(tokens, *it, "/");
+ assert(tokens.size() == 3 && "Bad option format, format is: function/[ptr_arg_name]/[len_arg_name]");
+
+ Function *function = M.getFunction(tokens[0]);
+ if(!function) {
+ continue;
+ }
+ std::string &ptrArgName = tokens[1];
+ std::string &lenArgName = tokens[2];
+ MagicMmapCtlFunction magicMmapCtlFunction(function, PointerType::get(IntegerType::get(M.getContext(), 8), 0), ptrArgName, lenArgName);
+ magicMmapCtlFunctions.push_back(magicMmapCtlFunction);
+ }
+#endif
+
+ //everything as expected, set magic enabled variable to TRUE
+ magicEnabled->setInitializer(ConstantInt::get(M.getContext(), APInt(32, 1)));
+
+ //scan the list of global variables
+ unsigned strGlobalVariables = 0;
+ unsigned constGlobalVariables = 0;
+ for (Module::global_iterator it = globalList.begin(); it != globalList.end(); ++it) {
+ GlobalVariable *GV = it;
+ StringRef GVName = GV->getName();
+ TYPECONST Type *GVType = GV->getType()->getElementType();
+ bool isPrimitiveOrPointerType = !GVType->isAggregateType();
+ DATA_LAYOUT_TY DL = DATA_LAYOUT_TY(&M);
+ bool isExternal = GV->hasExternalLinkage() || GV->hasExternalWeakLinkage();
+ int typeSize = isExternal ? 0 : DL.getTypeSizeInBits(GVType)/8;
+ int align = MAGIC_FORCE_ALIGN;
+
+ if(isMagicGV(M, GV)) {
+ magicPassLog("Skipping magic variable: " << GVName);
+ continue;
+ }
+ assert(!MAGIC_STRINGREF_HAS_MAGIC_HIDDEN_PREFIX(GVName));
+ if(GVName.startswith("C.")) {
+ //LLVM code we are not interested in
+ continue;
+ }
+ if(MagicUtil::isLocalConstant(M, GV)) {
+ //Local constants we are not interested in
+ continue;
+ }
+#if GLOBAL_VARS_IN_SECTION
+ MagicUtil::setGlobalVariableSection(GV, GV->isConstant() ? GLOBAL_VARS_SECTION_RO : GLOBAL_VARS_SECTION_DATA);
+#endif
+ if(GVName.startswith(".str")) {
+ assert(GV->hasInitializer());
+#if LLVM_VERSION >= 31
+ /* XXX Check. */
+ ConstantDataArray *initializer = dyn_cast<ConstantDataArray>(GV->getInitializer());
+#else
+ ConstantArray *initializer = dyn_cast<ConstantArray>(GV->getInitializer());
+#endif
+ if(initializer) {
+ assert(initializer->isString());
+ MagicUtil::putStringRefCache(M, initializer->getAsString(), GV);
+ }
+ else {
+ MagicUtil::putStringRefCache(M, "", GV);
+ }
+
+ strGlobalVariables++;
+ Value *stringOwner = MagicUtil::getStringOwner(GV);
+ if(stringOwner) {
+ GlobalVariable *GVOwner = dyn_cast<GlobalVariable>(stringOwner);
+ AllocaInst *AIOwner = dyn_cast<AllocaInst>(stringOwner);
+ assert(GVOwner || AIOwner);
+ bool stringOwnerFound = false;
+ std::string ownerName;
+ raw_string_ostream ostream(ownerName);
+ if(GVOwner && !isMagicGV(M, GVOwner)) {
+ ostream << "#" << MagicUtil::getGVSourceName(M, GVOwner, NULL, baseBuildDir);
+ stringOwnerFound = true;
+ }
+ else if(AIOwner && !isMagicFunction(M, AIOwner->getParent()->getParent())) {
+ ostream << MagicUtil::getFunctionSourceName(M, AIOwner->getParent()->getParent(), NULL, baseBuildDir) << "#" << MagicUtil::getLVSourceName(M, AIOwner);
+ stringOwnerFound = true;
+ }
+ if(stringOwnerFound) {
+ ostream.flush();
+ stringOwnerMapIt = stringOwnerMap.find(ownerName);
+ if(stringOwnerMapIt == stringOwnerMap.end()) {
+ stringOwnerMap.insert(std::pair<std::string, GlobalVariable*>(ownerName, GV));
+ stringOwnerInvertedMap.insert(std::pair<GlobalVariable*, std::string>(GV, ownerName));
+ }
+ else {
+ stringOwnerInvertedMapIt = stringOwnerInvertedMap.find(stringOwnerMapIt->second);
+ if(stringOwnerInvertedMapIt != stringOwnerInvertedMap.end()) {
+ stringOwnerInvertedMap.erase(stringOwnerInvertedMapIt);
+ }
+ }
+ }
+ }
+ }
+ else if(GV->isConstant()) {
+ constGlobalVariables++;
+ }
+ if(!isPrimitiveOrPointerType && align) {
+ GV->setAlignment(align);
+ if(typeSize % align) {
+ typeSize = typeSize - (typeSize % align) + align;
+ }
+ }
+ else if(MAGIC_OFF_BY_N_PROTECTION_N && GVType->isArrayTy() && typeSize>0) {
+ unsigned alignment = typeSize + (DL.getTypeSizeInBits(GVType->getContainedType(0))/8) * MAGIC_OFF_BY_N_PROTECTION_N;
+ unsigned a = 2;
+ while(a < alignment) a = a << 1;
+ GV->setAlignment(a);
+ }
+ globalVariableSizes.push_back(typeSize);
+ globalVariables.push_back(GV);
+ if(MagicUtil::hasAddressTaken(GV)) {
+ globalVariablesWithAddressTaken.insert(GV);
+ }
+ }
+ magicPassLog(">>>> Number of global variables found: " << globalVariables.size() << " of which " << strGlobalVariables << " .str variables, " << constGlobalVariables << " constants, and " << globalVariables.size()-strGlobalVariables-constGlobalVariables << " regular variables");
+
+ //build the list of functions having their address taken (include the last function no matter what to get the function ranges right)
+ std::vector<const SmartType *> functionTypes;
+ std::vector<GlobalValue *> functionTypeParents;
+ std::vector<TYPECONST FunctionType *> externalFunctionTypes;
+ std::vector<GlobalValue *> externalFunctionTypeParents;
+ for (Module::iterator it = functionList.begin(); it != functionList.end(); ++it) {
+ Function *F = it;
+ if(F->hasAddressTaken() || it == --functionList.end() || F->getName().startswith(MAGIC_EVAL_FUNC_PREFIX)) {
+ if(isMagicFunction(M, F)) {
+ continue;
+ }
+ functions.push_back(F);
+ const SmartType *FSmartType = SmartType::getSmartTypeFromFunction(M, F);
+ if(FSmartType && !FSmartType->isTypeConsistent()) {
+ delete FSmartType;
+ //pretend the function is external if an invalid type has been found.
+ FSmartType = NULL;
+ }
+ if(!FSmartType) {
+ externalFunctionTypes.push_back(F->getFunctionType());
+ externalFunctionTypeParents.push_back(F);
+ }
+ else {
+ functionTypes.push_back(FSmartType);
+ functionTypeParents.push_back(F);
+ }
+ }
+ }
+ magicPassLog(">>>> Number of functions with address taken found: " << functions.size() << ", of which " << functionTypes.size() << " internal and " << externalFunctionTypes.size() << " external...");
+
+ //build the list of global types
+ std::vector<const SmartType *> smartTypes;
+ std::vector<GlobalValue *> smartTypeParents;
+ std::vector<TYPECONST Type *> externalTypes;
+ std::vector<GlobalValue *> externalTypeParents;
+ for(i=0;i<globalVariables.size();i++) {
+ GlobalVariable *GV = globalVariables[i];
+ TYPECONST Type* GVType = GV->getType()->getElementType();
+
+ const SmartType *GVSmartType = SmartType::getSmartTypeFromGV(M, GV);
+
+ if(!GV->hasAppendingLinkage()){
+ // llvm.global_ctors and llvm.global_dtors have appending linkage, don't have compile unit debug info, and therefore cannot be linked to GV debug info, and so are skipped.
+ if(!GVSmartType) {
+ bool isExternal = GV->hasExternalLinkage() || GV->hasExternalWeakLinkage();
+ if (!isExternal && !GV->isConstant()) {
+ magicPassErr("var is: " << GV->getName());
+ magicPassErr("type is: " << TypeUtil::getDescription(GV->getType()->getElementType(), MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL));
+ }
+ assert(isExternal || GV->isConstant());
+ externalTypes.push_back(GVType);
+ externalTypeParents.push_back(GV);
+ }
+ else {
+ smartTypes.push_back(GVSmartType);
+ smartTypeParents.push_back(GV);
+ }
+ }
+ }
+ magicPassLog(">>>> Number of global types found: " << globalVariables.size() << ", of which " << smartTypes.size() << " internal and " << externalTypes.size() << " external...");
+
+ //build type infos
+ TypeInfo* magicVoidPtrTypeInfo = NULL;
+ TypeInfo* magicVoidArrTypeInfo = NULL;
+ TypeInfo* magicVoidTypeInfo = NULL;
+ for(i=0;i<smartTypes.size();i++) {
+ TypeInfo sourceTypeInfo(smartTypes[i]);
+ sourceTypeInfo.addParent(smartTypeParents[i]);
+ TypeInfo *aTypeInfo = fillTypeInfos(sourceTypeInfo, globalTypeInfos);
+ if(smartTypeParents[i] == magicVoidPtr) {
+ //get a pointer to void and void* types
+ magicVoidPtrTypeInfo = aTypeInfo;
+ assert(magicVoidPtrTypeInfo->getTypeID() == MAGIC_TYPE_POINTER);
+ magicVoidTypeInfo = magicVoidPtrTypeInfo->getContainedType(0);
+ assert(magicVoidTypeInfo->getTypeID() == MAGIC_TYPE_VOID);
+ }
+ else if(smartTypeParents[i] == magicVoidArr) {
+ //get a pointer to void array types
+ magicVoidArrTypeInfo = aTypeInfo;
+ assert(magicVoidArrTypeInfo->getTypeID() == MAGIC_TYPE_ARRAY);
+ }
+ }
+ assert(magicVoidPtrTypeInfo && magicVoidTypeInfo && magicVoidArrTypeInfo);
+ std::vector<TypeInfo*> magicVoidTypeInfoArr;
+ magicVoidTypeInfoArr.push_back(magicVoidTypeInfo);
+ magicVoidArrTypeInfo->setContainedTypes(magicVoidTypeInfoArr);
+ magicPassLog(">>>> Number of types found: " << globalTypeInfos.size());
+ for(i=0;i<functionTypes.size();i++) {
+ TypeInfo sourceTypeInfo(functionTypes[i]);
+ sourceTypeInfo.addParent(functionTypeParents[i]);
+ fillTypeInfos(sourceTypeInfo, globalTypeInfos);
+ }
+ magicPassLog(">>>> Number of types + function types found: " << globalTypeInfos.size());
+
+ //add external function types
+ for(i=0;i<externalFunctionTypes.size();i++) {
+ TypeInfo sourceTypeInfo(externalFunctionTypes[i]);
+ sourceTypeInfo.addParent(externalFunctionTypeParents[i]);
+ fillTypeInfos(sourceTypeInfo, globalTypeInfos);
+ }
+ magicPassLog(">>>> Number of types + function types + external function types found: " << globalTypeInfos.size());
+
+ //add external variable types
+ for(i=0;i<externalTypes.size();i++) {
+ TypeInfo* aTypeInfo = fillExternalTypeInfos(externalTypes[i], externalTypeParents[i], globalTypeInfos);
+ if(aTypeInfo == NULL) {
+ magicPassErr("var is: " << externalTypeParents[i]->getName());
+ magicPassErr("type is: " << TypeUtil::getDescription(externalTypes[i], MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL));
+ }
+ assert(aTypeInfo != NULL && "External type not supported!");
+ }
+ magicPassLog(">>>> Number of types + external types + function types + external function types found: " << globalTypeInfos.size());
+
+ //process types, split them when some parent has a valid value set
+ std::vector<TypeInfo*> splitTypeInfos;
+ for(i=0;i<globalTypeInfos.size();i++) {
+ bool isTypeInfoSplit = globalTypeInfos[i]->splitByParentValueSet(splitTypeInfos, globalVariablesWithAddressTaken);
+ if(isTypeInfoSplit) {
+#if DEBUG_VALUE_SET
+ unsigned splitTypeInfosSize = splitTypeInfos.size();
+ errs() << "MagicPass: Found type info split with different parents and value sets: original type is: " << globalTypeInfos[i]->getDescription() << ", type splits are:\n";
+ for(unsigned j=splitTypeInfosSize;j<splitTypeInfos.size();j++) {
+ errs() << " - value set is: [ ";
+ std::vector<int> valueSet = splitTypeInfos[j]->getValueSet();
+ for(unsigned k=1;k<valueSet.size();k++) {
+ errs() << (k==1 ? "" : ", ") << valueSet[k];
+ }
+ errs() << " ], parents are: [ ";
+ std::vector<GlobalValue*> parents = splitTypeInfos[j]->getParents();
+ for(unsigned k=0;k<parents.size();k++) {
+ errs() << (k==0 ? "" : ", ") << parents[k]->getName();
+ }
+ errs() << " ]\n";
+ }
+#endif
+ }
+ }
+
+ //index type parents
+ globalTypeInfos.clear();
+ for(i=0;i<splitTypeInfos.size();i++) {
+ TypeInfo *aTypeInfo = splitTypeInfos[i];
+ std::vector<GlobalValue*> parents = aTypeInfo->getParents();
+ for(unsigned j=0;j<parents.size();j++) {
+ parentMapIt = globalParentMap.find(parents[j]);
+ assert(parentMapIt == globalParentMap.end());
+ globalParentMap.insert(std::pair<GlobalValue*, TypeInfo*>(parents[j], aTypeInfo));
+ }
+ globalTypeInfos.push_back(aTypeInfo);
+ }
+
+ std::vector< TypeInfo* > magicDsindexTypeInfoList;
+ std::vector< std::pair<std::string,std::string> > magicDsindexNamesList;
+ std::vector<int> magicDsindexFlagsList;
+
+#if MAGIC_INSTRUMENT_MEM_FUNCS
+ //gather magic memory function calls to replace and figure out the type (adding more (local) types if needed)
+ std::vector<MagicMemFunction> magicMemFunctionCalls;
+ std::map< std::pair<std::string,std::string>, int> namesMap;
+ int allocFlags;
+ std::set<Function*> extendedMagicMemFunctions;
+ for (std::set<Function*>::iterator it = originalMagicMemFunctions.begin(); it != originalMagicMemFunctions.end(); ++it) {
+ PassUtil::getFunctionsInDirectBUCallgraph(*it, extendedMagicMemFunctions);
+ }
+ while(!magicMemFunctions.empty()) {
+ MagicMemFunction magicMemFunction = magicMemFunctions.front();
+ magicMemFunctions.erase(magicMemFunctions.begin());
+ std::vector<User*> Users(magicMemFunction.getFunction()->use_begin(), magicMemFunction.getFunction()->use_end());
+ std::vector<Value*> EqPointers;
+ while (!Users.empty()) {
+ int annotation;
+ User *U = Users.back();
+ Users.pop_back();
+
+ if (Instruction *I = dyn_cast<Instruction>(U)) {
+ Function *parent = I->getParent()->getParent();
+ if (isMagicFunction(M, parent) || MagicMemFunction::isCustomWrapper(parent)) {
+ continue;
+ }
+ CallSite CS = MagicUtil::getCallSiteFromInstruction(I);
+ if (CS.getInstruction() &&
+ (!CS.arg_empty() || magicMemFunction.getWrapper() == NULL) &&
+ (MagicUtil::getCalledFunctionFromCS(CS) == magicMemFunction.getFunction() ||
+ std::find(EqPointers.begin(), EqPointers.end(),
+ CS.getCalledValue()) != EqPointers.end())) {
+ bool isDeallocFunction = magicMemFunction.isDeallocFunction();
+ bool wrapParent = false;
+ TypeInfo *typeInfo = magicVoidTypeInfo;
+ std::string allocName = "";
+ std::string allocParentName = "";
+ //check if we have to skip
+ if(extendedMagicMemFunctions.find(CS.getInstruction()->getParent()->getParent()) != extendedMagicMemFunctions.end()) {
+ //this call site is only called from some predefined mem function. skip.
+ continue;
+ }
+ if(sbrkFunctions.find(MagicUtil::getCalledFunctionFromCS(CS)) != sbrkFunctions.end()) {
+ ConstantInt *arg = dyn_cast<ConstantInt>(CS.getArgument(0));
+ if(arg && arg->getZExtValue() == 0) {
+ //ignore sbrk(0) calls. This does not skip calls with a variable argument (when arg == NULL)
+#if DEBUG_ALLOC_LEVEL >= 1
+ magicPassErr("Skipping instrumentation of sbrk(0) MM call found in " << parent->getName() << "():");
+ I->print(errs());
+ errs() << "\n";
+#endif
+ continue;
+ }
+ }
+ else if(MagicUtil::getCallAnnotation(M, CS, &annotation)
+ && annotation == MAGIC_CALL_MEM_SKIP_INSTRUMENTATION) {
+ //ignore calls we are supposed to skip
+#if DEBUG_ALLOC_LEVEL >= 1
+ magicPassErr("Skipping instrumentation of annotated MM call found in " << parent->getName() << "():");
+ I->print(errs());
+ errs() << "\n";
+#endif
+ continue;
+ }
+ //figure out the type and the names
+ if(!isDeallocFunction) {
+ int allocCounter = 1;
+ int ret;
+ std::map< std::pair<std::string,std::string>, int>::iterator namesMapIt;
+ //get alloc types and names
+ TypeInfo *allocTypeInfo = getAllocTypeInfo(M, magicVoidPtrTypeInfo, CS, allocName, allocParentName);
+#if !MAGIC_INSTRUMENT_MEM_CUSTOM_WRAPPERS
+ if(!allocTypeInfo) {
+ allocTypeInfo = voidTypeInfo;
+ }
+#endif
+ if(allocTypeInfo) {
+ typeInfo = allocTypeInfo;
+ }
+ else {
+ int pointerParam = MagicMemFunction::getMemFunctionPointerParam(I->getParent()->getParent(), brkFunctions, magicVoidPtrTypeInfo);
+ if(pointerParam >= 0 /* && !I->getParent()->getParent()->hasAddressTaken() */) {
+ //the parent is a valid magic mem function to wrap
+ wrapParent = true;
+ }
+ }
+ if(!wrapParent) {
+ assert(allocParentName.compare("") && "Empty parent name!");
+ if(!allocName.compare("")) {
+ allocName = MAGIC_ALLOC_NONAME;
+ }
+
+#if (MAGIC_NAMED_ALLOC_USE_DBG_INFO || (MAGIC_MEM_USAGE_OUTPUT_CTL == 1))
+ //extend names with debug information when requested
+ if (MDNode *N = I->getMetadata("dbg")) {
+ DILocation Loc(N);
+ std::string string;
+ raw_string_ostream ostream(string);
+ ostream << allocName << MAGIC_ALLOC_NAME_SEP << Loc.getFilename() << MAGIC_ALLOC_NAME_SEP << Loc.getLineNumber();
+ ostream.flush();
+ allocName = string;
+ }
+#endif
+
+#if MAGIC_FORCE_ALLOC_EXT_NAMES
+ if (isExtLibrary(parent, NULL)) {
+ allocName = MAGIC_ALLOC_EXT_NAME;
+ allocName = MAGIC_ALLOC_EXT_PARENT_NAME;
+ }
+#endif
+
+ //avoid duplicates
+ namesMapIt = namesMap.find(std::pair<std::string, std::string>(allocParentName, allocName));
+ if(namesMapIt != namesMap.end()) {
+ allocCounter = namesMapIt->second + 1;
+ ret = namesMap.erase(std::pair<std::string, std::string>(allocParentName, allocName));
+ assert(ret == 1);
+ namesMap.insert(std::pair<std::pair<std::string, std::string>, int>(std::pair<std::string, std::string>(allocParentName, allocName), allocCounter));
+ std::string string;
+ raw_string_ostream ostream(string);
+ ostream << allocName << MAGIC_ALLOC_NAME_SUFFIX << allocCounter;
+ ostream.flush();
+ allocName = string;
+ }
+ else {
+ namesMap.insert(std::pair<std::pair<std::string, std::string>, int>(std::pair<std::string, std::string>(allocParentName, allocName), allocCounter));
+ allocName += MAGIC_ALLOC_NAME_SUFFIX;
+ }
+ magicMemFunction.setInstructionTypeInfo(typeInfo, allocName, allocParentName);
+ //add dsindex entries
+ magicDsindexTypeInfoList.push_back(typeInfo);
+ magicDsindexNamesList.push_back(std::pair<std::string, std::string>(allocParentName, allocName));
+ allocFlags = magicMemFunction.getAllocFlags();
+ assert(allocFlags);
+ magicDsindexFlagsList.push_back(allocFlags);
+ }
+ }
+ magicMemFunction.setInstruction(I);
+ Function *instructionParent = I->getParent()->getParent();
+ //see if we can find the parent in our lists
+ MagicMemFunction *magicMemParent = NULL;
+ for(unsigned k=0;k<magicMemFunctions.size();k++) {
+ if(magicMemFunctions[k].getFunction() == instructionParent) {
+ magicMemParent = &magicMemFunctions[k];
+ break;
+ }
+ }
+ if(!magicMemParent) {
+ for(unsigned k=0;k<magicMemFunctionCalls.size();k++) {
+ if(magicMemFunctionCalls[k].getFunction() == instructionParent) {
+ magicMemParent = &magicMemFunctionCalls[k];
+ break;
+ }
+ }
+ }
+ if(!magicMemParent && wrapParent) {
+ //if there is no existing parent but we have to wrap the parent, create a parent now and add it to the function queue
+ MagicMemFunction newMagicMemFunction(M, instructionParent, NULL, false, 0);
+ magicMemFunctions.push_back(newMagicMemFunction);
+ magicMemParent = &magicMemFunctions[magicMemFunctions.size()-1];
+ }
+ if(magicMemParent) {
+ //if we have a parent, add a dependency
+ magicMemParent->addInstructionDep(magicMemFunction);
+ assert(magicMemParent->getAllocFlags());
+
+ }
+ else {
+ //if there is no parent, add it to the call queue
+ magicMemFunctionCalls.push_back(magicMemFunction);
+ }
+ }
+ } else if (GlobalValue *GV = dyn_cast<GlobalValue>(U)) {
+ Users.insert(Users.end(), GV->use_begin(), GV->use_end());
+ EqPointers.push_back(GV);
+ } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(U)) {
+ if (CE->isCast()) {
+ Users.insert(Users.end(), CE->use_begin(), CE->use_end());
+ EqPointers.push_back(CE);
+ }
+ }
+ }
+ }
+#endif
+
+#if MAGIC_INSTRUMENT_STACK
+ std::vector<std::map<AllocaInst*, std::pair<TypeInfo*, std::string> > > localTypeInfoMaps;
+ std::map<AllocaInst*, std::pair<TypeInfo*, std::string> > localTypeInfoMap;
+ std::vector<Function*> stackIntrumentedFuncs;
+ fillStackInstrumentedFunctions(stackIntrumentedFuncs, deepestLLFunction);
+ std::string stackIntrumentedFuncsStr;
+ for(i=0;i<stackIntrumentedFuncs.size();i++) {
+ localTypeInfoMap.clear();
+ indexLocalTypeInfos(M, stackIntrumentedFuncs[i], localTypeInfoMap);
+ localTypeInfoMaps.push_back(localTypeInfoMap);
+ stackIntrumentedFuncsStr += (i==0 ? "" : ", ") + stackIntrumentedFuncs[i]->getName().str() + "()";
+ }
+ magicPassLog(">>>> Set of stack-instrumented functions expanded from function " << deepestLLFunction->getName() << "(): " << stackIntrumentedFuncsStr);
+ magicPassLog(">>>> Number of types + external types + function types + external function types + local types found: " << globalTypeInfos.size());
+#endif
+
+ //add raw types
+ std::vector<TypeInfo*> rawTypeInfos;
+ for(i=0;i<globalTypeInfos.size();i++) {
+ TypeInfo* aTypeInfo = globalTypeInfos[i];
+ if(!aTypeInfo->hasRawTypeRepresentation()) {
+ continue;
+ }
+ assert(aTypeInfo->getNumContainedTypes() == 0);
+ TypeInfo* aRawTypeInfo = new TypeInfo(*magicVoidArrTypeInfo);
+ aRawTypeInfo->setPersistent();
+ aRawTypeInfo->removeAllParents();
+ rawTypeInfos.push_back(aRawTypeInfo);
+ std::vector<TypeInfo*> aTypeInfoContainedTypes;
+ aTypeInfoContainedTypes.push_back(aRawTypeInfo);
+ aTypeInfo->setContainedTypes(aTypeInfoContainedTypes);
+ assert(aTypeInfo->getContainedType(0)->getContainedType(0) == magicVoidTypeInfo);
+ }
+ for(i=0;i<rawTypeInfos.size();i++) {
+ globalTypeInfos.push_back(rawTypeInfos[i]);
+ assert(rawTypeInfos[i]->getNumContainedTypes() == 1);
+ }
+ magicPassLog(">>>> Number of types + external types + function types + external function types + local types found + raw types: " << globalTypeInfos.size());
+
+ //find max recursive sequence length
+ unsigned length, maxRecursiveSequenceLength = 0;
+ for(i=0;i<globalTypeInfos.size();i++) {
+ if(globalTypeInfos[i]->getParents().size() > 0) {
+ length = getMaxRecursiveSequenceLength(globalTypeInfos[i]);
+ if(length > maxRecursiveSequenceLength) {
+ maxRecursiveSequenceLength = length;
+ }
+ }
+ }
+ magicPassLog(">>>> Max recursive sequence length: " << maxRecursiveSequenceLength);
+
+ //debug type infos when needed
+#if DEBUG_TYPE_INFOS
+ for(i=0;i<globalTypeInfos.size();i++) {
+ std::vector<GlobalValue*> parents = globalTypeInfos[i]->getParents();
+ if(parents.size() > 0) {
+ std::string parentString, typeString;
+ for(unsigned j=0;j<parents.size();j++) {
+ parentString.append((j>0 ? ", " : "") + parents[j]->getName().str());
+ }
+ typeString = globalTypeInfos[i]->getDescription();
+ magicPassErr(" Global type group found, parents=( " << parentString << "), type=" << typeString << ", name=" << globalTypeInfos[i]->getName() << ", names_string=" << globalTypeInfos[i]->getNamesString());
+ if(DEBUG_TYPE_INFOS >= 2) {
+ printInterestingTypes(globalTypeInfos[i]);
+ }
+ }
+ }
+ for(i=0;i<globalTypeInfos.size();i++) {
+ std::string name = globalTypeInfos[i]->getName();
+ if(name.compare("")) {
+ magicPassErr(" Named type found: " << name << " (names string: " << globalTypeInfos[i]->getNamesString() << ", id: " << i << ")");
+ }
+ }
+#endif
+
+#if DEBUG_DUPLICATED_TYPE_INFOS
+ std::map<std::string, TypeInfo*> duplicatedTypeInfoMap;
+ std::map<std::string, TypeInfo*>::iterator duplicatedTypeInfoMapIt;
+ for(i=0;i<globalTypeInfos.size();i++) {
+ if(globalTypeInfos[i]->getType()->isStructTy()) {
+ std::string name = globalTypeInfos[i]->getName();
+ if(!name.compare("")) {
+ continue;
+ }
+ duplicatedTypeInfoMapIt = duplicatedTypeInfoMap.find(name);
+ if(duplicatedTypeInfoMapIt != duplicatedTypeInfoMap.end()) {
+ magicPassErr("Duplicated struct name found: " << name << ": " << globalTypeInfos[i]->getVerboseDescription() << " != " << (duplicatedTypeInfoMapIt->second)->getVerboseDescription());
+ }
+ else {
+ duplicatedTypeInfoMap.insert(std::pair<std::string, TypeInfo*>(name, globalTypeInfos[i]));
+ }
+ }
+ }
+#endif
+
+ //allocate magic type array
+ ArrayType* magicTypeArrayType = ArrayType::get(magicTypeStructType, globalTypeInfos.size());
+ magicTypeArray = new GlobalVariable(M, magicTypeArrayType, false, GlobalValue::InternalLinkage, ConstantAggregateZero::get(magicTypeArrayType), MAGIC_TYPE_ARRAY_NAME);
+ MagicUtil::setGlobalVariableSection(magicTypeArray, MAGIC_STATIC_VARS_SECTION_DATA);
+
+ //allocate magic array
+ ArrayType* magicArrayType = ArrayType::get(magicStructType, globalVariables.size());
+ magicArray = new GlobalVariable(M, magicArrayType, false, GlobalValue::InternalLinkage, ConstantAggregateZero::get(magicArrayType), MAGIC_ARRAY_NAME);
+ MagicUtil::setGlobalVariableSection(magicArray, MAGIC_STATIC_VARS_SECTION_DATA);
+
+ //allocate magic function array
+ ArrayType* magicFunctionArrayType = ArrayType::get(magicFunctionStructType, functions.size());
+ magicFunctionArray = new GlobalVariable(M, magicFunctionArrayType, false, GlobalValue::InternalLinkage, ConstantAggregateZero::get(magicFunctionArrayType), MAGIC_FUNC_ARRAY_NAME);
+ MagicUtil::setGlobalVariableSection(magicFunctionArray, MAGIC_STATIC_VARS_SECTION_DATA);
+
+ //build magic type array in build function
+ i=0;
+ std::map<TypeInfo*, Constant*> magicArrayTypePtrMap;
+ std::map<TypeInfo*, Constant*>::iterator magicArrayTypePtrMapIt;
+ std::map<TypeInfo*, unsigned> magicArrayTypeIndexMap;
+ std::map<TypeInfo*, unsigned>::iterator magicArrayTypeIndexMapIt;
+ std::vector<Value*> arrayIndexes;
+ for(;i<globalTypeInfos.size();i++) {
+ TypeInfo* aTypeInfo = globalTypeInfos[i];
+ TYPECONST Type *aType = aTypeInfo->getType();
+ arrayIndexes.clear();
+ arrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(64, 0, 10))); //pointer to A[]
+ arrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(64, i, 10))); //pointer to A[index]
+ Constant* magicTypeArrayPtr = MagicUtil::getGetElementPtrConstant(magicTypeArray, arrayIndexes);
+ magicArrayTypePtrMap.insert(std::pair<TypeInfo*, Constant*>(aTypeInfo, magicTypeArrayPtr));
+ magicArrayTypeIndexMap.insert(std::pair<TypeInfo*, unsigned>(aTypeInfo, i));
+
+ //storing id field
+ Value* structIdField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_ID);
+ Constant* idValue = ConstantInt::get(M.getContext(), APInt(32, i+1, 10));
+ new StoreInst(idValue, structIdField, false, magicArrayBuildFuncInst);
+
+ //storing name field
+ Value* structNameField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_NAME);
+ Constant* nameValue = MagicUtil::getArrayPtr(M, MagicUtil::getStringRef(M, aTypeInfo->getName()));
+ new StoreInst(nameValue, structNameField, false, magicArrayBuildFuncInst);
+
+ //storing names field
+ std::vector<std::string> names = aTypeInfo->getNames();
+ Value* structNamesField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_NAMES);
+ Constant* namesValue;
+ if(names.size() > 0) {
+ namesValue = MagicUtil::getArrayPtr(M, MagicUtil::getStringArrayRef(M, names.size(), &names));
+ }
+ else {
+ namesValue = ConstantPointerNull::get((TYPECONST PointerType*) ((TYPECONST PointerType*)structNamesField->getType())->getElementType());
+ }
+ new StoreInst(namesValue, structNamesField, false, magicArrayBuildFuncInst);
+
+ //storing num_names field
+ Value* structNumNamesField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_NUM_NAMES);
+ Constant* numNamesValue = ConstantInt::get(M.getContext(), APInt(32, names.size(), 10));
+ new StoreInst(numNamesValue, structNumNamesField, false, magicArrayBuildFuncInst);
+
+ //storing type_str field
+ Value* structTypeStrField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_TYPE_STR);
+ Constant* typeStrValue = MagicUtil::getArrayPtr(M, MagicUtil::getStringRef(M, aTypeInfo->getTypeString()));
+ new StoreInst(typeStrValue, structTypeStrField, false, magicArrayBuildFuncInst);
+
+ //filling size field
+ Value* structSizeField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_SIZE);
+ Value* typeSizeValue;
+ if(aType->isFunctionTy() || TypeUtil::isOpaqueTy(aType) || aType->isVoidTy()) {
+ typeSizeValue = ConstantInt::get(M.getContext(), APInt(32, 1, 10));
+ }
+ else {
+ assert(aType->isSized());
+ typeSizeValue = ConstantExpr::getIntegerCast(ConstantExpr::getSizeOf(aType), (TYPECONST IntegerType*)((TYPECONST PointerType*)structSizeField->getType())->getElementType(), true);
+ }
+ new StoreInst(typeSizeValue, structSizeField, false, magicArrayBuildFuncInst);
+
+ //storing num_child_types field
+ Value* structNumChildTypesField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_NUM_CHILD_TYPES);
+ Constant* numChildTypesValue = ConstantInt::get(M.getContext(), APInt(32, aTypeInfo->getNumChildTypes(), 10));
+ new StoreInst(numChildTypesValue, structNumChildTypesField, false, magicArrayBuildFuncInst);
+
+ //storing member_names field
+ std::vector<std::string> memberNames = aTypeInfo->getMemberNames();
+ Value* structMemberNamesField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_MEMBER_NAMES);
+ Constant* memberNamesValue;
+ if(memberNames.size() > 0) {
+ assert(aType->isStructTy());
+ assert(aTypeInfo->getNumContainedTypes() == memberNames.size());
+ memberNamesValue = MagicUtil::getArrayPtr(M, MagicUtil::getStringArrayRef(M, memberNames.size(), &memberNames));
+ }
+ else {
+ memberNamesValue = ConstantPointerNull::get((TYPECONST PointerType*) ((TYPECONST PointerType*)structMemberNamesField->getType())->getElementType());
+ }
+ new StoreInst(memberNamesValue, structMemberNamesField, false, magicArrayBuildFuncInst);
+
+ //storing member_offsets field
+ Value* structMemberOffsetsField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_MEMBER_OFFSETS);
+ Constant* memberOffsetsValue;
+ if(memberNames.size() > 0) {
+ assert(aType->isStructTy());
+ assert(aTypeInfo->getNumContainedTypes() == aTypeInfo->getNumChildTypes());
+ bool isConstant = false;
+ GlobalVariable *memberOffsetArray = MagicUtil::getIntArrayRef(M, aTypeInfo->getNumChildTypes(), NULL, isConstant);
+ for(unsigned j=0;j<aTypeInfo->getNumChildTypes();j++) {
+ std::vector<Value*> arrayIndexes;
+ arrayIndexes.clear();
+ arrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(64, 0, 10))); //pointer to A[]
+ arrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(64, j, 10))); //pointer to A[j]
+ Constant* memberOffsetArrayPtr = MagicUtil::getGetElementPtrConstant(memberOffsetArray, arrayIndexes);
+
+ Value* memberOffsetValue = ConstantExpr::getIntegerCast(ConstantExpr::getOffsetOf((TYPECONST StructType*) aTypeInfo->getType(), j), (TYPECONST IntegerType*)((TYPECONST PointerType*)memberOffsetArrayPtr->getType())->getElementType(), true);
+ new StoreInst(memberOffsetValue, memberOffsetArrayPtr, false, magicArrayBuildFuncInst);
+ }
+ memberOffsetsValue = MagicUtil::getArrayPtr(M, memberOffsetArray);
+ }
+ else {
+ memberOffsetsValue = ConstantPointerNull::get((TYPECONST PointerType*) ((TYPECONST PointerType*)structMemberOffsetsField->getType())->getElementType());
+ }
+ new StoreInst(memberOffsetsValue, structMemberOffsetsField, false, magicArrayBuildFuncInst);
+
+ //storing value set field (for enum values and value set analysis)
+ std::vector<int> valueSet = aTypeInfo->getValueSet();
+ Value* structValueSetField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_VALUE_SET);
+ Constant* valueSetValue;
+ if(valueSet.size() > 0) {
+ valueSetValue = ConstantExpr::getCast(Instruction::BitCast, MagicUtil::getArrayPtr(M, MagicUtil::getIntArrayRef(M, valueSet.size(), &valueSet)), magicVoidPtrTypeInfo->getType());
+ }
+ else {
+ valueSetValue = ConstantPointerNull::get((TYPECONST PointerType*)magicVoidPtrTypeInfo->getType());
+ }
+ new StoreInst(valueSetValue, structValueSetField, false, magicArrayBuildFuncInst);
+
+ //storing type_id field
+ Value* structTypeIDField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_TYPE_ID);
+ Constant* typeIDValue = ConstantInt::get(M.getContext(), APInt(32, aTypeInfo->getTypeID(), 10));
+ new StoreInst(typeIDValue, structTypeIDField, false, magicArrayBuildFuncInst);
+
+ //storing flags field
+ Value* structFlagsField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_FLAGS);
+ Constant* flagsValue = ConstantInt::get(M.getContext(), APInt(32, aTypeInfo->getFlags(), 10));
+ new StoreInst(flagsValue, structFlagsField, false, magicArrayBuildFuncInst);
+
+ //storing bit_width field
+ Value* structBitWidthField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_BIT_WIDTH);
+ Constant* bitWidthValue = ConstantInt::get(M.getContext(), APInt(32, aTypeInfo->getBitWidth(), 10));
+ new StoreInst(bitWidthValue, structBitWidthField, false, magicArrayBuildFuncInst);
+ }
+
+ i=0;
+ //build contained types pointers
+ unsigned dstIndex, voidTypeIndex;
+ magicArrayTypeIndexMapIt = magicArrayTypeIndexMap.find(magicVoidTypeInfo);
+ assert(magicArrayTypeIndexMapIt != magicArrayTypeIndexMap.end());
+ voidTypeIndex = magicArrayTypeIndexMapIt->second;
+ for(;i<globalTypeInfos.size();i++) {
+ TypeInfo* aTypeInfo = globalTypeInfos[i];
+ std::vector<Constant*> containedTypePtrs;
+ for(unsigned j=0;j<aTypeInfo->getNumContainedTypes();j++) {
+ TypeInfo* containedType = aTypeInfo->getContainedType(j);
+ magicArrayTypePtrMapIt = magicArrayTypePtrMap.find(containedType);
+ assert(magicArrayTypePtrMapIt != magicArrayTypePtrMap.end());
+
+ containedTypePtrs.push_back(magicArrayTypePtrMapIt->second);
+ }
+ Value* structContainedTypesField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_CONTAINED_TYPES);
+ Constant *containedTypesValue;
+ if(containedTypePtrs.size() > 0) {
+ containedTypesValue = MagicUtil::getArrayPtr(M, MagicUtil::getGenericArrayRef(M, containedTypePtrs));
+ }
+ else {
+ containedTypesValue = ConstantPointerNull::get((TYPECONST PointerType*) ((TYPECONST PointerType*)structContainedTypesField->getType())->getElementType());
+ }
+ new StoreInst(containedTypesValue, structContainedTypesField, false, magicArrayBuildFuncInst);
+ if(!aTypeInfo->hasRawTypeRepresentation()) {
+ continue;
+ }
+
+ //handle raw array types
+ assert(aTypeInfo->getNumContainedTypes() == 1 && aTypeInfo->getContainedType(0)->getType()->isArrayTy());
+ magicArrayTypeIndexMapIt = magicArrayTypeIndexMap.find(aTypeInfo->getContainedType(0));
+ assert(magicArrayTypeIndexMapIt != magicArrayTypeIndexMap.end());
+ dstIndex = magicArrayTypeIndexMapIt->second;
+
+ //fix size field (inherited by parent type)
+ Value* srcStructSizeField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_SIZE);
+ Value* dstStructSizeField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, dstIndex, 10)), MAGIC_TSTRUCT_FIELD_SIZE);
+ Value* srcStructSizeValue = new LoadInst(srcStructSizeField, "", false, magicArrayBuildFuncInst);
+ new StoreInst(srcStructSizeValue, dstStructSizeField, false, magicArrayBuildFuncInst);
+
+ //fix num_child_types field
+ Value* dstStructNumChildTypesField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, dstIndex, 10)), MAGIC_TSTRUCT_FIELD_NUM_CHILD_TYPES);
+ Value* voidStructSizeField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, voidTypeIndex, 10)), MAGIC_TSTRUCT_FIELD_SIZE);
+ Value* voidStructSizeValue = new LoadInst(voidStructSizeField, "", false, magicArrayBuildFuncInst);
+ BinaryOperator* numChildTypesValue = BinaryOperator::Create(Instruction::SDiv, srcStructSizeValue, voidStructSizeValue, "", magicArrayBuildFuncInst);
+ new StoreInst(numChildTypesValue, dstStructNumChildTypesField, false, magicArrayBuildFuncInst);
+ }
+
+ i=0;
+ //build cast types pointers
+ for(;i<globalTypeInfos.size();i++) {
+ TypeInfo* aTypeInfo = globalTypeInfos[i];
+ std::vector<Constant*> castTypePtrs;
+ std::vector<TypeInfo*> castTypes = aTypeInfo->getCastTypes();
+
+ Value* structCompatibleTypesField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_COMPATIBLE_TYPES);
+ TYPECONST PointerType* nullArrayType = (TYPECONST PointerType*) ((TYPECONST PointerType*)structCompatibleTypesField->getType())->getElementType();
+ for(unsigned j=0;j<castTypes.size();j++) {
+ TypeInfo* castType = castTypes[j];
+ if(castType == NULL) {
+ castTypePtrs.push_back(ConstantPointerNull::get((TYPECONST PointerType*) nullArrayType->getContainedType(0)));
+ }
+ else {
+ magicArrayTypePtrMapIt = magicArrayTypePtrMap.find(castType);
+ assert(magicArrayTypePtrMapIt != magicArrayTypePtrMap.end());
+
+ castTypePtrs.push_back(magicArrayTypePtrMapIt->second);
+ }
+ }
+
+ Constant *compatibleTypesValue;
+ if(castTypePtrs.size() > 0) {
+ compatibleTypesValue = MagicUtil::getArrayPtr(M, MagicUtil::getGenericArrayRef(M, castTypePtrs));
+ }
+ else {
+ compatibleTypesValue = ConstantPointerNull::get(nullArrayType);
+ }
+ new StoreInst(compatibleTypesValue, structCompatibleTypesField, false, magicArrayBuildFuncInst);
+ }
+
+ //build magic array in build function
+ i=0;
+ strGlobalVariables = 0;
+ PointerType* voidPointerType = PointerType::get(IntegerType::get(M.getContext(), 8), 0);
+ for(;i<globalVariables.size();i++) {
+ GlobalVariable *GV = globalVariables[i];
+ DIGlobalVariable *DIGV = NULL;
+ StringRef GVName;
+ bool isFromLibrary, hasAddressTaken, isString, isNamedString;
+ isString = GV->getName().startswith(".str");
+ isNamedString = false;
+ if(isString) {
+ stringOwnerInvertedMapIt = stringOwnerInvertedMap.find(GV);
+ if(stringOwnerInvertedMapIt != stringOwnerInvertedMap.end()) {
+ isNamedString = true;
+ DIGV = NULL;
+ GVName = ".str#" + stringOwnerInvertedMapIt->second;
+ }
+ }
+ if(!isNamedString) {
+ GVName = MagicUtil::getGVSourceName(M, GV, &DIGV, baseBuildDir);
+ }
+ isFromLibrary = isExtLibrary(GV, DIGV);
+ hasAddressTaken = globalVariablesWithAddressTaken.find(GV) != globalVariablesWithAddressTaken.end();
+ std::string GVNameStr(GVName.str());
+
+ //storing id field
+ Value* structIdField = MagicUtil::getMagicSStructFieldPtr(M, magicArrayBuildFuncInst, magicArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_SSTRUCT_FIELD_ID);
+ Constant* idValue = ConstantInt::get(M.getContext(), APInt(32, i+1, 10));
+ new StoreInst(idValue, structIdField, false, magicArrayBuildFuncInst);
+
+ //storing name field
+ Value* structNameField = MagicUtil::getMagicSStructFieldPtr(M, magicArrayBuildFuncInst, magicArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_SSTRUCT_FIELD_NAME);
+ Constant* nameValue = MagicUtil::getArrayPtr(M, MagicUtil::getStringRef(M, GVNameStr));
+ new StoreInst(nameValue, structNameField, false, magicArrayBuildFuncInst);
+
+ //storing type field
+ parentMapIt = globalParentMap.find(GV);
+ if(parentMapIt == globalParentMap.end()) {
+ continue;
+ }
+ assert(parentMapIt != globalParentMap.end());
+ TypeInfo* aTypeInfo = parentMapIt->second;
+ magicArrayTypePtrMapIt = magicArrayTypePtrMap.find(aTypeInfo);
+ assert(magicArrayTypePtrMapIt != magicArrayTypePtrMap.end());
+ Value* structTypeField = MagicUtil::getMagicSStructFieldPtr(M, magicArrayBuildFuncInst, magicArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_SSTRUCT_FIELD_TYPE);
+ Constant* typeValue = magicArrayTypePtrMapIt->second;
+ new StoreInst(typeValue, structTypeField, false, magicArrayBuildFuncInst);
+
+ //filling flags field
+ int annotation, flags = MAGIC_STATE_DATA;
+ if(GV->hasExternalLinkage() || GV->hasExternalWeakLinkage()) {
+ flags |= MAGIC_STATE_EXTERNAL;
+ }
+ if(GV->isConstant()) {
+ flags |= MAGIC_STATE_CONSTANT;
+ }
+ if(GV->isThreadLocal()) {
+ flags |= MAGIC_STATE_THREAD_LOCAL;
+ }
+ if(isFromLibrary) {
+ flags |= MAGIC_STATE_LIB;
+ }
+ if(!hasAddressTaken) {
+ flags |= MAGIC_STATE_ADDR_NOT_TAKEN;
+ }
+ if(isString) {
+ flags |= MAGIC_STATE_STRING;
+ if(isNamedString) {
+ flags |= MAGIC_STATE_NAMED_STRING;
+ }
+ strGlobalVariables++;
+ }
+ if(MagicUtil::getVarAnnotation(M, GV, &annotation)) {
+ magicPassLog("Magic annotation found for global variable: " << GV->getName());
+ flags |= (annotation & MAGIC_STATE_ANNOTATION_MASK);
+ }
+ Value* structFlagsField = MagicUtil::getMagicSStructFieldPtr(M, magicArrayBuildFuncInst, magicArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_SSTRUCT_FIELD_FLAGS);
+ Constant* flagsValue = ConstantInt::get(M.getContext(), APInt(32, flags, 10));
+ new StoreInst(flagsValue, structFlagsField, false, magicArrayBuildFuncInst);
+
+ //filling address field
+ Value* structAddressField = MagicUtil::getMagicSStructFieldPtr(M, magicArrayBuildFuncInst, magicArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_SSTRUCT_FIELD_ADDRESS);
+ Constant* varAddressValue = ConstantExpr::getCast(Instruction::BitCast, GV, voidPointerType);
+ new StoreInst(varAddressValue, structAddressField, false, magicArrayBuildFuncInst);
+
+ //filling shadow address field
+ Value* structShadowAddressField = MagicUtil::getMagicSStructFieldPtr(M, magicArrayBuildFuncInst, magicArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_SSTRUCT_FIELD_SHADOW_ADDRESS);
+ Constant* varShadowAddressValue;
+ if(EnableShadowing && !GV->isConstant()) {
+ GlobalVariable* varShadow = MagicUtil::getShadowRef(M, GV);
+ shadowGlobalVariables.push_back(varShadow);
+ varShadowAddressValue = ConstantExpr::getCast(Instruction::BitCast, varShadow, voidPointerType);
+ }
+ else {
+ varShadowAddressValue = ConstantPointerNull::get((TYPECONST PointerType*) ((TYPECONST PointerType*)structShadowAddressField->getType())->getElementType());
+ }
+ new StoreInst(varShadowAddressValue, structShadowAddressField, false, magicArrayBuildFuncInst);
+ }
+
+ //build magic function array in build function
+ i=0;
+ for(;i<functions.size();i++) {
+ Function *F = functions[i];
+ DISubprogram *DIS = NULL;
+ StringRef FName = MagicUtil::getFunctionSourceName(M, F, &DIS, baseBuildDir);
+ std::string FNameStr(FName.str());
+ bool isFromLibrary = isExtLibrary(F, DIS);
+
+ //storing id field
+ Value* structIdField = MagicUtil::getMagicFStructFieldPtr(M, magicArrayBuildFuncInst, magicFunctionArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_FSTRUCT_FIELD_ID);
+ Constant* idValue = ConstantInt::get(M.getContext(), APInt(32, i+1, 10));
+ new StoreInst(idValue, structIdField, false, magicArrayBuildFuncInst);
+
+ //storing name field
+ Value* structNameField = MagicUtil::getMagicFStructFieldPtr(M, magicArrayBuildFuncInst, magicFunctionArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_FSTRUCT_FIELD_NAME);
+ Constant* nameValue = MagicUtil::getArrayPtr(M, MagicUtil::getStringRef(M, FNameStr));
+ new StoreInst(nameValue, structNameField, false, magicArrayBuildFuncInst);
+
+ //storing type field
+ parentMapIt = globalParentMap.find(F);
+ assert(parentMapIt != globalParentMap.end());
+ TypeInfo* aTypeInfo = parentMapIt->second;
+ magicArrayTypePtrMapIt = magicArrayTypePtrMap.find(aTypeInfo);
+ assert(magicArrayTypePtrMapIt != magicArrayTypePtrMap.end());
+ Value* structTypeField = MagicUtil::getMagicFStructFieldPtr(M, magicArrayBuildFuncInst, magicFunctionArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_FSTRUCT_FIELD_TYPE);
+ Constant* typeValue = magicArrayTypePtrMapIt->second;
+ new StoreInst(typeValue, structTypeField, false, magicArrayBuildFuncInst);
+
+ //filling flags field
+ int flags = MAGIC_STATE_TEXT|MAGIC_STATE_CONSTANT;
+ if(isFromLibrary) {
+ flags |= MAGIC_STATE_LIB;
+ }
+ if(!F->hasAddressTaken()) {
+ flags |= MAGIC_STATE_ADDR_NOT_TAKEN;
+ }
+ Value* structFlagsField = MagicUtil::getMagicFStructFieldPtr(M, magicArrayBuildFuncInst, magicFunctionArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_FSTRUCT_FIELD_FLAGS);
+ Constant* flagsValue = ConstantInt::get(M.getContext(), APInt(32, flags, 10));
+ new StoreInst(flagsValue, structFlagsField, false, magicArrayBuildFuncInst);
+
+ //filling address field
+ Value* structAddressField = MagicUtil::getMagicFStructFieldPtr(M, magicArrayBuildFuncInst, magicFunctionArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_FSTRUCT_FIELD_ADDRESS);
+ Constant* varAddressValue = ConstantExpr::getCast(Instruction::BitCast, F, voidPointerType);
+ new StoreInst(varAddressValue, structAddressField, false, magicArrayBuildFuncInst);
+ }
+
+#if MAGIC_INSTRUMENT_MEM_FUNCS
+ //replace magic memory function calls with their wrappers
+ for(i=0;i<magicMemFunctionCalls.size();i++) {
+ MagicMemFunction *magicMemFunctionCall = &magicMemFunctionCalls[i];
+ magicMemFunctionCall->replaceInstruction(magicArrayTypePtrMap, magicVoidPtrTypeInfo);
+ }
+
+ //fix debug function calls and their arguments
+ for (i=0;i<magicDebugFunctions.size();i++) {
+ MagicDebugFunction *magicDebugFunction = &magicDebugFunctions[i];
+ magicDebugFunction->fixCalls(M, baseBuildDir);
+ }
+
+ //fix mmap ctl function calls and their arguments
+ for (i=0;i<magicMmapCtlFunctions.size();i++) {
+ MagicMmapCtlFunction *magicMmapCtlFunction = &magicMmapCtlFunctions[i];
+ magicMmapCtlFunction->fixCalls(M, magicGetPageSizeFunc);
+ }
+#endif
+
+#if MAGIC_INSTRUMENT_STACK
+ //instrument the stack for the relevant set of functions and add dsindex entries
+ for(i=0;i<stackIntrumentedFuncs.size();i++) {
+ addMagicStackDsentryFuncCalls(M, stackIntrumentedFuncs[i], stackIntrumentedFuncs[i], magicStackDsentryCreateFunc, magicStackDsentryDestroyFunc,
+ magicDsentryStructType, localTypeInfoMaps[i], magicArrayTypePtrMap, magicVoidPtrTypeInfo, magicDsindexTypeInfoList, magicDsindexNamesList, magicDsindexFlagsList);
+ }
+#endif
+
+ //allocate magic dsindex array
+ ArrayType* magicDsindexArrayType = ArrayType::get(magicDsindexStructType, magicDsindexTypeInfoList.size());
+ magicDsindexArray = new GlobalVariable(M, magicDsindexArrayType, false, GlobalValue::InternalLinkage, ConstantAggregateZero::get(magicDsindexArrayType), MAGIC_DSINDEX_ARRAY_NAME);
+ MagicUtil::setGlobalVariableSection(magicDsindexArray, MAGIC_STATIC_VARS_SECTION_DATA);
+
+ //build magic dsindex array in build function
+ i=0;
+ for(;i<magicDsindexTypeInfoList.size();i++) {
+ //storing type field
+ TypeInfo* aTypeInfo = magicDsindexTypeInfoList[i];
+ magicArrayTypePtrMapIt = magicArrayTypePtrMap.find(aTypeInfo);
+ assert(magicArrayTypePtrMapIt != magicArrayTypePtrMap.end());
+ Value* structTypeField = MagicUtil::getMagicDStructFieldPtr(M, magicArrayBuildFuncInst, magicDsindexArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_DSTRUCT_FIELD_TYPE);
+ Constant* typeValue = magicArrayTypePtrMapIt->second;
+ new StoreInst(typeValue, structTypeField, false, magicArrayBuildFuncInst);
+
+ //storing name field
+ Value* structNameField = MagicUtil::getMagicDStructFieldPtr(M, magicArrayBuildFuncInst, magicDsindexArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_DSTRUCT_FIELD_NAME);
+ Constant* nameValue = MagicUtil::getArrayPtr(M, MagicUtil::getStringRef(M, magicDsindexNamesList[i].second));
+ new StoreInst(nameValue, structNameField, false, magicArrayBuildFuncInst);
+
+ //storing parent name field
+ Value* structParentNameField = MagicUtil::getMagicDStructFieldPtr(M, magicArrayBuildFuncInst, magicDsindexArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_DSTRUCT_FIELD_PARENT_NAME);
+ Constant* parentNameValue = MagicUtil::getArrayPtr(M, MagicUtil::getStringRef(M, magicDsindexNamesList[i].first));
+ new StoreInst(parentNameValue, structParentNameField, false, magicArrayBuildFuncInst);
+
+ //storing flags field
+ Value* structFlagsField = MagicUtil::getMagicDStructFieldPtr(M, magicArrayBuildFuncInst, magicDsindexArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_DSTRUCT_FIELD_FLAGS);
+ Constant* flagsValue = ConstantInt::get(M.getContext(), APInt(32, magicDsindexFlagsList[i], 10));
+ new StoreInst(flagsValue, structFlagsField, false, magicArrayBuildFuncInst);
+ }
+
+ // apply qprof instrumentation
+ qprofInstrumentationApply(M);
+
+ //set pointer to magic type array in build function
+ new StoreInst(MagicUtil::getArrayPtr(M, magicTypeArray), magicTypeArrayPtr, false, magicArrayBuildFuncInst);
+
+ //set magic type array size in build function
+ new StoreInst(ConstantInt::get(M.getContext(), APInt(32, globalTypeInfos.size())), magicTypeArraySize, false, magicArrayBuildFuncInst);
+
+ //set magic type next id in build function
+ new StoreInst(ConstantInt::get(M.getContext(), APInt(32, globalTypeInfos.size()+1)), magicTypeNextId, false, magicArrayBuildFuncInst);
+
+ //set pointer to magic array in build function
+ new StoreInst(MagicUtil::getArrayPtr(M, magicArray), magicArrayPtr, false, magicArrayBuildFuncInst);
+
+ //set magic array size in build function
+ new StoreInst(ConstantInt::get(M.getContext(), APInt(32, globalVariables.size())), magicArraySize, false, magicArrayBuildFuncInst);
+
+ //set magic array string size in build function
+ new StoreInst(ConstantInt::get(M.getContext(), APInt(32, strGlobalVariables)), magicArrayStrSize, false, magicArrayBuildFuncInst);
+
+ //set magic next id in build function
+ new StoreInst(ConstantInt::get(M.getContext(), APInt(32, globalVariables.size()+1)), magicNextId, false, magicArrayBuildFuncInst);
+
+ //set pointer to magic function array in build function
+ new StoreInst(MagicUtil::getArrayPtr(M, magicFunctionArray), magicFunctionArrayPtr, false, magicArrayBuildFuncInst);
+
+ //set magic function array size in build function
+ new StoreInst(ConstantInt::get(M.getContext(), APInt(32, functions.size())), magicFunctionArraySize, false, magicArrayBuildFuncInst);
+
+ //set magic function next id in build function
+ new StoreInst(ConstantInt::get(M.getContext(), APInt(32, functions.size()+1)), magicFunctionNextId, false, magicArrayBuildFuncInst);
+
+ //set pointer to magic dsindex array in build function
+ new StoreInst(MagicUtil::getArrayPtr(M, magicDsindexArray), magicDsindexArrayPtr, false, magicArrayBuildFuncInst);
+
+ //set magic dsindex array size in build function
+ new StoreInst(ConstantInt::get(M.getContext(), APInt(32, magicDsindexTypeInfoList.size())), magicDsindexArraySize, false, magicArrayBuildFuncInst);
+
+ //set magic void type pointer in build function
+ magicArrayTypePtrMapIt = magicArrayTypePtrMap.find(magicVoidPtrTypeInfo);
+ assert(magicArrayTypePtrMapIt != magicArrayTypePtrMap.end());
+ Constant* magicVoidPtrTypeValue = magicArrayTypePtrMapIt->second;
+ new StoreInst(magicVoidPtrTypeValue, magicVoidPtrTypePtr, false, magicArrayBuildFuncInst);
+
+ //inject magic init call at the beginning of magic entry point function
+ std::vector<Value*> args;
+ MagicUtil::createCallInstruction(magicInitFunc, args, "", magicEntryPointFunc->getBasicBlockList().begin()->begin());
+
+ //check invariants
+#if MAGIC_CHECK_INVARIANTS
+ if(maxRecursiveSequenceLength > MAGIC_MAX_RECURSIVE_TYPES) {
+ magicPassErr("Max recursive sequence length is: " << maxRecursiveSequenceLength);
+ }
+ assert(maxRecursiveSequenceLength <= MAGIC_MAX_RECURSIVE_TYPES && "MAGIC_MAX_RECURSIVE_TYPES is too small!");
+ if(TypeInfo::getMaxNameLength() > MAGIC_MAX_NAME_LEN) {
+ magicPassErr("Max name length is: " << TypeInfo::getMaxNameLength());
+ }
+ assert(TypeInfo::getMaxNameLength() <= MAGIC_MAX_NAME_LEN && "MAGIC_MAX_NAME_LEN is too small!");
+ if(TypeInfo::getMaxTypeStringLength() > MAGIC_MAX_TYPE_STR_LEN) {
+ magicPassErr("Max type string length is: " << TypeInfo::getMaxTypeStringLength());
+ }
+ assert(TypeInfo::getMaxTypeStringLength() <= MAGIC_MAX_TYPE_STR_LEN && "MAGIC_MAX_TYPE_STR_LEN is too small!");
+#endif
+
+ return true;
+}
+
+//===----------------------------------------------------------------------===//
+// Private methods
+//===----------------------------------------------------------------------===//
+
+static std::vector<int> currPtrVarIndexes;
+static std::set< std::pair<Value*,std::vector<int> > > visitedValues;
+
+bool MagicPass::checkPointerVariableIndexes(TYPECONST Type *type, std::vector<int> &ptrVarIndexes, unsigned offset)
+{
+ if(offset >= ptrVarIndexes.size()) {
+ return true;
+ }
+ unsigned ptrVarIndex = (unsigned) ptrVarIndexes[ptrVarIndexes.size()-1 - offset];
+ if(ptrVarIndex >= type->getNumContainedTypes()) {
+ return false;
+ }
+ return checkPointerVariableIndexes(type->getContainedType(ptrVarIndex), ptrVarIndexes, offset+1);
+}
+
+void MagicPass::findPointerVariables(Function* function, Value *value, std::vector<Value*> &ptrVars, std::vector<std::vector<int> > &ptrVarIndexes, Value *parent, bool isUser)
+{
+
+#define RETURN_IF(X) do{ if(X){ return; } } while(0)
+#define DEBUG_VALUE(M, V) do{ if(DEBUG_ALLOC_LEVEL >= 2) { errs() << M; V->print(errs()); errs() << "\n"; } } while(0)
+#define DEBUG_INDEXES() do{ if(DEBUG_ALLOC_LEVEL >= 3) { errs() << ">>> Indexes: "; for(unsigned i=0;i<currPtrVarIndexes.size();i++) errs() << currPtrVarIndexes[i] << " "; errs() << "\n"; } } while(0)
+
+ std::pair<Value*,std::vector<int> > visitedPair(value, currPtrVarIndexes);
+ if(visitedValues.find(visitedPair) != visitedValues.end()) {
+ return;
+ }
+
+ DEBUG_VALUE(" >>>> findPointerVariables: Value is: ", value);
+ DEBUG_VALUE(" >>>> findPointerVariables: Parent value is: ", parent);
+ DEBUG_INDEXES();
+ std::vector<int> savedPtrVarIndexes;
+ visitedValues.insert(visitedPair);
+ ConstantExpr *constantExpr = dyn_cast<ConstantExpr>(value);
+ if(currPtrVarIndexes.size() == 0) {
+ if(DEBUG_ALLOC_LEVEL >= 2) {
+ magicPassErr("Empty indexes, skipping search path!");
+ }
+ RETURN_IF(true);
+ }
+ else if(GlobalVariable *GV = dyn_cast<GlobalVariable>(value)) {
+ if(DEBUG_ALLOC_LEVEL >= 2) {
+ magicPassErr("Found global variable!");
+ }
+ ptrVars.push_back(GV);
+ ptrVarIndexes.push_back(currPtrVarIndexes);
+ assert(!isUser);
+ if(GV->getType()->getElementType() != PointerType::get(IntegerType::get(function->getParent()->getContext(), 8), 0)) {
+ RETURN_IF(true);
+ }
+ }
+ else if(AllocaInst *AI = dyn_cast<AllocaInst>(value)) {
+ if(DEBUG_ALLOC_LEVEL >= 2) {
+ magicPassErr("Found local variable!");
+ }
+ ptrVars.push_back(AI);
+ ptrVarIndexes.push_back(currPtrVarIndexes);
+ assert(!isUser);
+ if(AI->getAllocatedType() != PointerType::get(IntegerType::get(function->getParent()->getContext(), 8), 0)) {
+ RETURN_IF(true);
+ }
+ }
+ else if(dyn_cast<ReturnInst>(value)) {
+ if(DEBUG_ALLOC_LEVEL >= 2) {
+ magicPassErr("Found return variable!");
+ }
+ assert(isUser);
+ RETURN_IF(true);
+ }
+ else if(StoreInst *SI = dyn_cast<StoreInst>(value)) {
+ DEBUG_VALUE(" >>>> findPointerVariables: Digging store instruction: ", value);
+ assert(isUser);
+ if(parent == SI->getOperand(1)) {
+ assert(currPtrVarIndexes.size() > 0 && currPtrVarIndexes[currPtrVarIndexes.size()-1] == 0);
+ currPtrVarIndexes.pop_back();
+ findPointerVariables(function, SI->getOperand(0), ptrVars, ptrVarIndexes, value);
+ currPtrVarIndexes.push_back(0);
+ }
+ else {
+ currPtrVarIndexes.push_back(0);
+ findPointerVariables(function, SI->getOperand(1), ptrVars, ptrVarIndexes, value);
+ currPtrVarIndexes.pop_back();
+ }
+ }
+ else if(LoadInst *LI = dyn_cast<LoadInst>(value)) {
+ DEBUG_VALUE(" >>>> findPointerVariables: Digging load instruction: ", value);
+ if(isUser) {
+ assert(currPtrVarIndexes.size() > 0 && currPtrVarIndexes[currPtrVarIndexes.size()-1] == 0);
+ savedPtrVarIndexes.push_back(currPtrVarIndexes.back());
+ currPtrVarIndexes.pop_back();
+ }
+ else {
+ currPtrVarIndexes.push_back(0);
+ findPointerVariables(function, LI->getOperand(0), ptrVars, ptrVarIndexes, value);
+ currPtrVarIndexes.pop_back();
+ }
+ }
+ else if(GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(value)) {
+ if(GEPI->getNumIndices() == 1) {
+ DEBUG_VALUE(" >>>> findPointerVariables: Digging GEP instruction: ", value);
+ findPointerVariables(function, GEPI->getOperand(0), ptrVars, ptrVarIndexes, value);
+ }
+ else {
+ RETURN_IF(isUser);
+ DEBUG_VALUE(" >>>> findPointerVariables: Digging GEP instruction: ", value);
+ unsigned k = 0;
+ int index;
+ assert(currPtrVarIndexes.size() > 0 && currPtrVarIndexes[currPtrVarIndexes.size()-1] == 0);
+ currPtrVarIndexes.pop_back(); //pop 0
+ for(GetElementPtrInst::const_op_iterator i=GEPI->idx_end()-1, b=GEPI->idx_begin();i>b;i--,k++) {
+ index = 0;
+ if(ConstantInt *CI = dyn_cast<ConstantInt>(*i)) {
+ index = CI->getSExtValue();
+ }
+ currPtrVarIndexes.push_back(index);
+ }
+ currPtrVarIndexes.push_back(0); //push 0
+ findPointerVariables(function, GEPI->getOperand(0), ptrVars, ptrVarIndexes, value);
+ currPtrVarIndexes.pop_back(); //pop 0
+ while(k-->0) {
+ currPtrVarIndexes.pop_back();
+ }
+ currPtrVarIndexes.push_back(0); //push 0
+ }
+ }
+ else if(constantExpr && constantExpr->getOpcode() == Instruction::GetElementPtr) {
+ assert(constantExpr->getNumOperands() >= 2);
+ if(constantExpr->getNumOperands() == 2) {
+ DEBUG_VALUE(" >>>> findPointerVariables: Digging GEP expression: ", value);
+ findPointerVariables(function, constantExpr->getOperand(0), ptrVars, ptrVarIndexes, value);
+ }
+ else {
+ RETURN_IF(isUser);
+ DEBUG_VALUE(" >>>> findPointerVariables: Digging GEP expression: ", value);
+ unsigned k = 0;
+ int index;
+ assert(currPtrVarIndexes.size() > 0 && currPtrVarIndexes[currPtrVarIndexes.size()-1] == 0);
+ currPtrVarIndexes.pop_back(); //pop 0
+ for(unsigned i=constantExpr->getNumOperands()-1;i>1;i--,k++) {
+ index = 0;
+ if(ConstantInt *CI = dyn_cast<ConstantInt>(constantExpr->getOperand(i))) {
+ index = CI->getSExtValue();
+ }
+ currPtrVarIndexes.push_back(index);
+ }
+ currPtrVarIndexes.push_back(0); //push 0
+ findPointerVariables(function, constantExpr->getOperand(0), ptrVars, ptrVarIndexes, value);
+ currPtrVarIndexes.pop_back(); //pop 0
+ while(k-->0) {
+ currPtrVarIndexes.pop_back();
+ }
+ currPtrVarIndexes.push_back(0); //push 0
+ }
+ }
+ else if(BitCastInst *CI = dyn_cast<BitCastInst>(value)) {
+ if((isUser && !checkPointerVariableIndexes(CI->getType(), currPtrVarIndexes))
+ || (!isUser && !checkPointerVariableIndexes(CI->getOperand(0)->getType(), currPtrVarIndexes))) {
+ DEBUG_VALUE(" >>>> findPointerVariables: Skipping unsafe cast instruction: ", value);
+ RETURN_IF(true);
+ }
+ DEBUG_VALUE(" >>>> findPointerVariables: Digging cast instruction: ", value);
+ findPointerVariables(function, CI->getOperand(0), ptrVars, ptrVarIndexes, value);
+ }
+ else if(dyn_cast<CallInst>(value) || dyn_cast<InvokeInst>(value)) {
+ RETURN_IF(isUser);
+ DEBUG_VALUE(" >>>> findPointerVariables: found call instruction: ", value);
+ }
+ else if(CmpInst *CI = dyn_cast<CmpInst>(value)) {
+ assert(isUser);
+ DEBUG_VALUE(" >>>> findPointerVariables: Digging cmp instruction: ", value);
+ findPointerVariables(function, CI->getOperand(0), ptrVars, ptrVarIndexes, value);
+ findPointerVariables(function, CI->getOperand(1), ptrVars, ptrVarIndexes, value);
+ RETURN_IF(true);
+ }
+ else if(SelectInst *SI = dyn_cast<SelectInst>(value)) {
+ DEBUG_VALUE(" >>>> findPointerVariables: Digging select instruction: ", value);
+ findPointerVariables(function, SI->getOperand(1), ptrVars, ptrVarIndexes, value);
+ findPointerVariables(function, SI->getOperand(2), ptrVars, ptrVarIndexes, value);
+ }
+ else if(constantExpr && constantExpr->getOpcode() == Instruction::Select) {
+ DEBUG_VALUE(" >>>> findPointerVariables: Digging select expression: ", value);
+ findPointerVariables(function, constantExpr->getOperand(1), ptrVars, ptrVarIndexes, value);
+ findPointerVariables(function, constantExpr->getOperand(2), ptrVars, ptrVarIndexes, value);
+ }
+ else if(PHINode *PN = dyn_cast<PHINode>(value)) {
+ DEBUG_VALUE(" >>>> findPointerVariables: Digging PHI instruction: ", value);
+ for(unsigned i=0;i<PN->getNumIncomingValues();i++) {
+ findPointerVariables(function, PN->getIncomingValue(i), ptrVars, ptrVarIndexes, value);
+ }
+ }
+ else if(Argument *ARG = dyn_cast<Argument>(value)) {
+ DEBUG_VALUE(" >>>> findPointerVariables: Digging Argument: ", value);
+ AllocaInst *AI = MagicUtil::getAllocaInstFromArgument(ARG);
+ assert(AI);
+ currPtrVarIndexes.push_back(0);
+ findPointerVariables(function, AI, ptrVars, ptrVarIndexes, value);
+ currPtrVarIndexes.pop_back();
+ RETURN_IF(true);
+ }
+ else {
+ DEBUG_VALUE(" ************************************************************ findPointerVariables: Unknown value: ", value);
+ RETURN_IF(true);
+ }
+ for (Value::use_iterator i = value->use_begin(), e = value->use_end(); i != e; ++i) {
+ User *user = *i;
+ Instruction *instruction = dyn_cast<Instruction>(user);
+ if(!instruction || instruction->getParent()->getParent() != function) {
+ continue;
+ }
+ DEBUG_VALUE(" >>>> findPointerVariables: Found user: ", user);
+ findPointerVariables(function, user, ptrVars, ptrVarIndexes, value, true);
+ }
+ while(savedPtrVarIndexes.size() > 0) {
+ currPtrVarIndexes.push_back(savedPtrVarIndexes.back());
+ savedPtrVarIndexes.pop_back();
+ }
+}
+
+TypeInfo* MagicPass::typeInfoFromPointerVariables(Module &M, TypeInfo *voidPtrTypeInfo, std::vector<Value*> &ptrVars, std::vector<std::vector<int> > &ptrVarIndexes, std::string &allocName)
+{
+ std::vector<TypeInfo*> validTypeInfos;
+ std::set<TypeInfo*> validTypeInfoSet;
+ std::vector<unsigned> validTypeTags;
+ std::vector<unsigned> voidTypeTags;
+ std::vector<int> indexes;
+ TypeInfo *aTypeInfo = NULL;
+ TypeInfo *voidTypeInfo = voidPtrTypeInfo->getContainedType(0);
+ allocName = "";
+ if(ptrVars.size()==0) {
+ return voidTypeInfo;
+ }
+
+ for(unsigned i=0;i<ptrVars.size();i++) {
+ DIVariable DIV;
+ unsigned tag = 0;
+ std::string varName = "";
+ if(GlobalVariable *GV = dyn_cast<GlobalVariable>(ptrVars[i])) {
+ parentMapIt = globalParentMap.find(GV);
+ assert(parentMapIt != globalParentMap.end());
+ aTypeInfo = parentMapIt->second;
+ tag = dwarf::DW_TAG_variable;
+ varName = MagicUtil::getGVSourceName(M, GV, NULL, baseBuildDir);
+ }
+ else {
+ AllocaInst *AI = dyn_cast<AllocaInst>(ptrVars[i]);
+ assert(AI);
+ if(DEBUG_ALLOC_LEVEL >= 4) {
+ AI->print(errs()); errs() << "\n";
+ }
+ const SmartType *aSmartType = SmartType::getSmartTypeFromLV(M, AI, &DIV);
+ if(aSmartType == (const SmartType *)-1) {
+ //a temporary variable
+ if(DEBUG_ALLOC_LEVEL >= 4) {
+ magicPassErr("typeInfoFromPointerVariables: Skipping temporary variable");
+ }
+ continue;
+ }
+ else if(!aSmartType) {
+ //a return variable
+ if(DEBUG_ALLOC_LEVEL >= 4) {
+ magicPassErr("typeInfoFromPointerVariables: Processing return variable");
+ }
+ if(AI->getAllocatedType() == voidPtrTypeInfo->getType()) {
+ aTypeInfo = voidPtrTypeInfo;
+ }
+ else {
+ aTypeInfo = fillExternalTypeInfos(AI->getAllocatedType(), NULL, globalTypeInfos);
+ if(aTypeInfo == NULL) {
+ magicPassErr("typeInfoFromPointerVariables: type is: " << TypeUtil::getDescription(AI->getAllocatedType(), MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL));
+ if(!MAGIC_ABORT_ON_UNSUPPORTED_LOCAL_EXTERNAL_TYPE) {
+ magicPassErr("typeInfoFromPointerVariables: Warning: Local external type not supported, resorting to void* type...");
+ aTypeInfo = voidPtrTypeInfo;
+ }
+ else {
+ assert(aTypeInfo != NULL && "Local external type not supported!");
+ }
+ }
+ }
+ tag = dwarf::DW_TAG_unspecified_type;
+ }
+ else {
+ //a regular variable (potentially returning a value to the caller)
+ if(DEBUG_ALLOC_LEVEL >= 4) {
+ magicPassErr("typeInfoFromPointerVariables: Processing regular variable");
+ }
+ TypeInfo newTypeInfo(aSmartType);
+ aTypeInfo = fillTypeInfos(newTypeInfo, globalTypeInfos);
+ if(aTypeInfo->getSmartType() != aSmartType) {
+ delete aSmartType;
+ }
+ if (PassUtil::isReturnedValue(AI->getParent()->getParent(), AI)) {
+ // treat this variable as a return variable
+ tag = dwarf::DW_TAG_unspecified_type;
+ }
+ else {
+ tag = DIV.getTag();
+ }
+ }
+ varName = DIV.getName();
+ }
+ //see if the target type is an alias for void*
+ assert(aTypeInfo);
+ if(aTypeInfo->getType()->isPointerTy()) {
+ stringSetIt = voidTypeAliasesSet.find(aTypeInfo->getContainedType(0)->getName());
+ if(stringSetIt != voidTypeAliasesSet.end()) {
+ aTypeInfo = voidPtrTypeInfo;
+ }
+ }
+ //fix tag if needed
+ if(tag == dwarf::DW_TAG_unspecified_type) {
+ TYPECONST Type *type = aTypeInfo->getType();
+ if(!type->isPointerTy() || type->getContainedType(0)->isPointerTy()) {
+ //not a good return type, switch to a regular variable
+ tag = dwarf::DW_TAG_auto_variable;
+ }
+ }
+ if(tag == dwarf::DW_TAG_arg_variable) {
+ TYPECONST Type *type = aTypeInfo->getType();
+ if(!type->isPointerTy() || !type->getContainedType(0)->isPointerTy() || type->getContainedType(0)->getContainedType(0)->isPointerTy()) {
+ //not a good arg type, switch to a regular variable
+ tag = dwarf::DW_TAG_auto_variable;
+ }
+ }
+ if(DEBUG_ALLOC_LEVEL >= 3) {
+ switch(tag) {
+ case dwarf::DW_TAG_unspecified_type:
+ magicPassErr("typeInfoFromPointerVariables: Found return variable: " << varName);
+ break;
+ case dwarf::DW_TAG_variable:
+ magicPassErr("typeInfoFromPointerVariables: Found global variable:" << varName);
+ break;
+ case dwarf::DW_TAG_auto_variable:
+ magicPassErr("typeInfoFromPointerVariables: Found local variable:" << varName);
+ break;
+ case dwarf::DW_TAG_arg_variable:
+ magicPassErr("typeInfoFromPointerVariables: Found argument variable:" << varName);
+ break;
+ default:
+ assert(0 && "Should never get here!");
+ break;
+ }
+ }
+ indexes = ptrVarIndexes[i];
+ assert(indexes.back() == 0);
+ indexes.pop_back();
+ if(DEBUG_ALLOC_LEVEL >= 4) {
+ magicPassErr("typeInfoFromPointerVariables: " << indexes.size() << " indexes to process.");
+ }
+ while(!indexes.empty()) {
+ int index = indexes.back();
+ if(aTypeInfo->hasRawTypeRepresentation()) {
+ if(DEBUG_ALLOC_LEVEL >= 4) {
+ magicPassErr("typeInfoFromPointerVariables: Skipping index (raw type representation): " << index << ", type is: " << aTypeInfo->getVerboseDescription());
+ }
+ aTypeInfo = voidTypeInfo;
+ break;
+ }
+ if(!aTypeInfo->getType()->isStructTy()) {
+ index = 0;
+ }
+ aTypeInfo = aTypeInfo->getContainedType(index);
+ if(DEBUG_ALLOC_LEVEL >= 4) {
+ magicPassErr("typeInfoFromPointerVariables: Processing index: " << index << ", type is: " << aTypeInfo->getVerboseDescription());
+ }
+ indexes.pop_back();
+ }
+ if(aTypeInfo == voidTypeInfo) {
+ voidTypeTags.push_back(tag);
+ }
+ else {
+ validTypeInfos.push_back(aTypeInfo);
+ validTypeInfoSet.insert(aTypeInfo);
+ validTypeTags.push_back(tag);
+ }
+ if(!allocName.compare("")) {
+ allocName = varName;
+ }
+ }
+ //see if we have a valid void return type
+ bool hasValidVoidReturnType = false;
+ for(unsigned i=0;i<voidTypeTags.size();i++) {
+ if(voidTypeTags[i] == dwarf::DW_TAG_unspecified_type || voidTypeTags[i] == dwarf::DW_TAG_arg_variable) {
+ hasValidVoidReturnType = true;
+ break;
+ }
+ }
+
+ //count the number of weak local types
+ unsigned numWeakLocalTypes = 0;
+ unsigned nonWeakTypeIndex = 0;
+ unsigned index = 0;
+ for (std::set<TypeInfo*>::iterator it=validTypeInfoSet.begin() ; it != validTypeInfoSet.end(); it++ ) {
+ if((*it)->getType() == voidTypeInfo->getType()) {
+ numWeakLocalTypes++;
+ } else {
+ nonWeakTypeIndex = index;
+ }
+ index++;
+ }
+ bool hasOnlyWeakLocalTypes = (numWeakLocalTypes == validTypeInfoSet.size());
+ bool hasOnlyOneNonWeakLocalType = (validTypeInfoSet.size() - numWeakLocalTypes == 1);
+
+ if(DEBUG_ALLOC_LEVEL >= 3) {
+ magicPassErr("typeInfoFromPointerVariables: Status: voidTypeTagsSize=" << voidTypeTags.size() << ", hasValidVoidReturnType=" << hasValidVoidReturnType << ", hasOnlyWeakLocalTypes=" << hasOnlyWeakLocalTypes << ", hasOnlyOneNonWeakLocalType=" << hasOnlyOneNonWeakLocalType);
+ }
+
+ //return NULL (treat the function as a wrapper) if we have a valid return type and only weak local types
+ if(hasValidVoidReturnType && hasOnlyWeakLocalTypes) {
+ if(DEBUG_ALLOC_LEVEL >= 3) {
+ magicPassErr("typeInfoFromPointerVariables: Returning no type at all: treat the function as a wrapper");
+ }
+ return NULL;
+ }
+
+ //a single valid type has been found, return it
+ if(hasOnlyOneNonWeakLocalType || (hasOnlyWeakLocalTypes && validTypeInfoSet.size() > 0)) {
+ if(validTypeTags[nonWeakTypeIndex] == dwarf::DW_TAG_unspecified_type) {
+ if(DEBUG_ALLOC_BAD_TYPES) {
+ magicPassErr("typeInfoFromPointerVariables: warning: non-void return type");
+ }
+ }
+ if(validTypeTags[nonWeakTypeIndex] == dwarf::DW_TAG_arg_variable) {
+ if(DEBUG_ALLOC_BAD_TYPES) {
+ magicPassErr("typeInfoFromPointerVariables: warning: non-void arg type");
+ }
+ }
+ if(DEBUG_ALLOC_LEVEL >= 3) {
+ magicPassErr("typeInfoFromPointerVariables: Returning single valid type");
+ }
+ return validTypeInfos[nonWeakTypeIndex];
+ }
+ //multiple valid types found, print warning and resort to void
+ else if(validTypeInfoSet.size() > 1 && DEBUG_ALLOC_BAD_TYPES) {
+ magicPassErr("typeInfoFromPointerVariables: warning: multiple valid types found:");
+ for (std::set<TypeInfo*>::iterator it=validTypeInfoSet.begin() ; it != validTypeInfoSet.end(); it++ ) {
+ magicPassErr(" - " << (*it)->getVerboseDescription());
+ }
+ if(DEBUG_ALLOC_LEVEL >= 3) {
+ magicPassErr("typeInfoFromPointerVariables: Multiple valid types found");
+ }
+ }
+
+ if(DEBUG_ALLOC_LEVEL >= 3) {
+ magicPassErr("typeInfoFromPointerVariables: Returning default void type");
+ }
+ return voidTypeInfo;
+}
+
+TypeInfo* MagicPass::getAllocTypeInfo(Module &M, TypeInfo *voidPtrTypeInfo, const CallSite &CS, std::string &allocName, std::string &allocParentName)
+{
+ Value *allocPointer = NULL;
+ Function *function = MagicUtil::getCalledFunctionFromCS(CS);
+ Function *parentFunction = CS.getInstruction()->getParent()->getParent();
+ if(DEBUG_ALLOC_LEVEL >= 1) {
+ magicPassErr("Function is: " << function->getName());
+ magicPassErr("Parent is: " << parentFunction->getName());
+ }
+ std::vector<Value*> ptrVars;
+ std::vector<std::vector<int> > ptrVarIndexes;
+ currPtrVarIndexes.clear();
+ visitedValues.clear();
+ int pointerParam = MagicMemFunction::getMemFunctionPointerParam(function, brkFunctions, voidPtrTypeInfo);
+ assert(pointerParam >= 0 && "Invalid wrapper function!");
+ if(pointerParam == 0) {
+ allocPointer = CS.getInstruction();
+ currPtrVarIndexes.push_back(0);
+ }
+ else {
+ allocPointer = CS.getArgument(pointerParam-1);
+ currPtrVarIndexes.push_back(0);
+ //brk is a special case and takes the pointer by value
+ if(brkFunctions.find(function) == brkFunctions.end()) {
+ currPtrVarIndexes.push_back(0);
+ }
+ }
+ findPointerVariables(parentFunction, allocPointer, ptrVars, ptrVarIndexes);
+ TypeInfo* aTypeInfo = typeInfoFromPointerVariables(M, voidPtrTypeInfo, ptrVars, ptrVarIndexes, allocName);
+ allocParentName = MagicUtil::getFunctionSourceName(M, parentFunction, NULL, baseBuildDir);
+ if(DEBUG_ALLOC_LEVEL >= 1) {
+ magicPassErr("**************** type found: " << (aTypeInfo ? aTypeInfo->getType()->isStructTy() ? "struct " + aTypeInfo->getName() : aTypeInfo->getVerboseDescription() : "NULL"));
+ }
+ return aTypeInfo;
+}
+
+TypeInfo* MagicPass::fillTypeInfos(TypeInfo &sourceTypeInfo, std::vector<TypeInfo*> &typeInfos) {
+ static std::vector<TypeInfo*> nestedTypes;
+ static unsigned level = 0;
+ if(DEBUG_FILL_TYPE_INFOS) {
+ magicPassErr("Entering level: " << level << ", Examining type: " << sourceTypeInfo.getDescription() << ", types so far: " << typeInfos.size());
+ }
+
+ if(sourceTypeInfo.getType()) {
+ TYPECONST Type* type = sourceTypeInfo.getType();
+ for(unsigned i=0;i<nestedTypes.size();i++) {
+ if(type == nestedTypes[i]->getType()) {
+ const SmartType *nestedSType = nestedTypes[i]->getSmartType();
+ const SmartType *sourceSType = sourceTypeInfo.getSmartType();
+ if((!nestedSType && !sourceSType) || (nestedSType && sourceSType && nestedSType->getEDIType()->equals(sourceSType->getEDIType()))) {
+ nestedTypes[i]->addParents(sourceTypeInfo.getParents());
+ return nestedTypes[i];
+ }
+ }
+ }
+ }
+ assert(sourceTypeInfo.getParents().size() <= 1);
+ for(unsigned i=0;i<typeInfos.size();i++) {
+ if(typeInfos[i]->equals(&sourceTypeInfo)) {
+ typeInfos[i]->addParents(sourceTypeInfo.getParents());
+ return typeInfos[i];
+ }
+ }
+ TypeInfo *aTypeInfo = new TypeInfo(sourceTypeInfo);
+ aTypeInfo->setPersistent();
+ const SmartType *aSmartType = aTypeInfo->getSmartType();
+ unsigned numContainedTypes = aSmartType ? aSmartType->getNumContainedTypes() : 0;
+ const SmartType* containedSmartType = NULL;
+ TypeInfo* addedTypeInfo = NULL;
+ std::vector<TypeInfo*> aTypeInfoContainedTypes;
+ nestedTypes.push_back(aTypeInfo);
+ level++;
+ for(unsigned i=0;i<numContainedTypes;i++) {
+ containedSmartType = aSmartType->getContainedType(i);
+ if(!containedSmartType->isFunctionTy() || containedSmartType->isTypeConsistent()) {
+ TypeInfo containedTypeInfo(containedSmartType);
+ addedTypeInfo = fillTypeInfos(containedTypeInfo, typeInfos);
+ }
+ else {
+ TYPECONST FunctionType* type = (TYPECONST FunctionType*) containedSmartType->getType();
+ TypeInfo containedTypeInfo(type);
+ addedTypeInfo = fillTypeInfos(containedTypeInfo, typeInfos);
+ }
+ if(addedTypeInfo->getSmartType() != containedSmartType) {
+ delete containedSmartType;
+ }
+ aTypeInfoContainedTypes.push_back(addedTypeInfo);
+ }
+ level--;
+ nestedTypes.pop_back();
+ aTypeInfo->setContainedTypes(aTypeInfoContainedTypes);
+ typeInfos.push_back(aTypeInfo);
+ if(DEBUG_FILL_TYPE_INFOS) {
+ magicPassErr("Exiting level: " << level << ", types so far: " << typeInfos.size());
+ }
+ return aTypeInfo;
+}
+
+TypeInfo* MagicPass::fillExternalTypeInfos(TYPECONST Type *sourceType, GlobalValue* parent, std::vector<TypeInfo*> &typeInfos) {
+ static std::map<TYPECONST Type *, TypeInfo*> externalTypeInfoCache;
+ std::map<TYPECONST Type*, TypeInfo*>::iterator externalTypeInfoCacheIt;
+ TypeInfo* aTypeInfo = NULL;
+ std::vector<TypeInfo*> compatibleTypeInfos;
+ //see if we already have the type in the cache first
+ externalTypeInfoCacheIt = externalTypeInfoCache.find(sourceType);
+ if(externalTypeInfoCacheIt != externalTypeInfoCache.end()) {
+ aTypeInfo = externalTypeInfoCacheIt->second;
+ if(parent) {
+ aTypeInfo->addParent(parent);
+ }
+ return aTypeInfo;
+ }
+
+ for(unsigned i=0;i<typeInfos.size();i++) {
+ if(typeInfos[i]->getSmartType() && typeInfos[i]->getSmartType()->getType() == sourceType && (!sourceType->isArrayTy() || typeInfos[i]->getTypeID() == MAGIC_TYPE_ARRAY)) {
+ compatibleTypeInfos.push_back(typeInfos[i]);
+ }
+ }
+ if(compatibleTypeInfos.size() > 0) {
+ unsigned minStringTypeInfo = 0;
+ if(compatibleTypeInfos.size() > 1) {
+ /* Select the first type in alphabetical order to ensure deterministic behavior. */
+ for(unsigned i=1;i<compatibleTypeInfos.size();i++) {
+ if(compatibleTypeInfos[i]->getSmartType()->getEDIType()->getDescription().compare(compatibleTypeInfos[minStringTypeInfo]->getSmartType()->getEDIType()->getDescription()) < 0) {
+ minStringTypeInfo = i;
+ }
+ }
+ }
+ aTypeInfo = compatibleTypeInfos[minStringTypeInfo];
+ }
+ if(DEBUG_FILL_EXT_TYPE_INFOS && compatibleTypeInfos.size() > 1) {
+ std::string typeString;
+ for(unsigned i=0;i<compatibleTypeInfos.size();i++) {
+ assert(compatibleTypeInfos[i]->getSmartType());
+ typeString += (i==0 ? "" : ", ") + compatibleTypeInfos[i]->getSmartType()->getEDIType()->getDescription();
+ }
+ magicPassErr("Multiple compatible types found for external type " << TypeUtil::getDescription(sourceType, MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL) << ": " << typeString << "; selecting the first type in alphabetical order: " << aTypeInfo->getSmartType()->getEDIType()->getDescription());
+ }
+ if(aTypeInfo == NULL) {
+ TypeInfo *targetTypeInfo = NULL;
+ if(TypeUtil::isOpaqueTy(sourceType)) {
+ aTypeInfo = new TypeInfo((TYPECONST StructType*) sourceType, TYPEINFO_PERSISTENT);
+ typeInfos.push_back(aTypeInfo);
+ }
+ else if(sourceType->isPointerTy()) {
+ TYPECONST Type *targetType = sourceType->getContainedType(0);
+ targetTypeInfo = fillExternalTypeInfos(targetType, NULL, typeInfos);
+ if(targetTypeInfo == NULL) {
+ return NULL;
+ }
+ aTypeInfo = new TypeInfo((TYPECONST PointerType*) sourceType, TYPEINFO_PERSISTENT);
+ }
+ else if(sourceType->isArrayTy()) {
+ TYPECONST Type *targetType = sourceType->getContainedType(0);
+ targetTypeInfo = fillExternalTypeInfos(targetType, NULL, typeInfos);
+ if(targetTypeInfo == NULL) {
+ return NULL;
+ }
+ aTypeInfo = new TypeInfo((TYPECONST ArrayType*) sourceType, TYPEINFO_PERSISTENT);
+ }
+ else if(sourceType->isIntegerTy()) {
+ aTypeInfo = new TypeInfo((TYPECONST IntegerType*) sourceType, TYPEINFO_PERSISTENT);
+ typeInfos.push_back(aTypeInfo);
+ }
+ else if(sourceType->isFunctionTy()) {
+ aTypeInfo = new TypeInfo((TYPECONST FunctionType*) sourceType, TYPEINFO_PERSISTENT);
+ typeInfos.push_back(aTypeInfo);
+ }
+ if(targetTypeInfo != NULL) {
+ std::vector<TypeInfo*> containedTypes;
+ containedTypes.push_back(targetTypeInfo);
+ aTypeInfo->setContainedTypes(containedTypes);
+ typeInfos.push_back(aTypeInfo);
+ }
+ }
+ if(aTypeInfo && parent) {
+ aTypeInfo->addParent(parent);
+ }
+ externalTypeInfoCache.insert(std::pair<TYPECONST Type*, TypeInfo*>(sourceType, aTypeInfo));
+ return aTypeInfo;
+}
+
+void MagicPass::printInterestingTypes(TYPECONST TypeInfo *aTypeInfo) {
+ static std::vector<TYPECONST TypeInfo*> nestedTypes;
+ static std::vector<unsigned> nestedIndexes;
+ static std::vector<TYPECONST TypeInfo*> interestingTypesSoFar;
+ static std::string typeName;
+ static unsigned level = 0;
+ for(unsigned i=0;i<nestedTypes.size();i++) {
+ if(aTypeInfo == nestedTypes[i]) {
+ return;
+ }
+ }
+
+ bool isInterestingType = false;
+ const SmartType *aSmartType = aTypeInfo->getSmartType();
+ if(aSmartType) {
+ if(aSmartType->isStructTy() && !aTypeInfo->getName().compare("")) {
+ isInterestingType = true;
+ typeName = "Anonymous";
+ }
+ if(aSmartType->getEDIType()->isEnumTy()) {
+ isInterestingType = true;
+ typeName = "Enum";
+ }
+ if(aSmartType->isOpaqueTy()) {
+ isInterestingType = true;
+ typeName = "Opaque";
+ }
+ }
+ if(isInterestingType) {
+ bool isNewInterestingType = true;
+ for(unsigned i=0;i<interestingTypesSoFar.size();i++) {
+ if(aTypeInfo == interestingTypesSoFar[i]) {
+ isNewInterestingType = false;
+ break;
+ }
+ }
+ if(isNewInterestingType) {
+ interestingTypesSoFar.push_back(aTypeInfo);
+ if(nestedTypes.size() == 0) {
+ dbgs() << "**** " << typeName << " top type found, printing it: \n";
+ dbgs() << aSmartType->getDescription();
+ aSmartType->getEDIType()->getDIType()->print(dbgs());
+ }
+ else {
+ dbgs() << "**** " << typeName << " type found, printing path: \n";
+ dbgs() << "**************** LEVEL 0\n";
+ dbgs() << "**************** NAME: " << nestedTypes[0]->getName() << "\n";
+ dbgs() << nestedTypes[0]->getSmartType()->getDescription();
+ unsigned i;
+ for(i=1;i<nestedTypes.size();i++) {
+ dbgs() << "**************** LEVEL " << i << "\n";
+ dbgs() << "**************** NAME: " << nestedTypes[i]->getName() << "\n";
+ dbgs() << "**************** PARENT INDEX " << nestedIndexes[i-1] << "\n";
+ dbgs() << nestedTypes[i]->getSmartType()->getDescription();
+ }
+ dbgs() << "**************** LAST LEVEL " << i << "\n";
+ dbgs() << "**************** PARENT INDEX " << nestedIndexes[i-1] << "\n";
+ dbgs() << aSmartType->getDescription();
+ aSmartType->getEDIType()->getDIType()->print(dbgs());
+ dbgs() << "*****************************************\n";
+ }
+ }
+ }
+
+ unsigned numContainedTypes = aTypeInfo->getNumContainedTypes();
+ nestedTypes.push_back(aTypeInfo);
+ level++;
+ for(unsigned i=0;i<numContainedTypes;i++) {
+ nestedIndexes.push_back(i);
+ printInterestingTypes(aTypeInfo->getContainedType(i));
+ nestedIndexes.pop_back();
+ }
+ level--;
+ nestedTypes.pop_back();
+}
+
+unsigned MagicPass::getMaxRecursiveSequenceLength(TYPECONST TypeInfo *aTypeInfo) {
+ static std::vector<TYPECONST TypeInfo*> nestedTypes;
+ static unsigned level = 0;
+ for(unsigned i=0;i<nestedTypes.size();i++) {
+ if(aTypeInfo == nestedTypes[i]) {
+ return nestedTypes.size()+1;
+ }
+ }
+
+ unsigned numContainedTypes = aTypeInfo->getNumContainedTypes();
+ unsigned length, maxLength = 0;
+ nestedTypes.push_back(aTypeInfo);
+ level++;
+ for(unsigned i=0;i<numContainedTypes;i++) {
+ length = getMaxRecursiveSequenceLength(aTypeInfo->getContainedType(i));
+ if(length > maxLength) {
+ maxLength = length;
+ }
+ }
+ level--;
+ nestedTypes.pop_back();
+ return maxLength;
+}
+
+FunctionType* MagicPass::getFunctionType(TYPECONST FunctionType *baseType, std::vector<unsigned> selectedArgs) {
+ std::vector<TYPECONST Type*> ArgTypes;
+ for (unsigned i = 0; i < selectedArgs.size(); i++) {
+ ArgTypes.push_back(baseType->getParamType(selectedArgs[i] - 1));
+ }
+ // Create a new function type...
+ FunctionType *FTy = FunctionType::get(baseType->getReturnType(), ArgTypes, baseType->isVarArg());
+ return FTy;
+}
+
+bool MagicPass::isCompatibleMagicMemFuncType(TYPECONST FunctionType *type, TYPECONST FunctionType* magicType) {
+ if(type->getReturnType() != magicType->getReturnType()) {
+ return false;
+ }
+ unsigned numContainedTypes = type->getNumContainedTypes();
+ unsigned numContainedMagicTypes = magicType->getNumContainedTypes();
+ if(numContainedTypes > numContainedMagicTypes) {
+ return false;
+ }
+ for(unsigned i=0;i<numContainedTypes-1;i++) {
+ TYPECONST Type* cType = type->getContainedType(numContainedTypes-1-i);
+ TYPECONST Type* cMagicType = magicType->getContainedType(numContainedMagicTypes-1-i);
+ if (!MagicUtil::isCompatibleType(cType, cMagicType)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+void MagicPass::indexCasts(Module &M, User *U, std::vector<TYPECONST Type*> &intCastTypes, std::vector<int> &intCastValues, std::map<TYPECONST Type*, std::set<TYPECONST Type*> > &bitCastMap) {
+ unsigned i;
+ std::map<TYPECONST Type*, std::set<TYPECONST Type*> >::iterator bitCastMapIt;
+ TYPECONST Type* voidPtrType = PointerType::get(IntegerType::get(M.getContext(), 8), 0);
+
+ //look at instructions first
+#if MAGIC_INDEX_INT_CAST
+ if(CastInst* CI = dyn_cast<IntToPtrInst>(U)) {
+ TYPECONST Type* type = TypeUtil::getArrayFreePointerType(CI->getDestTy());
+ TYPECONST Type* elType = TypeUtil::getRecursiveElementType(type);
+ if((MAGIC_INDEX_FUN_PTR_INT_CAST && elType->isFunctionTy()) || (MAGIC_INDEX_STR_PTR_INT_CAST && elType->isStructTy()) || MAGIC_INDEX_OTH_PTR_INT_CAST) {
+ if(MAGIC_INDEX_VOID_PTR_INT_CAST || type != voidPtrType) {
+ intCastTypes.push_back(type);
+ ConstantInt *value = dyn_cast<ConstantInt>(CI->getOperand(0));
+ intCastValues.push_back(value ? value->getSExtValue() : 0);
+#if DEBUG_CASTS
+ CI->print(errs()); errs() << "\n";
+#endif
+ }
+ }
+ }
+#endif
+
+#if MAGIC_INDEX_BIT_CAST
+ if(BitCastInst* CI = dyn_cast<BitCastInst>(U)) {
+ TYPECONST Type* type = TypeUtil::getArrayFreePointerType(CI->getDestTy());
+ TYPECONST Type* elType = TypeUtil::getRecursiveElementType(type);
+ if((MAGIC_INDEX_FUN_PTR_BIT_CAST && elType->isFunctionTy()) || (MAGIC_INDEX_STR_PTR_BIT_CAST && elType->isStructTy()) || MAGIC_INDEX_OTH_PTR_BIT_CAST) {
+ if(MAGIC_INDEX_VOID_PTR_BIT_CAST || type != voidPtrType) {
+ TYPECONST Type* srcType = TypeUtil::getArrayFreePointerType(CI->getSrcTy());
+ if(srcType != type && (!MAGIC_SKIP_TOVOID_PTR_BIT_CAST || srcType != voidPtrType)) {
+#if DEBUG_CASTS
+ CI->print(errs()); errs() << "\n";
+#endif
+ bitCastMapIt = bitCastMap.find(type);
+ if(bitCastMapIt == bitCastMap.end()) {
+ std::set<TYPECONST Type*> typeSet;
+ typeSet.insert(srcType);
+ bitCastMap.insert(std::pair<TYPECONST Type*, std::set<TYPECONST Type*> >(type, typeSet));
+ }
+ else {
+ std::set<TYPECONST Type*> *typeSet = &(bitCastMapIt->second);
+ typeSet->insert(srcType);
+ }
+ }
+ }
+ }
+ }
+#endif
+
+ //now dig looking for constant expressions
+ std::vector<User*> users;
+ users.push_back(U);
+ while(!users.empty()) {
+ User *user = users.front();
+ users.erase(users.begin());
+ ConstantExpr *CE = dyn_cast<ConstantExpr>(user);
+
+#if MAGIC_INDEX_INT_CAST
+ if(CE && CE->getOpcode() == Instruction::IntToPtr) {
+ TYPECONST Type* type = TypeUtil::getArrayFreePointerType(CE->getType());
+ TYPECONST Type* elType = TypeUtil::getRecursiveElementType(type);
+ if((MAGIC_INDEX_FUN_PTR_INT_CAST && elType->isFunctionTy()) || (MAGIC_INDEX_STR_PTR_INT_CAST && elType->isStructTy()) || MAGIC_INDEX_OTH_PTR_INT_CAST) {
+ if(MAGIC_INDEX_VOID_PTR_INT_CAST || type != voidPtrType) {
+#if DEBUG_CASTS
+ CE->print(errs()); errs() << "\n";
+#endif
+ intCastTypes.push_back(type);
+ ConstantInt *value = dyn_cast<ConstantInt>(CE->getOperand(0));
+ intCastValues.push_back(value ? value->getSExtValue() : 0);
+ }
+ }
+ }
+#endif
+
+#if MAGIC_INDEX_BIT_CAST
+ if(CE && CE->getOpcode() == Instruction::BitCast) {
+ TYPECONST Type* type = TypeUtil::getArrayFreePointerType(CE->getType());
+ TYPECONST Type* elType = TypeUtil::getRecursiveElementType(type);
+ if((MAGIC_INDEX_FUN_PTR_BIT_CAST && elType->isFunctionTy()) || (MAGIC_INDEX_STR_PTR_BIT_CAST && elType->isStructTy()) || MAGIC_INDEX_OTH_PTR_BIT_CAST) {
+ if(MAGIC_INDEX_VOID_PTR_BIT_CAST || type != voidPtrType) {
+ TYPECONST Type* srcType = TypeUtil::getArrayFreePointerType(CE->getOperand(0)->getType());
+ if(srcType != type && (!MAGIC_SKIP_TOVOID_PTR_BIT_CAST || srcType != voidPtrType)) {
+#if DEBUG_CASTS
+ CE->print(errs()); errs() << "\n";
+#endif
+ bitCastMapIt = bitCastMap.find(type);
+ if(bitCastMapIt == bitCastMap.end()) {
+ std::set<TYPECONST Type*> typeSet;
+ typeSet.insert(srcType);
+ bitCastMap.insert(std::pair<TYPECONST Type*, std::set<TYPECONST Type*> >(type, typeSet));
+ }
+ else {
+ std::set<TYPECONST Type*> *typeSet = &(bitCastMapIt->second);
+ typeSet->insert(srcType);
+ }
+ }
+ }
+ }
+ }
+#endif
+
+ for(i=0;i<user->getNumOperands();i++) {
+ User *operand = dyn_cast<User>(user->getOperand(i));
+ if(operand && !isa<Instruction>(operand) && !isa<GlobalVariable>(operand)) {
+ users.push_back(operand);
+ }
+ }
+ }
+}
+
+void MagicPass::fillStackInstrumentedFunctions(std::vector<Function*> &stackIntrumentedFuncs, Function *deepestLLFunction) {
+ assert(!deepestLLFunction->hasAddressTaken() && "Indirect calls not supported for detection of long-lived functions");
+ for(unsigned i=0;i<stackIntrumentedFuncs.size();i++) {
+ if(stackIntrumentedFuncs[i] == deepestLLFunction) {
+ return;
+ }
+ }
+ stackIntrumentedFuncs.push_back(deepestLLFunction);
+ for (Value::use_iterator i = deepestLLFunction->use_begin(), e = deepestLLFunction->use_end(); i != e; ++i) {
+ User *user = *i;
+ if(Instruction *I = dyn_cast<Instruction>(user)) {
+ fillStackInstrumentedFunctions(stackIntrumentedFuncs, I->getParent()->getParent());
+ }
+ }
+}
+
+void MagicPass::indexLocalTypeInfos(Module &M, Function *F, std::map<AllocaInst*, std::pair<TypeInfo*, std::string> > &localMap) {
+ DIVariable DIV;
+ for (inst_iterator it = inst_begin(F), et = inst_end(F); it != et; ++it) {
+ AllocaInst *AI = dyn_cast<AllocaInst>(&(*it));
+ if(!AI) {
+ break;
+ }
+ const SmartType *aSmartType = SmartType::getSmartTypeFromLV(M, AI, &DIV);
+ if(!aSmartType || aSmartType == (const SmartType *)-1) {
+ // skip return and temporary variables
+ continue;
+ }
+ TypeInfo newTypeInfo(aSmartType);
+ TypeInfo *aTypeInfo = fillTypeInfos(newTypeInfo, globalTypeInfos);
+ if(aTypeInfo->getSmartType() != aSmartType) {
+ delete aSmartType;
+ }
+ std::string name = MagicUtil::getLVSourceName(M, AI).data();
+ std::pair<TypeInfo*, std::string> infoNamePair(aTypeInfo, name);
+ localMap.insert(std::pair<AllocaInst*, std::pair<TypeInfo*, std::string> >(AI, infoNamePair));
+ }
+}
+
+void MagicPass::addMagicStackDsentryFuncCalls(Module &M, Function *insertCallsInFunc, Function *localsFromFunc, Function *dsentryCreateFunc, Function *dsentryDestroyFunc, TYPECONST StructType *dsentryStructType, std::map<AllocaInst*, std::pair<TypeInfo*, std::string> > localTypeInfoMap, std::map<TypeInfo*, Constant*> &magicArrayTypePtrMap, TypeInfo *voidPtrTypeInfo, std::vector<TypeInfo*> &typeInfoList, std::vector<std::pair<std::string, std::string> > &namesList, std::vector<int> &flagsList) {
+ std::vector<Value*> locals;
+ std::map<AllocaInst*, std::pair<TypeInfo*, std::string> >::iterator localTypeInfoMapIt;
+ std::map<TypeInfo*, Constant*>::iterator magicArrayTypePtrMapIt;
+ std::vector<TypeInfo*> localTypeInfos;
+ std::vector<Value*> localTypeInfoValues;
+ std::vector<Value*> localDsentryValues;
+ std::string allocName, allocParentName;
+ Instruction *allocaI = NULL, *dsentryCreateI = NULL, *dsentryDestroyI = NULL;
+ // find local variables and types
+ for (inst_iterator it = inst_begin(localsFromFunc), et = inst_end(localsFromFunc); it != et; ++it) {
+ AllocaInst *AI = dyn_cast<AllocaInst>(&(*it));
+ if(!AI) {
+ break;
+ }
+ localTypeInfoMapIt = localTypeInfoMap.find(AI);
+ if(localTypeInfoMapIt != localTypeInfoMap.end()) {
+ assert(AI->hasName());
+ TypeInfo *aTypeInfo = localTypeInfoMapIt->second.first;
+ magicArrayTypePtrMapIt = magicArrayTypePtrMap.find(aTypeInfo);
+ assert(magicArrayTypePtrMapIt != magicArrayTypePtrMap.end());
+ Constant *aTypeInfoValue = magicArrayTypePtrMapIt->second;
+ localTypeInfos.push_back(aTypeInfo);
+ localTypeInfoValues.push_back(aTypeInfoValue);
+ locals.push_back(AI);
+ }
+ }
+ // find the first and the last valid instruction to place a call and the alloca point
+ dsentryCreateI = MagicUtil::getFirstNonAllocaInst(insertCallsInFunc);
+ dsentryDestroyI = insertCallsInFunc->back().getTerminator();
+ allocaI = MagicUtil::getFirstNonAllocaInst(insertCallsInFunc, false);
+
+ // create one dsentry for each local variable
+ for(unsigned i=0;i<locals.size();i++) {
+ AllocaInst *AI = new AllocaInst(dsentryStructType, "dsentry_" + (locals[i]->hasName() ? locals[i]->getName() : "anon"), allocaI);
+ localDsentryValues.push_back(AI);
+ }
+ assert(localTypeInfoValues.size() == localDsentryValues.size());
+
+ // create one dsentry and value set array for the return address
+ localTypeInfos.push_back(voidPtrTypeInfo);
+ localTypeInfoValues.push_back(new AllocaInst(ArrayType::get(IntegerType::get(M.getContext(), 32), 2), "dsentry_ret_addr_value_set", allocaI)); //pass the value set pointer as though it were a type pointer
+ localDsentryValues.push_back(new AllocaInst(dsentryStructType, "dsentry_ret_addr", allocaI));
+
+ // create one dsentry pointer to remember the last stack dsentry
+ AllocaInst *prevLastStackDsentry = new AllocaInst(PointerType::get(dsentryStructType, 0), "prev_last_stack_dsentry", allocaI);
+
+ // get the frame address of the function and pass the value as though it were a data pointer
+ Function *frameAddrIntrinsic = MagicUtil::getIntrinsicFunction(M, Intrinsic::frameaddress);
+ std::vector<Value*> frameAddrArgs;
+ frameAddrArgs.push_back(ConstantInt::get(M.getContext(), APInt(32, 0)));
+ CallInst *callInst = MagicUtil::createCallInstruction(frameAddrIntrinsic, frameAddrArgs, "", dsentryCreateI);
+ locals.push_back(callInst);
+
+ // place calls
+ std::vector<Value*> dsentryCreateArgs;
+ std::vector<Value*> dsentryDestroyArgs;
+ dsentryCreateArgs.push_back(prevLastStackDsentry);
+ dsentryDestroyArgs.push_back(prevLastStackDsentry);
+ dsentryCreateArgs.push_back(ConstantInt::get(M.getContext(), APInt(32, locals.size())));
+ dsentryDestroyArgs.push_back(ConstantInt::get(M.getContext(), APInt(32, locals.size())));
+ allocParentName = MagicUtil::getFunctionSourceName(M, insertCallsInFunc, NULL, baseBuildDir);
+ int allocFlags = MAGIC_STATE_STACK;
+ for(unsigned i=0;i<locals.size();i++) {
+ //get name
+ if(AllocaInst *AI = dyn_cast<AllocaInst>(locals[i])) {
+ // local variable
+ localTypeInfoMapIt = localTypeInfoMap.find(AI);
+ assert(localTypeInfoMapIt != localTypeInfoMap.end());
+ allocName = localTypeInfoMapIt->second.second;
+ }
+ else {
+ // return address
+ allocName = MAGIC_ALLOC_RET_ADDR_NAME;
+ }
+ //add args
+ dsentryCreateArgs.push_back(localDsentryValues[i]);
+ dsentryCreateArgs.push_back(localTypeInfoValues[i]);
+ dsentryCreateArgs.push_back(locals[i]);
+ dsentryCreateArgs.push_back(MagicUtil::getStringRef(M, allocParentName));
+ dsentryCreateArgs.push_back(MagicUtil::getStringRef(M, allocName));
+ dsentryDestroyArgs.push_back(localDsentryValues[i]);
+ //add elements to type and names lists
+ typeInfoList.push_back(localTypeInfos[i]);
+ namesList.push_back(std::pair<std::string, std::string>(allocParentName, allocName));
+ flagsList.push_back(allocFlags);
+ }
+ MagicUtil::createCallInstruction(dsentryCreateFunc, dsentryCreateArgs, "", dsentryCreateI);
+ if(isa<ReturnInst>(dsentryDestroyI)) {
+ MagicUtil::createCallInstruction(dsentryDestroyFunc, dsentryDestroyArgs, "", dsentryDestroyI);
+ }
+}
+
+bool MagicPass::isExtLibrary(GlobalValue *GV, DIDescriptor *DID)
+{
+ static bool regexesInitialized = false;
+ static std::vector<Regex*> regexes;
+ if(!regexesInitialized) {
+ std::vector<std::string>::iterator it;
+ for (it = libPathRegexes.begin(); it != libPathRegexes.end(); ++it) {
+ Regex* regex = new Regex(*it, 0);
+ std::string error;
+ assert(regex->isValid(error));
+ regexes.push_back(regex);
+ }
+ regexesInitialized = true;
+ }
+ if (DID) {
+ std::string relPath;
+ PassUtil::getDbgLocationInfo(*DID, baseBuildDir, NULL, NULL, &relPath);
+ for(unsigned i=0;i<regexes.size();i++) {
+ if(regexes[i]->match(relPath, NULL)) {
+ return true;
+ }
+ }
+ }
+ return PassUtil::matchRegexes(GV->getSection(), extLibSectionRegexes);
+}
+
+bool MagicPass::isMagicGV(Module &M, GlobalVariable *GV)
+{
+ if (GV->isThreadLocal() && (GV->getName().startswith(MAGIC_PREFIX_STR) || GV->getName().startswith("rcu"))) {
+ return true;
+ }
+ if (!GV->getSection().compare(MAGIC_LLVM_METADATA_SECTION)) {
+ return true;
+ }
+ if (GV->getName().startswith("__start") || GV->getName().startswith("__stop") || GV->getName().startswith("llvm.")) {
+ return true;
+ }
+ return PassUtil::matchRegexes(GV->getSection(), magicDataSectionRegexes);
+}
+
+bool MagicPass::isMagicFunction(Module &M, Function *F)
+{
+ if (F->getName().startswith("llvm.")) return true;
+ return PassUtil::matchRegexes(F->getSection(), magicFunctionSectionRegexes);
+}
+
+#if MAGIC_USE_QPROF_INSTRUMENTATION
+
+void MagicPass::qprofInstrumentationInit(Module &M)
+{
+ // look up qprof configuration
+ qprofConf = QProfConf::get(M, &magicLLSitestacks,
+ &magicDeepestLLLoops,
+ &magicDeepestLLLibs,
+ &magicTaskClasses);
+ qprofConf->mergeAllTaskClassesWithSameDeepestLLLoops();
+
+#if DEBUG_QPROF
+ qprofConf->print(errs());
+#endif
+}
+
+void MagicPass::qprofInstrumentationApply(Module &M)
+{
+ Function *hook;
+ std::vector<Value*> hookParams;
+ QProfSite* site;
+ std::vector<TYPECONST Type*>functionTyArgs;
+ FunctionType *hookFunctionTy;
+
+ /*
+ * Instrument deepest long-lived loops. This creates a function
+ * pointer of the form void (*MAGIC_DEEPEST_LL_LOOP_HOOK_NAME)(char*, int)
+ * called (if set by instrumentation libraries) at the top of every loop.
+ */
+ functionTyArgs.push_back(PointerType::get(IntegerType::get(M.getContext(), 8), 0));
+ functionTyArgs.push_back(IntegerType::get(M.getContext(), 32));
+ hookFunctionTy = PassUtil::getFunctionType(Type::getVoidTy(M.getContext()), functionTyArgs, false);
+ std::vector<QProfSite*> deepestLLLoops = qprofConf->getDeepestLLLoops();
+ hook = PassUtil::getOrInsertFunction(M, MAGIC_DEEPEST_LL_LOOP_HOOK_NAME, hookFunctionTy,
+ PASS_UTIL_LINKAGE_WEAK_POINTER, PASS_UTIL_FLAG(PASS_UTIL_PROP_PRESERVE));
+ assert(hook);
+ for (unsigned i=0;i<deepestLLLoops.size();i++) {
+ site = deepestLLLoops[i];
+ hookParams.clear();
+ Constant* siteString = MagicUtil::getArrayPtr(M, MagicUtil::getStringRef(M, site->toString()));
+ hookParams.push_back(siteString);
+ hookParams.push_back(ConstantInt::get(M.getContext(), APInt(32, site->taskClassID, 10)));
+ PassUtil::createCallInstruction(hook, hookParams, "", site->siteInstruction);
+ }
+
+ /*
+ * Instrument deepest long-lived library calls. This creates a function
+ * pointer of the form void (*MAGIC_DEEPEST_LL_LIB_HOOK_NAME)(char*, int, int, int)
+ * called (if set by instrumentation libraries) before every library call.
+ */
+ functionTyArgs.clear();
+ functionTyArgs.push_back(PointerType::get(IntegerType::get(M.getContext(), 8), 0));
+ functionTyArgs.push_back(IntegerType::get(M.getContext(), 32));
+ functionTyArgs.push_back(IntegerType::get(M.getContext(), 32));
+ functionTyArgs.push_back(IntegerType::get(M.getContext(), 32));
+ hookFunctionTy = PassUtil::getFunctionType(Type::getVoidTy(M.getContext()), functionTyArgs, false);
+ std::vector<QProfSite*> deepestLLLibs = qprofConf->getDeepestLLLibs();
+ hook = PassUtil::getOrInsertFunction(M, MAGIC_DEEPEST_LL_LIB_HOOK_NAME, hookFunctionTy,
+ PASS_UTIL_LINKAGE_WEAK_POINTER, PASS_UTIL_FLAG(PASS_UTIL_PROP_PRESERVE));
+ assert(hook);
+ for (unsigned i=0;i<deepestLLLibs.size();i++) {
+ site = deepestLLLibs[i];
+ hookParams.clear();
+ Constant* siteString = MagicUtil::getArrayPtr(M, MagicUtil::getStringRef(M, site->toString()));
+ hookParams.push_back(siteString);
+ hookParams.push_back(ConstantInt::get(M.getContext(), APInt(32, site->taskClassID, 10)));
+ hookParams.push_back(ConstantInt::get(M.getContext(), APInt(32, site->taskSiteID, 10)));
+ hookParams.push_back(ConstantInt::get(M.getContext(), APInt(32, site->libFlags, 10)));
+ PassUtil::createCallInstruction(hook, hookParams, "", site->siteInstruction);
+ }
+
+ /*
+ * Create relevant exported variables in use by the libraries.
+ */
+ MagicUtil::getExportedIntGlobalVar(M, MAGIC_NUM_LL_TASK_CLASSES_NAME, qprofConf->getNumLLTaskClasses());
+ MagicUtil::getExportedIntGlobalVar(M, MAGIC_NUM_LL_BLOCK_EXT_TASK_CLASSES_NAME, qprofConf->getNumLLBlockExtTaskClasses());
+ MagicUtil::getExportedIntGlobalVar(M, MAGIC_NUM_LL_BLOCK_INT_TASK_CLASSES_NAME, qprofConf->getNumLLBlockIntTaskClasses());
+ MagicUtil::getExportedIntGlobalVar(M, MAGIC_NUM_LL_BLOCK_EXT_LIBS_NAME, qprofConf->getNumLLBlockExtLibs());
+ MagicUtil::getExportedIntGlobalVar(M, MAGIC_NUM_LL_BLOCK_INT_LIBS_NAME, qprofConf->getNumLLBlockIntLibs());
+}
+
+#else
+
+void MagicPass::qprofInstrumentationInit(Module &M) {}
+void MagicPass::qprofInstrumentationApply(Module &M) {}
+
+#endif
+
+} // end namespace
+
+char MagicPass::ID = 0;
+RegisterPass<MagicPass> MP("magic", "Magic Pass to Build a Table of Global Variables");
+
--- /dev/null
+PASSNAME = magic
+
+OBJS = support/Backports.o support/EDIType.o support/TypeUtil.o support/BitFieldAggregation.o support/SmartType.o support/VariableRefs.o support/MagicUtil.o MagicPass.o
+HEADERS = $(wildcard ../include/magic/support/*.h)
+
+include ../Makefile.inc
--- /dev/null
+#include <pass.h>
+
+#include <magic/support/Backports.h>
+#include <magic/support/EDIType.h>
+#include <magic/support/SmartType.h>
+
+using namespace llvm;
+
+namespace llvm {
+
+//===----------------------------------------------------------------------===//
+// Public static methods
+//===----------------------------------------------------------------------===//
+
+/// Find the debug info descriptor corresponding to this global variable.
+Value *Backports::findDbgGlobalDeclare(GlobalVariable *V) {
+ return PassUtil::findDbgGlobalDeclare(V);
+}
+
+/// Find the debug info descriptor corresponding to this function.
+Value *Backports::findDbgSubprogramDeclare(Function *V) {
+ return PassUtil::findDbgSubprogramDeclare(V);
+}
+
+/// Finds the llvm.dbg.declare intrinsic corresponding to this value if any.
+/// It looks through pointer casts too.
+const DbgDeclareInst *Backports::findDbgDeclare(const Value *V) {
+ V = V->stripPointerCasts();
+
+ if (!isa<Instruction>(V) && !isa<Argument>(V))
+ return 0;
+
+ const Function *F = NULL;
+ if (const Instruction *I = dyn_cast<Instruction>(V))
+ F = I->getParent()->getParent();
+ else if (const Argument *A = dyn_cast<Argument>(V))
+ F = A->getParent();
+
+ for (Function::const_iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI)
+ for (BasicBlock::const_iterator BI = (*FI).begin(), BE = (*FI).end();
+ BI != BE; ++BI)
+ if (const DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(BI))
+ if (DDI->getAddress() == V)
+ return DDI;
+
+ return 0;
+}
+
+/// FindAllocaDbgDeclare - Finds the llvm.dbg.declare intrinsic describing the
+/// alloca 'V', if any.
+DbgDeclareInst *Backports::FindAllocaDbgDeclare(Value *V) {
+#if LLVM_VERSION >= 33
+ if (MDNode *DebugNode = MDNode::getIfExists(V->getContext(), V))
+ for (Value::use_iterator UI = DebugNode->use_begin(),
+ E = DebugNode->use_end(); UI != E; ++UI)
+ if (DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(*UI))
+ return DDI;
+
+ return 0;
+#else
+
+///
+/// There is an unfixed bug (http://llvm.org/bugs/show_bug.cgi?id=10887)
+/// that drops debug information references for local variables at linking time.
+/// This is way the method FindAllocaDbgDeclare() will always return NULL and
+/// we need to resort to some ugly workaround.
+///
+ AllocaInst *AI = dyn_cast<AllocaInst>(V);
+ if(!AI) {
+ return NULL;
+ }
+ BasicBlock *varParent = AI->getParent();
+ Function *varFunc = varParent->getParent();
+ if(!AI->hasName() || !AI->getName().compare("retval")) {
+ return NULL;
+ }
+ StringRef varName = AI->getName();
+ bool isInlinedVar = false;
+ bool isScopedVar = false;
+ DIType aDIType, aAddrDIType, tmpDIType;
+ DbgDeclareInst *DDI = NULL, *addrDDI = NULL;
+ SmallVector< StringRef, 8 > vector;
+ varName.split(vector, ".");
+ if(vector.size() >= 2 && vector[1][0] == 'i') {
+ isInlinedVar = true;
+ varName = vector[0];
+ }
+ if(!isInlinedVar) {
+ //for non-inlined variables we have to look in the first bb first.
+ for(BasicBlock::iterator i=varParent->begin(), e=varParent->end();i!=e;i++) {
+ if(DbgDeclareInst *DI = dyn_cast<DbgDeclareInst>(i)) {
+ MDNode *node = DI->getVariable();
+ assert(node);
+ DIVariable DIV(node);
+ if(!DIV.getName().compare(varName)) {
+ aDIType = DIV.getType();
+ DDI = DI;
+ break;
+ }
+ StringRef addrVarName(DIV.getName().str() + "_addr");
+ if(!addrVarName.compare(varName)) {
+ aAddrDIType = DIV.getType();
+ addrDDI = DI;
+ break;
+ }
+ }
+ }
+ if(!DDI && !addrDDI) {
+ //not found? probably a scoped variable, look anywhere else.
+ isScopedVar = true;
+ }
+ }
+ if(isInlinedVar || isScopedVar) {
+ //for inlined/scoped variables we have to look everywhere in the function and name clashing could also occur.
+ bool isDuplicate = false;
+ for (inst_iterator it = inst_begin(varFunc), et = inst_end(varFunc); it != et; ++it) {
+ Instruction *inst = &(*it);
+ if(DbgDeclareInst *DI = dyn_cast<DbgDeclareInst>(inst)) {
+ MDNode *node = DI->getVariable();
+ assert(node);
+ DIVariable DIV(node);
+ StringRef addrVarName(DIV.getName().str() + "_addr");
+ if(!DIV.getName().compare(varName) || !addrVarName.compare(varName)) {
+ tmpDIType = DIV.getType();
+ EDIType tmpEDIType(tmpDIType);
+ if(!SmartType::isTypeConsistent(AI->getAllocatedType(), &tmpEDIType)) {
+ continue;
+ }
+ bool skipDIType = false;
+ if(DDI) {
+ EDIType aEDIType(aDIType);
+ skipDIType = true;
+ if(!aEDIType.equals(&tmpEDIType)) {
+ isDuplicate = true;
+ }
+ }
+ if(addrDDI) {
+ EDIType aAddrEDIType(aAddrDIType);
+ skipDIType = true;
+ if(!aAddrEDIType.equals(&tmpEDIType)) {
+ isDuplicate = true;
+ }
+ }
+ if(!skipDIType && !DIV.getName().compare(varName)) {
+ aDIType = tmpDIType;
+ DDI = DI;
+ continue;
+ }
+ if(!skipDIType && !addrVarName.compare(varName)) {
+ aAddrDIType = tmpDIType;
+ addrDDI = DI;
+ continue;
+ }
+ }
+ }
+ }
+ if(isDuplicate) {
+ //name clashing problem with inline/scoped variables, pretend nothing was found
+ DDI = NULL;
+ addrDDI = NULL;
+ }
+ }
+ if(!DDI && !addrDDI) {
+ return (DbgDeclareInst*)-1;
+ }
+ assert((DDI && !addrDDI) || (!DDI && addrDDI));
+ DDI = DDI ? DDI : addrDDI;
+ return DDI;
+#endif
+}
+
+}
--- /dev/null
+#include <magic/support/BitFieldAggregation.h>
+
+using namespace llvm;
+
+namespace llvm {
+
+#define DEBUG_BFA 0
+
+#define BitFieldAggregation_assert_or_return(R,RV,T,ET,X) do { \
+ if(!(X)) { \
+ if(R) return RV; \
+ errs() << "Assertion failed, dumping types...\n"; \
+ errs() << TypeUtil::getDescription(T, ET); \
+ } \
+ assert(X); \
+ } while(0)
+
+//===----------------------------------------------------------------------===//
+// Constructors, destructor, and operators
+//===----------------------------------------------------------------------===//
+
+BitFieldAggregation::BitFieldAggregation(TYPECONST Type* type, std::vector<EDIType> EDITypes, unsigned typeIndex, unsigned EDITypeIndex, std::vector<DIDerivedType> members, unsigned counter) {
+ init(type, EDITypes, typeIndex, EDITypeIndex, members, counter);
+}
+
+BitFieldAggregation::BitFieldAggregation() {
+ type = NULL;
+ typeIndex = 0;
+ EDITypeIndex = 0;
+ name = "";
+}
+
+void BitFieldAggregation::init(TYPECONST Type* type, std::vector<EDIType> EDITypes, unsigned typeIndex, unsigned EDITypeIndex, std::vector<DIDerivedType> members, unsigned counter) {
+ assert(members.size() == EDITypes.size());
+ assert(typeIndex <= EDITypeIndex);
+ size = members.size();
+ assert(size > 0);
+
+ this->type = type;
+ this->EDITypes = EDITypes;
+ this->typeIndex = typeIndex;
+ this->EDITypeIndex = EDITypeIndex;
+ this->members = members;
+ raw_string_ostream ostream(name);
+ ostream << bfaNamePrefix << counter;
+ ostream.flush();
+}
+
+//===----------------------------------------------------------------------===//
+// Getters
+//===----------------------------------------------------------------------===//
+
+const std::string BitFieldAggregation::getDescription() const {
+ std::string string;
+ raw_string_ostream ostream(string);
+ ostream << "[\nname = " << name << "\nmembers = ";
+ for(unsigned i=0;i<size;i++) {
+ ostream << (i==0 ? "" : ", ") << members[i].getName();
+ }
+ ostream << "\ntype = \n" << TypeUtil::getDescription(getType());
+ std::vector<EDIType> EDITypes = getEDITypes();
+ for(unsigned i=0;i<EDITypes.size();i++) {
+ ostream << "\nEDIType" << i << " =\n" << TypeUtil::getDescription(&EDITypes[i]);
+ }
+ ostream << "\n]";
+ ostream.flush();
+ return string;
+}
+
+//===----------------------------------------------------------------------===//
+// Public static methods
+//===----------------------------------------------------------------------===//
+
+bool BitFieldAggregation::getBitFieldAggregations(TYPECONST Type *type, const EDIType *aEDIType, std::vector<BitFieldAggregation> &bfas, bool returnOnError) {
+ std::vector<BitFieldAggregation> emptyBfas;
+ if(!hasBitFields(type, aEDIType)) {
+ return true;
+ }
+ unsigned typeIndex = 0;
+ unsigned EDITypeIndex = 0;
+ unsigned typeContainedTypes = type->getNumContainedTypes();
+ unsigned aEDITypeContainedTypes = aEDIType->getNumContainedTypes();
+ unsigned counter = 1;
+ const EDIType privateEDIType(*aEDIType);
+ aEDIType = &privateEDIType;
+ while(typeIndex < typeContainedTypes) {
+ TYPECONST Type *containedType = type->getContainedType(typeIndex);
+ if(EDITypeIndex >= aEDITypeContainedTypes && typeIndex == typeContainedTypes-1 && TypeUtil::isPaddedType(type)) {
+ break;
+ }
+ BitFieldAggregation_assert_or_return(returnOnError, false, type, aEDIType, EDITypeIndex < aEDITypeContainedTypes);
+ const EDIType containedEDIType = aEDIType->getContainedType(EDITypeIndex);
+ unsigned typeBits = TypeUtil::typeToBits(containedType);
+ if(typeBits > 0 && containedEDIType.isIntegerTy()) {
+ unsigned EDITypeBits = aEDIType->getMember(EDITypeIndex).getSizeInBits();
+ assert(typeBits >= EDITypeBits);
+ if(typeBits > EDITypeBits) {
+ unsigned lastTypeIndex = typeIndex;
+ unsigned lastEDITypeIndex = EDITypeIndex;
+ while(lastEDITypeIndex+1 < aEDITypeContainedTypes && isBitField(type, aEDIType, lastEDITypeIndex+1)) { // grab all the bitfields following the first one found
+ lastEDITypeIndex++;
+ EDITypeBits += aEDIType->getMember(lastEDITypeIndex).getSizeInBits();
+ }
+ while(lastTypeIndex+1 < typeContainedTypes && EDITypeBits > typeBits) { // grab all the necessary fields to cover all the bits found in the bitfields
+ lastTypeIndex++;
+ typeBits += TypeUtil::typeToBits(type->getContainedType(lastTypeIndex));
+ }
+ BitFieldAggregation *bfa = BitFieldAggregation::getBitFieldAggregation(type, aEDIType, returnOnError, typeIndex, EDITypeIndex, lastTypeIndex, lastEDITypeIndex, counter++);
+ BitFieldAggregation_assert_or_return(returnOnError, false, type, aEDIType, bfa != NULL);
+ if(bfa->getSize() > 1) {
+ //we don't care about single-element aggregates
+ bfas.push_back(*bfa);
+ }
+ typeIndex++;
+ EDITypeIndex += bfa->getSize();
+ continue;
+ }
+ }
+ typeIndex++;
+ EDITypeIndex++;
+ }
+ return true;
+}
+
+BitFieldAggregation *BitFieldAggregation::getBitFieldAggregation(TYPECONST Type *type, const EDIType *aEDIType, bool returnOnError, unsigned typeIndex, unsigned EDITypeIndex, unsigned lastTypeIndex, unsigned lastEDITypeIndex, unsigned counter) {
+ static BitFieldAggregation bfa;
+ TYPECONST Type *containedType = type->getContainedType(typeIndex);
+ unsigned typeBits = TypeUtil::typeToBits(containedType);
+ assert(typeBits > 0);
+ unsigned nextTypeBits = 0;
+ if (typeIndex < lastTypeIndex) {
+ nextTypeBits = TypeUtil::typeToBits(type->getContainedType(typeIndex+1));
+ }
+ const int maxNumMembers = (lastEDITypeIndex - EDITypeIndex) - (lastTypeIndex - typeIndex) + 1;
+ unsigned index = EDITypeIndex;
+ std::vector<DIDerivedType> members;
+ std::vector<EDIType> containedEDITypes;
+
+ BitFieldAggregation_assert_or_return(returnOnError, NULL, type, aEDIType, maxNumMembers > 0);
+#if DEBUG_BFA
+ BitFieldAggregationErr("getBitFieldAggregation(): typeIndex = " << typeIndex << ", EDITypeIndex = " << EDITypeIndex << ", maxNumMembers = " << maxNumMembers);
+ BitFieldAggregationErr("getBitFieldAggregation(): lastTypeIndex = " << lastTypeIndex << ", lastEDITypeIndex = " << lastEDITypeIndex);
+ BitFieldAggregationErr("getBitFieldAggregation(): " << TypeUtil::getDescription(type) << " VS " << TypeUtil::getDescription(aEDIType));
+#endif
+ while(index <= lastEDITypeIndex && members.size() < (unsigned)maxNumMembers) {
+ const EDIType containedEDIType = aEDIType->getContainedType(index);
+#if DEBUG_BFA
+ BitFieldAggregationErr("Examining type " << TypeUtil::getDescription(&containedEDIType));
+#endif
+ BitFieldAggregation_assert_or_return(returnOnError, NULL, type, aEDIType, containedEDIType.isIntegerTy());
+ DIDerivedType member = aEDIType->getMember(index);
+ unsigned EDITypeBits = member.getSizeInBits();
+#if DEBUG_BFA
+ BitFieldAggregationErr("Type bits = " << typeBits << ", next type bits = " << nextTypeBits << ", index = " << index);
+ BitFieldAggregationErr("This is member " << member.getName() << " with bits " << EDITypeBits);
+#endif
+ if((index > EDITypeIndex && EDITypeBits == nextTypeBits) || EDITypeBits > typeBits) {
+ break;
+ }
+ typeBits -= EDITypeBits;
+ members.push_back(member);
+ containedEDITypes.push_back(containedEDIType);
+ index++;
+ }
+ bfa.init(containedType, containedEDITypes, typeIndex, EDITypeIndex, members, counter);
+ return &bfa;
+}
+
+std::string BitFieldAggregation::bfaNamePrefix = BFA_NAME_PREFIX;
+
+}
--- /dev/null
+
+#include <magic/support/EDIType.h>
+
+using namespace llvm;
+
+namespace llvm {
+
+#define DEBUG_EDI_EQUALS 0
+int debugEDIEquals = 0;
+
+//===----------------------------------------------------------------------===//
+// Constructors, destructor, and operators
+//===----------------------------------------------------------------------===//
+
+EDIType::EDIType(const MDNode *N, bool norm, bool checkOpaqueTypes) : aDIType(N) {
+ init(norm, checkOpaqueTypes);
+}
+
+EDIType::EDIType(bool norm, bool checkOpaqueTypes) : aDIType() {
+ init(norm, checkOpaqueTypes);
+}
+
+EDIType::EDIType(const DIType aDIType, bool norm, bool checkOpaqueTypes) : aDIType(aDIType) {
+ init(norm, checkOpaqueTypes);
+}
+
+bool EDIType::operator == (const EDIType& aEDIType) const {
+ const DIType oDIType = *(aEDIType.getDIType());
+ return (aDIType == oDIType);
+}
+
+//===----------------------------------------------------------------------===//
+// Getters
+//===----------------------------------------------------------------------===//
+
+const std::string EDIType::getDescription(int skipUnions, int skipStructs, int allowMultiNames) const {
+ std::string string;
+ raw_string_ostream ostream(string);
+ printDescription(ostream, skipUnions, skipStructs, allowMultiNames);
+ ostream.flush();
+ return string;
+}
+
+const EDIType& EDIType::getContainedType(unsigned i, bool norm) const {
+ static EDIType subType;
+ EDIType_assert(!isBasicType() && !isVoidTy() && !isEnumTy());
+ bool isArrayOrVectorTy = isArrayTy() || isVectorTy();
+ if(isDerivedType() || isArrayOrVectorTy) {
+ EDIType_assert(i == 0);
+ if(isArrayOrVectorTy && getCurrentDimension() < getNumDimensions()-1) {
+ subType = *this;
+ subType.setCurrentDimension(getCurrentDimension() + 1);
+ }
+ else {
+ subType = getTypeDerivedFrom();
+ }
+ return subType;
+ }
+ DIArray aDIArray = getTypeArray();
+ unsigned numContainedTypes = aDIArray.getNumElements();
+ assert(i < numContainedTypes);
+ EDIType tmpType((const DIType) aDIArray.getElement(i), norm);
+ subType = tmpType;
+ return subType;
+}
+
+unsigned EDIType::getNumContainedTypes() const {
+ if(isBasicType() || isVoidTy() || isEnumTy()) {
+ return 0;
+ }
+ bool isArrayOrVectorTy = isArrayTy() || isVectorTy();
+ if(isDerivedType() || isArrayOrVectorTy) {
+ return 1;
+ }
+ DIArray aDIArray = getTypeArray();
+ unsigned numContainedTypes = aDIArray.getNumElements();
+ return numContainedTypes;
+}
+
+const DIDerivedType& EDIType::getMember(unsigned i) const {
+ static DIDerivedType aDIDerivedType;
+ EDIType_assert(isUnionOrStructTy());
+ DIArray aDIArray = getTypeArray();
+ DIDescriptor aDIDescriptor = aDIArray.getElement(i);
+ assert(aDIDescriptor.getTag() == dwarf::DW_TAG_member);
+ aDIDerivedType = (DIDerivedType) aDIDescriptor;
+ return aDIDerivedType;
+}
+
+bool EDIType::isUnionOrStructTy(bool isStruct, bool isUnion) const {
+ if(isOpaqueTy()) {
+ return false;
+ }
+ if((isStruct && getTag() == dwarf::DW_TAG_structure_type) ||
+ (isUnion && getTag() == dwarf::DW_TAG_union_type)) {
+ EDIType_assert(isCompositeType());
+ return true;
+ }
+ return false;
+}
+
+bool EDIType::hasInnerPointers() const {
+ if(isOpaqueTy() || isFunctionTy()) {
+ return false;
+ }
+ if(isPointerTy()) {
+ return true;
+ }
+
+ unsigned numContainedTypes = getNumContainedTypes();
+ if(numContainedTypes == 0) {
+ return false;
+ }
+ else if(isArrayTy() || isVectorTy()) {
+ const EDIType subType = getContainedType(0);
+ return subType.hasInnerPointers();
+ }
+ else {
+ assert(isUnionOrStructTy());
+ for(unsigned i=0;i<numContainedTypes;i++) {
+ const EDIType subType = getContainedType(i);
+ if(subType.hasInnerPointers()) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+DIArray EDIType::getTypeArray() const {
+ static std::set<std::string> nonOpaqueEmptyTypes;
+ static std::set<std::string>::iterator nonOpaqueEmptyTypesIt;
+ EDIType_assert(isCompositeType());
+ DIArray aDIArray = ((const DICompositeType)aDIType).getTypeArray();
+ if(aDIArray.getNumElements() == 0 && checkOpaqueTypes && myNames.size() > 0) {
+ const EDIType *aType = NULL;
+ std::string name;
+ for(int i=myNames.size()-1;i>=0;i--) {
+ name = myNames[i];
+ aType = getStructEDITypeByName(name);
+ if(aType) {
+ break;
+ }
+ }
+ if(aType) {
+ aDIArray = ((const DICompositeType *)aType->getDIType())->getTypeArray();
+ nonOpaqueEmptyTypesIt = nonOpaqueEmptyTypes.find(name);
+ if(nonOpaqueEmptyTypesIt == nonOpaqueEmptyTypes.end()) {
+ EDITypeLog("Found a non-opaque composite type with 0 members! Name is: " << name);
+ nonOpaqueEmptyTypes.insert(name);
+ }
+ }
+ }
+ return aDIArray;
+}
+
+const EDIType* EDIType::getTopStructType(unsigned index) const {
+ static unsigned level = 0;
+ static unsigned structsLeft;
+ static EDIType targetType;
+
+ if(level == 0) {
+ structsLeft = index;
+ }
+
+ if(isUnionOrStructTy() || isOpaqueTy()) {
+ if(structsLeft == 0) {
+ targetType = *this;
+ return &targetType;
+ }
+ else {
+ structsLeft--;
+ return NULL;
+ }
+ }
+ unsigned numContainedTypes = getNumContainedTypes();
+ for(unsigned i=0;i<numContainedTypes;i++) {
+ const EDIType containedType(getContainedType(i));
+ level++;
+ const EDIType *topStructType = containedType.getTopStructType(index);
+ level--;
+ if(topStructType != NULL) {
+ return topStructType;
+ }
+ }
+ return NULL;
+}
+
+//===----------------------------------------------------------------------===//
+// Other public methods
+//===----------------------------------------------------------------------===//
+
+void EDIType::print(raw_ostream &OS) const {
+ OS << getDescription();
+}
+
+void EDIType::printDescription(raw_ostream &OS, int skipUnions, int skipStructs, int allowMultiNames) const {
+ static std::vector<const EDIType*> nestedTypes;
+ int printMultiNames = allowMultiNames && myNames.size() > 1;
+ if(allowMultiNames && !printMultiNames && isPointerTy() && myName.compare("")) {
+ printMultiNames = 1;
+ }
+
+ if(isOpaqueTy()) {
+ OS << "opaque";
+ return;
+ }
+
+ unsigned numContainedTypes = getNumContainedTypes();
+ if(numContainedTypes == 0) {
+ OS << (printMultiNames ? getNamesString() : getName());
+ return;
+ }
+
+ if(isPointerTy() && getContainedType(0).isUnionOrStructTy()) {
+ bool isNestedType = false;
+ unsigned j;
+ for(j=0;j<nestedTypes.size();j++) {
+ if(nestedTypes[j]->equals(this)) {
+ isNestedType = true;
+ break;
+ }
+ }
+ if(isNestedType) {
+ OS << "\\" << nestedTypes.size() - j;
+ return;
+ }
+ }
+
+ nestedTypes.push_back(this);
+ if(isPointerTy()) {
+ const EDIType subType = getContainedType(0);
+ subType.printDescription(OS, skipUnions, skipStructs, allowMultiNames);
+ OS << "*";
+ if(printMultiNames) {
+ OS << "|" << getNamesString();
+ }
+ }
+ else if(isArrayTy() || isVectorTy()) {
+ const EDIType subType = getContainedType(0);
+ unsigned numElements = getNumElements();
+ char startSep = isArrayTy() ? '[' : '<';
+ char endSep = isArrayTy() ? ']' : '>';
+ OS << startSep;
+ if(numElements) {
+ OS << numElements << " x ";
+ }
+ subType.printDescription(OS, skipUnions, skipStructs, allowMultiNames);
+ OS << endSep;
+ }
+ else if(isUnionOrStructTy()) {
+ if(skipUnions && isUnionTy()) {
+ OS << "(U) $" << (printMultiNames ? getNamesString() : (myName.compare("") ? myName : "ANONYMOUS"));
+ nestedTypes.pop_back();
+ return;
+ }
+ if(skipStructs && isStructTy()) {
+ OS << "$" << (printMultiNames ? getNamesString() : (myName.compare("") ? myName : "ANONYMOUS"));
+ nestedTypes.pop_back();
+ return;
+ }
+ unsigned numContainedTypes = getNumContainedTypes();
+ OS << "{ ";
+ if(isUnionTy()) {
+ OS << "(U) ";
+ }
+ OS << "$" << (printMultiNames ? getNamesString() : (myName.compare("") ? myName : "ANONYMOUS")) << " ";
+ for(unsigned i=0;i<numContainedTypes;i++) {
+ if(i > 0) {
+ OS << ", ";
+ }
+ EDIType subType = getContainedType(i);
+ subType.printDescription(OS, skipUnions, skipStructs, allowMultiNames);
+ }
+ OS << " }";
+ }
+ else if(isFunctionTy()) {
+ unsigned numContainedTypes = getNumContainedTypes();
+ assert(numContainedTypes > 0);
+ EDIType subType = getContainedType(0);
+ subType.printDescription(OS, skipUnions, skipStructs, allowMultiNames);
+ numContainedTypes--;
+ OS << " (";
+ for(unsigned i=0;i<numContainedTypes;i++) {
+ if(i > 0) {
+ OS << ", ";
+ }
+ subType = getContainedType(i+1);
+ subType.printDescription(OS, skipUnions, skipStructs, allowMultiNames);
+ }
+ OS << ")";
+ }
+ else {
+ OS << "???";
+ }
+ nestedTypes.pop_back();
+}
+
+bool EDIType::equals(const EDIType *other) const {
+ static std::set<std::pair<MDNode*, MDNode*> > compatibleMDNodes;
+ static std::set<std::pair<MDNode*, MDNode*> >::iterator compatibleMDNodesIt;
+ static int max_recursive_steps = -1;
+#if DEBUG_EDI_EQUALS
+ if(debugEDIEquals>1) EDITypeErr("COMPARING :" << getTag() << ":" << getName() << " VS " << other->getTag() << ":" << other->getName());
+#endif
+ if(isOpaqueTy() || other->isOpaqueTy()) {
+#if DEBUG_EDI_EQUALS
+ if(debugEDIEquals) EDITypeErr("----> ???1");
+#endif
+ return isOpaqueTy() && other->isOpaqueTy();
+ }
+ if(getTag() != other->getTag()) {
+#if DEBUG_EDI_EQUALS
+ if(debugEDIEquals) EDITypeErr("----> false1");
+#endif
+ return false;
+ }
+ unsigned numContainedTypes = getNumContainedTypes();
+ unsigned numOtherContainedTypes = other->getNumContainedTypes();
+ if(numContainedTypes != numOtherContainedTypes) {
+#if DEBUG_EDI_EQUALS
+ if(debugEDIEquals) EDITypeErr("----> false2");
+#endif
+ return false;
+ }
+ if(getNumElements() != other->getNumElements()) {
+#if DEBUG_EDI_EQUALS
+ if(debugEDIEquals) EDITypeErr("----> false3");
+#endif
+ return false;
+ }
+ if(myName.compare(other->getName())) {
+#if DEBUG_EDI_EQUALS
+ if(debugEDIEquals) EDITypeErr("----> false4");
+#endif
+ return false;
+ }
+ if((myNames.size() > 0 || other->getNames().size() > 0) && getNamesString().compare(other->getNamesString())) {
+#if DEBUG_EDI_EQUALS
+ if(debugEDIEquals) EDITypeErr("----> false5");
+#endif
+ return false;
+ }
+ if(numContainedTypes == 0) {
+#if DEBUG_EDI_EQUALS
+ if(debugEDIEquals) EDITypeErr("----> true1");
+#endif
+ return true;
+ }
+ MDNode *aNode = *(&aDIType);
+ MDNode *otherNode = *(other->getDIType());
+ if(aNode == otherNode) {
+#if DEBUG_EDI_EQUALS
+ if(debugEDIEquals) EDITypeErr("----> true2");
+#endif
+ return true;
+ }
+ int isUnionOrStruct = isUnionOrStructTy();
+ int isNonAnonUnionOrStruct = isUnionOrStruct && myName.size() > 0;
+ int saved_max_recursive_steps = max_recursive_steps;
+ if(max_recursive_steps == -1 && isNonAnonUnionOrStruct) {
+ //A simple way to break recursion for recursive non-anonymous structs/unions.
+ max_recursive_steps = 10;
+ }
+ else if(max_recursive_steps == 0) {
+#if DEBUG_EDI_EQUALS
+ if(debugEDIEquals) EDITypeErr("----> true4");
+#endif
+ return true;
+ }
+ else {
+ max_recursive_steps--;
+ }
+ for(unsigned i=0;i<numContainedTypes;i++) {
+ const EDIType &subEDIType = getContainedType(i);
+ const EDIType &subOtherEDIType = other->getContainedType(i);
+ if(!subEDIType.equals(&subOtherEDIType)) {
+ max_recursive_steps = saved_max_recursive_steps;
+ return false;
+ }
+ }
+ max_recursive_steps = saved_max_recursive_steps;
+ return true;
+}
+
+//===----------------------------------------------------------------------===//
+// Public static methods
+//===----------------------------------------------------------------------===//
+
+std::string EDIType::lookupTypedefName(std::string &typedefName) {
+ static std::string noName;
+ for (DebugInfoFinder::iterator I = DIFinder.type_begin(),
+ E = DIFinder.type_end(); I != E; ++I) {
+ DIType aDIType(*I);
+ if(aDIType.getTag() == dwarf::DW_TAG_typedef && aDIType.getName().compare(typedefName)) {
+ while(aDIType.getTag() == dwarf::DW_TAG_typedef) {
+ aDIType = PassUtil::getDITypeDerivedFrom((const DIDerivedType)aDIType);
+ }
+ if(aDIType.getName().compare("")) {
+ return aDIType.getName();
+ }
+ }
+ }
+ return noName;
+}
+
+std::string EDIType::lookupUnionMemberName(TYPECONST Type* type) {
+ std::string string;
+ std::string error;
+ if(!type->isStructTy() || type->getNumContainedTypes() != 1) {
+ return "";
+ }
+ raw_string_ostream ostream(string);
+ writeTypeSymbolic(ostream, type->getContainedType(0), EDIType::module);
+ ostream.flush();
+ Regex unionRegex("%(union|struct)\\.([^ ]+)", 0);
+ assert(unionRegex.isValid(error));
+ SmallVector<StringRef, 8> unionMatches;
+ if(unionRegex.match(string, &unionMatches)) {
+ return unionMatches[2];
+ }
+ return "";
+}
+
+const EDIType* EDIType::getStructEDITypeByName(std::string &typeName) {
+ static EDIType aEDIType;
+ assert(module);
+ for (DebugInfoFinder::iterator I = DIFinder.type_begin(),
+ E = DIFinder.type_end(); I != E; ++I) {
+ const DIType aDIType(*I);
+ //skip zero-element stuct types, necessary to avoid infinite recursion during opaque type lookup
+ //xxx opaque type lookup should not be necessary but is there a bug in the frontend that leaves certain concrete types unnecessarily opaque?
+ const EDIType tmpEDIType(aDIType, NORMALIZE, DO_NOT_CHECK_OPAQUE_TYPES);
+ aEDIType = tmpEDIType;
+ if(typeName.compare(aEDIType.getName())) {
+ continue;
+ }
+ if(aEDIType.isUnionOrStructTy()) {
+ return &aEDIType;
+ }
+ }
+ return NULL;
+}
+
+void EDIType::setModule(Module *M) {
+ assert(module == NULL);
+ module = M;
+ DIFinder.processModule(*module);
+}
+
+//===----------------------------------------------------------------------===//
+// Private methods
+//===----------------------------------------------------------------------===//
+void EDIType::init(bool norm, bool checkOpaqueTypes) {
+ EDIType_assert(isType());
+ currentDimension = 0;
+ this->checkOpaqueTypes = checkOpaqueTypes;
+ myName = "";
+ if(norm) {
+ normalize();
+ }
+ if(myNames.size() == 0) {
+ //nobody assigned names yet, do it here
+ myName = isVoidTy() ? voidName : aDIType.getName();
+ if(myName.compare("")) {
+ myNames.push_back(myName);
+ }
+ }
+}
+
+void EDIType::normalize() {
+ if(getTag() == dwarf::DW_TAG_typedef) {
+ normalizeTypedef();
+ }
+ if(isBasicType() || isVoidTy() || isEnumTy() || isOpaqueTy()) {
+ return;
+ }
+ if(isDerivedType()) {
+ if(isPointerTy() || isUnionOrStructTy()) {
+ return;
+ }
+ aDIType = PassUtil::getDITypeDerivedFrom((const DIDerivedType)aDIType);
+ normalize();
+ return;
+ }
+ EDIType_assert(isCompositeType());
+ if(isAggregateType() || isVectorTy() || isFunctionTy()) {
+ return;
+ }
+ EDIType_assert(getNumContainedTypes() == 1);
+ aDIType = *(getContainedType(0, DO_NOT_NORMALIZE).getDIType());
+ normalize();
+}
+
+void EDIType::normalizeTypedef() {
+ myNames.clear();
+ while(aDIType.getTag() == dwarf::DW_TAG_typedef) {
+ if(aDIType.getName().compare("")) {
+ myNames.push_back(aDIType.getName());
+ }
+ aDIType = PassUtil::getDITypeDerivedFrom((const DIDerivedType)aDIType);
+ }
+ myName = isVoidTy() ? voidName : aDIType.getName();
+ if(!myName.compare("")) {
+ //anonymous typedefed type, use the deepest typedef name
+ assert(!isBasicType());
+ assert(myNames.size() > 0);
+ myName = myNames[myNames.size()-1];
+ }
+ else {
+ myNames.push_back(myName);
+ }
+}
+
+StringRef EDIType::voidName("void");
+Module *EDIType::module = NULL;
+DebugInfoFinder EDIType::DIFinder;
+
+}
--- /dev/null
+#include <magic/support/MagicUtil.h>
+
+using namespace llvm;
+
+namespace llvm {
+
+//===----------------------------------------------------------------------===//
+// Public static methods
+//===----------------------------------------------------------------------===//
+
+static std::map<const std::string, GlobalVariable*> stringRefCache;
+
+unsigned getLabelHash(std::string label) {
+ unsigned hash = 0;
+ for(unsigned i=0;i<label.length();i++){
+ hash ^= (label[i]);
+ hash = (hash << 9) | (hash >> ((sizeof(unsigned)*8)-9));
+ }
+ return hash;
+}
+
+unsigned getModuleHash(DIDescriptor DID, const std::string &baseDir, StringRef extraField="") {
+ std::string relPath;
+ PassUtil::getDbgLocationInfo(DID, baseDir, NULL, NULL, &relPath);
+ return getLabelHash(relPath + "/" + extraField.data());
+}
+
+StringRef MagicUtil::getGVSourceName(Module &M, GlobalVariable *GV, DIGlobalVariable **DIGVP, const std::string &baseDir) {
+ static DIGlobalVariable Var;
+ Value *DIGV = Backports::findDbgGlobalDeclare(GV);
+ if(DIGV) {
+ Var = DIGlobalVariable(cast<MDNode>(DIGV));
+ if(DIGVP) *DIGVP = &Var;
+ if(GV->getLinkage() == GlobalValue::InternalLinkage){
+ /* static variable */
+ StringRef funcName, countStr;
+ DIScope scope = Var.getContext();
+ if(scope.isLexicalBlock()){
+ /* find the subprogram that contains this basic block recursively */
+ while(!scope.isSubprogram()){
+ scope = DILexicalBlock(scope).getContext();
+ }
+ }
+ if(scope.isSubprogram()){
+ /* static function variable */
+
+ funcName = DISubprogram(scope).getName();
+
+ int count=0;
+ Module::GlobalListType &globalList = M.getGlobalList();
+ for (Module::global_iterator it = globalList.begin(); it != globalList.end(); ++it) {
+ GlobalVariable *OtherGV = &(*it);
+ Value *OtherDIGV = Backports::findDbgGlobalDeclare(OtherGV);
+ if(OtherDIGV) {
+ DIGlobalVariable OtherVar(cast<MDNode>(OtherDIGV));
+
+ DIScope otherScope = OtherVar.getContext();
+ if(otherScope.isLexicalBlock()){
+ /* find the subprogram that contains this basic block recursively */
+ while(!otherScope.isSubprogram()){
+ otherScope = DILexicalBlock(otherScope).getContext();
+ }
+ }
+ if(otherScope.isSubprogram()){
+ if(!strcmp(Var.getName().data(), OtherVar.getName().data())){
+ if(DIGV == OtherDIGV){
+ break;
+ }
+ count++;
+ }
+ }
+ }
+ }
+
+ std::stringstream stm;
+ if(count > 0){
+ stm << "." << count;
+ }
+ countStr = StringRef(*new std::string(stm.str()));
+
+ }else{
+ /* static global variable */
+ funcName = "";
+ countStr = "";
+ }
+
+ std::stringstream stm;
+ stm << Var.getName().data() << "." << getModuleHash(Var, baseDir, funcName) << countStr.data();
+ return StringRef(*new std::string(stm.str()));
+
+ }else{
+ /* global variable */
+ return Var.getName();
+ }
+ }else{
+ /* llvm .str variables and assembly */
+ if(DIGVP) *DIGVP = NULL;
+ return GV->getName();
+ }
+}
+
+StringRef MagicUtil::getLVSourceName(Module &M, AllocaInst *V, DIVariable **DIVP) {
+ static DIVariable Var;
+ const DbgDeclareInst *DDI = Backports::FindAllocaDbgDeclare(V);
+ if(DDI && DDI != (const DbgDeclareInst *) -1){
+ Var = DIVariable(cast<MDNode>(DDI->getVariable()));
+ if(DIVP) *DIVP = &Var;
+
+ int count = 0;
+
+ Function *F = V->getParent()->getParent();
+ for (inst_iterator it = inst_begin(F), et = inst_end(F); it != et; ++it) {
+ Instruction *inst = &(*it);
+ if (DbgDeclareInst *OtherDDI = dyn_cast<DbgDeclareInst>(inst)){
+ DIVariable otherVar(cast<MDNode>(OtherDDI->getVariable()));
+ if(!strcmp(Var.getName().data(), otherVar.getName().data())){
+ if(OtherDDI == DDI){
+ break;
+ }
+ count++;
+ }
+ }
+ }
+
+ std::stringstream stm;
+ stm << Var.getName().data();
+ if(count > 0){
+ stm << "." << count;
+ }
+ return StringRef(*new std::string(stm.str()));
+ }else{
+ if(DIVP) *DIVP = NULL;
+ return V->getName();
+ }
+}
+
+StringRef MagicUtil::getFunctionSourceName(Module &M, Function *F, DISubprogram **DISP, const std::string &baseDir) {
+ static DISubprogram Func;
+ Value *DIF = Backports::findDbgSubprogramDeclare(F);
+ if(DIF) {
+ Func = DISubprogram(cast<MDNode>(DIF));
+ if(DISP) *DISP = &Func;
+ if(F->getLinkage() == GlobalValue::InternalLinkage){
+ std::stringstream stm;
+ stm << Func.getName().data() << "." << getModuleHash(Func, baseDir);
+ return StringRef(*new std::string(stm.str()));
+ }else{
+ return Func.getName();
+ }
+ }else{
+ /* assembly */
+ if(DISP) *DISP = NULL;
+ return F->getName();
+ }
+}
+
+void MagicUtil::putStringRefCache(Module &M, const std::string &str, GlobalVariable *GV) {
+ std::map<const std::string, GlobalVariable*>::iterator it;
+ it = stringRefCache.find(str);
+ if(it == stringRefCache.end()) {
+ stringRefCache.insert(std::pair<const std::string, GlobalVariable*>(str, GV));
+ }
+}
+
+Constant* MagicUtil::getGetElementPtrConstant(Constant *constant, std::vector<Value*> &indexes) {
+ return PassUtil::getGetElementPtrConstant(constant, indexes);
+}
+
+GetElementPtrInst* MagicUtil::createGetElementPtrInstruction(Value *ptr, std::vector<Value*> &indexes, const Twine &NameStr, Instruction *InsertBefore) {
+ return PassUtil::createGetElementPtrInstruction(ptr, indexes, NameStr, InsertBefore);
+}
+
+GetElementPtrInst* MagicUtil::createGetElementPtrInstruction(Value *ptr, std::vector<Value*> &indexes, const Twine &NameStr, BasicBlock *InsertAtEnd) {
+ return PassUtil::createGetElementPtrInstruction(ptr, indexes, NameStr, InsertAtEnd);
+}
+
+CallInst* MagicUtil::createCallInstruction(Value *F, std::vector<Value*> &args, const Twine &NameStr, Instruction *InsertBefore) {
+ return PassUtil::createCallInstruction(F, args, NameStr, InsertBefore);
+}
+
+CallInst* MagicUtil::createCallInstruction(Value *F, std::vector<Value*> &args, const Twine &NameStr, BasicBlock *InsertAtEnd) {
+ return PassUtil::createCallInstruction(F, args, NameStr, InsertAtEnd);
+}
+
+Function* MagicUtil::getIntrinsicFunction(Module &M, Intrinsic::ID id, TYPECONST Type** types, unsigned size) {
+ return PassUtil::getIntrinsicFunction(M, id, types, size);
+}
+
+GlobalVariable *MagicUtil::getStringRef(Module &M, const std::string &str) {
+ std::map<const std::string, GlobalVariable*>::iterator it;
+ GlobalVariable *stringRef = NULL;
+ bool debug = false;
+
+ it = stringRefCache.find(str);
+ if(it != stringRefCache.end()) {
+ if(debug) magicUtilLog("*** getStringRef: cache hit for " << str);
+ stringRef = it->second;
+ }
+ if(stringRef == NULL) {
+ stringRef = PassUtil::getStringGlobalVariable(M, str, MAGIC_HIDDEN_STR_PREFIX, MAGIC_STATIC_VARS_SECTION_RO);
+ stringRefCache.insert(std::pair<const std::string, GlobalVariable*>(str, stringRef));
+ }
+
+ return stringRef;
+ }
+
+
+GlobalVariable *MagicUtil::getIntArrayRef(Module &M, unsigned arrSize, std::vector<int> *arr, bool isConstant) {
+ static std::map<std::vector<int>, GlobalVariable*> arrayRefCache;
+ std::map<std::vector<int>, GlobalVariable*>::iterator it;
+ static std::vector<int> defInitilizer;
+
+ //construct an appropriate initializer if we do not have one
+ if(!arr) {
+ arr = &defInitilizer;
+ arr->clear();
+ for(unsigned i=0;i<arrSize;i++) arr->push_back(0);
+ }
+ assert(arrSize == arr->size());
+
+ //cache lookup
+ if(isConstant) {
+ it = arrayRefCache.find(*arr);
+ if(it != arrayRefCache.end()) {
+ return it->second;
+ }
+ }
+
+ //create a constant internal array reference
+ std::vector<Constant*> arrayElems;
+ for(unsigned i=0;i<arr->size();i++) {
+ arrayElems.push_back(ConstantInt::get(M.getContext(), APInt(32, (*arr)[i], 10)));
+ }
+ ArrayType* arrayTy = ArrayType::get(IntegerType::get(M.getContext(), 32), arr->size());
+ Constant *arrayValue = ConstantArray::get(arrayTy, arrayElems);
+
+ //create the global variable and record it in the module
+ GlobalVariable *arrayRef = new GlobalVariable(arrayValue->getType(), isConstant,
+ GlobalValue::InternalLinkage, arrayValue,
+ MAGIC_HIDDEN_ARRAY_PREFIX);
+ MagicUtil::setGlobalVariableSection(arrayRef, isConstant ? MAGIC_STATIC_VARS_SECTION_RO : MAGIC_STATIC_VARS_SECTION_DATA);
+ M.getGlobalList().push_back(arrayRef);
+
+ //populate cache
+ if(isConstant) {
+ arrayRefCache.insert(std::pair<std::vector<int>, GlobalVariable*>(*arr, arrayRef));
+ }
+
+ return arrayRef;
+}
+
+GlobalVariable *MagicUtil::getStringArrayRef(Module &M, unsigned arrSize, std::vector<std::string> *arr, bool isConstant) {
+ static std::map<std::vector<std::string>, GlobalVariable*> arrayRefCache;
+ std::map<std::vector<std::string>, GlobalVariable*>::iterator it;
+ static std::vector<std::string> defInitilizer;
+ //construct an appropriate initializer if we do not have one
+ if(!arr) {
+ arr = &defInitilizer;
+ arr->clear();
+ for(unsigned i=0;i<arrSize;i++) arr->push_back("");
+ }
+ assert(arrSize == arr->size());
+
+ //cache lookup
+ if(isConstant) {
+ it = arrayRefCache.find(*arr);
+ if(it != arrayRefCache.end()) {
+ return it->second;
+ }
+ }
+
+ //create a constant internal array reference
+ std::vector<Constant*> arrayElems;
+ std::vector<Value*> arrayIndexes;
+ arrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(32, 0, 10)));
+ arrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(32, 0, 10)));
+ for(unsigned i=0;i<arr->size();i++) {
+ arrayElems.push_back(getGetElementPtrConstant(getStringRef(M, (*arr)[i]), arrayIndexes));
+ }
+ ArrayType* arrayTy = ArrayType::get(PointerType::get(IntegerType::get(M.getContext(), 8), 0), arr->size());
+ Constant *arrayValue = ConstantArray::get(arrayTy, arrayElems);
+
+ //create the global variable and record it in the module
+ GlobalVariable *arrayRef = new GlobalVariable(arrayValue->getType(), isConstant,
+ GlobalValue::InternalLinkage, arrayValue,
+ MAGIC_HIDDEN_ARRAY_PREFIX);
+ MagicUtil::setGlobalVariableSection(arrayRef, isConstant ? MAGIC_STATIC_VARS_SECTION_RO : MAGIC_STATIC_VARS_SECTION_DATA);
+ M.getGlobalList().push_back(arrayRef);
+
+ //populate cache
+ if(isConstant) {
+ arrayRefCache.insert(std::pair<std::vector<std::string>, GlobalVariable*>(*arr, arrayRef));
+ }
+
+ return arrayRef;
+}
+
+GlobalVariable *MagicUtil::getGenericArrayRef(Module &M, std::vector<Constant*> &arrayElems, bool isConstant) {
+ static std::map<std::vector<Constant*>, GlobalVariable*> arrayRefCache;
+ std::map<std::vector<Constant*>, GlobalVariable*>::iterator it;
+ assert(arrayElems.size() > 0);
+
+ //cache lookup
+ if(isConstant) {
+ it = arrayRefCache.find(arrayElems);
+ if(it != arrayRefCache.end()) {
+ return it->second;
+ }
+ }
+
+ //create a constant internal array reference
+ ArrayType* arrayTy = ArrayType::get(arrayElems[0]->getType(), arrayElems.size());
+ Constant *arrayValue = ConstantArray::get(arrayTy, arrayElems);
+
+ //create the global variable and record it in the module
+ GlobalVariable *arrayRef = new GlobalVariable(arrayValue->getType(), isConstant,
+ GlobalValue::InternalLinkage, arrayValue,
+ MAGIC_HIDDEN_ARRAY_PREFIX);
+ MagicUtil::setGlobalVariableSection(arrayRef, isConstant ? MAGIC_STATIC_VARS_SECTION_RO : MAGIC_STATIC_VARS_SECTION_DATA);
+ M.getGlobalList().push_back(arrayRef);
+
+ //populate cache
+ if(isConstant) {
+ arrayRefCache.insert(std::pair<std::vector<Constant*>, GlobalVariable*>(arrayElems, arrayRef));
+ }
+
+ return arrayRef;
+}
+
+GlobalVariable *MagicUtil::getMagicTypePtrArrayRef(Module &M, Instruction *InsertBefore, std::vector<Value*> &globalTypeIndexes, GlobalVariable *magicTypeArray) {
+ int numTypeIndexes = globalTypeIndexes.size();
+ TYPECONST StructType* magicTypeStructTy = (TYPECONST StructType*) ((TYPECONST ArrayType*)magicTypeArray->getType()->getElementType())->getElementType();
+ ArrayType* typeIndexesArrTy = ArrayType::get(PointerType::get(magicTypeStructTy, 0), numTypeIndexes+1);
+ std::vector<Constant*> arrayElems;
+ for(int i=0;i<numTypeIndexes;i++) {
+ std::vector<Value*> magicTypeArrayIndexes;
+ magicTypeArrayIndexes.clear();
+ magicTypeArrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(64, 0, 10)));
+ magicTypeArrayIndexes.push_back(globalTypeIndexes[i]);
+ Constant* typePtr = getGetElementPtrConstant(magicTypeArray, magicTypeArrayIndexes);
+ arrayElems.push_back(typePtr);
+ }
+ arrayElems.push_back(ConstantPointerNull::get(PointerType::get(magicTypeStructTy, 0))); //NULL-terminated array
+
+ //create the global variable and record it in the module
+ Constant *arrayValue = ConstantArray::get(typeIndexesArrTy, arrayElems);
+ GlobalVariable *arrayRef = new GlobalVariable(arrayValue->getType(), true,
+ GlobalValue::InternalLinkage, arrayValue,
+ MAGIC_HIDDEN_ARRAY_PREFIX);
+ MagicUtil::setGlobalVariableSection(arrayRef, MAGIC_STATIC_VARS_SECTION_RO);
+ M.getGlobalList().push_back(arrayRef);
+
+ return arrayRef;
+}
+
+GlobalVariable* MagicUtil::getExportedIntGlobalVar(Module &M, std::string name, int value, bool isConstant) {
+ Constant *intValue = ConstantInt::get(M.getContext(), APInt(32, value, 10));
+
+ //create the global variable and record it in the module
+ GlobalVariable *GV = new GlobalVariable(intValue->getType(), isConstant,
+ GlobalValue::LinkOnceAnyLinkage, intValue, name);
+ MagicUtil::setGlobalVariableSection(GV, isConstant ? MAGIC_STATIC_VARS_SECTION_RO : MAGIC_STATIC_VARS_SECTION_DATA);
+ M.getGlobalList().push_back(GV);
+
+ return GV;
+}
+
+GlobalVariable* MagicUtil::getShadowRef(Module &M, GlobalVariable *GV) {
+ //create the shadow global variable and record it in the module
+ TYPECONST Type* type = GV->getType()->getElementType();
+ GlobalVariable *SGV = new GlobalVariable(type, GV->isConstant(),
+ GlobalValue::InternalLinkage, 0,
+ MAGIC_SHADOW_VAR_PREFIX + GV->getName());
+ SGV->setInitializer(Constant::getNullValue(type));
+ MagicUtil::setGlobalVariableSection(SGV, GV->isConstant() ? MAGIC_SHADOW_VARS_SECTION_RO : MAGIC_SHADOW_VARS_SECTION_DATA);
+ M.getGlobalList().push_back(SGV);
+
+ if(!GV->hasInitializer()) {
+ magicUtilLog("Shadowing for extern variable: " << GV->getName());
+ }
+ if(GV->isConstant()) {
+ magicUtilLog("Shadowing for constant variable: " << GV->getName());
+ }
+
+ return SGV;
+}
+
+Value* MagicUtil::getMagicStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* var, Value* arrayIndex, const std::string &structFieldName, std::string *structFieldNames) {
+ //lookup field index
+ int structFieldIndex;
+ Value *varPtr;
+ for(structFieldIndex=0; structFieldName.compare(structFieldNames[structFieldIndex]) != 0; structFieldIndex++) {}
+
+ if(arrayIndex) {
+ //get array ptr
+ std::vector<Value*> arrayIndexes;
+ arrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(64, 0, 10)));
+ arrayIndexes.push_back(arrayIndex);
+ varPtr = createGetElementPtrInstruction(var, arrayIndexes, "", InsertBefore);
+ }
+ else {
+ varPtr = var;
+ }
+
+ //get struct field ptr
+ std::vector<Value*> structFieldIndexes;
+ structFieldIndexes.push_back(ConstantInt::get(M.getContext(), APInt(32, 0, 10)));
+ structFieldIndexes.push_back(ConstantInt::get(M.getContext(), APInt(32, structFieldIndex, 10)));
+ Instruction* structFieldPtr = createGetElementPtrInstruction(varPtr, structFieldIndexes, "", InsertBefore);
+
+ return structFieldPtr;
+}
+
+Value* MagicUtil::getMagicSStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* magicArray, Value* magicArrayIndex, const std::string &structFieldName) {
+ static std::string structFieldNames[] = { MAGIC_SSTRUCT_FIELDS };
+ return getMagicStructFieldPtr(M, InsertBefore, magicArray, magicArrayIndex, structFieldName, structFieldNames);
+}
+
+Value* MagicUtil::getMagicTStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* magicTypeArray, Value* magicTypeArrayIndex, const std::string &structFieldName) {
+ static std::string structFieldNames[] = { MAGIC_TSTRUCT_FIELDS };
+ return getMagicStructFieldPtr(M, InsertBefore, magicTypeArray, magicTypeArrayIndex, structFieldName, structFieldNames);
+}
+
+Value* MagicUtil::getMagicFStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* magicFunctionArray, Value* magicFunctionArrayIndex, const std::string &structFieldName) {
+ static std::string structFieldNames[] = { MAGIC_FSTRUCT_FIELDS };
+ return getMagicStructFieldPtr(M, InsertBefore, magicFunctionArray, magicFunctionArrayIndex, structFieldName, structFieldNames);
+}
+
+Value* MagicUtil::getMagicRStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* magicVar, const std::string &structFieldName) {
+ static std::string structFieldNames[] = { MAGIC_RSTRUCT_FIELDS };
+ return getMagicStructFieldPtr(M, InsertBefore, magicVar, NULL, structFieldName, structFieldNames);
+}
+
+Value* MagicUtil::getMagicDStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* magicDsindexArray, Value* magicDsindexArrayIndex, const std::string &structFieldName) {
+ static std::string structFieldNames[] = { MAGIC_DSTRUCT_FIELDS };
+ return getMagicStructFieldPtr(M, InsertBefore, magicDsindexArray, magicDsindexArrayIndex, structFieldName, structFieldNames);
+}
+
+Constant* MagicUtil::getArrayPtr(Module &M, GlobalVariable* array) {
+ //indexes for array
+ static std::vector<Value*> arrayIndexes;
+ if(arrayIndexes.empty()) {
+ arrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(64, 0, 10))); //pointer to A[]
+ arrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(64, 0, 10))); //pointer to A[0]
+ }
+
+ //get array ptr
+ Constant* arrayPtr = getGetElementPtrConstant(array, arrayIndexes);
+
+ return arrayPtr;
+}
+
+void MagicUtil::insertMemcpyInst(Module &M, Instruction *InsertBefore, Value *Dst, Value *Src, Value *Len, unsigned Align) {
+ bool useMemCpyIntrinsics = false;
+ Function *MemCpy = M.getFunction("memcpy");
+ if(!MemCpy) {
+ TYPECONST Type *ArgTys[1] = { IntegerType::getInt32Ty(M.getContext()) };
+ MemCpy = getIntrinsicFunction(M, Intrinsic::memcpy, ArgTys, 1);
+ useMemCpyIntrinsics = true;
+ }
+ else {
+ MemCpy = (Function*) M.getOrInsertFunction(MAGIC_MEMCPY_FUNC_NAME, MemCpy->getFunctionType());
+ }
+
+ // Insert the memcpy instruction
+ std::vector<Value*> MemCpyArgs;
+ MemCpyArgs.push_back(Dst);
+ MemCpyArgs.push_back(Src);
+ MemCpyArgs.push_back(Len);
+ if(useMemCpyIntrinsics) {
+ MemCpyArgs.push_back(ConstantInt::get(M.getContext(), APInt(32, Align, 10)));
+ }
+ createCallInstruction(MemCpy, MemCpyArgs, "", InsertBefore);
+}
+
+void MagicUtil::insertCopyInst(Module &M, Instruction *InsertBefore, GlobalVariable *GV, GlobalVariable *SGV, int GVSize, bool forceMemcpy) {
+ //get type and type size
+ TYPECONST Type *GVType = GV->getType()->getElementType();
+ bool isPrimitiveOrPointerType = !GVType->isAggregateType();
+
+ //no need for memcpy for primitive types or pointer types
+ if(isPrimitiveOrPointerType && !forceMemcpy) {
+ LoadInst* primitiveValue = new LoadInst(GV, "", false, InsertBefore);
+ new StoreInst(primitiveValue, SGV, false, InsertBefore);
+ return;
+ }
+
+ //cast pointers to match memcpy prototype
+ PointerType* voidPointerType = PointerType::get(IntegerType::get(M.getContext(), 8), 0);
+ Constant* varAddress = ConstantExpr::getCast(Instruction::BitCast, GV, voidPointerType);
+ Constant* varShadowAddress = ConstantExpr::getCast(Instruction::BitCast, SGV, voidPointerType);
+
+ //insert the memcpy instruction
+ MagicUtil::insertMemcpyInst(M, InsertBefore, varShadowAddress, varAddress, ConstantInt::get(M.getContext(), APInt(32, GVSize, 10)), 0);
+}
+
+Function* MagicUtil::getCalledFunctionFromCS(const CallSite &CS) {
+ assert(CS.getInstruction());
+ Function *function = CS.getCalledFunction();
+ if(function) {
+ return function;
+ }
+
+ //handle the weird case of bitcasted function call
+ //IMPORTANT! function may still be null, if it's an indirect call
+ ConstantExpr *CE = dyn_cast<ConstantExpr>(CS.getCalledValue());
+ if (CE) {
+ assert(CE->getOpcode() == Instruction::BitCast && "Bitcast expected, something else found!");
+ function = dyn_cast<Function>(CE->getOperand(0));
+ assert(function);
+ } else {
+ errs() << "Warning! Indirect call encountered!\n";
+ }
+
+ return function;
+}
+
+void MagicUtil::replaceCallInst(Instruction *originalInst, CallInst *newInst, int argOffset, bool removeUnusedFunction) {
+ SmallVector< std::pair< unsigned, MDNode * >, 8> MDs;
+ originalInst->getAllMetadata(MDs);
+ for(unsigned i=0;i<MDs.size();i++) {
+ newInst->setMetadata(MDs[i].first, MDs[i].second);
+ }
+ CallSite CS = MagicUtil::getCallSiteFromInstruction(originalInst);
+ assert(CS);
+ CallingConv::ID CC = CS.getCallingConv();
+ Function *originalFunction = getCalledFunctionFromCS(CS);
+ newInst->setCallingConv(CC);
+ ATTRIBUTE_SET_TY NewAttrs = PassUtil::remapCallSiteAttributes(CS, argOffset);
+ newInst->setAttributes(NewAttrs);
+
+ originalInst->replaceAllUsesWith(newInst);
+
+ // If the old instruction was an invoke, add an unconditional branch
+ // before the invoke, which will become the new terminator.
+ if (InvokeInst *II = dyn_cast<InvokeInst>(originalInst))
+ BranchInst::Create(II->getNormalDest(), originalInst);
+
+ // Delete the old call site
+ originalInst->eraseFromParent();
+
+ // When asked, remove the original function when nobody uses it any more.
+ if(removeUnusedFunction && originalFunction->use_empty()) {
+ originalFunction->eraseFromParent();
+ }
+}
+
+std::vector<Function*> MagicUtil::getGlobalVariablesShadowFunctions(Module &M, std::vector<GlobalVariable*> globalVariables, std::vector<GlobalVariable*> shadowGlobalVariables, std::vector<int> globalVariableSizes, GlobalVariable* magicArray, int magicArraySize, bool forceShadow, bool setDirtyFlag) {
+ std::vector<Function*> globalVariableShadowFunctions;
+ for(int i=0;i<magicArraySize;i++) {
+ Function* func = getGlobalVariableShadowFunction(M, globalVariables[i], shadowGlobalVariables[i], globalVariableSizes[i], magicArray, i, forceShadow, setDirtyFlag);
+ globalVariableShadowFunctions.push_back(func);
+ }
+
+ return globalVariableShadowFunctions;
+}
+
+Function* MagicUtil::getGlobalVariableShadowFunction(Module &M, GlobalVariable* GV, GlobalVariable* SGV, int GVSize, GlobalVariable* magicArray, int magicArrayIndex, bool forceShadow, bool setDirtyFlag) {
+ static Constant* magicStateDirty = ConstantInt::get(M.getContext(), APInt(32, MAGIC_STATE_DIRTY, 10));
+ static Function* shadowFunc = NULL;
+ ConstantInt* magicArrayIndexConst = ConstantInt::get(M.getContext(), APInt(32, magicArrayIndex, 10));
+
+ //determine name
+ std::string name(MAGIC_SHADOW_FUNC_PREFIX);
+ name.append("_");
+ if(forceShadow) {
+ name.append("force_");
+ }
+ if(setDirtyFlag) {
+ name.append("setdf_");
+ }
+ name.append(GV->getName());
+
+ //create function
+ std::vector<TYPECONST Type*>shadowFuncArgs;
+ FunctionType* shadowFuncType = FunctionType::get(Type::getVoidTy(M.getContext()), shadowFuncArgs, false);
+ shadowFunc = Function::Create(shadowFuncType, GlobalValue::InternalLinkage, name, &M);
+ shadowFunc->setCallingConv(CallingConv::C);
+
+ //create blocks
+ BasicBlock* label_entry = BasicBlock::Create(M.getContext(), "entry",shadowFunc,0);
+ BasicBlock* label_shadow = BasicBlock::Create(M.getContext(), "shadow",shadowFunc,0);
+ BasicBlock* label_return = BasicBlock::Create(M.getContext(), "return",shadowFunc,0);
+ BranchInst::Create(label_shadow, label_entry);
+ BranchInst::Create(label_return, label_shadow);
+ Instruction* entryTerm = label_entry->getTerminator();
+ Instruction* shadowTerm = label_shadow->getTerminator();
+
+ if(!forceShadow || setDirtyFlag) {
+ //get flags
+ Value* structFlagsField = MagicUtil::getMagicSStructFieldPtr(M, entryTerm, magicArray, magicArrayIndexConst, MAGIC_SSTRUCT_FIELD_FLAGS);
+ LoadInst* varFlags = new LoadInst(structFlagsField, "", false, entryTerm);
+
+ //when not forcing, don't shadow if dirty is already set
+ if(!forceShadow) {
+ BinaryOperator* andedVarFlags = BinaryOperator::Create(Instruction::And, varFlags, magicStateDirty, "", entryTerm);
+ ICmpInst* flagsCmp = new ICmpInst(entryTerm, ICmpInst::ICMP_EQ, andedVarFlags, ConstantInt::get(M.getContext(), APInt(32, 0, 10)), "");
+ BranchInst::Create(label_shadow, label_return, flagsCmp, entryTerm);
+ entryTerm->eraseFromParent();
+ }
+
+ //set the dirty flag for the variable
+ if(setDirtyFlag) {
+ BinaryOperator* oredVarFlags = BinaryOperator::Create(Instruction::Or, varFlags, magicStateDirty, "", shadowTerm);
+ new StoreInst(oredVarFlags, structFlagsField, false, shadowTerm);
+ }
+ }
+
+ //perform a memory copy from the original variable to the shadow variable
+ MagicUtil::insertCopyInst(M, shadowTerm, GV, SGV, GVSize, /* forceMemcpy */ false);
+
+ ReturnInst::Create(M.getContext(), label_return);
+
+ return shadowFunc;
+}
+
+void MagicUtil::insertGlobalVariableCleanDirtyFlag(Module &M, GlobalVariable* GV, GlobalVariable* magicArray, int magicArrayIndex, Instruction *InsertBefore) {
+ Value* structFlagsField = MagicUtil::getMagicSStructFieldPtr(M, InsertBefore, magicArray, ConstantInt::get(M.getContext(), APInt(32, magicArrayIndex, 10)), MAGIC_SSTRUCT_FIELD_FLAGS);
+ new StoreInst(ConstantInt::get(M.getContext(), APInt(32, 0, 10)), structFlagsField, false, InsertBefore);
+}
+
+void MagicUtil::insertShadowTag(Module &M, GlobalVariable *GV, Instruction *InsertBefore) {
+ static Function* shadowFunc = NULL;
+ PointerType* voidPointerType = PointerType::get(IntegerType::get(M.getContext(), 8), 0);
+
+ //create function
+ if(!shadowFunc) {
+ std::vector<TYPECONST Type*>shadowFuncArgs;
+ shadowFuncArgs.push_back(voidPointerType);
+ FunctionType* shadowFuncType = FunctionType::get(Type::getVoidTy(M.getContext()), shadowFuncArgs, false);
+ shadowFunc = Function::Create(shadowFuncType, GlobalValue::ExternalLinkage, MAGIC_LAZY_CHECKPOINT_SHADOW_TAG, &M);
+ shadowFunc->setCallingConv(CallingConv::C);
+ }
+
+ //shadow global variable
+ std::vector<Value*> args;
+ args.push_back(new BitCastInst(GV, voidPointerType, "", InsertBefore));
+ CallInst *callInst = createCallInstruction(shadowFunc, args, "", InsertBefore);
+ callInst->setCallingConv(CallingConv::C);
+}
+
+bool MagicUtil::isShadowTag(Instruction *inst) {
+ if(dyn_cast<CallInst>(inst)) {
+ CallInst *callInst = dyn_cast<CallInst>(inst);
+ Function *function = callInst->getCalledFunction();
+ if(function == NULL) {
+ return false;
+ }
+ std::string funcName = function->getName();
+ if(!funcName.compare(MAGIC_LAZY_CHECKPOINT_SHADOW_TAG)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+GlobalVariable* MagicUtil::getGlobalVariableFromShadowTag(Instruction *inst, std::vector<Instruction*> &instructionsToRemove) {
+ CallSite CS = MagicUtil::getCallSiteFromInstruction(inst);
+ assert(CS.arg_size() == 1);
+ instructionsToRemove.push_back(inst);
+ CallSite::arg_iterator AI = CS.arg_begin();
+ Value *ActualArg = *AI;
+
+ while(true) {
+ BitCastInst *castInst = dyn_cast<BitCastInst>(ActualArg);
+ ConstantExpr *castExpr = dyn_cast<ConstantExpr>(ActualArg);
+ if(castInst) {
+ assert(castInst->getNumOperands() == 1);
+ ActualArg = castInst->getOperand(0);
+ instructionsToRemove.push_back(castInst);
+ }
+ else if(castExpr) {
+ //assert(castExpr->getNumOperands() == 1);
+ ActualArg = castExpr->getOperand(0);
+ }
+ else {
+ break;
+ }
+ }
+
+ GlobalVariable *GV = dyn_cast<GlobalVariable>(ActualArg);
+ if(GV == NULL) {
+ magicUtilLog("Weird ActualArg: " << *ActualArg);
+ }
+ assert(GV != NULL);
+
+ return GV;
+}
+
+void MagicUtil::cleanupShadowTag(Module &M, std::vector<Instruction*> &instructionsToRemove) {
+ int i=0;
+
+ for(i =0;i<(int)instructionsToRemove.size();i++) {
+ Instruction *inst = instructionsToRemove[i];
+ inst->eraseFromParent();
+ }
+ Function* func = M.getFunction(MAGIC_LAZY_CHECKPOINT_SHADOW_TAG);
+ if(func && func->getNumUses() == 0) {
+ func->eraseFromParent();
+ }
+}
+
+bool MagicUtil::hasAddressTaken(const GlobalValue *GV, bool includeMembers) {
+ //Most of the code taken from LLVM's SCCP.cpp
+
+ // Delete any dead constantexpr klingons.
+ GV->removeDeadConstantUsers();
+
+ std::vector<const User*> sourceUsers;
+ sourceUsers.push_back(GV);
+ if(includeMembers && isa<GlobalVariable>(GV)) {
+ for (Value::const_use_iterator UI = GV->use_begin(), E = GV->use_end();
+ UI != E; ++UI) {
+ const User *U = *UI;
+ const ConstantExpr *constantExpr = dyn_cast<ConstantExpr>(U);
+ if(isa<GetElementPtrInst>(U)) {
+ sourceUsers.push_back(U);
+ }
+ else if(constantExpr && constantExpr->getOpcode() == Instruction::GetElementPtr) {
+ sourceUsers.push_back(U);
+ }
+ }
+ }
+
+ for(unsigned i=0;i<sourceUsers.size();i++) {
+ for (Value::const_use_iterator UI = sourceUsers[i]->use_begin(), E = sourceUsers[i]->use_end();
+ UI != E; ++UI) {
+ const User *U = *UI;
+ if (const StoreInst *SI = dyn_cast<StoreInst>(U)) {
+ if (SI->getOperand(0) == sourceUsers[i] || SI->isVolatile())
+ return true; // Storing addr of sourceUsers[i].
+ } else if (isa<InvokeInst>(U) || isa<CallInst>(U)) {
+ // Make sure we are calling the function, not passing the address.
+ ImmutableCallSite CS(cast<Instruction>(U));
+ if (!CS.isCallee(UI))
+ return true;
+ } else if (const LoadInst *LI = dyn_cast<LoadInst>(U)) {
+ if (LI->isVolatile())
+ return true;
+ } else if (isa<BlockAddress>(U)) {
+ // blockaddress doesn't take the address of the function, it takes addr
+ // of label.
+ } else {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool MagicUtil::lookupValueSet(const GlobalVariable *GV, std::vector<int> &valueSet) {
+ //Similar to hasAddressTaken above, but we look for values
+
+ if(!isa<IntegerType>(GV->getType()->getElementType())) {
+ //integers is all we are interested in
+ return false;
+ }
+ if(!GV->hasInitializer()) {
+ //external variable
+ return false;
+ }
+
+ // Delete any dead constantexpr klingons.
+ GV->removeDeadConstantUsers();
+
+ std::set<int> set;
+ for (Value::const_use_iterator UI = GV->use_begin(), E = GV->use_end();
+ UI != E; ++UI) {
+ const User *U = *UI;
+ if (const StoreInst *SI = dyn_cast<StoreInst>(U)) {
+ if (SI->getOperand(1) == GV) {
+ Value *value = SI->getOperand(0);
+ if(ConstantInt *intValue = dyn_cast<ConstantInt>(value)) {
+ set.insert(intValue->getSExtValue());
+ }
+ else {
+ return false;
+ }
+ }
+ }
+ }
+ const Constant *constant = GV->getInitializer();
+ if(const ConstantInt *intConstant = dyn_cast<const ConstantInt>(constant)) {
+ set.insert(intConstant->getSExtValue());
+ }
+ else {
+ return false;
+ }
+
+ assert(set.size() > 0);
+ valueSet.push_back(set.size()); //push length as the first value
+ for(std::set<int>::iterator it=set.begin() ; it != set.end(); it++) {
+ valueSet.push_back(*it);
+ }
+
+ return true;
+}
+
+Value* MagicUtil::getStringOwner(GlobalVariable *GV)
+{
+ //Similar to hasAddressTaken above, but we look for string owners
+ assert(GV && GV->isConstant());
+
+ // Skip emtpy strings.
+ if(GV->hasInitializer() && GV->getInitializer()->isNullValue()) {
+ return NULL;
+ }
+
+ // Delete any dead constantexpr klingons.
+ GV->removeDeadConstantUsers();
+
+ std::vector<User*> sourceUsers;
+ sourceUsers.push_back(GV);
+ for (Value::use_iterator UI = GV->use_begin(), E = GV->use_end();
+ UI != E; ++UI) {
+ User *U = *UI;
+ ConstantExpr *constantExpr = dyn_cast<ConstantExpr>(U);
+ if(isa<GetElementPtrInst>(U)) {
+ sourceUsers.push_back(U);
+ }
+ else if(constantExpr && constantExpr->getOpcode() == Instruction::GetElementPtr) {
+ sourceUsers.push_back(U);
+ }
+ }
+
+ Value *stringOwner = NULL;
+ for(unsigned i=0;i<sourceUsers.size();i++) {
+ for (Value::use_iterator UI = sourceUsers[i]->use_begin(), E = sourceUsers[i]->use_end();
+ UI != E; ++UI) {
+ User *U = *UI;
+ Value *V = U;
+ if (StoreInst *SI = dyn_cast<StoreInst>(U)) {
+ V = SI->getPointerOperand();
+ }
+ if(isa<GlobalVariable>(V) || isa<AllocaInst>(V)) {
+ if(stringOwner != NULL && stringOwner != V) {
+ //no owner in the ambiguous cases
+ return NULL;
+ }
+ stringOwner = V;
+ }
+ }
+ }
+
+ return stringOwner;
+}
+
+Instruction* MagicUtil::getFirstNonAllocaInst(Function *F, bool skipAllocaPoint)
+{
+ Instruction *I = NULL;
+ if (skipAllocaPoint) {
+ PassUtil::getAllocaInfo(F, NULL, &I);
+ }
+ else {
+ PassUtil::getAllocaInfo(F, &I, NULL);
+ }
+ assert(I);
+ return I;
+}
+
+void MagicUtil::setGlobalVariableSection(GlobalVariable *GV, const std::string §ion)
+{
+ if(GV->isThreadLocal()) {
+ return;
+ }
+
+ GV->setSection(section);
+}
+
+bool MagicUtil::getCallAnnotation(Module &M, const CallSite &CS, int *annotation)
+{
+ static GlobalVariable *magicAnnotationVar = NULL;
+ bool instFound = false;
+ bool annotationFound = false;
+ if(!magicAnnotationVar) {
+ magicAnnotationVar = M.getNamedGlobal(MAGIC_CALL_ANNOTATION_VAR_NAME);
+ assert(magicAnnotationVar);
+ }
+ Instruction *I = CS.getInstruction();
+ if(!I) {
+ return false;
+ }
+ BasicBlock *parent = I->getParent();
+ for (BasicBlock::iterator i = parent->begin(), e = parent->end(); i != e; ++i) {
+ Instruction *inst = i;
+ if(inst != I && !instFound) {
+ continue;
+ }
+ instFound = true;
+ if(inst == I) {
+ continue;
+ }
+ if(StoreInst *SI = dyn_cast<StoreInst>(inst)) {
+ if(SI->getOperand(1) == magicAnnotationVar) {
+ ConstantInt *CI = dyn_cast<ConstantInt>(SI->getOperand(0));
+ assert(CI && "Bad call annotation!");
+ annotationFound = true;
+ *annotation = CI->getSExtValue();
+ break;
+ }
+ }
+ else if(isa<CallInst>(inst) || isa<InvokeInst>(inst)) {
+ break;
+ }
+ }
+ return annotationFound;
+}
+
+bool MagicUtil::getVarAnnotation(Module &M, const GlobalVariable *GV, int *annotation)
+{
+ std::string GVName = GV->getName();
+ GlobalVariable *annotationGV = M.getNamedGlobal(MAGIC_VAR_ANNOTATION_PREFIX_NAME + GVName);
+ if(!annotationGV || !annotationGV->hasInitializer()) {
+ return false;
+ }
+ ConstantInt* annotationValue = dyn_cast<ConstantInt>(annotationGV->getInitializer());
+ if(!annotationValue) {
+ return false;
+ }
+ *annotation = (int) annotationValue->getSExtValue();
+ return true;
+}
+
+CallSite MagicUtil::getCallSiteFromInstruction(Instruction *I)
+{
+ return PassUtil::getCallSiteFromInstruction(I);
+}
+
+AllocaInst* MagicUtil::getAllocaInstFromArgument(Argument *argument)
+{
+ Function *parent = argument->getParent();
+ std::string targetString = argument->getName().str() + "_addr";
+ std::string targetString2 = argument->getName().str() + ".addr";
+ StringRef targetName(targetString);
+ StringRef targetName2(targetString2);
+ for (inst_iterator it = inst_begin(parent), et = inst_end(parent); it != et; ++it) {
+ AllocaInst *AI = dyn_cast<AllocaInst>(&(*it));
+ if(!AI) {
+ break;
+ }
+ if(AI->getName().startswith(targetName) || AI->getName().startswith(targetName2)) {
+ return AI;
+ }
+ }
+
+ return NULL;
+}
+
+// searches for the specified function in module symbol table assuming that its name has been mangled
+// returns NULL if the function has not been found
+Function* MagicUtil::getMangledFunction(Module &M, StringRef functionName)
+{
+ Function *F = NULL;
+ char* outbuf;
+ const char* functionNameString = functionName.data();
+ int status;
+ for (Module::iterator it = M.begin(); it != M.end(); ++it) {
+ StringRef mangledName = (*it).getName();
+ outbuf = abi::__cxa_demangle(mangledName.data(), NULL, NULL, &status);
+ if (status == -2) {
+ continue; // mangledName is not a valid name under the C++ ABI mangling rules
+ }
+ assert(status == 0 && outbuf && "Error when trying to demangle a function name.");
+ // testing whether this is the function we are looking for
+ // the unmangled name is similar to a function prototype eg my_func(int, void*, int)
+ char* pos = strstr(outbuf, functionNameString);
+ if (!pos) {
+ free(outbuf);
+ continue;
+ }
+ // function names can only contain alpha-numeric characters and '_'
+ // if the unmangled name refers to the target function, then that substring should not
+ // be surrounded by characters allowed in a function name
+ // (to exclude cases such as myfunc vs _myfunc vs myfunc2)
+ if (pos > outbuf) {
+ if (isalnum(*(pos - 1)) || (*(pos - 1) == '_')) {
+ free(outbuf);
+ continue;
+ }
+ }
+ if (strlen(pos) > strlen(functionNameString)) {
+ if (isalnum(*(pos + strlen(functionNameString))) || (*(pos + strlen(functionNameString)) == '_')) {
+ free(outbuf);
+ continue;
+ }
+ }
+ F = it;
+ free(outbuf);
+ break;
+ }
+
+ return F;
+}
+
+Function* MagicUtil::getFunction(Module &M, StringRef functionName)
+{
+ Function* F = M.getFunction(functionName);
+ if (!F) {
+ F = MagicUtil::getMangledFunction(M, functionName);
+ }
+ return F;
+}
+
+// can Type1 be represented as Type2 (with no precision loss)
+bool MagicUtil::isCompatibleType(const Type* Type1, const Type* Type2)
+{
+ if (Type1 == Type2) {
+ return true;
+ }
+ if (Type1->isIntegerTy() && Type2->isIntegerTy()) {
+ if (((const IntegerType*)Type1)->getBitWidth() <= ((const IntegerType*)Type2)->getBitWidth()) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// inserts an inlined call to the pre-hook function before any other instruction is executed
+// it can forward (some of) the original function's parameters and additional trailing arguments
+void MagicUtil::inlinePreHookForwardingCall(Function* function, Function* preHookFunction, std::vector<unsigned> argsMapping, std::vector<Value*> trailingArgs)
+{
+ std::vector<Value*> callArgs;
+ assert(preHookFunction->arg_size() == argsMapping.size() + trailingArgs.size() &&
+ "The number of parameter values specified for the pre-hook function does not match the signature of the function.");
+ for (std::vector<unsigned>::iterator it = argsMapping.begin(); it != argsMapping.end(); it++) {
+ callArgs.push_back(MagicUtil::getFunctionParam(function, *it - 1));
+ }
+ for (std::vector<Value*>::iterator it = trailingArgs.begin(); it != trailingArgs.end(); it++) {
+ callArgs.push_back(*it);
+ }
+ // insert the call after the alloca instructions so that they remain for sure in the entry block
+ Instruction *FirstInst = MagicUtil::getFirstNonAllocaInst(function);
+ for (unsigned i = 0; i < callArgs.size(); ++i) {
+ TYPECONST Type* ArgType = callArgs[i]->getType();
+ TYPECONST Type* ParamType = preHookFunction->getFunctionType()->getParamType(i);
+
+ if (!MagicUtil::isCompatibleType(ArgType, ParamType)) {
+ assert(CastInst::isCastable(ArgType, ParamType) && "The value of the argument cannot be "
+ "casted to the parameter type required by the function to be called.");
+ Instruction::CastOps CastOpCode = CastInst::getCastOpcode(callArgs[i], false, ParamType, false);
+ callArgs[i] = CastInst::Create(CastOpCode, callArgs[i], ParamType, "", FirstInst);
+ }
+ }
+
+ CallInst* WrapperFuncCall = MagicUtil::createCallInstruction(preHookFunction, callArgs, "", FirstInst);
+ InlineFunctionInfo IFI;
+ InlineFunction(WrapperFuncCall, IFI);
+}
+
+// inserts an inlined call to the post-hook function before all return instructions
+// forwarded arguments from the first function come first, followed by the trailing ones
+// use offsets > 0 for function parameter mappings, and 0 for the return value of the function
+void MagicUtil::inlinePostHookForwardingCall(Function* function, Function* postHookFunction, std::vector<unsigned> mapping, std::vector<Value*> trailingArgs)
+{
+ std::vector<CallInst*> wrapperCalls;
+ assert(postHookFunction->arg_size() == mapping.size() + trailingArgs.size()
+ && "The number of parameter values specified for the post-hook function does not match the signature of the function.");
+
+ for (Function::iterator BI = function->getBasicBlockList().begin(); BI != function->getBasicBlockList().end(); ++BI) {
+ ReturnInst *RetInst = dyn_cast<ReturnInst>(BI->getTerminator());
+ if (RetInst) {
+ std::vector<Value*> callArgs;
+ for (std::vector<unsigned>::iterator it = mapping.begin(); it != mapping.end(); it++) {
+ if (*it > 0) {
+ callArgs.push_back(MagicUtil::getFunctionParam(function, *it - 1));
+ } else {
+ callArgs.push_back(RetInst->getReturnValue());
+ }
+ }
+ for (std::vector<Value*>::iterator it = trailingArgs.begin(); it != trailingArgs.end(); it++) {
+ callArgs.push_back(*it);
+ }
+ for (unsigned i = 0; i < callArgs.size(); i++) {
+ TYPECONST Type* ArgType = callArgs[i]->getType();
+ TYPECONST Type* ParamType = postHookFunction->getFunctionType()->getParamType(i);
+
+ if (!MagicUtil::isCompatibleType(ArgType, ParamType)) {
+ assert(CastInst::isCastable(ArgType, ParamType) && "The value of the argument cannot be "
+ "casted to the parameter type required by the function to be called.");
+ Instruction::CastOps CastOpCode = CastInst::getCastOpcode(callArgs[i], false, ParamType, false);
+ callArgs[i] = CastInst::Create(CastOpCode, callArgs[i], ParamType, "", RetInst);
+ }
+ }
+ CallInst* WrapperFuncCall = MagicUtil::createCallInstruction(postHookFunction, callArgs, "", RetInst);
+ wrapperCalls.push_back(WrapperFuncCall);
+ }
+ }
+ for (std::vector<CallInst*>::iterator it = wrapperCalls.begin(); it != wrapperCalls.end(); ++it) {
+ InlineFunctionInfo IFI;
+ InlineFunction(*it, IFI);
+ }
+}
+
+int MagicUtil::getPointerIndirectionLevel(const Type* type)
+{
+ int level = 0;
+ if (const PointerType* ptr_type = dyn_cast<PointerType>(type)) {
+ while (ptr_type) {
+ level++;
+ ptr_type = dyn_cast<PointerType>(ptr_type->getElementType());
+ }
+ }
+
+ return level;
+}
+
+Value* MagicUtil::getFunctionParam(Function* function, unsigned index)
+{
+ if (index >= function->arg_size()) {
+ return NULL;
+ }
+ Function::arg_iterator AI = function->arg_begin();
+ while (index --> 0) {
+ AI++;
+ }
+ return AI;
+}
+
+bool MagicUtil::isLocalConstant(Module &M, GlobalVariable *GV)
+{
+ if (!GV->isConstant()) {
+ return false;
+ }
+ if (GV->getName().endswith(".v")) {
+ return true;
+ }
+ std::pair<StringRef, StringRef> stringPair = GV->getName().split('.');
+ StringRef functionName = stringPair.first;
+ if (!functionName.compare("") || M.getFunction(functionName) == NULL) {
+ return false;
+ }
+
+ return true;
+}
+
+}
--- /dev/null
+#include <magic/support/SmartType.h>
+#include <limits.h>
+
+using namespace llvm;
+
+namespace llvm {
+
+#define DEBUG_EQUALS 0
+#define DEBUG_BFAS 0
+#define DEBUG_UNIONS 0
+int debugEquals = 0;
+
+//===----------------------------------------------------------------------===//
+// Constructors, destructor, and operators
+//===----------------------------------------------------------------------===//
+SmartType::SmartType(const SmartType& et) {
+ cloneFrom(et);
+}
+
+SmartType::SmartType(TYPECONST Type *type, const DIType *aDIType, bool useExceptions, bool forceRawTypeRepresentation) {
+ EDIType tmp(*aDIType);
+ init(type, &tmp, useExceptions, forceRawTypeRepresentation);
+ normalize();
+}
+
+SmartType::SmartType(TYPECONST Type *type, const EDIType *aEDIType, bool useExceptions, bool forceRawTypeRepresentation) {
+ init(type, aEDIType, useExceptions, forceRawTypeRepresentation);
+ normalize();
+}
+
+SmartType::~SmartType() {
+ if(hasExplicitContainedEDITypes) {
+ for(unsigned i=0;i<explicitContainedEDITypes.size();i++) {
+ const EDIType* aEDIType = explicitContainedEDITypes[i];
+ delete aEDIType;
+ }
+ }
+}
+
+SmartType& SmartType::operator=(const SmartType& et) {
+ if (this != &et) {
+ cloneFrom(et);
+ }
+ return *this;
+}
+
+void SmartType::cloneFrom(const SmartType& et) {
+ init(et.type, &et.aEDIType, et.useExceptions, false);
+ if(et.hasExplicitContainedEDITypes) {
+ hasExplicitContainedEDITypes = true;
+ for(unsigned i=0;i<et.explicitContainedEDITypes.size();i++) {
+ const EDIType* aEDIType = et.explicitContainedEDITypes[i];
+ explicitContainedEDITypes.push_back(new EDIType(*aEDIType));
+ }
+ }
+ isInconsistent = et.isInconsistent;
+ rawTypeRepresentation = et.rawTypeRepresentation;
+ bfas = et.bfas;
+}
+
+//===----------------------------------------------------------------------===//
+// Getters
+//===----------------------------------------------------------------------===//
+
+const std::string SmartType::getDescription() const {
+ return TypeUtil::getDescription(type, &aEDIType);
+}
+
+const SmartType* SmartType::getContainedType(unsigned i) const {
+ assert(!rawTypeRepresentation);
+ bool hasBitFields = false;
+ TYPECONST Type *subType = type->getContainedType(i);
+ const SmartType* retSmartType = NULL;
+ if(hasExplicitContainedEDITypes) {
+ const EDIType subEDIType(*(explicitContainedEDITypes[i]));
+ retSmartType = new SmartType(subType, &subEDIType, useExceptions);
+ }
+ else {
+ if(aEDIType.isUnionTy()) {
+ assert(i == 0);
+ i = unionMemberIdx;
+ }
+ else if(bfas.size() > 0) {
+ i = getBFAFreeIdx(i, bfas);
+ hasBitFields = true;
+ }
+ const EDIType subEDIType(aEDIType.getContainedType(i));
+ retSmartType = new SmartType(subType, &subEDIType, useExceptions, hasBitFields && subEDIType.isIntegerTy() && subType->isArrayTy());
+ }
+ return retSmartType;
+}
+
+unsigned SmartType::getNumContainedTypes() const {
+ if(rawTypeRepresentation || aEDIType.isComplexFloatingPointTy() || isOpaqueTy()) {
+ return 0;
+ }
+ unsigned numContainedTypes = type->getNumContainedTypes();
+ unsigned numContainedEDITypes;
+ if(hasExplicitContainedEDITypes) {
+ numContainedEDITypes = explicitContainedEDITypes.size();
+ }
+ else {
+ if(aEDIType.isUnionTy()) {
+ numContainedEDITypes = 1;
+ }
+ else {
+ numContainedEDITypes = aEDIType.getNumContainedTypes();
+ if(bfas.size() > 0) {
+ for(unsigned i=0;i<bfas.size();i++) {
+ numContainedEDITypes -= (bfas[i].getSize() - 1);
+ }
+ }
+ }
+ }
+ if(numContainedTypes == numContainedEDITypes+1 && isPaddedTy()) {
+ numContainedTypes--;
+ }
+ if(numContainedTypes != numContainedEDITypes) {
+ if(isArrayTy() && TypeUtil::isArrayAsStructTy(type)) {
+ numContainedTypes = 1;
+ }
+ }
+ SmartType_assert(numContainedTypes == numContainedEDITypes);
+ return numContainedTypes;
+}
+
+const DIDerivedType& SmartType::getMember(unsigned i) const {
+ assert(!rawTypeRepresentation);
+ if(bfas.size() > 0) {
+ i = getBFAFreeIdx(i, bfas);
+ }
+ return aEDIType.getMember(i);
+}
+
+unsigned SmartType::getUnionMemberIdx() const {
+ assert(!rawTypeRepresentation);
+ SmartType_assert(isTy(type->isStructTy(), aEDIType.isUnionTy(), "getUnionMemberIdx"));
+ SmartType_assert(getNumContainedTypes() == 1);
+ TYPECONST Type* uMemberType = type->getContainedType(0);
+ unsigned numSubEDITypes = aEDIType.getNumContainedTypes();
+ std::vector<unsigned> indexes;
+ int maxWeakConsistencyLevel = -1;
+ unsigned maxWeakConsistencyIndex = -1;
+ int maxWeakConsistencyLevelEntries;
+ unsigned index;
+ for(unsigned i=0;i<numSubEDITypes;i++) {
+ int weakConsistencyLevel;
+ EDIType subEDIType = aEDIType.getContainedType(i);
+ if(isTypeConsistent(uMemberType, &subEDIType, true, &weakConsistencyLevel)) {
+ indexes.push_back(i);
+ if(weakConsistencyLevel > maxWeakConsistencyLevel) {
+ maxWeakConsistencyLevel = weakConsistencyLevel;
+ maxWeakConsistencyIndex = i;
+ maxWeakConsistencyLevelEntries = 1;
+ }
+ else if(weakConsistencyLevel == maxWeakConsistencyLevel) {
+ maxWeakConsistencyLevelEntries++;
+ }
+ }
+ }
+ if(indexes.size() == 0) {
+ //try to match names if we failed before
+ std::string name = EDIType::lookupUnionMemberName(type);
+ if(name.compare("")) {
+ for(unsigned i=0;i<numSubEDITypes;i++) {
+ EDIType subEDIType = aEDIType.getContainedType(i);
+ if(!subEDIType.getName().compare(name)) {
+ indexes.push_back(i);
+ maxWeakConsistencyIndex = i;
+ }
+ }
+ }
+ }
+ if(indexes.size() == 0) {
+ //No valid union member found
+#if DEBUG_UNIONS
+ SmartTypeErr("getUnionMemberIdx: resorting to a raw type. No valid union member found for: " << getDescription());
+#endif
+ return UINT_MAX;
+ }
+ index = maxWeakConsistencyIndex;
+ if(indexes.size() > 1) {
+ SmartTypeLog("getUnionMemberIdx: warning: multiple valid union members found, automatically selecting the first most-consistent member:");
+ SmartTypeLog(" - target member type is: " << TypeUtil::getDescription(uMemberType));
+ SmartTypeLog(" - selected index is: " << index);
+ for(unsigned i=0;i<indexes.size();i++) {
+ EDIType subEDIType = aEDIType.getContainedType(indexes[i]);
+ SmartTypeLog(" - " << indexes[i] << ". " << TypeUtil::getDescription(&subEDIType));
+ }
+ }
+
+ return index;
+}
+
+const SmartType* SmartType::getTopStructType(unsigned index) const {
+ TYPECONST Type *topType = TypeUtil::lookupTopStructType(type, index);
+ const EDIType *topEDIType = aEDIType.getTopStructType(index);
+ assert((topType && topEDIType) || (!topType && !topEDIType));
+ if(topType) {
+ const SmartType* retSmartType = new SmartType(topType, topEDIType);
+ return retSmartType;
+ }
+ return NULL;
+}
+
+//===----------------------------------------------------------------------===//
+// Other public methods
+//===----------------------------------------------------------------------===//
+
+void SmartType::verify() const {
+ SmartType_assert(isTypeConsistent());
+}
+
+void SmartType::print(raw_ostream &OS) const {
+ OS << getDescription();
+}
+
+bool SmartType::equals(const SmartType* other, bool isDebug) const {
+ static std::set<std::pair<MDNode*, MDNode*> > compatibleMDNodes;
+ static std::set<std::pair<MDNode*, MDNode*> >::iterator compatibleMDNodesIt;
+#if DEBUG_EQUALS
+ if(debugEquals) SmartTypeErr("COMPARING :" << getDescription() << " VS " << other->getDescription());
+#endif
+ if(type != other->getType()) {
+#if DEBUG_EQUALS
+ if(debugEquals) SmartTypeErr("----> false1");
+#endif
+ return false;
+ }
+ if(isOpaqueTy() || other->isOpaqueTy()) {
+ return isOpaqueTy() && other->isOpaqueTy();
+ }
+ if(aEDIType.getTag() != other->getEDIType()->getTag()) {
+#if DEBUG_EQUALS
+ if(debugEquals) SmartTypeErr("----> false1b");
+#endif
+ return false;
+ }
+ if(isFunctionTy() && (!isTypeConsistent() || !other->isTypeConsistent())) {
+ //we just compare the types for inconsistent functions types
+ return true;
+ }
+ if(hasRawTypeRepresentation() || other->hasRawTypeRepresentation()) {
+ return !aEDIType.getNamesString().compare(other->getEDIType()->getNamesString());
+ }
+ unsigned numContainedTypes = getNumContainedTypes();
+ unsigned otherNumContainedTypes = other->getNumContainedTypes();
+ if(numContainedTypes != otherNumContainedTypes) {
+#if DEBUG_EQUALS
+ if(debugEquals) SmartTypeErr("----> false2");
+#endif
+ return false;
+ }
+ unsigned numElements = aEDIType.getNumElements();
+ unsigned otherNumElements = other->getEDIType()->getNumElements();
+ if(numElements != otherNumElements) {
+#if DEBUG_EQUALS
+ if(debugEquals) SmartTypeErr("----> false2b");
+#endif
+ return false;
+ }
+ std::string name = aEDIType.getName();
+ std::string otherName = other->getEDIType()->getName();
+ if(name.compare(otherName)) {
+#if DEBUG_EQUALS
+ if(debugEquals) SmartTypeErr("----> false3: " << name << " vs " << otherName);
+#endif
+ return false;
+ }
+ if(aEDIType.getNames().size() > 1 || other->getEDIType()->getNames().size() > 1) {
+ std::string namesString = aEDIType.getNamesString();
+ std::string otherNamesString = other->getEDIType()->getNamesString();
+ if(namesString.compare(otherNamesString)) {
+#if DEBUG_EQUALS
+ if(debugEquals) SmartTypeErr("----> false4: " << namesString << " vs " << otherNamesString);
+#endif
+ return false;
+ }
+ }
+ if(numContainedTypes == 0) {
+#if DEBUG_EQUALS
+ if(debugEquals) SmartTypeErr("----> true4");
+#endif
+ return true;
+ }
+ MDNode *node = *(aEDIType.getDIType());
+ MDNode *otherNode = *(other->getEDIType()->getDIType());
+ if(node == otherNode) {
+ return true;
+ }
+ for(unsigned i=0;i<SmartType::equalsNestedTypes.size();i++) {
+ if(type == SmartType::equalsNestedTypes[i]) {
+#if DEBUG_EQUALS
+ if(debugEquals) SmartTypeErr("----> true5");
+#endif
+ return true;
+ }
+ }
+ //before digging the type tree, see if we have these 2 metadata nodes in cache
+ //this gives us an impressive speedup
+ MDNode *minNode = node < otherNode ? node : otherNode;
+ MDNode *maxNode = node < otherNode ? otherNode : node;
+ compatibleMDNodesIt = compatibleMDNodes.find(std::pair<MDNode*, MDNode*>(minNode, maxNode));
+ if(compatibleMDNodesIt != compatibleMDNodes.end()) {
+ return true;
+ }
+ SmartType::equalsNestedTypes.push_back(type);
+ const SmartType* containedType = NULL;
+ const SmartType* otherContainedType = NULL;
+ bool sameContainedTypes = true;
+ for(unsigned i=0;i<numContainedTypes;i++) {
+ containedType = getContainedType(i);
+ otherContainedType = other->getContainedType(i);
+ sameContainedTypes = containedType->equals(otherContainedType);
+ delete containedType;
+ delete otherContainedType;
+ if(!sameContainedTypes) {
+ break;
+ }
+ }
+ SmartType::equalsNestedTypes.pop_back();
+ if(!sameContainedTypes) {
+#if DEBUG_EQUALS
+ if(debugEquals) SmartTypeErr("----> false6");
+#endif
+ return false;
+ }
+#if DEBUG_EQUALS
+ if(debugEquals) SmartTypeErr("----> true7");
+#endif
+ compatibleMDNodes.insert(std::pair<MDNode*, MDNode*>(minNode, maxNode));
+ return true;
+}
+
+//===----------------------------------------------------------------------===//
+// Public static methods
+//===----------------------------------------------------------------------===//
+
+const SmartType* SmartType::getSmartTypeFromGV(Module &M, GlobalVariable *GV, DIGlobalVariable *DIG) {
+ //ignore anonymous strings
+ if(GV->getName().startswith(".str")) {
+ return NULL;
+ }
+ Value *DIGV = Backports::findDbgGlobalDeclare(GV);
+ if (!DIGV) {
+ return NULL;
+ }
+ DIGlobalVariable Var(cast<MDNode>(DIGV));
+ DIType aDIType = Var.getType();
+ const SmartType* retSmartType = new SmartType(GV->getType()->getElementType(), &aDIType);
+ if(DIG) {
+ *DIG = Var;
+ }
+ return retSmartType;
+}
+
+const SmartType* SmartType::getSmartTypeFromLV(Module &M, AllocaInst *AI, DIVariable *DIV) {
+ const DbgDeclareInst *DDI = Backports::FindAllocaDbgDeclare(AI);
+ if (!DDI) {
+ return NULL;
+ }
+ if(DDI == (const DbgDeclareInst *) -1) {
+ return (const SmartType*)-1;
+ }
+ DIVariable Var(cast<MDNode>(DDI->getVariable()));
+ DIType aDIType = Var.getType();
+ if(DIV) {
+ *DIV = Var;
+ }
+ const SmartType* aSmartType = new SmartType(AI->getAllocatedType(), &aDIType);
+ return aSmartType;
+}
+
+const SmartType* SmartType::getSmartTypeFromFunction(Module &M, Function *F, DISubprogram *DIS) {
+ Value *DIF = Backports::findDbgSubprogramDeclare(F);
+ if (!DIF) {
+ return NULL;
+ }
+ DISubprogram Sub(cast<MDNode>(DIF));
+ DIType aDIType = Sub.getType();
+ const SmartType* retSmartType = new SmartType(F->getType()->getElementType(), &aDIType);
+ if(DIS) {
+ *DIS = Sub;
+ }
+ return retSmartType;
+}
+
+const SmartType* SmartType::getStructSmartTypeByName(Module &M, GlobalVariable* GV, std::string &name, bool isUnion) {
+ std::string structName((isUnion ? "union." : "struct.") + name);
+
+ TYPECONST Type *targetType = M.getTypeByName(structName);
+ const EDIType *targetEDIType = EDIType::getStructEDITypeByName(name);
+
+ const SmartType *retSmartType = NULL;
+ if(targetType && targetEDIType) {
+ retSmartType = new SmartType(targetType, targetEDIType);
+ }
+ return retSmartType;
+}
+
+std::vector<const SmartType*>* SmartType::getTopStructSmartTypes(Module &M, GlobalVariable* GV) {
+ std::vector<std::string> names;
+ std::vector<unsigned> flags;
+ TypeUtil::parseTopStructTypes(M, GV->getType()->getElementType(), &names, &flags);
+ std::vector<const SmartType*> *vector = new std::vector<const SmartType*>;
+ for(unsigned i=0;i<names.size();i++) {
+ std::string entryName = names[i];
+ unsigned entryFlags = flags[i];
+ const SmartType *aSmartType = NULL;
+ if(!(entryFlags & TypeUtil::TYPE_ANONYMOUS) && !(entryFlags & TypeUtil::TYPE_UNNAMED)) {
+ aSmartType = getStructSmartTypeByName(M, GV, entryName, (entryFlags & TypeUtil::TYPE_UNION));
+ }
+ if(aSmartType == NULL) {
+ //this method can fail due to name clashing but is the only one possible for anonymous or unnamed struct types
+ const SmartType *GVSmartType = getSmartTypeFromGV(M, GV);
+ assert(GVSmartType && "Unable to find a match for anonymous or unnamed struct type");
+ aSmartType = GVSmartType->getTopStructType(i);
+ delete GVSmartType;
+ assert(aSmartType != NULL);
+ }
+ vector->push_back(aSmartType);
+ }
+
+ return vector;
+}
+
+//===----------------------------------------------------------------------===//
+// Private methods
+//===----------------------------------------------------------------------===//
+
+void SmartType::init(TYPECONST Type *type, const EDIType *aEDIType, bool useExceptions, bool forceRawTypeRepresentation) {
+ this->type = type;
+ this->aEDIType = *aEDIType;
+ this->useExceptions = useExceptions;
+ hasExplicitContainedEDITypes = false;
+ isInconsistent = false;
+ rawTypeRepresentation = false;
+ unionMemberIdx = 0;
+ if(aEDIType->isUnionTy()) {
+ if(forceRawUnions) {
+ rawTypeRepresentation = true;
+ }
+ else {
+ unionMemberIdx = getUnionMemberIdx();
+ if(unionMemberIdx == UINT_MAX) {
+ rawTypeRepresentation = true;
+ unionMemberIdx = 0;
+ }
+ }
+ }
+ else if(forceRawTypeRepresentation || (forceRawBitfields && BitFieldAggregation::hasBitFields(type, &(this->aEDIType)))) {
+ rawTypeRepresentation = true;
+ }
+}
+
+void SmartType::normalize() {
+ if(isFunctionTy() && !hasExplicitContainedEDITypes) {
+ flattenFunctionTy();
+ hasExplicitContainedEDITypes = true;
+ }
+ if(!hasExplicitContainedEDITypes && !rawTypeRepresentation) {
+ if(!BitFieldAggregation::getBitFieldAggregations(type, &aEDIType, bfas, true)) {
+ //failed to determine bfas
+#if DEBUG_BFAS
+ SmartTypeErr("normalize: resorting to a raw type. Cannot determine bfas for: " << getDescription());
+#endif
+ rawTypeRepresentation = true;
+ }
+ }
+}
+
+void SmartType::flattenFunctionTy() {
+ SmartType_assert(isFunctionTy() && !hasExplicitContainedEDITypes);
+ SmartType_assert(explicitContainedEDITypes.size() == 0);
+#if MAGIC_FLATTEN_FUNCTION_ARGS
+ int ret = flattenFunctionArgs(type, &aEDIType, 0);
+ if(ret < 0 || explicitContainedEDITypes.size() != type->getNumContainedTypes()) {
+ SmartTypeLog("Warning: function flattening produced an inconsistent type!");
+ isInconsistent = true;
+ }
+#else
+ isInconsistent = true;
+#endif
+}
+
+int SmartType::flattenFunctionArgs(TYPECONST Type *type, const EDIType *aEDIType, unsigned nextContainedType) {
+ unsigned containedTypes = type->getNumContainedTypes();
+ unsigned containedEDITypes = aEDIType->isUnionTy() ? 1 : aEDIType->getNumContainedTypes();
+ unsigned containedEDIOptions = aEDIType->isUnionTy() ? aEDIType->getNumContainedTypes() : 1;
+ int ret;
+
+ unsigned nextContainedEDIType = 0;
+ while(nextContainedEDIType < containedEDITypes) {
+ SmartType_assert(nextContainedType < containedTypes);
+ TYPECONST Type *containedType = type->getContainedType(nextContainedType);
+ unsigned currExplicitEDITypes = explicitContainedEDITypes.size();
+ unsigned i;
+ for(i=nextContainedEDIType;i<nextContainedEDIType+containedEDIOptions;i++) {
+ const EDIType containedEDIType = aEDIType->getContainedType(i);
+ if(isTypeConsistent(containedType, &containedEDIType)) {
+ explicitContainedEDITypes.push_back(new EDIType(containedEDIType));
+ break;
+ }
+ if(!containedEDIType.isAggregateType()) {
+ continue;
+ }
+ ret = flattenFunctionArgs(type, &containedEDIType, nextContainedType);
+ if(ret == 0) {
+ break;
+ }
+ }
+ if(i >= nextContainedEDIType+containedEDIOptions) {
+ while(explicitContainedEDITypes.size() > currExplicitEDITypes) {
+ EDIType* aEDIType = explicitContainedEDITypes[explicitContainedEDITypes.size()-1];
+ explicitContainedEDITypes.pop_back();
+ delete aEDIType;
+ }
+ return -1;
+ }
+ nextContainedType += (explicitContainedEDITypes.size() - currExplicitEDITypes);
+ nextContainedEDIType++;
+ }
+ return 0;
+}
+
+bool SmartType::isTy(bool isTyType, bool isTyEDIType, const char* source) const {
+ bool check = (isTyType && isTyEDIType) || (!isTyType && !isTyEDIType);
+ if(!check) {
+ SmartTypeErr(source << " failed");
+ }
+ SmartType_assert(check);
+ return isTyType;
+}
+
+//===----------------------------------------------------------------------===//
+// Private static methods
+//===----------------------------------------------------------------------===//
+unsigned SmartType::getBFAFreeIdx(unsigned i, const std::vector<BitFieldAggregation> &inputBfas) {
+ for(unsigned j=0;j<inputBfas.size();j++) {
+ if(i<inputBfas[j].getEDITypeIndex()) {
+ break;
+ }
+ else if(i>inputBfas[j].getEDITypeIndex()) {
+ i += (inputBfas[j].getSize() - 1);
+ }
+ else {
+ i = inputBfas[j].getRepresentativeEDITypeIndex();
+ break;
+ }
+ }
+ return i;
+}
+
+bool SmartType::isRawTypeConsistent(TYPECONST Type *type, const EDIType *aEDIType) {
+ if(aEDIType->isVoidTy()) {
+ return type->isVoidTy() || (type->isIntegerTy() && ((IntegerType*)type)->getBitWidth() == 8);
+ }
+ if(type->isFloatingPointTy()) {
+ return aEDIType->isFloatingPointTy();
+ }
+ if(type->isIntegerTy()) {
+ if(aEDIType->isCharTy() || aEDIType->isBoolTy()) {
+ return (((IntegerType*)type)->getBitWidth() <= 8);
+ }
+ return aEDIType->isIntegerTy() || aEDIType->isEnumTy();
+ }
+ if(type->isFunctionTy()) {
+ return aEDIType->isFunctionTy();
+ }
+ if(TypeUtil::isOpaqueTy(type)) {
+ return (aEDIType->isOpaqueTy());
+ }
+ return false;
+}
+
+bool SmartType::isTypeConsistent2(std::vector<TYPECONST Type*> &nestedTypes, std::vector<const EDIType*> &nestedEDITypes, const SmartType *aSmartType) {
+ assert(aSmartType->isUseExceptions());
+ TYPECONST Type *type = aSmartType->getType();
+ const EDIType *aEDIType = aSmartType->getEDIType();
+ if(aEDIType->isPointerTy() || aEDIType->isUnionOrStructTy()) {
+ for(unsigned j=0;j<nestedTypes.size();j++) {
+ if(nestedTypes[j] == type && nestedEDITypes[j]->equals(aEDIType)) {
+ return true;
+ }
+ }
+ }
+
+ unsigned nTypes = type->getNumContainedTypes();
+ unsigned nEDITypes = aEDIType->getNumContainedTypes();
+ if(nTypes == 0 || nEDITypes == 0) {
+ if(nTypes != 0 || nEDITypes != 0) {
+ return false;
+ }
+ return isRawTypeConsistent(type, aEDIType);
+ }
+ if(!aSmartType->verifyTy()) {
+ return false;
+ }
+ unsigned numContainedTypes = aSmartType->getNumContainedTypes();
+ nestedTypes.push_back(type);
+ nestedEDITypes.push_back(aEDIType);
+ for(unsigned i=0;i<numContainedTypes;i++) {
+ const SmartType *containedSmartType = aSmartType->getContainedType(i);
+ assert(containedSmartType->isUseExceptions());
+ SmartType clonedSmartType(*containedSmartType);
+ assert(clonedSmartType.isUseExceptions());
+ delete containedSmartType;
+ if(!isTypeConsistent2(nestedTypes, nestedEDITypes, &clonedSmartType)) {
+ return false;
+ }
+ }
+ nestedTypes.pop_back();
+ nestedEDITypes.pop_back();
+ return true;
+}
+
+bool SmartType::isTypeConsistent2(TYPECONST Type *type, const EDIType *aEDIType) {
+ /* Exception-handling based isTypeConsistent(). Broken with -fno-exceptions. */
+ static std::vector<TYPECONST Type*> nestedTypes;
+ static std::vector<const EDIType*> nestedEDITypes;
+ static unsigned level = 0;
+
+ if(level == 0) {
+ nestedTypes.clear();
+ nestedEDITypes.clear();
+ }
+
+ bool checkTypeConsistent = false;
+ bool useExceptions = true;
+ level++;
+ assert(useExceptions);
+ TRY(
+ const SmartType aSmartType(type, aEDIType, useExceptions);
+ checkTypeConsistent = isTypeConsistent2(nestedTypes, nestedEDITypes, &aSmartType);
+ )
+ CATCH(std::exception& e,
+ checkTypeConsistent = false;
+ )
+ level--;
+ return checkTypeConsistent;
+}
+
+bool SmartType::isTypeConsistent(TYPECONST Type *type, const EDIType *aEDIType, bool useBfas, int *weakConsistencyLevel) {
+ static std::vector<TYPECONST Type*> nestedTypes;
+ static std::vector<const EDIType*> nestedEDITypes;
+ static unsigned level = 0;
+
+ if(level == 0) {
+ if(weakConsistencyLevel) {
+ *weakConsistencyLevel = INT_MAX;
+ }
+ }
+
+ if(aEDIType->isPointerTy() || aEDIType->isUnionOrStructTy()) {
+ for(unsigned j=0;j<nestedTypes.size();j++) {
+ if(nestedTypes[j] == type && nestedEDITypes[j]->equals(aEDIType)) {
+ return true;
+ }
+ }
+ }
+
+ unsigned nTypes = type->getNumContainedTypes();
+ unsigned nEDITypes = aEDIType->getNumContainedTypes();
+ if(nTypes == 0 || nEDITypes == 0) {
+ if(nTypes != 0 || nEDITypes != 0) {
+ return false;
+ }
+ return isRawTypeConsistent(type, aEDIType);
+ }
+
+ if(aEDIType->isOpaqueTy()) {
+ return (TypeUtil::isOpaqueTy(type));
+ }
+
+ bool isArrayOrVectorTy = aEDIType->isArrayTy() || aEDIType->isVectorTy();
+ unsigned nEDINumElements = aEDIType->getNumElements();
+ if(aEDIType->isDerivedType() || isArrayOrVectorTy) {
+ TYPECONST Type *nextType = type;
+ if(aEDIType->isPointerTy()) {
+ if(!type->isPointerTy()) {
+ return false;
+ }
+ nextType = type->getContainedType(0);
+ }
+ else if(aEDIType->isArrayTy()) {
+ if(!type->isArrayTy() || ((ArrayType*)type)->getNumElements() != nEDINumElements) {
+ return false;
+ }
+ nextType = type->getContainedType(0);
+ }
+ else if(aEDIType->isVectorTy()) {
+ if(!type->isVectorTy() || ((VectorType*)type)->getNumElements() != nEDINumElements) {
+ return false;
+ }
+ nextType = type->getContainedType(0);
+ }
+ const EDIType aEDISubType(aEDIType->getContainedType(0));
+ nestedEDITypes.push_back(aEDIType);
+ nestedTypes.push_back(type);
+ level++;
+ bool ret = isTypeConsistent(nextType, &aEDISubType, useBfas, weakConsistencyLevel);
+ level--;
+ nestedTypes.pop_back();
+ nestedEDITypes.pop_back();
+ return ret;
+ }
+ else if(aEDIType->isCompositeType()) {
+ if(!aEDIType->isUnionOrStructTy() && !aEDIType->isVectorTy() && !aEDIType->isFunctionTy()) {
+ return false;
+ }
+ if(aEDIType->isUnionOrStructTy() && !type->isStructTy()) {
+ return false;
+ }
+ if(aEDIType->isVectorTy() && !type->isVectorTy()) {
+ return false;
+ }
+ if(aEDIType->isFunctionTy() && !type->isFunctionTy()) {
+ return false;
+ }
+ if(aEDIType->isUnionTy() || aEDIType->isFunctionTy()) {
+ if(weakConsistencyLevel) {
+ *weakConsistencyLevel = level;
+ }
+ return true; //xxx we should be less conservative here
+ }
+ unsigned numContainedEDITypes = aEDIType->getNumContainedTypes();
+ std::vector<BitFieldAggregation> myBfas;
+ if(numContainedEDITypes != type->getNumContainedTypes()) {
+ if(!useBfas) {
+ return false;
+ }
+ if(!BitFieldAggregation::getBitFieldAggregations(type, aEDIType, myBfas, true)) {
+ return false;
+ }
+ for(unsigned i=0;i<myBfas.size();i++) {
+ numContainedEDITypes -= (myBfas[i].getSize() - 1);
+ }
+ if(numContainedEDITypes != type->getNumContainedTypes()) {
+ return false;
+ }
+ nestedEDITypes.push_back(aEDIType);
+ nestedTypes.push_back(type);
+ level++;
+ for(unsigned i=0;i<numContainedEDITypes;i++) {
+ const EDIType aEDISubType(aEDIType->getContainedType(getBFAFreeIdx(i, myBfas)));
+ if(!isTypeConsistent(type->getContainedType(i), &aEDISubType, useBfas, weakConsistencyLevel)) {
+ level--;
+ nestedTypes.pop_back();
+ nestedEDITypes.pop_back();
+ return false;
+ }
+ }
+ level--;
+ nestedTypes.pop_back();
+ nestedEDITypes.pop_back();
+ return true;
+ }
+ nestedEDITypes.push_back(aEDIType);
+ nestedTypes.push_back(type);
+ level++;
+ for(unsigned i=0;i<numContainedEDITypes;i++) {
+ const EDIType aEDISubType(aEDIType->getContainedType(i));
+ if(!isTypeConsistent(type->getContainedType(i), &aEDISubType, useBfas, weakConsistencyLevel)) {
+ level--;
+ nestedTypes.pop_back();
+ nestedEDITypes.pop_back();
+ return false;
+ }
+ }
+ level--;
+ nestedTypes.pop_back();
+ nestedEDITypes.pop_back();
+ return true;
+ }
+ return false;
+}
+
+std::vector<TYPECONST Type*> SmartType::equalsNestedTypes;
+
+}
--- /dev/null
+#include <magic/support/TypeUtil.h>
+
+using namespace llvm;
+
+namespace llvm {
+
+//===----------------------------------------------------------------------===//
+// Public static methods
+//===----------------------------------------------------------------------===//
+
+bool TypeUtil::isPaddedType(TYPECONST Type *type) {
+ if(type->getNumContainedTypes() < 2) {
+ return false;
+ }
+ TYPECONST Type *lastContainedType = type->getContainedType(type->getNumContainedTypes() - 1);
+ bool paddedTy = lastContainedType->isIntegerTy() || (lastContainedType->isArrayTy() &&
+ lastContainedType->getContainedType(0)->isIntegerTy());
+ return paddedTy;
+}
+
+TYPECONST Type* TypeUtil::lookupTopStructType(TYPECONST Type *type, unsigned index) {
+ static unsigned level = 0;
+ static unsigned structsLeft;
+
+ if(level == 0) {
+ structsLeft = index;
+ }
+
+ if(type->isStructTy() || TypeUtil::isOpaqueTy(type)) {
+ if(structsLeft == 0) {
+ return type;
+ }
+ else {
+ structsLeft--;
+ return NULL;
+ }
+ }
+ unsigned numContainedTypes = type->getNumContainedTypes();
+ for(unsigned i=0;i<numContainedTypes;i++) {
+ TYPECONST Type *containedType = type->getContainedType(i);
+ level++;
+ TYPECONST Type *topStructType = lookupTopStructType(containedType, index);
+ level--;
+ if(topStructType != NULL) {
+ return topStructType;
+ }
+ }
+ return NULL;
+}
+
+void TypeUtil::parseTopStructTypes(Module &M, TYPECONST Type *type, std::vector<std::string> *names, std::vector<unsigned> *flags) {
+ std::string string;
+ raw_string_ostream ostream(string);
+ EDIType::writeTypeSymbolic(ostream, type, &M);
+ ostream.flush();
+ Regex anonRegex("%(union|struct)\\.(\\.*[0-9]*anon)", 0);
+ Regex regularRegex("%(union|struct)\\.([^{}(), *]+)", 0);
+ Regex unnamedRegex("%(%)?([0-9]+)", 0);
+ std::string error;
+ assert(anonRegex.isValid(error) && regularRegex.isValid(error) && unnamedRegex.isValid(error));
+ size_t index = -1;
+ while((index=string.find("%", index+1))!=std::string::npos) {
+ std::string entryString = string.substr(index);
+ if(entryString[entryString.size()-1] == ']') {
+ entryString = entryString.substr(0, entryString.size()-1);
+ }
+ StringRef entryStringRef(entryString);
+ SmallVector<StringRef, 8> entryMatches;
+ unsigned entryFlags;
+ entryMatches.clear();
+ entryFlags = 0;
+ if(anonRegex.match(entryString, &entryMatches)) {
+ entryFlags |= TypeUtil::TYPE_ANONYMOUS;
+ }
+ else if(unnamedRegex.match(entryString, &entryMatches)) {
+ entryFlags |= TypeUtil::TYPE_UNNAMED;
+ }
+ else {
+ assert(regularRegex.match(entryString, &entryMatches) && "Unsupported struct type");
+ }
+ assert(entryStringRef.startswith(entryMatches[0]));
+ std::string prefix = entryMatches[1];
+ std::string name = entryMatches[2];
+ entryFlags |= !prefix.compare("union") ? TypeUtil::TYPE_UNION : TypeUtil::TYPE_STRUCT;
+ if(names) names->push_back(name);
+ if(flags) flags->push_back(entryFlags);
+ }
+}
+
+int TypeUtil::findTopStructTypeIndex(Module &M, TYPECONST Type *type, std::string &name, unsigned flagsToAccept) {
+ std::vector<std::string> names;
+ std::vector<unsigned> flags;
+ parseTopStructTypes(M, type, &names, &flags);
+ int index = -1;
+ for(unsigned i=0;i<names.size();i++) {
+ if(!name.compare(names[i]) && (flagsToAccept | flags[i]) == flagsToAccept) {
+ index = i;
+ break;
+ }
+ }
+ return index;
+}
+
+TYPECONST Type* TypeUtil::getRecursiveElementType(TYPECONST Type *type) {
+ TYPECONST PointerType* pointerType = dyn_cast<PointerType>(type);
+ if(!pointerType) {
+ return type;
+ }
+ return getRecursiveElementType(pointerType->getElementType());
+}
+
+TYPECONST Type* TypeUtil::getArrayFreePointerType(TYPECONST Type *type) {
+ if(type->isPointerTy() || type->isArrayTy()) {
+ TYPECONST Type* elementType = getArrayFreePointerType(type->getContainedType(0));
+ type = PointerType::get(elementType, 0);
+ }
+ return type;
+}
+
+bool TypeUtil::hasInnerPointers(TYPECONST Type *type) {
+ if(TypeUtil::isOpaqueTy(type) || type->isFunctionTy()) {
+ return false;
+ }
+ if(type->isPointerTy()) {
+ return true;
+ }
+
+ unsigned numContainedTypes = type->getNumContainedTypes();
+ if(numContainedTypes == 0) {
+ return false;
+ }
+ else if(type->isArrayTy() || type->isVectorTy()) {
+ return hasInnerPointers(type->getContainedType(0));
+ }
+ else {
+ assert(type->isStructTy());
+ for(unsigned i=0;i<numContainedTypes;i++) {
+ if(hasInnerPointers(type->getContainedType(i))) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool TypeUtil::isArrayAsStructTy(TYPECONST Type *type) {
+ if(!type->isStructTy()) {
+ return false;
+ }
+ return type->getNumContainedTypes() == 1 || type->getContainedType(0) == type->getContainedType(1);
+}
+
+unsigned TypeUtil::getHash(TYPECONST Type* type) {
+ return (unsigned) PassUtil::getTypeHash(type);
+}
+
+const std::string TypeUtil::getDescription(TYPECONST Type* type,
+ size_t max_chars /*= 0*/, size_t max_levels /*= 0*/) {
+ std::string string;
+ if(!PRINT_SKIP_UNIONS && !PRINT_SKIP_STRUCTS && PRINT_USE_BUILTIN_PRINTING) {
+ string = PassUtil::getTypeDescription(type);
+ }
+ else {
+ raw_string_ostream ostream(string);
+ printTypeString(ostream, type, max_chars, max_levels);
+ ostream.flush();
+ }
+ if(VERBOSE_LEVEL > 0) {
+ string = getFormattedDescription(string);
+ }
+ return string;
+}
+
+const std::string TypeUtil::getDescription(const EDIType* aEDIType) {
+ std::string string;
+ string = aEDIType->getDescription(PRINT_SKIP_UNIONS, PRINT_SKIP_STRUCTS, PRINT_MULTI_NAMES);
+ if(VERBOSE_LEVEL > 0) {
+ string = getFormattedDescription(string);
+ }
+ if(VERBOSE_LEVEL > 1) {
+ raw_string_ostream ostream(string);
+ ostream << "\n\t";
+ aEDIType->getDIType()->print(ostream);
+ ostream.flush();
+ }
+ return string;
+}
+
+const std::string TypeUtil::getDescription(TYPECONST Type* type, const EDIType* aEDIType,
+ size_t max_chars /*= 0*/, size_t max_levels /*= 0*/) {
+ std::string string;
+ string = "[\ntype = \n";
+ string.append(TypeUtil::getDescription(type, max_chars, max_levels));
+ string.append("\nEDIType =\n");
+ string.append(TypeUtil::getDescription(aEDIType));
+ string.append("\n]");
+ return string;
+}
+
+const std::string TypeUtil::getFormattedDescription(std::string &description) {
+ std::string string;
+ raw_string_ostream ostream(string);
+ printFormattedTypeString(ostream, description, 0, description.size());
+ ostream.flush();
+ return string;
+}
+
+void TypeUtil::printFormattedTypeString(raw_ostream &OS, std::string &typeStr, int start, int length) {
+ static int indent = 0;
+ for(int k=0;k<indent;k++) OS << " ";
+ for(int i=start;i<start+length;i++) {
+ OS << typeStr[i];
+ if(typeStr[i] == '{') {
+ int newLength = 0;
+ int structsFound = 0;
+ int j;
+ for(j=i+2;j<start+length;j++) {
+ switch(typeStr[j]) {
+ case '{':
+ structsFound++;
+ break;
+ case '}':
+ if(structsFound == 0) {
+ newLength = j-i-3;
+ }
+ else {
+ structsFound--;
+ }
+ break;
+ }
+ if(newLength != 0) {
+ break;
+ }
+ }
+ assert(newLength > 0);
+ OS << "\n";
+ indent += 2;
+ printFormattedTypeString(OS, typeStr, i+2, newLength);
+ indent -= 2;
+ OS << "\n";
+ for(int k=0;k<indent;k++) OS << " ";
+ i = j;
+ OS << typeStr[i];
+ }
+ }
+}
+
+void TypeUtil::printTypeString(raw_ostream &OS, TYPECONST Type* type,
+ size_t max_chars /*= 0*/, size_t max_levels /*= 0*/) {
+ static std::vector<TYPECONST Type*> nestedTypes;
+ static unsigned level = 0;
+ static unsigned counter;
+
+ if (level == 0) {
+ counter = 0;
+ }
+ else if(max_chars && counter >= max_chars) {
+ OS << "%%";
+ return;
+ }
+ else if(max_levels && level >= max_levels) {
+ OS << "%%";
+ return;
+ }
+
+ if(TypeUtil::isOpaqueTy(type)) {
+ OS << "opaque";
+ counter += 6;
+ return;
+ }
+
+ unsigned numContainedTypes = type->getNumContainedTypes();
+ if(numContainedTypes == 0) {
+ assert(!type->isStructTy());
+ type->print(OS);
+ counter += 2;
+ return;
+ }
+
+ if(type->isPointerTy() && type->getContainedType(0)->isStructTy()) {
+ bool isNestedType = false;
+ unsigned j;
+ for(j=0;j<nestedTypes.size();j++) {
+ if(nestedTypes[j] == type) {
+ isNestedType = true;
+ break;
+ }
+ }
+ if(isNestedType) {
+ OS << "\\" << nestedTypes.size() - j;
+ counter += 2;
+ return;
+ }
+ }
+
+ nestedTypes.push_back(type);
+ if(type->isPointerTy()) {
+ TYPECONST Type* subType = type->getContainedType(0);
+ level++;
+ printTypeString(OS, subType);
+ level--;
+ OS << "*";
+ counter++;
+ }
+ else if(type->isArrayTy() || type->isVectorTy()) {
+ TYPECONST Type* subType = type->getContainedType(0);
+ unsigned numElements = type->isArrayTy() ? ((TYPECONST ArrayType*) type)->getNumElements() : ((TYPECONST VectorType*) type)->getNumElements();
+ char startSep = type->isArrayTy() ? '[' : '<';
+ char endSep = type->isArrayTy() ? ']' : '>';
+ OS << startSep;
+ if(numElements) {
+ OS << numElements << " x ";
+ }
+ level++;
+ printTypeString(OS, subType);
+ level--;
+ OS << endSep;
+ counter += 4;
+ }
+ else if(type->isStructTy()) {
+ if(PRINT_SKIP_STRUCTS || PRINT_SKIP_UNIONS) {
+ OS << "$STRUCT/UNION";
+ counter += 13;
+ nestedTypes.pop_back();
+ return;
+ }
+ unsigned numContainedTypes = type->getNumContainedTypes();
+ OS << "{ ";
+ OS << "$STRUCT/UNION ";
+ for(unsigned i=0;i<numContainedTypes;i++) {
+ if(i > 0) {
+ OS << ", ";
+ }
+ TYPECONST Type* subType = type->getContainedType(i);
+ level++;
+ printTypeString(OS, subType);
+ level--;
+ }
+ OS << " }";
+ counter += 18 + 2*numContainedTypes;
+ }
+ else if(type->isFunctionTy()) {
+ unsigned numContainedTypes = type->getNumContainedTypes();
+ assert(numContainedTypes > 0);
+ TYPECONST Type* subType = type->getContainedType(0);
+ level++;
+ printTypeString(OS, subType);
+ level--;
+ numContainedTypes--;
+ OS << " (";
+ for(unsigned i=0;i<numContainedTypes;i++) {
+ if(i > 0) {
+ OS << ", ";
+ }
+ subType = type->getContainedType(i+1);
+ level++;
+ printTypeString(OS, subType);
+ level--;
+ }
+ OS << ")";
+ counter += 3 + 2*numContainedTypes;
+ }
+ else {
+ OS << "???";
+ counter +=3;
+ }
+ nestedTypes.pop_back();
+}
+
+unsigned TypeUtil::typeToBits(TYPECONST Type *type) {
+ if (type->isIntegerTy()) {
+ return ((IntegerType*)type)->getBitWidth();
+ }
+ else if (type->isArrayTy() && type->getContainedType(0)->isIntegerTy()) {
+ TYPECONST Type *containedType = type->getContainedType(0);
+ return ((IntegerType*)containedType)->getBitWidth() * ((ArrayType*)containedType)->getNumElements();
+ }
+ return 0;
+}
+
+int TypeUtil::VERBOSE_LEVEL = 1;
+int TypeUtil::PRINT_SKIP_UNIONS = 0;
+int TypeUtil::PRINT_SKIP_STRUCTS = 0;
+int TypeUtil::PRINT_USE_BUILTIN_PRINTING = 0;
+int TypeUtil::PRINT_MULTI_NAMES = 0;
+
+}
--- /dev/null
+#include <magic/support/VariableRefs.h>
+
+using namespace llvm;
+
+namespace llvm {
+
+//===----------------------------------------------------------------------===//
+// Constructors, destructor, and operators
+//===----------------------------------------------------------------------===//
+
+VariableRefs::VariableRefs() {
+ clear();
+}
+
+//===----------------------------------------------------------------------===//
+// Getters
+//===----------------------------------------------------------------------===//
+
+bool VariableRefs::isUnnecessaryInstruction(Instruction* inst) const {
+ //have already instruction in the entry block, skip
+ if(instructionInEntryBlock) {
+ return true;
+ }
+ //have already instruction in the same block, skip
+ if(instruction && inst->getParent() == instruction->getParent()) {
+ return true;
+ }
+
+ return false;
+}
+
+Instruction* VariableRefs::getInstruction() const {
+ return instruction;
+}
+
+bool VariableRefs::isInstructionInEntryBlock() const {
+ return instructionInEntryBlock;
+}
+
+//===----------------------------------------------------------------------===//
+// Other public methods
+//===----------------------------------------------------------------------===//
+
+void VariableRefs::addInstruction(Instruction* inst) {
+ //no instruction yet, update instruction
+ if(!instruction) {
+ instruction = inst;
+ return;
+ }
+ //have already instruction in another block, give up and resort to a single instruction in the entry block
+ setFunctionEntryInstruction(inst->getParent()->getParent());
+}
+
+void VariableRefs::clear() {
+ instruction = NULL;
+ instructionInEntryBlock = false;
+}
+
+//===----------------------------------------------------------------------===//
+// Private methods
+//===----------------------------------------------------------------------===//
+
+void VariableRefs::setFunctionEntryInstruction(Function* function) {
+ this->instruction = function->front().getFirstNonPHI();
+ this->instructionInEntryBlock = true;
+}
+
+}