From 3e457fe321c6af238c180a2b4a0f010f8b4f8c31 Mon Sep 17 00:00:00 2001 From: David van Moolenbroek Date: Tue, 30 Jun 2015 01:25:43 +0200 Subject: [PATCH] Import magic pass from llvm-apps Change-Id: I19535b913b50f2ff24aeb80ddefc92e305c31fe8 --- minix/llvm/include/common/util/stdlib.h | 148 + minix/llvm/include/common/util/util_def.h | 53 + minix/llvm/include/magic_common.h | 549 ++++ minix/llvm/passes/hello/hello.cpp | 2 +- minix/llvm/passes/hello/pass_hello.h | 224 -- .../llvm/passes/include/common/pass_common.h | 1011 ++++++ .../llvm/passes/include/common/qprof_common.h | 569 ++++ .../include/magic/MagicCTLazyCheckpointPass.h | 32 + .../include/magic/MagicCheckpointPass.h | 29 + .../include/magic/MagicLTLazyCheckpointPass.h | 29 + minix/llvm/passes/include/magic/MagicPass.h | 137 + minix/llvm/passes/include/magic/magic.h | 11 + .../passes/include/magic/support/Backports.h | 24 + .../magic/support/BitFieldAggregation.h | 117 + .../passes/include/magic/support/EDIType.h | 274 ++ .../magic/support/MagicDebugFunction.h | 230 ++ .../include/magic/support/MagicMemFunction.h | 547 ++++ .../magic/support/MagicMmapCtlFunction.h | 130 + .../passes/include/magic/support/MagicUtil.h | 72 + .../passes/include/magic/support/SmartType.h | 244 ++ .../passes/include/magic/support/TypeInfo.h | 636 ++++ .../passes/include/magic/support/TypeUtil.h | 52 + .../include/magic/support/VariableRefs.h | 30 + minix/llvm/passes/{hello => include}/pass.h | 4 +- minix/llvm/passes/magic/MagicPass.cpp | 2877 +++++++++++++++++ minix/llvm/passes/magic/Makefile | 6 + minix/llvm/passes/magic/support/Backports.cpp | 172 + .../magic/support/BitFieldAggregation.cpp | 171 + minix/llvm/passes/magic/support/EDIType.cpp | 520 +++ minix/llvm/passes/magic/support/MagicUtil.cpp | 1137 +++++++ minix/llvm/passes/magic/support/SmartType.cpp | 780 +++++ minix/llvm/passes/magic/support/TypeUtil.cpp | 388 +++ .../passes/magic/support/VariableRefs.cpp | 68 + 33 files changed, 11046 insertions(+), 227 deletions(-) create mode 100644 minix/llvm/include/common/util/stdlib.h create mode 100644 minix/llvm/include/common/util/util_def.h create mode 100644 minix/llvm/include/magic_common.h delete mode 100644 minix/llvm/passes/hello/pass_hello.h create mode 100644 minix/llvm/passes/include/common/pass_common.h create mode 100644 minix/llvm/passes/include/common/qprof_common.h create mode 100644 minix/llvm/passes/include/magic/MagicCTLazyCheckpointPass.h create mode 100644 minix/llvm/passes/include/magic/MagicCheckpointPass.h create mode 100644 minix/llvm/passes/include/magic/MagicLTLazyCheckpointPass.h create mode 100644 minix/llvm/passes/include/magic/MagicPass.h create mode 100644 minix/llvm/passes/include/magic/magic.h create mode 100644 minix/llvm/passes/include/magic/support/Backports.h create mode 100644 minix/llvm/passes/include/magic/support/BitFieldAggregation.h create mode 100644 minix/llvm/passes/include/magic/support/EDIType.h create mode 100644 minix/llvm/passes/include/magic/support/MagicDebugFunction.h create mode 100644 minix/llvm/passes/include/magic/support/MagicMemFunction.h create mode 100644 minix/llvm/passes/include/magic/support/MagicMmapCtlFunction.h create mode 100644 minix/llvm/passes/include/magic/support/MagicUtil.h create mode 100644 minix/llvm/passes/include/magic/support/SmartType.h create mode 100644 minix/llvm/passes/include/magic/support/TypeInfo.h create mode 100644 minix/llvm/passes/include/magic/support/TypeUtil.h create mode 100644 minix/llvm/passes/include/magic/support/VariableRefs.h rename minix/llvm/passes/{hello => include}/pass.h (95%) create mode 100644 minix/llvm/passes/magic/MagicPass.cpp create mode 100644 minix/llvm/passes/magic/Makefile create mode 100644 minix/llvm/passes/magic/support/Backports.cpp create mode 100644 minix/llvm/passes/magic/support/BitFieldAggregation.cpp create mode 100644 minix/llvm/passes/magic/support/EDIType.cpp create mode 100644 minix/llvm/passes/magic/support/MagicUtil.cpp create mode 100644 minix/llvm/passes/magic/support/SmartType.cpp create mode 100644 minix/llvm/passes/magic/support/TypeUtil.cpp create mode 100644 minix/llvm/passes/magic/support/VariableRefs.cpp diff --git a/minix/llvm/include/common/util/stdlib.h b/minix/llvm/include/common/util/stdlib.h new file mode 100644 index 000000000..19a3c6d81 --- /dev/null +++ b/minix/llvm/include/common/util/stdlib.h @@ -0,0 +1,148 @@ +#ifndef _UTIL_STDLIB_H +#define _UTIL_STDLIB_H + +#include "util_def.h" + +#include + +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 */ + diff --git a/minix/llvm/include/common/util/util_def.h b/minix/llvm/include/common/util/util_def.h new file mode 100644 index 000000000..eff7a4bc8 --- /dev/null +++ b/minix/llvm/include/common/util/util_def.h @@ -0,0 +1,53 @@ + +#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 + diff --git a/minix/llvm/include/magic_common.h b/minix/llvm/include/magic_common.h new file mode 100644 index 000000000..7f9d2f1ed --- /dev/null +++ b/minix/llvm/include/magic_common.h @@ -0,0 +1,549 @@ +#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 */ + diff --git a/minix/llvm/passes/hello/hello.cpp b/minix/llvm/passes/hello/hello.cpp index 5d7f9dc6c..8ca5686de 100644 --- a/minix/llvm/passes/hello/hello.cpp +++ b/minix/llvm/passes/hello/hello.cpp @@ -1,4 +1,4 @@ -#include "pass_hello.h" +#include #include using namespace llvm; diff --git a/minix/llvm/passes/hello/pass_hello.h b/minix/llvm/passes/hello/pass_hello.h deleted file mode 100644 index 9d1f15e9a..000000000 --- a/minix/llvm/passes/hello/pass_hello.h +++ /dev/null @@ -1,224 +0,0 @@ -#ifndef _PASS_HELLO_H -#define _PASS_HELLO_H - -#if LLVM_VERSION >= 33 -#define ATTRIBUTE_SET_TY AttributeSet -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#else /* LLVM_VERSION < 33 */ -#define ATTRIBUTE_SET_TY AttrListPtr -#include -#include -#include -#include -#include -#include -#include -#include -#include -#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 -#if LLVM_VERSION == 32 -#include -#include -#endif -#else /* LLVM_VERSION < 32 */ -#define DATA_LAYOUT_TY TargetData -#define ATTRIBUTE_SET_RET_IDX 0 -#define ATTRIBUTE_SET_FN_IDX (~0U) -#include -#include -#include -#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 -#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 &indexes); - static CallInst* createCallInstruction(Value *F, std::vector &args, const Twine &NameStr="", Instruction *InsertBefore=0); - static CallInst* createCallInstruction(Value *F, std::vector &args, const Twine &NameStr="", BasicBlock *InsertAtEnd=0); - static FunctionType* getFunctionType(TYPECONST Type* Result, std::vector &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 &indexes) { -#if LLVM_VERSION >= 30 - ArrayRef 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 &args, const Twine &NameStr, Instruction *InsertBefore) { -#if LLVM_VERSION >= 30 - ArrayRef 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 &args, const Twine &NameStr, BasicBlock *InsertAtEnd) { -#if LLVM_VERSION >= 30 - ArrayRef 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 &argsTy, bool isVarArg) -{ -#if LLVM_VERSION >= 30 - ArrayRef 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 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 stringCache; - std::map::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 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(stringCacheKey, strGV)); - } - - return strGV; -} - -} - -#endif /* _PASS_HELLO_H */ diff --git a/minix/llvm/passes/include/common/pass_common.h b/minix/llvm/passes/include/common/pass_common.h new file mode 100644 index 000000000..6590621af --- /dev/null +++ b/minix/llvm/passes/include/common/pass_common.h @@ -0,0 +1,1011 @@ +#ifndef _PASS_COMMON_H +#define _PASS_COMMON_H + +#if LLVM_VERSION >= 33 +#define ATTRIBUTE_SET_TY AttributeSet +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#else /* LLVM_VERSION < 33 */ +#define ATTRIBUTE_SET_TY AttrListPtr +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 +#if LLVM_VERSION == 32 +#include +#include +#endif +#else /* LLVM_VERSION < 32 */ +#define DATA_LAYOUT_TY TargetData +#define ATTRIBUTE_SET_RET_IDX 0 +#define ATTRIBUTE_SET_FN_IDX (~0U) +#include +#include +#include +#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 +#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 &indexes); + static GetElementPtrInst* createGetElementPtrInstruction(Value *ptr, std::vector &indexes, const Twine &NameStr="", Instruction *InsertBefore=0); + static GetElementPtrInst* createGetElementPtrInstruction(Value *ptr, std::vector &indexes, const Twine &NameStr="", BasicBlock *InsertAtEnd=0); + static CallInst* createCallInstruction(Value *F, std::vector &args, const Twine &NameStr="", Instruction *InsertBefore=0); + static CallInst* createCallInstruction(Value *F, std::vector &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 &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 *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 &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 &vector, const std::string &string, const std::string &separator = ":"); + static void parseStringPairListOpt(std::set > &set, const std::string &string, const std::string &listSeparator = ":", const std::string &pairSeparator = ";"); + static void parseRegexListOpt(std::vector &list, const std::string &string); + static bool matchRegexes(std::string string, std::vector ®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(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(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 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(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 &indexes) { +#if LLVM_VERSION >= 30 + ArrayRef 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 &indexes, const Twine &NameStr, Instruction *InsertBefore) { +#if LLVM_VERSION >= 30 + ArrayRef 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 &indexes, const Twine &NameStr, BasicBlock *InsertAtEnd) { +#if LLVM_VERSION >= 30 + ArrayRef 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 &args, const Twine &NameStr, Instruction *InsertBefore) { +#if LLVM_VERSION >= 30 + ArrayRef 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 &args, const Twine &NameStr, BasicBlock *InsertAtEnd) { +#if LLVM_VERSION >= 30 + ArrayRef 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 typeVector; + for(unsigned i=0;i 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 &argsTy, bool isVarArg) +{ +#if LLVM_VERSION >= 30 + ArrayRef 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 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 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 functionMap; + std::map::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(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(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 *exitBlocks) +{ + if (entryBlock) { + *entryBlock = &F->front(); + } + if (exitBlocks) { + for(Function::iterator I = F->begin(), E = F->end(); I != E; ++I) { + if (isa(I->getTerminator()) || isa(I->getTerminator())) + exitBlocks->push_back(I); + } + } +} + +inline bool PassUtil::isReturnedValue(Function *F, Value *V) +{ + std::vector exitBlocks; + PassUtil::getFunctionEntryExits(F, NULL, &exitBlocks); + for (unsigned i=0;igetTerminator(); + ReturnInst *RI = dyn_cast(I); + if (RI && RI->getReturnValue()) { + Value *RV = RI->getReturnValue(); + if (RV == V) { + return true; + } + if (LoadInst *LI = dyn_cast(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(I) && dyn_cast(I)->isInlineAsm()) + return emptyCS; + Function *F = CS.getCalledFunction(); + if (F && F->isIntrinsic()) + return emptyCS; + return CS; +} + +inline void PassUtil::getFunctionsInDirectBUCallgraph(Function* F, std::set &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(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 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 stringCache; + std::map::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 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(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 &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 > &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(parts.front(), parts.back())); + } + } +} + +inline void PassUtil::parseRegexListOpt(std::vector &list, const std::string &string) +{ + std::vector stringList; + std::vector::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 ®exes) +{ + for (std::vector::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 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 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;igetTypeID(); + hash = (13*hash) ^ nestedIndex; + if(TYPECONST IntegerType *intType = dyn_cast(type)) { + hash = (13*hash) ^ intType->getBitWidth(); + } + else if(TYPECONST PointerType *ptrType = dyn_cast(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;igetContainedType(i), maxLevel); + } + nestedTypes.pop_back(); + level--; + + return hash; +} + +} + +#endif /* _PASS_COMMON_H */ diff --git a/minix/llvm/passes/include/common/qprof_common.h b/minix/llvm/passes/include/common/qprof_common.h new file mode 100644 index 000000000..c61296fc4 --- /dev/null +++ b/minix/llvm/passes/include/common/qprof_common.h @@ -0,0 +1,569 @@ +#ifndef _QPROF_COMMON_H +#define _QPROF_COMMON_H + +#include +#include + +#define QPROF_SEP "," +#define QPROF_SEP2 ":" +#define QPROF_SEP3 "|" + +#define QPROF_DECLARE_LL_SITESTACKS_OPT(P, VAR) \ + static cl::opt \ + 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 \ + 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 \ + 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 \ + 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 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 > getTaskClassLLSitestacks(); + std::map getTaskClassDeepestLLLoops(); + std::map > getTaskClassDeepestLLLibs(); + int getNumTaskClasses(); + int getNumLLTaskClasses(); + int getNumLLBlockExtTaskClasses(); + int getNumLLBlockIntTaskClasses(); + int getNumLLBlockExtLibs(); + int getNumLLBlockIntLibs(); + + std::vector getLLFunctions(); + std::vector getDeepestLLLoops(); + std::vector 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 &list); + + private: + QProfConf() {} + + static std::map > parseTaskClassSiteList(Module &M, std::string &str, bool refreshSites=true); + static std::map parseTaskClassSite(Module &M, std::string &str, bool refreshSites=true); + static std::vector parseIntList(std::string &str); + + std::map > taskClassLLSitestacks; + std::map taskClassDeepestLLLoops; + std::map > 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::getFromSitesString(Module &M, + std::string &sitesString, bool refreshSites) +{ + unsigned i; + int taskClassID; + std::vector 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;ibegin(), + 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 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 > QProfConf::getTaskClassLLSitestacks() +{ + return taskClassLLSitestacks; +} + +inline std::map QProfConf::getTaskClassDeepestLLLoops() +{ + return taskClassDeepestLLLoops; +} + +inline std::map > 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 QProfConf::getLLFunctions() +{ + std::vector sites; + std::map >::iterator it; + it = taskClassLLSitestacks.begin(); + for (; it != taskClassLLSitestacks.end(); it++) { + std::vector *siteVector = &it->second; + for (unsigned i=0;isize();i++) { + QProfSite* site = (*siteVector)[i]; + if (site->isFunction()) { + sites.push_back((*siteVector)[i]); + } + } + } + return sites; +} + +inline std::vector QProfConf::getDeepestLLLoops() +{ + std::vector sites; + std::map::iterator it; + it = taskClassDeepestLLLoops.begin(); + for (; it != taskClassDeepestLLLoops.end(); it++) { + sites.push_back(it->second); + } + return sites; +} + +inline std::vector QProfConf::getDeepestLLLibs() +{ + std::vector sites; + std::map >::iterator it; + it = taskClassDeepestLLLibs.begin(); + for (; it != taskClassDeepestLLLibs.end(); it++) { + std::vector *siteVector = &it->second; + for (unsigned i=0;isize();i++) { + sites.push_back((*siteVector)[i]); + } + } + return sites; +} + +inline bool QProfConf::lookupTaskClassLibFlags(int taskClassID, int *libFlags) +{ + bool found = false; + std::vector deepestLLLibs = getDeepestLLLibs(); + + *libFlags = 0; + for (unsigned i=0;itaskClassID == 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 deepestLLLoops = getDeepestLLLoops(); + std::vector > loopPairs; + + for (unsigned i=0;iequals(deepestLLLoops[j])) { + loopPairs.push_back(std::pair(site, deepestLLLoops[j])); + } + } + } + for (unsigned i=0;itaskClassID; + int otherTaskClassID = loopPairs[i].second->taskClassID; + mergeTaskClassPair(taskClassID, otherTaskClassID); + } +} + +inline void QProfConf::print(raw_ostream &O) +{ + std::vector 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 &list) +{ + for (std::vector::iterator it = list.begin(); it != list.end(); it++) { + QProfSite* site = *it; + if (it != list.begin()) { + O << ", "; + } + O << "{ "; + O << site->toString(); + O << " }"; + } +} + +inline std::map > QProfConf::parseTaskClassSiteList(Module &M, + std::string &str, bool refreshSites) +{ + std::map > siteListMap; + StringRef ref(str); + SmallVector< StringRef, 3 > tokenVector; + if (!str.compare("")) { + return siteListMap; + } + ref.split(tokenVector, QPROF_SEP); + for (unsigned i=0;i sites = QProfSite::getFromSitesString(M, + token, refreshSites); + if (sites.size() > 0) { + int taskClassID = sites[0]->taskClassID; + siteListMap.insert(std::pair >(taskClassID, + sites)); + } + } + return siteListMap; +} + +inline std::map QProfConf::parseTaskClassSite(Module &M, + std::string &str, bool refreshSites) +{ + std::map >::iterator it; + std::map > siteListMap = + parseTaskClassSiteList(M, str, refreshSites); + std::map siteMap; + for (it=siteListMap.begin();it!=siteListMap.end();it++) { + std::vector list = it->second; + assert(list.size() == 1); + siteMap.insert(std::pair(it->first, list[0])); + } + + return siteMap; +} + +inline std::vector QProfConf::parseIntList(std::string &str) +{ + std::vector intValues; + StringRef ref(str); + SmallVector< StringRef, 3 > tokenVector; + if (!str.compare("")) { + return intValues; + } + ref.split(tokenVector, QPROF_SEP); + for (unsigned i=0;i +#include +#include + +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 diff --git a/minix/llvm/passes/include/magic/MagicCheckpointPass.h b/minix/llvm/passes/include/magic/MagicCheckpointPass.h new file mode 100644 index 000000000..0858de86f --- /dev/null +++ b/minix/llvm/passes/include/magic/MagicCheckpointPass.h @@ -0,0 +1,29 @@ +#ifndef MAGIC_CHECKPOINT_PASS_H +#define MAGIC_CHECKPOINT_PASS_H + +#include +#include + +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 diff --git a/minix/llvm/passes/include/magic/MagicLTLazyCheckpointPass.h b/minix/llvm/passes/include/magic/MagicLTLazyCheckpointPass.h new file mode 100644 index 000000000..88681fae4 --- /dev/null +++ b/minix/llvm/passes/include/magic/MagicLTLazyCheckpointPass.h @@ -0,0 +1,29 @@ +#ifndef MAGIC_LTLAZY_CHECKPOINT_PASS_H +#define MAGIC_LTLAZY_CHECKPOINT_PASS_H + +#include +#include + +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 diff --git a/minix/llvm/passes/include/magic/MagicPass.h b/minix/llvm/passes/include/magic/MagicPass.h new file mode 100644 index 000000000..cb5ffa91e --- /dev/null +++ b/minix/llvm/passes/include/magic/MagicPass.h @@ -0,0 +1,137 @@ +#ifndef MAGIC_PASS_H + +#define MAGIC_PASS_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if MAGIC_USE_QPROF_INSTRUMENTATION +#include +#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 getGlobalVariables() const; + std::vector getGlobalVariableSizes() const; + std::vector getShadowGlobalVariables() const; + std::vector getFunctions() const; + GlobalVariable* getMagicArray() const; + GlobalVariable* getMagicTypeArray() const; + GlobalVariable* getMagicFunctionArray() const; + GlobalVariable* getMagicDsindexArray() const; + + virtual bool runOnModule(Module &M); + + private: + std::vector globalVariables; + std::set globalVariablesWithAddressTaken; + std::vector globalVariableSizes; + std::vector shadowGlobalVariables; + std::vector functions; + std::vector globalTypeInfos; + std::map globalParentMap; + std::map::iterator parentMapIt; + std::map stringOwnerMap; + std::map::iterator stringOwnerMapIt; + std::map stringOwnerInvertedMap; + std::map::iterator stringOwnerInvertedMapIt; + + GlobalVariable* magicArray; + GlobalVariable* magicTypeArray; + GlobalVariable* magicFunctionArray; + GlobalVariable* magicDsindexArray; + + std::vector libPathRegexes; + std::vector voidTypeAliases; + std::set voidTypeAliasesSet; + std::vector mmFuncPrefixes; + std::set > mmFuncPairs; + std::vector mmPoolFunctions; + std::vector mmapCtlFunctions; + std::set::iterator stringSetIt; + std::set brkFunctions; + std::set sbrkFunctions; + std::vector magicDataSectionRegexes; + std::vector magicFunctionSectionRegexes; + std::vector extLibSectionRegexes; + +#if MAGIC_USE_QPROF_INSTRUMENTATION + QProfConf *qprofConf; +#endif + + void qprofInstrumentationInit(Module &M); + void qprofInstrumentationApply(Module &M); + bool checkPointerVariableIndexes(TYPECONST Type* type, std::vector &ptrVarIndexes, unsigned offset=0); + void findPointerVariables(Function* function, Value *value, std::vector &ptrVars, std::vector > &ptrVarIndexes, Value *parent = NULL, bool isUser=false); + TypeInfo* typeInfoFromPointerVariables(Module &M, TypeInfo *voidPtrTypeInfo, std::vector &ptrVars, std::vector > &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 &typeInfos); + TypeInfo* fillExternalTypeInfos(TYPECONST Type* sourceType, GlobalValue *parent, std::vector &typeInfos); + void printInterestingTypes(TYPECONST TypeInfo *aTypeInfo); + unsigned getMaxRecursiveSequenceLength(TYPECONST TypeInfo *aTypeInfo); + FunctionType* getFunctionType(TYPECONST FunctionType *baseType, std::vector selectedArgs); + bool isCompatibleMagicMemFuncType(TYPECONST FunctionType *type, TYPECONST FunctionType* magicType); + void indexCasts(Module &M, User *U, std::vector &intCastTypes, std::vector &intCastValues, std::map > &bitcastMap); + + void fillStackInstrumentedFunctions(std::vector &stackIntrumentedFuncs, Function *deepestLLFunction); + void indexLocalTypeInfos(Module &M, Function *F, std::map > &localMap); + void addMagicStackDsentryFuncCalls(Module &M, Function *insertCallsInFunc, Function *localsFromFunc, Function *dsentryCreateFunc, Function *dsentryDestroyFunc, TYPECONST StructType *dsentryStructType, std::map > localTypeInfoMap, std::map &magicArrayTypePtrMap, TypeInfo *voidPtrTypeInfo, std::vector &typeInfoList, std::vector > &namesList, std::vector &flagsList); + bool isExtLibrary(GlobalValue *GV, DIDescriptor *DID); + bool isMagicGV(Module &M, GlobalVariable *GV); + bool isMagicFunction(Module &M, Function *F); +}; + +inline std::vector MagicPass::getGlobalVariables() const { + return globalVariables; +} + +inline std::vector MagicPass::getGlobalVariableSizes() const { + return globalVariableSizes; +} + +inline std::vector MagicPass::getShadowGlobalVariables() const { + return shadowGlobalVariables; +} + +inline std::vector 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 diff --git a/minix/llvm/passes/include/magic/magic.h b/minix/llvm/passes/include/magic/magic.h new file mode 100644 index 000000000..8b820a717 --- /dev/null +++ b/minix/llvm/passes/include/magic/magic.h @@ -0,0 +1,11 @@ +#ifndef _MAGIC_PASS_H +#define _MAGIC_PASS_H + +#include +#include + +#define MAGIC_FORCE_ALIGN 0 +#define MAGIC_FORCE_INLINING 0 + +#endif /* _MAGIC_PASS_H */ + diff --git a/minix/llvm/passes/include/magic/support/Backports.h b/minix/llvm/passes/include/magic/support/Backports.h new file mode 100644 index 000000000..96b9e0b84 --- /dev/null +++ b/minix/llvm/passes/include/magic/support/Backports.h @@ -0,0 +1,24 @@ +#ifndef BACKPORTS_H +#define BACKPORTS_H + +#include + +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 diff --git a/minix/llvm/passes/include/magic/support/BitFieldAggregation.h b/minix/llvm/passes/include/magic/support/BitFieldAggregation.h new file mode 100644 index 000000000..ac53beba4 --- /dev/null +++ b/minix/llvm/passes/include/magic/support/BitFieldAggregation.h @@ -0,0 +1,117 @@ +#ifndef BIT_FIELD_AGGREGATION_H +#define BIT_FIELD_AGGREGATION_H + +#include +#include + +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 EDITypes, unsigned typeIndex, unsigned EDITypeIndex, std::vector members, unsigned counter); + BitFieldAggregation(); + void init(TYPECONST Type* type, std::vector EDITypes, unsigned typeIndex, unsigned EDITypeIndex, std::vector members, unsigned counter); + + const std::string getDescription() const; + + unsigned getTypeIndex() const; + unsigned getEDITypeIndex() const; + std::string getName() const; + std::vector getMembers() const; + + unsigned getSize() const; + TYPECONST Type *getType() const; + std::vector getEDITypes() const; + unsigned getRepresentativeEDITypeIndex() const; + + void print(raw_ostream &OS) const; + + static bool getBitFieldAggregations(TYPECONST Type *type, const EDIType *aEDIType, std::vector &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 EDITypes; + unsigned typeIndex; + unsigned EDITypeIndex; + std::string name; + std::vector 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 BitFieldAggregation::getMembers() const { + return members; +} + +inline unsigned BitFieldAggregation::getSize() const { + return size; +} + +inline TYPECONST Type *BitFieldAggregation::getType() const { + return type; +} + +inline std::vector 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;igetMember(memberIdx); + unsigned EDITypeBits = subDIType.getSizeInBits(); + const DIType aDIType = PassUtil::getDITypeDerivedFrom(subDIType); + unsigned EDITypeOriginalBits = aDIType.getSizeInBits(); + return (EDITypeBits>0 && EDITypeOriginalBits>0 && EDITypeBits != EDITypeOriginalBits); +} + +} + +#endif diff --git a/minix/llvm/passes/include/magic/support/EDIType.h b/minix/llvm/passes/include/magic/support/EDIType.h new file mode 100644 index 000000000..a47fb69c4 --- /dev/null +++ b/minix/llvm/passes/include/magic/support/EDIType.h @@ -0,0 +1,274 @@ +#ifndef EDITYPE_H +#define EDITYPE_H + +#include + +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 getNames() const; + StringRef getNamesString() const; + std::vector 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 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 EDIType::getNames() const { + return myNames; +} + +inline StringRef EDIType::getNamesString() const { + std::string string; + raw_string_ostream ostream(string); + for(unsigned i=0;i0) ostream << "|"; + ostream << myNames[i]; + } + ostream.flush(); + return string; +} + +inline std::vector EDIType::getEnumValues() const { + assert(isEnumTy()); + std::vector enumValues; + DIArray aDIArray = getTypeArray(); + unsigned numValues = aDIArray.getNumElements(); + for(unsigned i=0;i + +#define NUM_DEBUG_ARGS 1 + +using namespace llvm; + +namespace llvm { + +class MagicDebugFunction { +public: + MagicDebugFunction(Function *function); + + Function* getFunction() const; + void addHooks(std::pair hooks, unsigned flags, std::vector argsMapping, std::vector 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 hooks, unsigned flags, std::vector argsMapping, + std::vector trailingArgs); + Function* getDebugFunction(Module &M); + +private: + Function *function; + + std::pair hooks; + unsigned flags; + std::vector argsMapping; + std::vector 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 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 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 aHooks, unsigned aFlags, std::vector aArgsMapping, + std::vector 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 Users(function->use_begin(), function->use_end()); + std::vector EqPointers; + while (!Users.empty()) { + User *U = Users.back(); + Users.pop_back(); + + if (Instruction * I = dyn_cast(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 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(U)) { + Users.insert(Users.end(), GV->use_begin(), GV->use_end()); + EqPointers.push_back(GV); + } else if (ConstantExpr * CE = dyn_cast(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 hooks, unsigned flags, + std::vector argsMapping, std::vector trailingArgs) { + std::vector emptyArgs; + std::vector emptyMapping; + std::vector debugEmptyMapping; + std::vector 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_ */ diff --git a/minix/llvm/passes/include/magic/support/MagicMemFunction.h b/minix/llvm/passes/include/magic/support/MagicMemFunction.h new file mode 100644 index 000000000..7e9cedbbb --- /dev/null +++ b/minix/llvm/passes/include/magic/support/MagicMemFunction.h @@ -0,0 +1,547 @@ +#ifndef MAGIC_MEM_FUNCTION_H +#define MAGIC_MEM_FUNCTION_H + +#include +#include + +#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 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 &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 &brkFunctions, TypeInfo *voidPtrTypeInfo); + static Function* getCustomWrapper(Function* function, Function* stdFunction, Function* stdWrapper, std::vector 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 instructionDeps; + + void buildWrapper(std::map &magicArrayTypePtrMap, TypeInfo *voidPtrTypeInfo); + + static Function *lastAllocWrapper; + static std::map allocWrapperCache; + static std::set 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::getInstructionDeps() const { + return instructionDeps; +} + +inline void MagicMemFunction::setInstruction(Instruction* I) { + this->instruction = I; + assert(isa(instruction) || isa(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 &magicArrayTypePtrMap, TypeInfo *voidPtrTypeInfo) { + Instruction *I = getInstruction(); + assert(I); + CallSite CS = MagicUtil::getCallSiteFromInstruction(I); + std::vector 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::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 &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 &magicArrayTypePtrMap, TypeInfo *voidPtrTypeInfo) { + assert(!isDeallocFunction()); + assert(lastAllocWrapper); + std::vector ArgTypes; + VALUE_TO_VALUE_MAP_TY VMap; + + std::map::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 Returns; // Ignore returns cloned... + CloneFunctionInto(wrapper, function, VMap, false, Returns, "", NULL); + + allocWrapperCache.insert(std::pair(function->getName(), wrapper)); + + // Create a mapping between the function instruction pointers and the wrapper instruction pointers + std::vector 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 argMapping, + bool isDealloc) { + Function* wrapper; + std::vector 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 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 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(*it)) { + if (!isa(C)) { + C->replaceUsesOfWith(ParamValue, ParamCastInst); + continue; + } + } + Instruction *I = dyn_cast(*it); + if (I && (I != ParamCastInst)) { + // replace all uses, except for the calls to the wrapped function + CallInst *CI = dyn_cast(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(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 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 + diff --git a/minix/llvm/passes/include/magic/support/MagicMmapCtlFunction.h b/minix/llvm/passes/include/magic/support/MagicMmapCtlFunction.h new file mode 100644 index 000000000..e21184d08 --- /dev/null +++ b/minix/llvm/passes/include/magic/support/MagicMmapCtlFunction.h @@ -0,0 +1,130 @@ +#ifndef MAGIC_MMAP_CTL_FUNCTION_H +#define MAGIC_MMAP_CTL_FUNCTION_H + +#include +#include + +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(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 Users(function->use_begin(), function->use_end()); + while (!Users.empty()) { + User *U = Users.back(); + Users.pop_back(); + + if (Instruction *I = dyn_cast(U)) { + Function *parent = I->getParent()->getParent(); + if(parent->getName().startswith("magic") || parent->getName().startswith("_magic")) { + continue; + } + CallSite CS = MagicUtil::getCallSiteFromInstruction(I); + + std::vector args; + CallInst* magicGetPageSizeCall = MagicUtil::createCallInstruction(magicGetPageSizeFunc, args, "", I); + magicGetPageSizeCall->setCallingConv(CallingConv::C); + magicGetPageSizeCall->setTailCall(false); + TYPECONST IntegerType *type = dyn_cast(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 + diff --git a/minix/llvm/passes/include/magic/support/MagicUtil.h b/minix/llvm/passes/include/magic/support/MagicUtil.h new file mode 100644 index 000000000..00927c32e --- /dev/null +++ b/minix/llvm/passes/include/magic/support/MagicUtil.h @@ -0,0 +1,72 @@ +#ifndef MAGIC_UTIL_H +#define MAGIC_UTIL_H + +#include +#include +#include + +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 &indexes); + static GetElementPtrInst* createGetElementPtrInstruction(Value *ptr, std::vector &indexes, const Twine &NameStr="", Instruction *InsertBefore=0); + static GetElementPtrInst* createGetElementPtrInstruction(Value *ptr, std::vector &indexes, const Twine &NameStr="", BasicBlock *InsertAtEnd=0); + static CallInst* createCallInstruction(Value *F, std::vector &args, const Twine &NameStr="", Instruction *InsertBefore=0); + static CallInst* createCallInstruction(Value *F, std::vector &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 *arr, bool isConstant=true); + static GlobalVariable *getStringArrayRef(Module &M, unsigned arrSize, std::vector *arr, bool isConstant=true); + static GlobalVariable *getGenericArrayRef(Module &M, std::vector &arrayElems, bool isConstant=true); + static GlobalVariable *getMagicTypePtrArrayRef(Module &M, Instruction *InsertBefore, std::vector &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 getGlobalVariablesShadowFunctions(Module &M, std::vector globalVariables, std::vector shadowGlobalVariables, std::vector 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 &instructionsToRemove); + static void cleanupShadowTag(Module &M, std::vector &instructionsToRemove); + static bool hasAddressTaken(const GlobalValue *GV, bool includeMembers=true); + static bool lookupValueSet(const GlobalVariable *GV, std::vector &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 argsMapping, std::vector trailingArgs); + static void inlinePostHookForwardingCall(Function* function, Function* postHookFunction, std::vector mapping, std::vector trailingArgs); + static int getPointerIndirectionLevel(const Type* type); + static Value* getFunctionParam(Function* function, unsigned index); + static bool isLocalConstant(Module &M, GlobalVariable *GV); +}; + +} + +#endif diff --git a/minix/llvm/passes/include/magic/support/SmartType.h b/minix/llvm/passes/include/magic/support/SmartType.h new file mode 100644 index 000000000..be5c6aecb --- /dev/null +++ b/minix/llvm/passes/include/magic/support/SmartType.h @@ -0,0 +1,244 @@ +#ifndef SMART_TYPE_H +#define SMART_TYPE_H + +#include +#include +#include +#include +#include + +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* 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 explicitContainedEDITypes; + std::vector bfas; + bool useExceptions; + bool rawTypeRepresentation; + unsigned unionMemberIdx; + static std::vector 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 &inputBfas); + static bool isRawTypeConsistent(TYPECONST Type *type, const EDIType *aEDIType); + static bool isTypeConsistent2(TYPECONST Type *type, const EDIType *aEDIType); + static bool isTypeConsistent2(std::vector &nestedTypes, std::vector &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 diff --git a/minix/llvm/passes/include/magic/support/TypeInfo.h b/minix/llvm/passes/include/magic/support/TypeInfo.h new file mode 100644 index 000000000..c60c945a0 --- /dev/null +++ b/minix/llvm/passes/include/magic/support/TypeInfo.h @@ -0,0 +1,636 @@ +#ifndef TYPE_INFO_H +#define TYPE_INFO_H + +#include +#include +#include +#include + +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 getParents() const; + std::string getTypeString() const; + std::string getDescription() const; + std::string getVerboseDescription() const; + std::string getName() const; + std::vector getNames() const; + std::string getNamesString() const; + std::vector getMemberNames() const; + std::vector getValueSet() const; + std::vector 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 &valueSet); + void setContainedTypes(const std::vector &containedTypes); + void addParent(GlobalValue* parent); + void addParents(const std::vector &parents); + bool removeParent(GlobalValue* parent); + bool removeAllParents(); + void setPersistent(); + bool splitByParentValueSet(std::vector &splitTypeInfos, std::set &globalVariablesWithAddressTaken); + + static unsigned getMaxNameLength(); + static unsigned getMaxTypeStringLength(); + static void setIntCastTypes(std::map > &intCastTypes); + static void setBitCastTypes(std::map > &bitCastTypes); + + private: + const SmartType *aSmartType; + TYPECONST Type *aType; + bool forceTypeDescription; + mutable std::string typeDescription; + std::string name; + std::vector names; + std::vector memberNames; + std::vector valueSet; + std::vector containedTypes; + std::vector parents; + unsigned bitWidth; + unsigned typeID; + unsigned numElements; + unsigned flags; + static unsigned maxNameLength; + static unsigned maxTypeStringLength; + static std::map > intCastTypes; + static std::map > bitCastTypes; + static std::map > 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 nameRefs = aSmartType->getEDIType()->getNames(); + for(i=0;i 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(;igetMember(i); + memberNames.push_back(formatMemberName(subDIType.getName(), numAnonMembers)); + } + } + } + else { + memberNames.push_back("raw"); + } + } + if(aSmartType->getEDIType()->isEnumTy()) { + std::vector enumValues = aSmartType->getEDIType()->getEnumValues(); + valueSet.push_back(enumValues.size()); //push length as the first value + for(unsigned i=0;igetType()); + 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 >::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 &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::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 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 TypeInfo::getNames() const { + return names; +} + +inline std::string TypeInfo::getNamesString() const { + std::string string; + raw_string_ostream ostream(string); + for(unsigned i=0;i0) ostream << "|"; + ostream << names[i]; + } + ostream.flush(); + return string; +} + +inline std::vector TypeInfo::getMemberNames() const { + for(unsigned i=0;i maxNameLength) { + maxNameLength = memberNames[i].size(); + } + } + return memberNames; +} + +inline std::vector TypeInfo::getValueSet() const { + return valueSet; +} + +inline std::vector TypeInfo::getCastTypes() const { + std::vector castTypes; + std::map >::iterator bitCastTypesIt; + std::map >::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 bitCastSet = bitCastTypesIt->second; +#if MAGIC_INDEX_TRANSITIVE_BIT_CASTS + std::vector bitCasts; + for(std::set::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 set = bitCastTypesIt->second; + for(std::set::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::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 *typeInfoSet = &(typeMapIt->second); + for(std::set::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 &valueSet) { + this->valueSet = valueSet; +} + +inline void TypeInfo::setContainedTypes(const std::vector &containedTypes) { + this->containedTypes = containedTypes; +} + +inline void TypeInfo::addParent(GlobalValue* parent) { + assert((typeID == MAGIC_TYPE_FUNCTION && dyn_cast(parent)) + || (typeID != MAGIC_TYPE_FUNCTION && dyn_cast(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 &parents) { + for(unsigned i=0;i originalParents = this->parents; + this->parents.clear(); + for(unsigned i=0;iparents.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 >::iterator typeMapIt; + typeMapIt = typeMap.find(aType); + if(typeMapIt == typeMap.end()) { + std::set set; + set.insert(this); + typeMap.insert(std::pair >(aType, set)); + } + else { + std::set *set; + set = &(typeMapIt->second); + set->insert(this); + } +} + +inline bool TypeInfo::splitByParentValueSet(std::vector &splitTypeInfos, std::set &globalVariablesWithAddressTaken) { + std::map, std::vector > valueSetMap; + std::map, std::vector >::iterator valueSetMapIt; + std::vector valueSet; + splitTypeInfos.push_back(this); + if(!isa(aType)) { + return false; + } + assert(valueSet.size() == 0); + for(unsigned i=0;i(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 vector; + valueSetMap.insert(std::pair, std::vector >(valueSet, vector)); + valueSetMapIt = valueSetMap.find(valueSet); + assert(valueSetMapIt != valueSetMap.end()); + } + std::vector *globalsVector = &valueSetMapIt->second; + globalsVector->push_back(GV); + } + } + if(valueSetMap.size() == 0) { + return false; + } + for(valueSetMapIt = valueSetMap.begin(); valueSetMapIt!=valueSetMap.end(); valueSetMapIt++) { + const std::vector &values = valueSetMapIt->first; + const std::vector &globalVariables = valueSetMapIt->second; + TypeInfo *aTypeInfo = new TypeInfo(*this); + aTypeInfo->setValueSet(values); + aTypeInfo->removeAllParents(); + for(unsigned i=0;iremoveParent(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 > &intCastTypes) { + TypeInfo::intCastTypes = intCastTypes; +} + +inline void TypeInfo::setBitCastTypes(std::map > &bitCastTypes) { + TypeInfo::bitCastTypes = bitCastTypes; +} + +} + +#endif diff --git a/minix/llvm/passes/include/magic/support/TypeUtil.h b/minix/llvm/passes/include/magic/support/TypeUtil.h new file mode 100644 index 000000000..5c77dc49a --- /dev/null +++ b/minix/llvm/passes/include/magic/support/TypeUtil.h @@ -0,0 +1,52 @@ +#ifndef TYPE_UTIL_H +#define TYPE_UTIL_H + +#include +#include + +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 *names, std::vector *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 diff --git a/minix/llvm/passes/include/magic/support/VariableRefs.h b/minix/llvm/passes/include/magic/support/VariableRefs.h new file mode 100644 index 000000000..0574d5a5a --- /dev/null +++ b/minix/llvm/passes/include/magic/support/VariableRefs.h @@ -0,0 +1,30 @@ +#ifndef VARIABLE_REFS_H +#define VARIABLE_REFS_H + +#include + +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 diff --git a/minix/llvm/passes/hello/pass.h b/minix/llvm/passes/include/pass.h similarity index 95% rename from minix/llvm/passes/hello/pass.h rename to minix/llvm/passes/include/pass.h index 59e542908..25db98f88 100644 --- a/minix/llvm/passes/hello/pass.h +++ b/minix/llvm/passes/include/pass.h @@ -2,8 +2,8 @@ #ifndef _PASS_H #define _PASS_H -#import -#import +#include +#include #include #include diff --git a/minix/llvm/passes/magic/MagicPass.cpp b/minix/llvm/passes/magic/MagicPass.cpp new file mode 100644 index 000000000..9badbddbc --- /dev/null +++ b/minix/llvm/passes/magic/MagicPass.cpp @@ -0,0 +1,2877 @@ +#include + +using namespace llvm; + +PASS_COMMON_INIT_ONCE(); + +// command-line arguments +static cl::opt +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 +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 +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 +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 +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 +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 +EnablePoolMemReuse("magic-mpool-enable-reuse", + cl::desc("Enable memory reuse across pools."), + cl::init(false), cl::NotHidden); + +static cl::opt +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 +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 +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 +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 +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 +EnableShadowing("magic-enable-shadowing", + cl::desc("Enable state shadowing"), + cl::init(false), cl::NotHidden); + +static cl::opt +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 > TypeInfo::intCastTypes; +std::map > TypeInfo::bitCastTypes; +std::map > TypeInfo::typeMap; + +bool SmartType::forceRawUnions = MAGIC_FORCE_RAW_UNIONS; +bool SmartType::forceRawBitfields = MAGIC_FORCE_RAW_BITFIELDS; + +Function *MagicMemFunction::lastAllocWrapper = NULL; +std::map MagicMemFunction::allocWrapperCache; +std::set 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 intCastTypes; + std::vector intCastValues; + std::map > 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 > intCastMap; + std::map >::iterator intCastMapIt; + for(i=0;i valueSet; + intCastMap.insert(std::pair >(type, valueSet)); + intCastMapIt = intCastMap.find(type); + } + assert(intCastMapIt != intCastMap.end()); + std::set *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 llvmCallPrefixes; + for (std::vector::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 magicMemFunctions; + std::set originalMagicMemFunctions; + for(i=0;magicMemFuncNames[i].compare("");i++) { + int allocFlags = magicMemFuncAllocFlags[i]; + for(unsigned j=0;jgetFunctionType(); + 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 >::iterator it = mmFuncPairs.begin(); it != mmFuncPairs.end(); ++it) { + std::vector 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 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 magicMempoolFuncNames[] = { + std::pair(MAGIC_MEMPOOL_CREATE_FUNCS), + std::pair(MAGIC_MEMPOOL_DESTROY_FUNCS), + std::pair(MAGIC_MEMPOOL_MGMT_FUNCS), + std::pair(MAGIC_MEMPOOL_RESET_FUNCS) + }; +#undef __X + int magicMempoolFuncFlags[] = { MAGIC_MEMPOOL_FUNC_FLAGS }; + unsigned numMagicMempoolFuncPairs = sizeof(magicMempoolFuncNames) / sizeof(magicMempoolFuncNames[0]); + std::vector > magicMempoolFuncs(numMagicMempoolFuncPairs, std::pair()); + 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 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::iterator mmPoolFuncsIt = mmPoolFunctions.begin(); + std::vector mempoolMagicMemFunctions; + + // memory pool block allocation functions + std::vector mempoolBlockAllocFuncs; + PassUtil::parseStringListOpt(mempoolBlockAllocFuncs, *(mmPoolFuncsIt++), ";"); + + for (std::vector::iterator funcIt = mempoolBlockAllocFuncs.begin(); funcIt != mempoolBlockAllocFuncs.end(); ++funcIt) { + std::vector 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 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 >::iterator magicMempoolFuncIt; + std::vector >::iterator magicMempoolFuncFlagsIt; + for (unsigned magicMempoolFuncIndex = 1; mmPoolFuncsIt != mmPoolFunctions.end(); ++mmPoolFuncsIt, ++magicMempoolFuncIndex) { + std::vector mempoolMgmtFuncs; + PassUtil::parseStringListOpt(mempoolMgmtFuncs, *mmPoolFuncsIt, ";"); + for (std::vector::iterator funcIt = mempoolMgmtFuncs.begin(); funcIt != mempoolMgmtFuncs.end(); ++funcIt) { + std::vector 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 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 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::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 magicMmapCtlFunctions; + for (std::vector::iterator it = mmapCtlFunctions.begin(); it != mmapCtlFunctions.end(); ++it) { + std::vector 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(GV->getInitializer()); +#else + ConstantArray *initializer = dyn_cast(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(stringOwner); + AllocaInst *AIOwner = dyn_cast(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(ownerName, GV)); + stringOwnerInvertedMap.insert(std::pair(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 functionTypes; + std::vector functionTypeParents; + std::vector externalFunctionTypes; + std::vector 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 smartTypes; + std::vector smartTypeParents; + std::vector externalTypes; + std::vector externalTypeParents; + for(i=0;igetType()->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;igetTypeID() == 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 magicVoidTypeInfoArr; + magicVoidTypeInfoArr.push_back(magicVoidTypeInfo); + magicVoidArrTypeInfo->setContainedTypes(magicVoidTypeInfoArr); + magicPassLog(">>>> Number of types found: " << globalTypeInfos.size()); + for(i=0;i>>> Number of types + function types found: " << globalTypeInfos.size()); + + //add external function types + for(i=0;i>>> Number of types + function types + external function types found: " << globalTypeInfos.size()); + + //add external variable types + for(i=0;igetName()); + 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 splitTypeInfos; + for(i=0;isplitByParentValueSet(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 valueSet = splitTypeInfos[j]->getValueSet(); + for(unsigned k=1;k parents = splitTypeInfos[j]->getParents(); + for(unsigned k=0;kgetName(); + } + errs() << " ]\n"; + } +#endif + } + } + + //index type parents + globalTypeInfos.clear(); + for(i=0;i parents = aTypeInfo->getParents(); + for(unsigned j=0;j(parents[j], aTypeInfo)); + } + globalTypeInfos.push_back(aTypeInfo); + } + + std::vector< TypeInfo* > magicDsindexTypeInfoList; + std::vector< std::pair > magicDsindexNamesList; + std::vector 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 magicMemFunctionCalls; + std::map< std::pair, int> namesMap; + int allocFlags; + std::set extendedMagicMemFunctions; + for (std::set::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 Users(magicMemFunction.getFunction()->use_begin(), magicMemFunction.getFunction()->use_end()); + std::vector EqPointers; + while (!Users.empty()) { + int annotation; + User *U = Users.back(); + Users.pop_back(); + + if (Instruction *I = dyn_cast(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(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, 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(allocParentName, allocName)); + if(namesMapIt != namesMap.end()) { + allocCounter = namesMapIt->second + 1; + ret = namesMap.erase(std::pair(allocParentName, allocName)); + assert(ret == 1); + namesMap.insert(std::pair, int>(std::pair(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, int>(std::pair(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(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;kaddInstructionDep(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(U)) { + Users.insert(Users.end(), GV->use_begin(), GV->use_end()); + EqPointers.push_back(GV); + } else if (ConstantExpr *CE = dyn_cast(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 > > localTypeInfoMaps; + std::map > localTypeInfoMap; + std::vector stackIntrumentedFuncs; + fillStackInstrumentedFunctions(stackIntrumentedFuncs, deepestLLFunction); + std::string stackIntrumentedFuncsStr; + for(i=0;igetName().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 rawTypeInfos; + for(i=0;ihasRawTypeRepresentation()) { + continue; + } + assert(aTypeInfo->getNumContainedTypes() == 0); + TypeInfo* aRawTypeInfo = new TypeInfo(*magicVoidArrTypeInfo); + aRawTypeInfo->setPersistent(); + aRawTypeInfo->removeAllParents(); + rawTypeInfos.push_back(aRawTypeInfo); + std::vector aTypeInfoContainedTypes; + aTypeInfoContainedTypes.push_back(aRawTypeInfo); + aTypeInfo->setContainedTypes(aTypeInfoContainedTypes); + assert(aTypeInfo->getContainedType(0)->getContainedType(0) == magicVoidTypeInfo); + } + for(i=0;igetNumContainedTypes() == 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;igetParents().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 parents = globalTypeInfos[i]->getParents(); + if(parents.size() > 0) { + std::string parentString, typeString; + for(unsigned j=0;j0 ? ", " : "") + 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;igetName(); + if(name.compare("")) { + magicPassErr(" Named type found: " << name << " (names string: " << globalTypeInfos[i]->getNamesString() << ", id: " << i << ")"); + } + } +#endif + +#if DEBUG_DUPLICATED_TYPE_INFOS + std::map duplicatedTypeInfoMap; + std::map::iterator duplicatedTypeInfoMapIt; + for(i=0;igetType()->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(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 magicArrayTypePtrMap; + std::map::iterator magicArrayTypePtrMapIt; + std::map magicArrayTypeIndexMap; + std::map::iterator magicArrayTypeIndexMapIt; + std::vector arrayIndexes; + for(;igetType(); + 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(aTypeInfo, magicTypeArrayPtr)); + magicArrayTypeIndexMap.insert(std::pair(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 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 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;jgetNumChildTypes();j++) { + std::vector 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 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 containedTypePtrs; + for(unsigned j=0;jgetNumContainedTypes();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 castTypePtrs; + std::vector 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;jgetContainedType(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(;igetName().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(;isecond; + 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;ireplaceInstruction(magicArrayTypePtrMap, magicVoidPtrTypeInfo); + } + + //fix debug function calls and their arguments + for (i=0;ifixCalls(M, baseBuildDir); + } + + //fix mmap ctl function calls and their arguments + for (i=0;ifixCalls(M, magicGetPageSizeFunc); + } +#endif + +#if MAGIC_INSTRUMENT_STACK + //instrument the stack for the relevant set of functions and add dsindex entries + for(i=0;isecond; + 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 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 currPtrVarIndexes; +static std::set< std::pair > > visitedValues; + +bool MagicPass::checkPointerVariableIndexes(TYPECONST Type *type, std::vector &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 &ptrVars, std::vector > &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 > 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 savedPtrVarIndexes; + visitedValues.insert(visitedPair); + ConstantExpr *constantExpr = dyn_cast(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(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(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(value)) { + if(DEBUG_ALLOC_LEVEL >= 2) { + magicPassErr("Found return variable!"); + } + assert(isUser); + RETURN_IF(true); + } + else if(StoreInst *SI = dyn_cast(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(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(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(*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(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(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(value) || dyn_cast(value)) { + RETURN_IF(isUser); + DEBUG_VALUE(" >>>> findPointerVariables: found call instruction: ", value); + } + else if(CmpInst *CI = dyn_cast(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(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(value)) { + DEBUG_VALUE(" >>>> findPointerVariables: Digging PHI instruction: ", value); + for(unsigned i=0;igetNumIncomingValues();i++) { + findPointerVariables(function, PN->getIncomingValue(i), ptrVars, ptrVarIndexes, value); + } + } + else if(Argument *ARG = dyn_cast(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(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 &ptrVars, std::vector > &ptrVarIndexes, std::string &allocName) +{ + std::vector validTypeInfos; + std::set validTypeInfoSet; + std::vector validTypeTags; + std::vector voidTypeTags; + std::vector indexes; + TypeInfo *aTypeInfo = NULL; + TypeInfo *voidTypeInfo = voidPtrTypeInfo->getContainedType(0); + allocName = ""; + if(ptrVars.size()==0) { + return voidTypeInfo; + } + + for(unsigned i=0;i(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(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::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::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 ptrVars; + std::vector > 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 &typeInfos) { + static std::vector 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;igetType()) { + 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;iequals(&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 aTypeInfoContainedTypes; + nestedTypes.push_back(aTypeInfo); + level++; + for(unsigned i=0;igetContainedType(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 &typeInfos) { + static std::map externalTypeInfoCache; + std::map::iterator externalTypeInfoCacheIt; + TypeInfo* aTypeInfo = NULL; + std::vector 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;igetSmartType() && 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;igetSmartType()->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;igetSmartType()); + 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 containedTypes; + containedTypes.push_back(targetTypeInfo); + aTypeInfo->setContainedTypes(containedTypes); + typeInfos.push_back(aTypeInfo); + } + } + if(aTypeInfo && parent) { + aTypeInfo->addParent(parent); + } + externalTypeInfoCache.insert(std::pair(sourceType, aTypeInfo)); + return aTypeInfo; +} + +void MagicPass::printInterestingTypes(TYPECONST TypeInfo *aTypeInfo) { + static std::vector nestedTypes; + static std::vector nestedIndexes; + static std::vector interestingTypesSoFar; + static std::string typeName; + static unsigned level = 0; + for(unsigned i=0;igetSmartType(); + 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;igetDescription(); + 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;igetName() << "\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;igetContainedType(i)); + nestedIndexes.pop_back(); + } + level--; + nestedTypes.pop_back(); +} + +unsigned MagicPass::getMaxRecursiveSequenceLength(TYPECONST TypeInfo *aTypeInfo) { + static std::vector nestedTypes; + static unsigned level = 0; + for(unsigned i=0;igetNumContainedTypes(); + unsigned length, maxLength = 0; + nestedTypes.push_back(aTypeInfo); + level++; + for(unsigned i=0;igetContainedType(i)); + if(length > maxLength) { + maxLength = length; + } + } + level--; + nestedTypes.pop_back(); + return maxLength; +} + +FunctionType* MagicPass::getFunctionType(TYPECONST FunctionType *baseType, std::vector selectedArgs) { + std::vector 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;igetContainedType(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 &intCastTypes, std::vector &intCastValues, std::map > &bitCastMap) { + unsigned i; + std::map >::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(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(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(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 typeSet; + typeSet.insert(srcType); + bitCastMap.insert(std::pair >(type, typeSet)); + } + else { + std::set *typeSet = &(bitCastMapIt->second); + typeSet->insert(srcType); + } + } + } + } + } +#endif + + //now dig looking for constant expressions + std::vector users; + users.push_back(U); + while(!users.empty()) { + User *user = users.front(); + users.erase(users.begin()); + ConstantExpr *CE = dyn_cast(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(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 typeSet; + typeSet.insert(srcType); + bitCastMap.insert(std::pair >(type, typeSet)); + } + else { + std::set *typeSet = &(bitCastMapIt->second); + typeSet->insert(srcType); + } + } + } + } + } +#endif + + for(i=0;igetNumOperands();i++) { + User *operand = dyn_cast(user->getOperand(i)); + if(operand && !isa(operand) && !isa(operand)) { + users.push_back(operand); + } + } + } +} + +void MagicPass::fillStackInstrumentedFunctions(std::vector &stackIntrumentedFuncs, Function *deepestLLFunction) { + assert(!deepestLLFunction->hasAddressTaken() && "Indirect calls not supported for detection of long-lived functions"); + for(unsigned i=0;iuse_begin(), e = deepestLLFunction->use_end(); i != e; ++i) { + User *user = *i; + if(Instruction *I = dyn_cast(user)) { + fillStackInstrumentedFunctions(stackIntrumentedFuncs, I->getParent()->getParent()); + } + } +} + +void MagicPass::indexLocalTypeInfos(Module &M, Function *F, std::map > &localMap) { + DIVariable DIV; + for (inst_iterator it = inst_begin(F), et = inst_end(F); it != et; ++it) { + AllocaInst *AI = dyn_cast(&(*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 infoNamePair(aTypeInfo, name); + localMap.insert(std::pair >(AI, infoNamePair)); + } +} + +void MagicPass::addMagicStackDsentryFuncCalls(Module &M, Function *insertCallsInFunc, Function *localsFromFunc, Function *dsentryCreateFunc, Function *dsentryDestroyFunc, TYPECONST StructType *dsentryStructType, std::map > localTypeInfoMap, std::map &magicArrayTypePtrMap, TypeInfo *voidPtrTypeInfo, std::vector &typeInfoList, std::vector > &namesList, std::vector &flagsList) { + std::vector locals; + std::map >::iterator localTypeInfoMapIt; + std::map::iterator magicArrayTypePtrMapIt; + std::vector localTypeInfos; + std::vector localTypeInfoValues; + std::vector 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(&(*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;ihasName() ? 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 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 dsentryCreateArgs; + std::vector 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[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(allocParentName, allocName)); + flagsList.push_back(allocFlags); + } + MagicUtil::createCallInstruction(dsentryCreateFunc, dsentryCreateArgs, "", dsentryCreateI); + if(isa(dsentryDestroyI)) { + MagicUtil::createCallInstruction(dsentryDestroyFunc, dsentryDestroyArgs, "", dsentryDestroyI); + } +} + +bool MagicPass::isExtLibrary(GlobalValue *GV, DIDescriptor *DID) +{ + static bool regexesInitialized = false; + static std::vector regexes; + if(!regexesInitialized) { + std::vector::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;imatch(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 hookParams; + QProfSite* site; + std::vectorfunctionTyArgs; + 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 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;itoString())); + 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 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;itoString())); + 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 MP("magic", "Magic Pass to Build a Table of Global Variables"); + diff --git a/minix/llvm/passes/magic/Makefile b/minix/llvm/passes/magic/Makefile new file mode 100644 index 000000000..9d89f58e6 --- /dev/null +++ b/minix/llvm/passes/magic/Makefile @@ -0,0 +1,6 @@ +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 diff --git a/minix/llvm/passes/magic/support/Backports.cpp b/minix/llvm/passes/magic/support/Backports.cpp new file mode 100644 index 000000000..748ae5071 --- /dev/null +++ b/minix/llvm/passes/magic/support/Backports.cpp @@ -0,0 +1,172 @@ +#include + +#include +#include +#include + +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(V) && !isa(V)) + return 0; + + const Function *F = NULL; + if (const Instruction *I = dyn_cast(V)) + F = I->getParent()->getParent(); + else if (const Argument *A = dyn_cast(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(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(*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(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(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(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 +} + +} diff --git a/minix/llvm/passes/magic/support/BitFieldAggregation.cpp b/minix/llvm/passes/magic/support/BitFieldAggregation.cpp new file mode 100644 index 000000000..c107d93af --- /dev/null +++ b/minix/llvm/passes/magic/support/BitFieldAggregation.cpp @@ -0,0 +1,171 @@ +#include + +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 EDITypes, unsigned typeIndex, unsigned EDITypeIndex, std::vector 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 EDITypes, unsigned typeIndex, unsigned EDITypeIndex, std::vector 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 EDITypes = getEDITypes(); + for(unsigned i=0;i &bfas, bool returnOnError) { + std::vector 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 members; + std::vector 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; + +} diff --git a/minix/llvm/passes/magic/support/EDIType.cpp b/minix/llvm/passes/magic/support/EDIType.cpp new file mode 100644 index 000000000..bea74a14d --- /dev/null +++ b/minix/llvm/passes/magic/support/EDIType.cpp @@ -0,0 +1,520 @@ + +#include + +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 nonOpaqueEmptyTypes; + static std::set::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 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;jequals(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 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 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 > compatibleMDNodes; + static std::set >::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;igetContainedType(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 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; + +} diff --git a/minix/llvm/passes/magic/support/MagicUtil.cpp b/minix/llvm/passes/magic/support/MagicUtil.cpp new file mode 100644 index 000000000..7c38871dc --- /dev/null +++ b/minix/llvm/passes/magic/support/MagicUtil.cpp @@ -0,0 +1,1137 @@ +#include + +using namespace llvm; + +namespace llvm { + +//===----------------------------------------------------------------------===// +// Public static methods +//===----------------------------------------------------------------------===// + +static std::map stringRefCache; + +unsigned getLabelHash(std::string label) { + unsigned hash = 0; + for(unsigned i=0;i> ((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(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(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(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(inst)){ + DIVariable otherVar(cast(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(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::iterator it; + it = stringRefCache.find(str); + if(it == stringRefCache.end()) { + stringRefCache.insert(std::pair(str, GV)); + } +} + +Constant* MagicUtil::getGetElementPtrConstant(Constant *constant, std::vector &indexes) { + return PassUtil::getGetElementPtrConstant(constant, indexes); +} + +GetElementPtrInst* MagicUtil::createGetElementPtrInstruction(Value *ptr, std::vector &indexes, const Twine &NameStr, Instruction *InsertBefore) { + return PassUtil::createGetElementPtrInstruction(ptr, indexes, NameStr, InsertBefore); +} + +GetElementPtrInst* MagicUtil::createGetElementPtrInstruction(Value *ptr, std::vector &indexes, const Twine &NameStr, BasicBlock *InsertAtEnd) { + return PassUtil::createGetElementPtrInstruction(ptr, indexes, NameStr, InsertAtEnd); +} + +CallInst* MagicUtil::createCallInstruction(Value *F, std::vector &args, const Twine &NameStr, Instruction *InsertBefore) { + return PassUtil::createCallInstruction(F, args, NameStr, InsertBefore); +} + +CallInst* MagicUtil::createCallInstruction(Value *F, std::vector &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::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(str, stringRef)); + } + + return stringRef; + } + + +GlobalVariable *MagicUtil::getIntArrayRef(Module &M, unsigned arrSize, std::vector *arr, bool isConstant) { + static std::map, GlobalVariable*> arrayRefCache; + std::map, GlobalVariable*>::iterator it; + static std::vector defInitilizer; + + //construct an appropriate initializer if we do not have one + if(!arr) { + arr = &defInitilizer; + arr->clear(); + for(unsigned i=0;ipush_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 arrayElems; + for(unsigned i=0;isize();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, GlobalVariable*>(*arr, arrayRef)); + } + + return arrayRef; +} + +GlobalVariable *MagicUtil::getStringArrayRef(Module &M, unsigned arrSize, std::vector *arr, bool isConstant) { + static std::map, GlobalVariable*> arrayRefCache; + std::map, GlobalVariable*>::iterator it; + static std::vector defInitilizer; + //construct an appropriate initializer if we do not have one + if(!arr) { + arr = &defInitilizer; + arr->clear(); + for(unsigned i=0;ipush_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 arrayElems; + std::vector 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;isize();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, GlobalVariable*>(*arr, arrayRef)); + } + + return arrayRef; +} + +GlobalVariable *MagicUtil::getGenericArrayRef(Module &M, std::vector &arrayElems, bool isConstant) { + static std::map, GlobalVariable*> arrayRefCache; + std::map, 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, GlobalVariable*>(arrayElems, arrayRef)); + } + + return arrayRef; +} + +GlobalVariable *MagicUtil::getMagicTypePtrArrayRef(Module &M, Instruction *InsertBefore, std::vector &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 arrayElems; + for(int i=0;i 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 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 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 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 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(CS.getCalledValue()); + if (CE) { + assert(CE->getOpcode() == Instruction::BitCast && "Bitcast expected, something else found!"); + function = dyn_cast(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;isetMetadata(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(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 MagicUtil::getGlobalVariablesShadowFunctions(Module &M, std::vector globalVariables, std::vector shadowGlobalVariables, std::vector globalVariableSizes, GlobalVariable* magicArray, int magicArraySize, bool forceShadow, bool setDirtyFlag) { + std::vector globalVariableShadowFunctions; + for(int i=0;igetName()); + + //create function + std::vectorshadowFuncArgs; + 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::vectorshadowFuncArgs; + 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 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(inst)) { + CallInst *callInst = dyn_cast(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 &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(ActualArg); + ConstantExpr *castExpr = dyn_cast(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(ActualArg); + if(GV == NULL) { + magicUtilLog("Weird ActualArg: " << *ActualArg); + } + assert(GV != NULL); + + return GV; +} + +void MagicUtil::cleanupShadowTag(Module &M, std::vector &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 sourceUsers; + sourceUsers.push_back(GV); + if(includeMembers && isa(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(U); + if(isa(U)) { + sourceUsers.push_back(U); + } + else if(constantExpr && constantExpr->getOpcode() == Instruction::GetElementPtr) { + sourceUsers.push_back(U); + } + } + } + + for(unsigned i=0;iuse_begin(), E = sourceUsers[i]->use_end(); + UI != E; ++UI) { + const User *U = *UI; + if (const StoreInst *SI = dyn_cast(U)) { + if (SI->getOperand(0) == sourceUsers[i] || SI->isVolatile()) + return true; // Storing addr of sourceUsers[i]. + } else if (isa(U) || isa(U)) { + // Make sure we are calling the function, not passing the address. + ImmutableCallSite CS(cast(U)); + if (!CS.isCallee(UI)) + return true; + } else if (const LoadInst *LI = dyn_cast(U)) { + if (LI->isVolatile()) + return true; + } else if (isa(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 &valueSet) { + //Similar to hasAddressTaken above, but we look for values + + if(!isa(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 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(U)) { + if (SI->getOperand(1) == GV) { + Value *value = SI->getOperand(0); + if(ConstantInt *intValue = dyn_cast(value)) { + set.insert(intValue->getSExtValue()); + } + else { + return false; + } + } + } + } + const Constant *constant = GV->getInitializer(); + if(const ConstantInt *intConstant = dyn_cast(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::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 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(U); + if(isa(U)) { + sourceUsers.push_back(U); + } + else if(constantExpr && constantExpr->getOpcode() == Instruction::GetElementPtr) { + sourceUsers.push_back(U); + } + } + + Value *stringOwner = NULL; + for(unsigned i=0;iuse_begin(), E = sourceUsers[i]->use_end(); + UI != E; ++UI) { + User *U = *UI; + Value *V = U; + if (StoreInst *SI = dyn_cast(U)) { + V = SI->getPointerOperand(); + } + if(isa(V) || isa(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(inst)) { + if(SI->getOperand(1) == magicAnnotationVar) { + ConstantInt *CI = dyn_cast(SI->getOperand(0)); + assert(CI && "Bad call annotation!"); + annotationFound = true; + *annotation = CI->getSExtValue(); + break; + } + } + else if(isa(inst) || isa(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(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(&(*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 argsMapping, std::vector trailingArgs) +{ + std::vector 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::iterator it = argsMapping.begin(); it != argsMapping.end(); it++) { + callArgs.push_back(MagicUtil::getFunctionParam(function, *it - 1)); + } + for (std::vector::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 mapping, std::vector trailingArgs) +{ + std::vector 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(BI->getTerminator()); + if (RetInst) { + std::vector callArgs; + for (std::vector::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::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::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(type)) { + while (ptr_type) { + level++; + ptr_type = dyn_cast(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 stringPair = GV->getName().split('.'); + StringRef functionName = stringPair.first; + if (!functionName.compare("") || M.getFunction(functionName) == NULL) { + return false; + } + + return true; +} + +} diff --git a/minix/llvm/passes/magic/support/SmartType.cpp b/minix/llvm/passes/magic/support/SmartType.cpp new file mode 100644 index 000000000..281f204d6 --- /dev/null +++ b/minix/llvm/passes/magic/support/SmartType.cpp @@ -0,0 +1,780 @@ +#include +#include + +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;igetContainedType(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 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 indexes; + int maxWeakConsistencyLevel = -1; + unsigned maxWeakConsistencyIndex = -1; + int maxWeakConsistencyLevelEntries; + unsigned index; + for(unsigned i=0;i 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 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 > compatibleMDNodes; + static std::set >::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 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(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;igetContainedType(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(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(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(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(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* SmartType::getTopStructSmartTypes(Module &M, GlobalVariable* GV) { + std::vector names; + std::vector flags; + TypeUtil::parseTopStructTypes(M, GV->getType()->getElementType(), &names, &flags); + std::vector *vector = new std::vector; + for(unsigned i=0;igetTopStructType(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;igetContainedType(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 &inputBfas) { + for(unsigned j=0;jinputBfas[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 &nestedTypes, std::vector &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;jequals(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;igetContainedType(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 nestedTypes; + static std::vector 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 nestedTypes; + static std::vector nestedEDITypes; + static unsigned level = 0; + + if(level == 0) { + if(weakConsistencyLevel) { + *weakConsistencyLevel = INT_MAX; + } + } + + if(aEDIType->isPointerTy() || aEDIType->isUnionOrStructTy()) { + for(unsigned j=0;jequals(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 myBfas; + if(numContainedEDITypes != type->getNumContainedTypes()) { + if(!useBfas) { + return false; + } + if(!BitFieldAggregation::getBitFieldAggregations(type, aEDIType, myBfas, true)) { + return false; + } + for(unsigned i=0;igetNumContainedTypes()) { + return false; + } + nestedEDITypes.push_back(aEDIType); + nestedTypes.push_back(type); + level++; + for(unsigned i=0;igetContainedType(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;igetContainedType(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 SmartType::equalsNestedTypes; + +} diff --git a/minix/llvm/passes/magic/support/TypeUtil.cpp b/minix/llvm/passes/magic/support/TypeUtil.cpp new file mode 100644 index 000000000..bab861ca6 --- /dev/null +++ b/minix/llvm/passes/magic/support/TypeUtil.cpp @@ -0,0 +1,388 @@ +#include + +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;igetContainedType(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 *names, std::vector *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 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 names; + std::vector flags; + parseTopStructTypes(M, type, &names, &flags); + int index = -1; + for(unsigned i=0;i(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;igetContainedType(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 0); + OS << "\n"; + indent += 2; + printFormattedTypeString(OS, typeStr, i+2, newLength); + indent -= 2; + OS << "\n"; + for(int k=0;k 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;jisPointerTy()) { + 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 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 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; + +} diff --git a/minix/llvm/passes/magic/support/VariableRefs.cpp b/minix/llvm/passes/magic/support/VariableRefs.cpp new file mode 100644 index 000000000..92bec82da --- /dev/null +++ b/minix/llvm/passes/magic/support/VariableRefs.cpp @@ -0,0 +1,68 @@ +#include + +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; +} + +} -- 2.44.0