Import magic pass from llvm-apps

Change-Id: I19535b913b50f2ff24aeb80ddefc92e305c31fe8
This commit is contained in:
David van Moolenbroek 2015-06-30 01:25:43 +02:00
parent b5e2faaaaf
commit 3e457fe321
33 changed files with 11046 additions and 227 deletions

View file

@ -0,0 +1,148 @@
#ifndef _UTIL_STDLIB_H
#define _UTIL_STDLIB_H
#include "util_def.h"
#include <string.h>
typedef struct util_stdlib_s {
int id;
char *name;
unsigned long flags;
} util_stdlib_t;
typedef enum util_stdlib_id_e {
STDLIB_ACCEPT = 0,
STDLIB_ACCEPT4,
STDLIB_BIND,
STDLIB_BRK,
STDLIB_CALLOC,
STDLIB_EPOLL_CREATE,
STDLIB_EPOLL_CREATE1,
STDLIB_EPOLL_WAIT,
STDLIB_FREE,
STDLIB_GETSOCKOPT,
STDLIB_KILL,
STDLIB_LISTEN,
STDLIB_MALLOC,
STDLIB_MEMALIGN,
STDLIB_MMAP,
STDLIB_MMAP64,
STDLIB_MUNMAP,
STDLIB_POLL,
STDLIB_POSIX_MEMALIGN,
STDLIB_PPOLL,
STDLIB_PTHREAD_COND_WAIT,
STDLIB_PTHREAD_COND_TIMEDWAIT,
STDLIB_PTHREAD_JOIN,
STDLIB_READ,
STDLIB_REALLOC,
STDLIB_RECV,
STDLIB_RECVFROM,
STDLIB_RECVMSG,
STDLIB_SBRK,
STDLIB_SELECT,
STDLIB_SEMOP,
STDLIB_SEMTIMEDOP,
STDLIB_SETSOCKOPT,
STDLIB_SHMAT,
STDLIB_SHMDT,
STDLIB_SIGSUSPEND,
STDLIB_SIGTIMEDWAIT,
STDLIB_SIGWAITINFO,
STDLIB_SLEEP,
STDLIB_SOCKET,
STDLIB_USLEEP,
STDLIB_VALLOC,
STDLIB_WAITPID,
__NUM_STDLIBS_IDS
} util_stdlib_id_t;
typedef enum util_stdlib_flag_e {
STLIB_BLOCK_EXT = 0,
STLIB_BLOCK_INT,
__NUM_STDLIBS_FLAGS
} util_stdlib_flag_t;
#define _UTIL_STLIB_FLAGS_STR "ei"
#define _UTIL_STLIB_FLAG(F) (1 << (F))
#define _UTIL_STLIB_BLOCK_MASK \
(_UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)|_UTIL_STLIB_FLAG(STLIB_BLOCK_INT))
#define _UTIL_STLIB_FLAGS_STR_BUFF_SIZE (__NUM_STDLIBS_FLAGS+1)
#define _UTIL_STLIB_FLAG_C(F, E) \
(((F) & _UTIL_STLIB_FLAG(E)) ? _UTIL_STLIB_FLAGS_STR[E] : '-')
#define _UTIL_STDLIB_DEF(ID, N, F) { (ID), (N), (F) }
#define _UTIL_STDLIBS_INITIALIZER { \
_UTIL_STDLIB_DEF(STDLIB_ACCEPT, "accept", _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)), \
_UTIL_STDLIB_DEF(STDLIB_ACCEPT4, "accept4", _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)), \
_UTIL_STDLIB_DEF(STDLIB_BIND, "bind", 0), \
_UTIL_STDLIB_DEF(STDLIB_BRK, "brk", 0), \
_UTIL_STDLIB_DEF(STDLIB_CALLOC, "calloc", 0), \
_UTIL_STDLIB_DEF(STDLIB_EPOLL_CREATE, "epoll_create", 0), \
_UTIL_STDLIB_DEF(STDLIB_EPOLL_CREATE1, "epoll_create1", 0), \
_UTIL_STDLIB_DEF(STDLIB_EPOLL_WAIT, "epoll_wait", _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)), \
_UTIL_STDLIB_DEF(STDLIB_FREE, "free", 0), \
_UTIL_STDLIB_DEF(STDLIB_GETSOCKOPT, "getsockopt", 0), \
_UTIL_STDLIB_DEF(STDLIB_KILL, "kill", 0), \
_UTIL_STDLIB_DEF(STDLIB_LISTEN, "listen", 0), \
_UTIL_STDLIB_DEF(STDLIB_MALLOC, "malloc", 0), \
_UTIL_STDLIB_DEF(STDLIB_MEMALIGN, "memalign", 0), \
_UTIL_STDLIB_DEF(STDLIB_MMAP, "mmap", 0), \
_UTIL_STDLIB_DEF(STDLIB_MMAP64, "mmap64", 0), \
_UTIL_STDLIB_DEF(STDLIB_MUNMAP, "munmap", 0), \
_UTIL_STDLIB_DEF(STDLIB_POLL, "poll", _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)), \
_UTIL_STDLIB_DEF(STDLIB_POSIX_MEMALIGN, "posix_memalign", 0), \
_UTIL_STDLIB_DEF(STDLIB_PPOLL, "ppoll", _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)), \
_UTIL_STDLIB_DEF(STDLIB_PTHREAD_COND_WAIT, "pthread_cond_wait", _UTIL_STLIB_FLAG(STLIB_BLOCK_INT)), \
_UTIL_STDLIB_DEF(STDLIB_PTHREAD_COND_TIMEDWAIT, "pthread_cond_timedwait", _UTIL_STLIB_FLAG(STLIB_BLOCK_INT)), \
_UTIL_STDLIB_DEF(STDLIB_PTHREAD_JOIN, "pthread_join", _UTIL_STLIB_FLAG(STLIB_BLOCK_INT)), \
_UTIL_STDLIB_DEF(STDLIB_READ, "read", _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)), \
_UTIL_STDLIB_DEF(STDLIB_REALLOC, "realloc", 0), \
_UTIL_STDLIB_DEF(STDLIB_RECV, "recv", _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)), \
_UTIL_STDLIB_DEF(STDLIB_RECVFROM, "recvfrom", _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)), \
_UTIL_STDLIB_DEF(STDLIB_RECVMSG, "recvsmg", _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)), \
_UTIL_STDLIB_DEF(STDLIB_SBRK, "sbrk", 0), \
_UTIL_STDLIB_DEF(STDLIB_SELECT, "select", _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)), \
_UTIL_STDLIB_DEF(STDLIB_SEMOP, "semop", _UTIL_STLIB_FLAG(STLIB_BLOCK_INT)), \
_UTIL_STDLIB_DEF(STDLIB_SEMTIMEDOP, "semtimedop", _UTIL_STLIB_FLAG(STLIB_BLOCK_INT)), \
_UTIL_STDLIB_DEF(STDLIB_SETSOCKOPT, "setsockopt", 0), \
_UTIL_STDLIB_DEF(STDLIB_SHMAT, "shmat", 0), \
_UTIL_STDLIB_DEF(STDLIB_SHMDT, "shmdt", 0), \
_UTIL_STDLIB_DEF(STDLIB_SIGSUSPEND, "sigsuspend", _UTIL_STLIB_FLAG(STLIB_BLOCK_INT)), \
_UTIL_STDLIB_DEF(STDLIB_SIGTIMEDWAIT, "sigtimedwait", _UTIL_STLIB_FLAG(STLIB_BLOCK_INT)), \
_UTIL_STDLIB_DEF(STDLIB_SIGWAITINFO, "sigwaitinfo", _UTIL_STLIB_FLAG(STLIB_BLOCK_INT)), \
_UTIL_STDLIB_DEF(STDLIB_SLEEP, "sleep", _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)), \
_UTIL_STDLIB_DEF(STDLIB_SOCKET, "socket", 0), \
_UTIL_STDLIB_DEF(STDLIB_USLEEP, "usleep", _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)), \
_UTIL_STDLIB_DEF(STDLIB_VALLOC, "valloc", 0), \
_UTIL_STDLIB_DEF(STDLIB_WAITPID, "waitpid", _UTIL_STLIB_FLAG(STLIB_BLOCK_INT)) \
}
static inline util_stdlib_t* util_stdlib_lookup_by_name(const char *name, util_stdlib_t *stlib_arr)
{
int i;
for (i=0;i<__NUM_STDLIBS_IDS;i++) {
if (!strcmp(name, stlib_arr[i].name)) {
return &stlib_arr[i];
}
}
return NULL;
}
static inline char* util_stdlib_flags_to_str(unsigned long flags,
char* buffer)
{
int i;
for(i=0;i<__NUM_STDLIBS_FLAGS;i++) {
buffer[i] = _UTIL_STLIB_FLAG_C(flags, i);
}
buffer[i] = '\0';
return buffer;
}
#endif /* _UTIL_STDLIB_H */

View file

@ -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

View file

@ -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 */

View file

@ -1,4 +1,4 @@
#include "pass_hello.h"
#include <pass.h>
#include <stdlib.h>
using namespace llvm;

View file

@ -1,224 +0,0 @@
#ifndef _PASS_HELLO_H
#define _PASS_HELLO_H
#if LLVM_VERSION >= 33
#define ATTRIBUTE_SET_TY AttributeSet
#include <llvm/IR/Function.h>
#include <llvm/IR/Module.h>
#include <llvm/IR/Instructions.h>
#include <llvm/IR/Type.h>
#include <llvm/IR/Constants.h>
#include <llvm/IR/Intrinsics.h>
#include <llvm/IR/DerivedTypes.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/IntrinsicInst.h>
#include <llvm/IR/DataLayout.h>
#include <llvm/IR/IRBuilder.h>
#include <llvm/Support/raw_ostream.h>
#else /* LLVM_VERSION < 33 */
#define ATTRIBUTE_SET_TY AttrListPtr
#include <llvm/Function.h>
#include <llvm/Module.h>
#include <llvm/Instructions.h>
#include <llvm/Type.h>
#include <llvm/Constants.h>
#include <llvm/Intrinsics.h>
#include <llvm/DerivedTypes.h>
#include <llvm/LLVMContext.h>
#include <llvm/IntrinsicInst.h>
#endif /* LLVM_VERSION >= 33 */
#if LLVM_VERSION >= 32
#define DATA_LAYOUT_TY DataLayout
#define ATTRIBUTE_SET_RET_IDX ATTRIBUTE_SET_TY::ReturnIndex
#define ATTRIBUTE_SET_FN_IDX ATTRIBUTE_SET_TY::FunctionIndex
#include <llvm/DebugInfo.h>
#if LLVM_VERSION == 32
#include <llvm/DataLayout.h>
#include <llvm/IRBuilder.h>
#endif
#else /* LLVM_VERSION < 32 */
#define DATA_LAYOUT_TY TargetData
#define ATTRIBUTE_SET_RET_IDX 0
#define ATTRIBUTE_SET_FN_IDX (~0U)
#include <llvm/Target/TargetData.h>
#include <llvm/Analysis/DebugInfo.h>
#include <llvm/Support/IRBuilder.h>
#endif /* LLVM_VERSION >= 32 */
#if LLVM_VERSION >= 31
/* XXX Check. */
#define CONSTANT_ARRAY_INITIALIZER_TY ConstantDataArray
#else /* LLVM_VERSION < 31 */
#define CONSTANT_ARRAY_INITIALIZER_TY ConstantArray
#endif /* LLVM_VERSION >= 31 */
#if LLVM_VERSION >= 30
#define BASE_PARSER parser
#define TYPECONST
#else /* LLVM_VERSION < 30 */
#define BASE_PARSER basic_parser
#define TYPECONST const
#endif /* LLVM_VERSION >= 30 */
#if LLVM_VERSION >= 29
#define VALUE_TO_VALUE_MAP_TY ValueToValueMapTy
#else /* LLVM_VERSION < 29 */
#define VALUE_TO_VALUE_MAP_TY ValueMap<const Value*, Value*>
#endif /* LLVM_VERSION >= 29 */
#define ZERO_CONSTANT_INT(M) ConstantInt::get((M).getContext(), APInt(32, 0, 10))
#define VOID_PTR_TY(M) PointerType::get(IntegerType::get((M).getContext(), 8), 0)
#define VOID_PTR_PTR_TY(M) PointerType::get(PointerType::get(IntegerType::get((M).getContext(), 8), 0), 0)
#define DEBUG_LLVM_DEBUG_API 0
typedef enum PassUtilLinkageTypeE {
PASS_UTIL_LINKAGE_NONE = 0,
PASS_UTIL_LINKAGE_WEAK,
PASS_UTIL_LINKAGE_COMMON,
PASS_UTIL_LINKAGE_EXTERNAL,
PASS_UTIL_LINKAGE_EXTERNAL_WEAK,
PASS_UTIL_LINKAGE_WEAK_POINTER,
PASS_UTIL_LINKAGE_PRIVATE,
__NUM_PASS_UTIL_LINKAGE_TYPES
/* Values here should only be appended at the end, external components (e.g., scripts) may be relying on them.*/
} PassUtilLinkageType;
#define PASS_UTIL_LINKAGE_TYPE_STRINGS \
"NONE", \
"WEAK", \
"COMMON", \
"EXTERNAL", \
"EXTERNAL_WEAK", \
"WEAK_POINTER", \
"PRIVATE"
typedef enum PassUtilPropE {
PASS_UTIL_PROP_NONE,
PASS_UTIL_PROP_NOINLINE,
PASS_UTIL_PROP_USED,
PASS_UTIL_PROP_PRESERVE,
__NUM_PASS_UTIL_PROPS
} PassUtilProp;
#define PASS_UTIL_FLAG(F) (1 << F)
#define PASS_COMMON_INIT_ONCE() \
Module *PassUtil::M = NULL; \
using namespace llvm;
namespace llvm {
class PassUtil {
public:
static Constant* getGetElementPtrConstant(Constant *constant, std::vector<Value*> &indexes);
static CallInst* createCallInstruction(Value *F, std::vector<Value*> &args, const Twine &NameStr="", Instruction *InsertBefore=0);
static CallInst* createCallInstruction(Value *F, std::vector<Value*> &args, const Twine &NameStr="", BasicBlock *InsertAtEnd=0);
static FunctionType* getFunctionType(TYPECONST Type* Result, std::vector<TYPECONST Type*> &argsTy, bool isVarArg=false);
static Constant* getStringConstantArray(Module &M, const std::string &string);
static GlobalVariable* getStringGlobalVariable(Module &M, const std::string &string, const std::string &varName, const std::string &varSection = "", Constant **getElementPtrExpr=NULL, bool cacheable=false);
private:
static Module *M;
};
inline Constant* PassUtil::getGetElementPtrConstant(Constant *constant, std::vector<Value*> &indexes) {
#if LLVM_VERSION >= 30
ArrayRef<Value*> ref(indexes);
return ConstantExpr::getGetElementPtr(constant, ref);
#else
return ConstantExpr::getGetElementPtr(constant, &indexes[0], indexes.size());
#endif
}
inline CallInst* PassUtil::createCallInstruction(Value *F, std::vector<Value*> &args, const Twine &NameStr, Instruction *InsertBefore) {
#if LLVM_VERSION >= 30
ArrayRef<Value*> ref(args);
return CallInst::Create(F, ref, NameStr, InsertBefore);
#else
return CallInst::Create(F, args.begin(), args.end(), NameStr, InsertBefore);
#endif
}
inline CallInst* PassUtil::createCallInstruction(Value *F, std::vector<Value*> &args, const Twine &NameStr, BasicBlock *InsertAtEnd) {
#if LLVM_VERSION >= 30
ArrayRef<Value*> ref(args);
return CallInst::Create(F, ref, NameStr, InsertAtEnd);
#else
return CallInst::Create(F, args.begin(), args.end(), NameStr, InsertAtEnd);
#endif
}
inline FunctionType* PassUtil::getFunctionType(TYPECONST Type* Result, std::vector<TYPECONST Type*> &argsTy, bool isVarArg)
{
#if LLVM_VERSION >= 30
ArrayRef<TYPECONST Type*> ref(argsTy);
return FunctionType::get(Result, ref, isVarArg);
#else
return FunctionType::get(Result, argsTy, isVarArg);
#endif
}
inline Constant* PassUtil::getStringConstantArray(Module &M, const std::string &string)
{
std::vector<Constant*> elements;
elements.reserve(string.size() + 1);
for (unsigned i = 0; i < string.size(); ++i)
elements.push_back(ConstantInt::get(Type::getInt8Ty(M.getContext()), string[i]));
// Add a null terminator to the string...
elements.push_back(ConstantInt::get(Type::getInt8Ty(M.getContext()), 0));
ArrayType *ATy = ArrayType::get(Type::getInt8Ty(M.getContext()), elements.size());
return ConstantArray::get(ATy, elements);
}
inline GlobalVariable* PassUtil::getStringGlobalVariable(Module &M, const std::string &string, const std::string &varName, const std::string &varSection, Constant **getElementPtrExpr, bool cacheable)
{
static std::map<std::string, GlobalVariable*> stringCache;
std::map<std::string, GlobalVariable*>::iterator stringCacheIt;
std::string stringCacheKey;
GlobalVariable *strGV = NULL;
if (cacheable) {
stringCacheKey = string + "~!~!" + varName + "~!~!" + varSection;
stringCacheIt = stringCache.find(stringCacheKey);
if (stringCacheIt != stringCache.end()) {
strGV = stringCacheIt->second;
cacheable = false;
}
}
if (!strGV) {
//create a constant internal string reference
Constant *stringValue = PassUtil::getStringConstantArray(M, string);
//create the global variable, cache it, and record it in the module
strGV = new GlobalVariable(M, stringValue->getType(), true,
GlobalValue::InternalLinkage, stringValue, varName);
if (varSection.compare("")) {
strGV->setSection(varSection);
}
}
if (getElementPtrExpr) {
std::vector<Value*> strConstantIndices;
strConstantIndices.push_back(ZERO_CONSTANT_INT(M));
strConstantIndices.push_back(ZERO_CONSTANT_INT(M));
*getElementPtrExpr = PassUtil::getGetElementPtrConstant(strGV, strConstantIndices);
}
if (cacheable) {
stringCache.insert(std::pair<std::string, GlobalVariable*>(stringCacheKey, strGV));
}
return strGV;
}
}
#endif /* _PASS_HELLO_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,569 @@
#ifndef _QPROF_COMMON_H
#define _QPROF_COMMON_H
#include <cstdlib>
#include <common/util/stdlib.h>
#define QPROF_SEP ","
#define QPROF_SEP2 ":"
#define QPROF_SEP3 "|"
#define QPROF_DECLARE_LL_SITESTACKS_OPT(P, VAR) \
static cl::opt<std::string> \
VAR(#P "-ll-sitestacks", \
cl::desc("Specify all the long-lived sitestacks on a per-task basis in qprof format"), \
cl::init(""), cl::NotHidden, cl::ValueRequired)
#define QPROF_DECLARE_DEEPEST_LL_LOOPS_OPT(P, VAR) \
static cl::opt<std::string> \
VAR(#P "-deepest-ll-loops", \
cl::desc("Specify all the deepest long-lived loops on a per-task basis in qprof format"), \
cl::init(""), cl::NotHidden, cl::ValueRequired)
#define QPROF_DECLARE_DEEPEST_LL_LIBS_OPT(P, VAR) \
static cl::opt<std::string> \
VAR(#P "-deepest-ll-libs", \
cl::desc("Specify all the deepest long-lived loop lib calls on a per-task basis in qprof format"), \
cl::init(""), cl::NotHidden, cl::ValueRequired)
#define QPROF_DECLARE_TASK_CLASSES_OPT(P, VAR) \
static cl::opt<std::string> \
VAR(#P "-task-classes", \
cl::desc("Specify all the task classes in qprof format"), \
cl::init(""), cl::NotHidden, cl::ValueRequired)
#define QPROF_DECLARE_ALL_OPTS(P, VAR1, VAR2, VAR3, VAR4) \
QPROF_DECLARE_LL_SITESTACKS_OPT(P, VAR1); \
QPROF_DECLARE_DEEPEST_LL_LOOPS_OPT(P, VAR2); \
QPROF_DECLARE_DEEPEST_LL_LIBS_OPT(P, VAR3); \
QPROF_DECLARE_TASK_CLASSES_OPT(P, VAR4) \
using namespace llvm;
namespace llvm {
class QProfSite {
public:
static QProfSite* get(Module &M, int taskClassID, int taskSiteID, std::string moduleName, int lineNum, std::string functionName, std::string siteName, std::string siteFuncName, int siteDepth, int lib, unsigned long libFlags, bool refreshSite=true);
static QProfSite* getFromString(Module &M, int taskClassID, int taskSiteID, std::string &siteString, bool refreshSite=true);
static std::vector<QProfSite*> getFromSitesString(Module &M, std::string &sitesString, bool refreshSites=true);
void refresh(Module &M);
std::string toString();
bool isLoop();
bool isFunction();
bool isCallsite();
bool isLibCallsite();
bool equals(QProfSite *other);
int taskClassID;
int taskSiteID;
std::string moduleName;
int lineNum;
std::string functionName;
std::string siteName;
std::string siteFuncName;
unsigned long libFlags;
Function *function;
Function *siteFunction;
Instruction *siteInstruction;
private:
QProfSite() {}
int siteDepth;
int lib;
};
class QProfConf {
public:
static QProfConf* get(Module &M, std::string *llSitestacks, std::string *deepestLLLoops, std::string *deepestLLLibs, std::string *taskClasses, bool refreshSites=true);
std::map<int, std::vector<QProfSite*> > getTaskClassLLSitestacks();
std::map<int, QProfSite*> getTaskClassDeepestLLLoops();
std::map<int, std::vector<QProfSite*> > getTaskClassDeepestLLLibs();
int getNumTaskClasses();
int getNumLLTaskClasses();
int getNumLLBlockExtTaskClasses();
int getNumLLBlockIntTaskClasses();
int getNumLLBlockExtLibs();
int getNumLLBlockIntLibs();
std::vector<QProfSite*> getLLFunctions();
std::vector<QProfSite*> getDeepestLLLoops();
std::vector<QProfSite*> getDeepestLLLibs();
bool lookupTaskClassLibFlags(int taskClassID, int *libFlags);
void mergeTaskClassLLSitestacks(int taskClassID, int otherTaskClassID);
void mergeTaskClassDeepestLLLoops(int taskClassID, int otherTaskClassID);
void mergeTaskClassDeepestLLLibs(int taskClassID, int otherTaskClassID);
void mergeTaskClassPair(int taskClassID, int otherTaskClassID);
void mergeAllTaskClassesWithSameDeepestLLLoops();
void print(raw_ostream &O);
void printSiteList(raw_ostream &O, std::vector<QProfSite*> &list);
private:
QProfConf() {}
static std::map<int, std::vector<QProfSite*> > parseTaskClassSiteList(Module &M, std::string &str, bool refreshSites=true);
static std::map<int, QProfSite*> parseTaskClassSite(Module &M, std::string &str, bool refreshSites=true);
static std::vector<int> parseIntList(std::string &str);
std::map<int, std::vector<QProfSite*> > taskClassLLSitestacks;
std::map<int, QProfSite*> taskClassDeepestLLLoops;
std::map<int, std::vector<QProfSite*> > taskClassDeepestLLLibs;
int numTaskClasses;
int numLLTaskClasses;
int numLLBlockExtTaskClasses;
int numLLBlockIntTaskClasses;
int numLLBlockExtLibs;
int numLLBlockIntLibs;
};
static int stringRefToInt(StringRef &ref)
{
return atoi(ref.str().c_str());
}
inline QProfSite* QProfSite::get(Module &M, int taskClassID, int taskSiteID,
std::string moduleName, int lineNum, std::string functionName,
std::string siteName, std::string siteFuncName, int siteDepth, int lib,
unsigned long libFlags, bool refreshSite)
{
QProfSite *site = new QProfSite();
site->taskClassID = taskClassID;
site->taskSiteID = taskSiteID;
site->moduleName = moduleName;
site->lineNum = lineNum;
site->functionName = functionName;
site->siteName = siteName;
site->siteFuncName = siteFuncName;
site->siteDepth = siteDepth;
site->lib = lib;
site->libFlags = libFlags;
site->function = NULL;
site->siteFunction = NULL;
site->siteInstruction = NULL;
if (refreshSite) {
site->refresh(M);
}
return site;
}
inline QProfSite* QProfSite::getFromString(Module &M, int taskClassID, int taskSiteID,
std::string &siteString, bool refreshSite)
{
StringRef ref(siteString);
SmallVector< StringRef, 3 > tokenVector;
if (!siteString.compare("")) {
return NULL;
}
ref.split(tokenVector, QPROF_SEP3);
assert(tokenVector.size() == 8);
return get(M, taskClassID, taskSiteID, tokenVector[0], stringRefToInt(tokenVector[1]),
tokenVector[2], tokenVector[3], tokenVector[4],
stringRefToInt(tokenVector[5]), stringRefToInt(tokenVector[6]),
stringRefToInt(tokenVector[7]), refreshSite);
}
inline std::vector<QProfSite*> QProfSite::getFromSitesString(Module &M,
std::string &sitesString, bool refreshSites)
{
unsigned i;
int taskClassID;
std::vector<QProfSite*> sites;
StringRef ref(sitesString);
SmallVector< StringRef, 3 > tokenVector;
if (!sitesString.compare("")) {
return sites;
}
ref.split(tokenVector, QPROF_SEP2);
assert(tokenVector.size() > 1);
taskClassID = stringRefToInt(tokenVector[0]);
for (i=1;i<tokenVector.size();i++) {
std::string token = tokenVector[i].str();
QProfSite *site = QProfSite::getFromString(M, taskClassID, i, token,
refreshSites);
sites.push_back(site);
}
return sites;
}
inline void QProfSite::refresh(Module &M)
{
BasicBlock *siteBB = NULL;
function = NULL;
siteFunction = NULL;
siteInstruction = NULL;
function = M.getFunction(functionName);
siteFunction = M.getFunction(siteFuncName);
if (!siteFunction) {
errs() << "Function " << siteFuncName << " not found. Invalid qprof profiling data?\n";
}
assert(siteFunction);
for (Function::iterator BB = siteFunction->begin(),
e = siteFunction->end(); BB != e; ++BB) {
if (!BB->getName().compare(siteName)) {
siteBB = BB;
break;
}
}
assert(siteBB);
if (isCallsite()) {
for (BasicBlock::iterator it = siteBB->begin(); it != siteBB->end(); ++it) {
CallSite CS(it);
if (CS.getInstruction() && CS.getCalledFunction() == function) {
siteInstruction = it;
break;
}
}
assert(siteInstruction && "Invalid qprof callsite?");
}
else {
siteInstruction = &siteBB->front();
}
}
inline std::string QProfSite::toString()
{
std::string str;
raw_string_ostream ostream(str);
ostream << taskClassID << QPROF_SEP3 << taskSiteID << QPROF_SEP3 << moduleName << QPROF_SEP3 << lineNum << QPROF_SEP3 << functionName << QPROF_SEP3 << siteName << QPROF_SEP3 << siteFuncName << QPROF_SEP3 << siteDepth << QPROF_SEP3 << lib << QPROF_SEP3 << libFlags;
ostream.flush();
return str;
}
inline bool QProfSite::isLoop()
{
return siteDepth > 0;
}
inline bool QProfSite::isFunction()
{
return !isLoop() && !isCallsite();
}
inline bool QProfSite::isCallsite()
{
return isLibCallsite();
}
inline bool QProfSite::isLibCallsite()
{
return lib != 0;
}
inline bool QProfSite::equals(QProfSite *other)
{
if (lineNum != other->lineNum) {
return false;
}
if (libFlags != other->libFlags) {
return false;
}
if (moduleName.compare(other->moduleName)) {
return false;
}
if (functionName.compare(other->functionName)) {
return false;
}
if (siteName.compare(other->siteName)) {
return false;
}
if (siteFuncName.compare(other->siteFuncName)) {
return false;
}
return true;
}
inline QProfConf* QProfConf::get(Module &M, std::string *llSitestacks,
std::string *deepestLLLoops, std::string *deepestLLLibs,
std::string *taskClasses, bool refreshSites)
{
std::vector<int> intValues;
QProfConf *conf = new QProfConf();
if (llSitestacks) {
conf->taskClassLLSitestacks = parseTaskClassSiteList(M,
*llSitestacks, refreshSites);
}
if (deepestLLLoops) {
conf->taskClassDeepestLLLoops = parseTaskClassSite(M,
*deepestLLLoops, refreshSites);
}
if (deepestLLLibs) {
conf->taskClassDeepestLLLibs = parseTaskClassSiteList(M,
*deepestLLLibs, refreshSites);
}
if (taskClasses) {
intValues = parseIntList(*taskClasses);
}
if (intValues.size() > 0) {
assert(intValues.size() == 6);
conf->numTaskClasses = intValues[0];
conf->numLLTaskClasses = intValues[1];
conf->numLLBlockExtTaskClasses = intValues[2];
conf->numLLBlockIntTaskClasses = intValues[3];
conf->numLLBlockExtLibs = intValues[4];
conf->numLLBlockIntLibs = intValues[5];
}
else {
conf->numTaskClasses = 0;
conf->numLLTaskClasses = 0;
conf->numLLBlockExtTaskClasses = 0;
conf->numLLBlockIntTaskClasses = 0;
conf->numLLBlockExtLibs = 0;
conf->numLLBlockIntLibs = 0;
}
return conf;
}
inline std::map<int, std::vector<QProfSite*> > QProfConf::getTaskClassLLSitestacks()
{
return taskClassLLSitestacks;
}
inline std::map<int, QProfSite*> QProfConf::getTaskClassDeepestLLLoops()
{
return taskClassDeepestLLLoops;
}
inline std::map<int, std::vector<QProfSite*> > QProfConf::getTaskClassDeepestLLLibs()
{
return taskClassDeepestLLLibs;
}
inline int QProfConf::getNumTaskClasses()
{
return numTaskClasses;
}
inline int QProfConf::getNumLLTaskClasses()
{
return numLLTaskClasses;
}
inline int QProfConf::getNumLLBlockExtTaskClasses()
{
return numLLBlockExtTaskClasses;
}
inline int QProfConf::getNumLLBlockIntTaskClasses()
{
return numLLBlockIntTaskClasses;
}
inline int QProfConf::getNumLLBlockExtLibs()
{
return numLLBlockExtLibs;
}
inline int QProfConf::getNumLLBlockIntLibs()
{
return numLLBlockIntLibs;
}
inline std::vector<QProfSite*> QProfConf::getLLFunctions()
{
std::vector<QProfSite*> sites;
std::map<int, std::vector<QProfSite*> >::iterator it;
it = taskClassLLSitestacks.begin();
for (; it != taskClassLLSitestacks.end(); it++) {
std::vector<QProfSite*> *siteVector = &it->second;
for (unsigned i=0;i<siteVector->size();i++) {
QProfSite* site = (*siteVector)[i];
if (site->isFunction()) {
sites.push_back((*siteVector)[i]);
}
}
}
return sites;
}
inline std::vector<QProfSite*> QProfConf::getDeepestLLLoops()
{
std::vector<QProfSite*> sites;
std::map<int, QProfSite*>::iterator it;
it = taskClassDeepestLLLoops.begin();
for (; it != taskClassDeepestLLLoops.end(); it++) {
sites.push_back(it->second);
}
return sites;
}
inline std::vector<QProfSite*> QProfConf::getDeepestLLLibs()
{
std::vector<QProfSite*> sites;
std::map<int, std::vector<QProfSite*> >::iterator it;
it = taskClassDeepestLLLibs.begin();
for (; it != taskClassDeepestLLLibs.end(); it++) {
std::vector<QProfSite*> *siteVector = &it->second;
for (unsigned i=0;i<siteVector->size();i++) {
sites.push_back((*siteVector)[i]);
}
}
return sites;
}
inline bool QProfConf::lookupTaskClassLibFlags(int taskClassID, int *libFlags)
{
bool found = false;
std::vector<QProfSite*> deepestLLLibs = getDeepestLLLibs();
*libFlags = 0;
for (unsigned i=0;i<deepestLLLibs.size();i++) {
QProfSite *site = deepestLLLibs[i];
if (site->taskClassID == taskClassID) {
*libFlags |= site->libFlags;
found = true;
}
}
return found;
}
inline void QProfConf::mergeTaskClassLLSitestacks(int taskClassID, int otherTaskClassID)
{
size_t erased = taskClassLLSitestacks.erase(otherTaskClassID);
assert(erased == 1);
}
inline void QProfConf::mergeTaskClassDeepestLLLoops(int taskClassID, int otherTaskClassID)
{
size_t erased = taskClassDeepestLLLoops.erase(otherTaskClassID);
assert(erased == 1);
}
inline void QProfConf::mergeTaskClassDeepestLLLibs(int taskClassID, int otherTaskClassID)
{
size_t erased = taskClassDeepestLLLibs.erase(otherTaskClassID);
assert(erased == 1);
}
inline void QProfConf::mergeTaskClassPair(int taskClassID,
int otherTaskClassID)
{
int libFlags;
mergeTaskClassLLSitestacks(taskClassID, otherTaskClassID);
mergeTaskClassDeepestLLLoops(taskClassID, otherTaskClassID);
mergeTaskClassDeepestLLLibs(taskClassID, otherTaskClassID);
numTaskClasses--;
if (lookupTaskClassLibFlags(taskClassID, &libFlags)) {
numLLTaskClasses--;
if (libFlags & _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)) {
numLLBlockExtTaskClasses--;
}
else {
numLLBlockIntTaskClasses--;
}
}
}
inline void QProfConf::mergeAllTaskClassesWithSameDeepestLLLoops()
{
std::vector<QProfSite*> deepestLLLoops = getDeepestLLLoops();
std::vector<std::pair<QProfSite*, QProfSite*> > loopPairs;
for (unsigned i=0;i<deepestLLLoops.size();i++) {
QProfSite *site = deepestLLLoops[i];
for (unsigned j=0;j<i;j++) {
if (site->equals(deepestLLLoops[j])) {
loopPairs.push_back(std::pair<QProfSite*, QProfSite*>(site, deepestLLLoops[j]));
}
}
}
for (unsigned i=0;i<loopPairs.size();i++) {
int taskClassID = loopPairs[i].first->taskClassID;
int otherTaskClassID = loopPairs[i].second->taskClassID;
mergeTaskClassPair(taskClassID, otherTaskClassID);
}
}
inline void QProfConf::print(raw_ostream &O)
{
std::vector<QProfSite*> list;
O << "*** QProfConf:\n";
O << " - numTaskClasses=" << getNumTaskClasses() << "\n";
O << " - numLLTaskClasses=" << getNumLLTaskClasses() << "\n";
O << " - numLLBlockExtTaskClasses=" << getNumLLBlockExtTaskClasses() << "\n";
O << " - numLLBlockIntTaskClasses=" << getNumLLBlockIntTaskClasses() << "\n";
O << " - numLLBlockExtLibs=" << getNumLLBlockExtLibs() << "\n";
O << " - numLLBlockIntLibs=" << getNumLLBlockIntLibs() << "\n";
list = getLLFunctions();
O << " - LLFunctions="; printSiteList(O, list); O << "\n";
list = getDeepestLLLoops();
O << " - deepestLLLoops="; printSiteList(O, list); O << "\n";
list = getDeepestLLLibs();
O << " - deepestLLLibs="; printSiteList(O, list); O << "\n";
}
inline void QProfConf::printSiteList(raw_ostream &O, std::vector<QProfSite*> &list)
{
for (std::vector<QProfSite*>::iterator it = list.begin(); it != list.end(); it++) {
QProfSite* site = *it;
if (it != list.begin()) {
O << ", ";
}
O << "{ ";
O << site->toString();
O << " }";
}
}
inline std::map<int, std::vector<QProfSite*> > QProfConf::parseTaskClassSiteList(Module &M,
std::string &str, bool refreshSites)
{
std::map<int, std::vector<QProfSite*> > siteListMap;
StringRef ref(str);
SmallVector< StringRef, 3 > tokenVector;
if (!str.compare("")) {
return siteListMap;
}
ref.split(tokenVector, QPROF_SEP);
for (unsigned i=0;i<tokenVector.size();i++) {
std::string token = tokenVector[i].str();
std::vector<QProfSite*> sites = QProfSite::getFromSitesString(M,
token, refreshSites);
if (sites.size() > 0) {
int taskClassID = sites[0]->taskClassID;
siteListMap.insert(std::pair<int, std::vector<QProfSite*> >(taskClassID,
sites));
}
}
return siteListMap;
}
inline std::map<int, QProfSite*> QProfConf::parseTaskClassSite(Module &M,
std::string &str, bool refreshSites)
{
std::map<int, std::vector<QProfSite*> >::iterator it;
std::map<int, std::vector<QProfSite*> > siteListMap =
parseTaskClassSiteList(M, str, refreshSites);
std::map<int, QProfSite*> siteMap;
for (it=siteListMap.begin();it!=siteListMap.end();it++) {
std::vector<QProfSite*> list = it->second;
assert(list.size() == 1);
siteMap.insert(std::pair<int, QProfSite*>(it->first, list[0]));
}
return siteMap;
}
inline std::vector<int> QProfConf::parseIntList(std::string &str)
{
std::vector<int> intValues;
StringRef ref(str);
SmallVector< StringRef, 3 > tokenVector;
if (!str.compare("")) {
return intValues;
}
ref.split(tokenVector, QPROF_SEP);
for (unsigned i=0;i<tokenVector.size();i++) {
intValues.push_back(stringRefToInt(tokenVector[i]));
}
return intValues;
}
}
#endif /* _QPROF_COMMON_H */

View file

@ -0,0 +1,32 @@
#ifndef MAGIC_CTLAZY_CHECKPOINT_PASS_H
#define MAGIC_CTLAZY_CHECKPOINT_PASS_H
#include <magic/magic.h>
#include <magic/MagicPass.h>
#include <magic/support/VariableRefs.h>
using namespace llvm;
namespace llvm {
#define magicCTLazyCheckpointPassLog(M) DEBUG(dbgs() << "MagicCTLazyCheckpointPass: " << M << "\n")
class MagicCTLazyCheckpointPass : public FunctionPass {
public:
static char ID;
MagicCTLazyCheckpointPass();
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
virtual bool runOnFunction(Function &F);
private:
AliasAnalysis *AA;
bool instructionModifiesVar(Module &M, Instruction *inst, GlobalVariable* var);
};
}
#endif

View file

@ -0,0 +1,29 @@
#ifndef MAGIC_CHECKPOINT_PASS_H
#define MAGIC_CHECKPOINT_PASS_H
#include <magic/magic.h>
#include <magic/MagicPass.h>
using namespace llvm;
namespace llvm {
#define magicCheckpointPassLog(M) DEBUG(dbgs() << "MagicCheckpointPass: " << M << "\n")
class MagicCheckpointPass : public ModulePass {
public:
static char ID;
MagicCheckpointPass();
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
virtual bool runOnModule(Module &M);
private:
MagicPass *MP;
};
}
#endif

View file

@ -0,0 +1,29 @@
#ifndef MAGIC_LTLAZY_CHECKPOINT_PASS_H
#define MAGIC_LTLAZY_CHECKPOINT_PASS_H
#include <magic/magic.h>
#include <magic/MagicPass.h>
using namespace llvm;
namespace llvm {
#define magicLTLazyCheckpointPassLog(M) DEBUG(dbgs() << "MagicLTLazyCheckpointPass: " << M << "\n")
class MagicLTLazyCheckpointPass : public FunctionPass {
public:
static char ID;
MagicLTLazyCheckpointPass();
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
virtual bool runOnFunction(Function &F);
private:
MagicPass *MP;
};
}
#endif

View file

@ -0,0 +1,137 @@
#ifndef MAGIC_PASS_H
#define MAGIC_PASS_H
#include <pass.h>
#include <magic/magic.h>
#include <magic/support/Backports.h>
#include <magic/support/MagicUtil.h>
#include <magic/support/SmartType.h>
#include <magic/support/TypeInfo.h>
#include <magic/support/MagicDebugFunction.h>
#include <magic/support/MagicMemFunction.h>
#include <magic/support/MagicMmapCtlFunction.h>
#if MAGIC_USE_QPROF_INSTRUMENTATION
#include <common/qprof_common.h>
#endif
using namespace llvm;
namespace llvm {
#define magicPassLog(M) DEBUG(dbgs() << "MagicPass: " << M << "\n")
#define magicPassErr(M) errs() << "MagicPass: " << M << "\n"
class MagicPass : public ModulePass {
public:
static char ID;
MagicPass();
std::vector<GlobalVariable*> getGlobalVariables() const;
std::vector<int> getGlobalVariableSizes() const;
std::vector<GlobalVariable*> getShadowGlobalVariables() const;
std::vector<Function*> getFunctions() const;
GlobalVariable* getMagicArray() const;
GlobalVariable* getMagicTypeArray() const;
GlobalVariable* getMagicFunctionArray() const;
GlobalVariable* getMagicDsindexArray() const;
virtual bool runOnModule(Module &M);
private:
std::vector<GlobalVariable*> globalVariables;
std::set<GlobalVariable*> globalVariablesWithAddressTaken;
std::vector<int> globalVariableSizes;
std::vector<GlobalVariable*> shadowGlobalVariables;
std::vector<Function*> functions;
std::vector<TypeInfo*> globalTypeInfos;
std::map<GlobalValue*, TypeInfo*> globalParentMap;
std::map<GlobalValue*, TypeInfo*>::iterator parentMapIt;
std::map<std::string, GlobalVariable*> stringOwnerMap;
std::map<std::string, GlobalVariable*>::iterator stringOwnerMapIt;
std::map<GlobalVariable*, std::string> stringOwnerInvertedMap;
std::map<GlobalVariable*, std::string>::iterator stringOwnerInvertedMapIt;
GlobalVariable* magicArray;
GlobalVariable* magicTypeArray;
GlobalVariable* magicFunctionArray;
GlobalVariable* magicDsindexArray;
std::vector<std::string> libPathRegexes;
std::vector<std::string> voidTypeAliases;
std::set<std::string> voidTypeAliasesSet;
std::vector<std::string> mmFuncPrefixes;
std::set<std::pair<std::string, std::string> > mmFuncPairs;
std::vector<std::string> mmPoolFunctions;
std::vector<std::string> mmapCtlFunctions;
std::set<std::string>::iterator stringSetIt;
std::set<Function*> brkFunctions;
std::set<Function*> sbrkFunctions;
std::vector<Regex*> magicDataSectionRegexes;
std::vector<Regex*> magicFunctionSectionRegexes;
std::vector<Regex*> extLibSectionRegexes;
#if MAGIC_USE_QPROF_INSTRUMENTATION
QProfConf *qprofConf;
#endif
void qprofInstrumentationInit(Module &M);
void qprofInstrumentationApply(Module &M);
bool checkPointerVariableIndexes(TYPECONST Type* type, std::vector<int> &ptrVarIndexes, unsigned offset=0);
void findPointerVariables(Function* function, Value *value, std::vector<Value*> &ptrVars, std::vector<std::vector<int> > &ptrVarIndexes, Value *parent = NULL, bool isUser=false);
TypeInfo* typeInfoFromPointerVariables(Module &M, TypeInfo *voidPtrTypeInfo, std::vector<Value*> &ptrVars, std::vector<std::vector<int> > &ptrVarIndexes, std::string &allocName);
TypeInfo* getAllocTypeInfo(Module &M, TypeInfo *voidPtrTypeInfo, const CallSite &CS, std::string &allocName, std::string &allocParentName);
TypeInfo* fillTypeInfos(TypeInfo &sourceTypeInfo, std::vector<TypeInfo*> &typeInfos);
TypeInfo* fillExternalTypeInfos(TYPECONST Type* sourceType, GlobalValue *parent, std::vector<TypeInfo*> &typeInfos);
void printInterestingTypes(TYPECONST TypeInfo *aTypeInfo);
unsigned getMaxRecursiveSequenceLength(TYPECONST TypeInfo *aTypeInfo);
FunctionType* getFunctionType(TYPECONST FunctionType *baseType, std::vector<unsigned> selectedArgs);
bool isCompatibleMagicMemFuncType(TYPECONST FunctionType *type, TYPECONST FunctionType* magicType);
void indexCasts(Module &M, User *U, std::vector<TYPECONST Type*> &intCastTypes, std::vector<int> &intCastValues, std::map<TYPECONST Type*, std::set<TYPECONST Type*> > &bitcastMap);
void fillStackInstrumentedFunctions(std::vector<Function*> &stackIntrumentedFuncs, Function *deepestLLFunction);
void indexLocalTypeInfos(Module &M, Function *F, std::map<AllocaInst*, std::pair<TypeInfo*, std::string> > &localMap);
void addMagicStackDsentryFuncCalls(Module &M, Function *insertCallsInFunc, Function *localsFromFunc, Function *dsentryCreateFunc, Function *dsentryDestroyFunc, TYPECONST StructType *dsentryStructType, std::map<AllocaInst*, std::pair<TypeInfo*, std::string> > localTypeInfoMap, std::map<TypeInfo*, Constant*> &magicArrayTypePtrMap, TypeInfo *voidPtrTypeInfo, std::vector<TypeInfo*> &typeInfoList, std::vector<std::pair<std::string, std::string> > &namesList, std::vector<int> &flagsList);
bool isExtLibrary(GlobalValue *GV, DIDescriptor *DID);
bool isMagicGV(Module &M, GlobalVariable *GV);
bool isMagicFunction(Module &M, Function *F);
};
inline std::vector<GlobalVariable*> MagicPass::getGlobalVariables() const {
return globalVariables;
}
inline std::vector<int> MagicPass::getGlobalVariableSizes() const {
return globalVariableSizes;
}
inline std::vector<GlobalVariable*> MagicPass::getShadowGlobalVariables() const {
return shadowGlobalVariables;
}
inline std::vector<Function*> MagicPass::getFunctions() const {
return functions;
}
inline GlobalVariable* MagicPass::getMagicArray() const {
return magicArray;
}
inline GlobalVariable* MagicPass::getMagicTypeArray() const {
return magicTypeArray;
}
inline GlobalVariable* MagicPass::getMagicFunctionArray() const {
return magicFunctionArray;
}
inline GlobalVariable* MagicPass::getMagicDsindexArray() const {
return magicDsindexArray;
}
}
#endif

View file

@ -0,0 +1,11 @@
#ifndef _MAGIC_PASS_H
#define _MAGIC_PASS_H
#include <pass.h>
#include <magic_common.h>
#define MAGIC_FORCE_ALIGN 0
#define MAGIC_FORCE_INLINING 0
#endif /* _MAGIC_PASS_H */

View file

@ -0,0 +1,24 @@
#ifndef BACKPORTS_H
#define BACKPORTS_H
#include <pass.h>
using namespace llvm;
namespace llvm {
class Backports {
public:
//From DbgInfoPrinter.cpp (LLVM 2.9)
static Value *findDbgGlobalDeclare(GlobalVariable *V);
static Value *findDbgSubprogramDeclare(Function *V);
static const DbgDeclareInst *findDbgDeclare(const Value *V);
//From Local.cpp (LLVM 2.9)
static DbgDeclareInst *FindAllocaDbgDeclare(Value *V);
};
}
#endif

View file

@ -0,0 +1,117 @@
#ifndef BIT_FIELD_AGGREGATION_H
#define BIT_FIELD_AGGREGATION_H
#include <magic/support/EDIType.h>
#include <magic/support/TypeUtil.h>
using namespace llvm;
namespace llvm {
#define BitFieldAggregationErr(M) errs() << "BitFieldAggregation: " << M << "\n"
#define BFA_NAME_PREFIX "__BFA__"
class BitFieldAggregation {
public:
BitFieldAggregation(TYPECONST Type* type, std::vector<EDIType> EDITypes, unsigned typeIndex, unsigned EDITypeIndex, std::vector<DIDerivedType> members, unsigned counter);
BitFieldAggregation();
void init(TYPECONST Type* type, std::vector<EDIType> EDITypes, unsigned typeIndex, unsigned EDITypeIndex, std::vector<DIDerivedType> members, unsigned counter);
const std::string getDescription() const;
unsigned getTypeIndex() const;
unsigned getEDITypeIndex() const;
std::string getName() const;
std::vector<DIDerivedType> getMembers() const;
unsigned getSize() const;
TYPECONST Type *getType() const;
std::vector<EDIType> getEDITypes() const;
unsigned getRepresentativeEDITypeIndex() const;
void print(raw_ostream &OS) const;
static bool getBitFieldAggregations(TYPECONST Type *type, const EDIType *aEDIType, std::vector<BitFieldAggregation> &bfas, bool returnOnError=false);
static bool hasBitFields(TYPECONST Type *type, const EDIType *aEDIType);
static bool isBitField(TYPECONST Type *type, const EDIType *aEDIType, unsigned memberIdx);
private:
TYPECONST Type *type;
std::vector<EDIType> EDITypes;
unsigned typeIndex;
unsigned EDITypeIndex;
std::string name;
std::vector<DIDerivedType> members;
unsigned size;
static std::string bfaNamePrefix;
static BitFieldAggregation* getBitFieldAggregation(TYPECONST Type *type, const EDIType *aEDIType, bool returnOnError, unsigned typeIndex, unsigned EDITypeIndex, unsigned lastTypeIndex, unsigned lastEDITypeIndex, unsigned counter);
};
inline raw_ostream &operator<<(raw_ostream &OS, const BitFieldAggregation &bfa) {
bfa.print(OS);
return OS;
}
inline unsigned BitFieldAggregation::getTypeIndex() const {
return typeIndex;
}
inline unsigned BitFieldAggregation::getEDITypeIndex() const {
return EDITypeIndex;
}
inline std::string BitFieldAggregation::getName() const {
return name;
}
inline std::vector<DIDerivedType> BitFieldAggregation::getMembers() const {
return members;
}
inline unsigned BitFieldAggregation::getSize() const {
return size;
}
inline TYPECONST Type *BitFieldAggregation::getType() const {
return type;
}
inline std::vector<EDIType> BitFieldAggregation::getEDITypes() const {
return EDITypes;
}
inline unsigned BitFieldAggregation::getRepresentativeEDITypeIndex() const {
return EDITypeIndex;
}
inline void BitFieldAggregation::print(raw_ostream &OS) const {
OS << getDescription();
}
inline bool BitFieldAggregation::hasBitFields(TYPECONST Type *type, const EDIType *aEDIType) {
if(!aEDIType->isStructTy()) {
return false;
}
unsigned numContainedTypes = aEDIType->getNumContainedTypes();
for(unsigned i=0;i<numContainedTypes;i++) {
if (isBitField(type, aEDIType, i)) {
return true;
}
}
return false;
}
inline bool BitFieldAggregation::isBitField(TYPECONST Type *type, const EDIType *aEDIType, unsigned memberIdx) {
const DIDerivedType subDIType = aEDIType->getMember(memberIdx);
unsigned EDITypeBits = subDIType.getSizeInBits();
const DIType aDIType = PassUtil::getDITypeDerivedFrom(subDIType);
unsigned EDITypeOriginalBits = aDIType.getSizeInBits();
return (EDITypeBits>0 && EDITypeOriginalBits>0 && EDITypeBits != EDITypeOriginalBits);
}
}
#endif

View file

@ -0,0 +1,274 @@
#ifndef EDITYPE_H
#define EDITYPE_H
#include <pass.h>
using namespace llvm;
namespace llvm {
#define EDITypeLog(M) DEBUG(dbgs() << "EDIType: " << M << "\n")
#define EDITypeErr(M) errs() << "EDIType: " << M << "\n"
#define EDIType_assert(X) do { \
if(!(X)) { \
errs() << "Assertion failed, dumping object...\n"; \
errs() << *this; \
} \
assert(X); \
} while(0)
class EDIType {
public:
EDIType(const MDNode *N, bool norm=true, bool checkOpaqueTypes=true);
EDIType(bool norm=false, bool checkOpaqueTypes=false);
EDIType(const DIType aDIType, bool norm=true, bool checkOpaqueTypes=true);
bool operator == (const EDIType& aEDIType) const;
static const bool NORMALIZE = true;
static const bool DO_NOT_NORMALIZE = false;
static const bool CHECK_OPAQUE_TYPES = true;
static const bool DO_NOT_CHECK_OPAQUE_TYPES = false;
const std::string getDescription(int skipUnions=0, int skipStructs=0, int allowMultiNames=0) const;
const EDIType& getContainedType(unsigned i, bool norm=true) const;
unsigned getNumContainedTypes() const;
const DIDerivedType& getMember(unsigned i) const;
bool isUnionOrStructTy(bool isStruct=true, bool isUnion=true) const;
bool hasInnerPointers() const;
DIArray getTypeArray() const;
const EDIType* getTopStructType(unsigned index) const;
unsigned getNumElements() const;
unsigned getNumDimensions() const;
void setCurrentDimension(unsigned dimension);
unsigned getCurrentDimension() const;
const DIType *getDIType() const;
StringRef getName() const;
std::vector<StringRef> getNames() const;
StringRef getNamesString() const;
std::vector<unsigned> getEnumValues() const;
unsigned getTag()const;
EDIType getTypeDerivedFrom() const;
bool isType() const;
bool isBasicType() const;
bool isDerivedType() const;
bool isCompositeType() const;
bool isPrimitiveType() const;
bool isAggregateType() const;
bool isVoidTy() const;
bool isComplexFloatingPointTy() const;
bool isFloatingPointTy() const;
bool isCharTy() const;
bool isIntTy() const;
bool isBoolTy() const;
bool isIntegerTy() const;
bool isFunctionTy() const;
bool isArrayTy() const;
bool isEnumTy() const;
bool isVectorTy() const;
bool isUnionTy() const;
bool isStructTy() const;
bool isPointerTy() const;
bool isOpaqueTy() const;
void print(raw_ostream &OS) const;
void printDescription(raw_ostream &OS, int skipUnions=0, int skipStructs=0, int allowMultiNames=0) const;
bool equals(const EDIType *other) const;
static std::string lookupTypedefName(std::string &name);
static std::string lookupUnionMemberName(TYPECONST Type* type);
static const EDIType* getStructEDITypeByName(std::string &name);
static void setModule(Module *M);
static void writeTypeSymbolic(raw_string_ostream &OS, TYPECONST Type *type, const Module *M);
private:
DIType aDIType;
unsigned currentDimension;
bool checkOpaqueTypes;
StringRef myName;
std::vector<StringRef> myNames;
static StringRef voidName;
static Module *module;
static DebugInfoFinder DIFinder;
void init(bool norm, bool checkOpaqueTypes);
void normalize();
void normalizeTypedef();
};
inline raw_ostream &operator<<(raw_ostream &OS, const EDIType &aEDIType) {
aEDIType.print(OS);
return OS;
}
inline unsigned EDIType::getNumElements() const {
if(!isArrayTy() && !isVectorTy()) {
return 1;
}
const DIArray aDIArray = getTypeArray();
const DIDescriptor aDIDescriptor = aDIArray.getElement(currentDimension);
assert(aDIDescriptor.getTag() == dwarf::DW_TAG_subrange_type);
return PassUtil::getDbgSubrangeNumElements((DISubrange)aDIDescriptor);
}
inline unsigned EDIType::getNumDimensions() const {
return isArrayTy() || isVectorTy() ? getTypeArray().getNumElements() : 1;
}
inline void EDIType::setCurrentDimension(unsigned dimension) {
assert(dimension < getNumDimensions());
this->currentDimension = dimension;
}
inline unsigned EDIType::getCurrentDimension() const {
return currentDimension;
}
inline const DIType *EDIType::getDIType() const {
return &aDIType;
}
inline StringRef EDIType::getName() const {
return myName;
}
inline std::vector<StringRef> EDIType::getNames() const {
return myNames;
}
inline StringRef EDIType::getNamesString() const {
std::string string;
raw_string_ostream ostream(string);
for(unsigned i=0;i<myNames.size();i++) {
if(i>0) ostream << "|";
ostream << myNames[i];
}
ostream.flush();
return string;
}
inline std::vector<unsigned> EDIType::getEnumValues() const {
assert(isEnumTy());
std::vector<unsigned> enumValues;
DIArray aDIArray = getTypeArray();
unsigned numValues = aDIArray.getNumElements();
for(unsigned i=0;i<numValues;i++) {
DIDescriptor aDIDescriptor = aDIArray.getElement(i);
assert(aDIDescriptor.getTag() == dwarf::DW_TAG_enumerator);
const unsigned value = (unsigned) ((DIEnumerator)aDIDescriptor).getEnumValue();
enumValues.push_back(value);
}
return enumValues;
}
inline unsigned EDIType::getTag()const {
return aDIType.getTag();
}
inline EDIType EDIType::getTypeDerivedFrom() const {
EDIType_assert(isDerivedType() || isCompositeType());
EDIType subType(PassUtil::getDITypeDerivedFrom((const DIDerivedType)aDIType));
return subType;
}
inline bool EDIType::isType() const {
return aDIType.isType() || isVoidTy();
}
inline bool EDIType::isBasicType() const {
return aDIType.isBasicType();
}
inline bool EDIType::isDerivedType() const {
return aDIType.isDerivedType() && !aDIType.isCompositeType();
}
inline bool EDIType::isCompositeType() const {
return aDIType.isCompositeType();
}
inline bool EDIType::isPrimitiveType() const {
return (isVoidTy() || isFloatingPointTy());
}
inline bool EDIType::isAggregateType() const {
return isUnionOrStructTy() || isArrayTy() || isVectorTy();
}
inline bool EDIType::isVoidTy() const {
return !aDIType.isValid(); //xxx we should keep track of this to spot all the i8* = void*
}
inline bool EDIType::isComplexFloatingPointTy() const {
if(!isBasicType()) return false;
return (((DIBasicType)aDIType).getEncoding() == dwarf::DW_ATE_complex_float);
}
inline bool EDIType::isFloatingPointTy() const {
if(!isBasicType()) return false;
return EDIType::isComplexFloatingPointTy() || (((DIBasicType)aDIType).getEncoding() == dwarf::DW_ATE_float);
}
inline bool EDIType::isCharTy() const {
if(!isBasicType()) return false;
return (((DIBasicType)aDIType).getEncoding() == dwarf::DW_ATE_signed_char ||
((DIBasicType)aDIType).getEncoding() == dwarf::DW_ATE_unsigned_char);
}
inline bool EDIType::isIntTy() const {
if(!isBasicType()) return false;
return (((DIBasicType)aDIType).getEncoding() == dwarf::DW_ATE_signed ||
((DIBasicType)aDIType).getEncoding() == dwarf::DW_ATE_unsigned);
}
inline bool EDIType::isBoolTy() const {
if(!isBasicType()) return false;
return (((DIBasicType)aDIType).getEncoding() == dwarf::DW_ATE_boolean);
}
inline bool EDIType::isIntegerTy() const {
return (isCharTy() || isIntTy() || isBoolTy());
}
inline bool EDIType::isFunctionTy() const {
return (getTag() == dwarf::DW_TAG_subroutine_type && !isOpaqueTy());
}
inline bool EDIType::isArrayTy() const {
return (getTag() == dwarf::DW_TAG_array_type && !isOpaqueTy());
}
inline bool EDIType::isEnumTy() const {
return (getTag() == dwarf::DW_TAG_enumeration_type && !isOpaqueTy());
}
inline bool EDIType::isVectorTy() const {
return (PassUtil::isDbgVectorTy(aDIType) && !isOpaqueTy());
}
inline bool EDIType::isUnionTy() const {
return isUnionOrStructTy(false, true);
}
inline bool EDIType::isStructTy() const {
return isUnionOrStructTy(true, false);
}
inline bool EDIType::isPointerTy() const {
return (getTag() == dwarf::DW_TAG_pointer_type);
}
inline bool EDIType::isOpaqueTy() const {
return (isCompositeType() && getTypeArray().getNumElements() == 0);
}
inline void EDIType::writeTypeSymbolic(raw_string_ostream &OS, TYPECONST Type *type, const Module *M) {
return PassUtil::writeTypeSymbolic(OS, type, M);
}
}
#endif

View file

@ -0,0 +1,230 @@
#ifndef MAGIC_DEBUG_FUNCTION_H_
#define MAGIC_DEBUG_FUNCTION_H_
#include <pass.h>
#define NUM_DEBUG_ARGS 1
using namespace llvm;
namespace llvm {
class MagicDebugFunction {
public:
MagicDebugFunction(Function *function);
Function* getFunction() const;
void addHooks(std::pair<Function*, Function*> hooks, unsigned flags, std::vector<unsigned> argsMapping, std::vector<Value*> trailingArgs);
void fixCalls(Module &M, const std::string &baseDir="");
void print(raw_ostream &OS) const;
void printDescription(raw_ostream &OS) const;
const std::string getDescription() const;
static bool inlineHookCalls(Function* function, std::pair<Function*, Function*> hooks, unsigned flags, std::vector<unsigned> argsMapping,
std::vector<Value*> trailingArgs);
Function* getDebugFunction(Module &M);
private:
Function *function;
std::pair<Function*, Function*> hooks;
unsigned flags;
std::vector<unsigned> argsMapping;
std::vector<Value*> trailingArgs;
Function* getDebugClone(Function* function, const Twine wrapperName, TYPECONST Type* debugArgType);
};
inline raw_ostream &operator<<(raw_ostream &OS, const MagicDebugFunction &aMagicDebugFunction) {
aMagicDebugFunction.print(OS);
return OS;
}
inline void MagicDebugFunction::print(raw_ostream &OS) const {
OS << getDescription();
}
inline void MagicDebugFunction::printDescription(raw_ostream &OS) const {
OS << "[ function = ";
OS << function->getName() << "(" << TypeUtil::getDescription(function->getFunctionType()) << ") ]";
}
inline const std::string MagicDebugFunction::getDescription() const {
std::string string;
raw_string_ostream ostream(string);
printDescription(ostream);
ostream.flush();
return string;
}
inline Function* MagicDebugFunction::getDebugClone(Function* function, const Twine wrapperName, TYPECONST Type* debugArgType) {
Function* wrapper;
std::vector<TYPECONST Type*> ArgTypes;
VALUE_TO_VALUE_MAP_TY VMap;
// Build arg types for wrapper
ArgTypes.push_back(debugArgType);
Function::const_arg_iterator E = function->arg_end();
for (Function::const_arg_iterator I = function->arg_begin(); I != E; ++I)
ArgTypes.push_back(I->getType());
// Create a new function type...
FunctionType *FTy = FunctionType::get(function->getFunctionType()->getReturnType(), ArgTypes, function->getFunctionType()->isVarArg());
// Create the wrapper
wrapper = Function::Create(FTy, function->getLinkage(), wrapperName, function->getParent());
// Loop over the arguments, copying the names of the mapped arguments over...
Function::arg_iterator DestI = wrapper->arg_begin();
Value *magicTypeValue = DestI;
magicTypeValue->setName("cs_info");
DestI++;
for (Function::const_arg_iterator I = function->arg_begin(), E = function->arg_end(); I != E; ++I) {
DestI->setName(I->getName());
VMap[I] = DestI++;
}
SmallVector<ReturnInst*, 8> Returns; // Ignore returns cloned...
CloneFunctionInto(wrapper, function, VMap, false, Returns, "", NULL);
return wrapper;
}
inline MagicDebugFunction::MagicDebugFunction(Function *function) {
this->function = function;
}
inline void MagicDebugFunction::addHooks(std::pair<Function*, Function*> aHooks, unsigned aFlags, std::vector<unsigned> aArgsMapping,
std::vector<Value*> aTrailingArgs) {
hooks = aHooks;
flags = aFlags;
trailingArgs = aTrailingArgs;
argsMapping = aArgsMapping;
}
inline Function* MagicDebugFunction::getFunction() const {
return function;
}
inline Function* MagicDebugFunction::getDebugFunction(Module &M) {
PointerType* PointerTy = PointerType::get(IntegerType::get((&M)->getContext(), 8), 0);
Function* debugFunction = MagicDebugFunction::getDebugClone(function, "debug_magic_" + function->getName(), PointerTy);
bool ret = MagicDebugFunction::inlineHookCalls(debugFunction, hooks, flags, argsMapping, trailingArgs);
if (ret) {
return debugFunction;
} else {
return NULL;
}
}
inline void MagicDebugFunction::fixCalls(Module &M, const std::string &baseDir) {
PointerType* PointerTy = PointerType::get(IntegerType::get((&M)->getContext(), 8), 0);
Function* debugFunction = MagicDebugFunction::getDebugClone(function, "debug_magic_" + function->getName(), PointerTy);
bool ret = MagicDebugFunction::inlineHookCalls(debugFunction, hooks, flags, argsMapping, trailingArgs);
assert(ret && "Unable to inline the calls to the hook functions.");
std::vector<User*> Users(function->use_begin(), function->use_end());
std::vector<Value*> EqPointers;
while (!Users.empty()) {
User *U = Users.back();
Users.pop_back();
if (Instruction * I = dyn_cast<Instruction>(U)) {
CallSite CS = MagicUtil::getCallSiteFromInstruction(I);
if (CS.getInstruction()
&& (MagicUtil::getCalledFunctionFromCS(CS) == function
|| std::find(EqPointers.begin(), EqPointers.end(), CS.getCalledValue()) != EqPointers.end())) {
Function *parentFunction = CS.getInstruction()->getParent()->getParent();
StringRef callParentName = MagicUtil::getFunctionSourceName(M, parentFunction, NULL, baseDir);
//extend function name with debug information
if (MDNode *N = I->getMetadata("dbg")) {
DILocation Loc(N);
std::string string;
raw_string_ostream ostream(string);
ostream << callParentName << MAGIC_ALLOC_NAME_SEP << Loc.getFilename() << MAGIC_ALLOC_NAME_SEP << Loc.getLineNumber();
ostream.flush();
callParentName = string;
}
Value* callParentNameValue = MagicUtil::getArrayPtr(M, MagicUtil::getStringRef(M, callParentName));
std::vector<Value*> debugArgs;
debugArgs.push_back(callParentNameValue);
debugArgs.insert(debugArgs.end(), CS.arg_begin(), CS.arg_end());
CallInst* newInst = MagicUtil::createCallInstruction(debugFunction, debugArgs, "", I);
newInst->takeName(I);
MagicUtil::replaceCallInst(I, newInst, 1);
}
} else if (GlobalValue * GV = dyn_cast<GlobalValue>(U)) {
Users.insert(Users.end(), GV->use_begin(), GV->use_end());
EqPointers.push_back(GV);
} else if (ConstantExpr * CE = dyn_cast<ConstantExpr>(U)) {
if (CE->isCast()) {
Users.insert(Users.end(), CE->use_begin(), CE->use_end());
EqPointers.push_back(CE);
}
}
}
}
}
// inlines calls to the pre and post hooks and returns true if the inlining succeeded, false otherwise
inline bool MagicDebugFunction::inlineHookCalls(Function* function, std::pair<Function*, Function*> hooks, unsigned flags,
std::vector<unsigned> argsMapping, std::vector<Value*> trailingArgs) {
std::vector<Value*> emptyArgs;
std::vector<unsigned> emptyMapping;
std::vector<unsigned> debugEmptyMapping;
std::vector<unsigned> debugArgsMapping;
// debug version of the function, argument mapping has to be adjusted
if (flags & MAGIC_HOOK_DEBUG_MASK) {
// re-adjusted the index of the arguments (do not re-adjust return value)
for (unsigned i = 0; i < argsMapping.size(); i++) {
if (argsMapping[i] > 0) {
argsMapping[i] += NUM_DEBUG_ARGS;
}
}
// first come the debug argument
for (unsigned i = 1; i <= NUM_DEBUG_ARGS; i++) {
debugEmptyMapping.push_back(i);
debugArgsMapping.push_back(i);
}
debugArgsMapping.insert(debugArgsMapping.end(), argsMapping.begin(), argsMapping.end());
}
if (hooks.first != NULL) {
// inline first hook call at the beginning of the function, according to the flag
switch (flags & MAGIC_PRE_HOOK_FLAGS_MASK) {
case MAGIC_PRE_HOOK_SIMPLE_CALL:
MagicUtil::inlinePreHookForwardingCall(function, hooks.first, (flags & MAGIC_PRE_HOOK_DEBUG) ? debugEmptyMapping : emptyMapping,
emptyArgs);
break;
case MAGIC_PRE_HOOK_FORWARDING_CALL:
MagicUtil::inlinePreHookForwardingCall(function, hooks.first, (flags & MAGIC_PRE_HOOK_DEBUG) ? debugArgsMapping : argsMapping,
trailingArgs);
break;
default:
// unknown flag
return false;
}
}
if (hooks.second != NULL) {
// inline the second wrapper call at the end of the function, according to the flag
switch (flags & MAGIC_POST_HOOK_FLAGS_MASK) {
case MAGIC_POST_HOOK_SIMPLE_CALL:
MagicUtil::inlinePostHookForwardingCall(function, hooks.second, (flags & MAGIC_POST_HOOK_DEBUG) ? debugEmptyMapping : emptyMapping,
emptyArgs);
break;
case MAGIC_POST_HOOK_FORWARDING_CALL:
MagicUtil::inlinePostHookForwardingCall(function, hooks.second, (flags & MAGIC_POST_HOOK_DEBUG) ? debugArgsMapping : argsMapping,
trailingArgs);
break;
default:
// unknown flag
return false;
}
}
return true;
}
#endif /* MAGIC_DEBUG_FUNCTION_H_ */

View file

@ -0,0 +1,547 @@
#ifndef MAGIC_MEM_FUNCTION_H
#define MAGIC_MEM_FUNCTION_H
#include <pass.h>
#include <magic/support/TypeInfo.h>
#define NUM_MAGIC_ARGS 3
using namespace llvm;
namespace llvm {
class MagicMemFunction {
public:
MagicMemFunction(Module &M, Function *function, Function *wrapper, bool isDealloc, int allocFlags);
Function* getFunction() const;
Function* getWrapper() const;
bool isDeallocFunction() const;
int getAllocFlags() const;
Instruction* getInstruction() const;
Function* getInstructionParent() const;
TypeInfo* getInstructionTypeInfo() const;
Value* getInstructionTypeValue() const;
bool hasInstructionType() const;
std::vector<MagicMemFunction> getInstructionDeps() const;
void setInstruction(Instruction* I);
void setInstructionTypeInfo(TypeInfo* aTypeInfo, std::string &allocName, std::string &allocParentName);
void setInstructionTypeValue(Value* typeValue, Value* allocNameValue, Value* allocParentNameValue);
void addInstructionDep(MagicMemFunction &function);
void replaceInstruction(std::map<TypeInfo*, Constant*> &magicArrayTypePtrMap, TypeInfo *voidPtrTypeInfo);
void print(raw_ostream &OS) const;
void printDescription(raw_ostream &OS) const;
const std::string getDescription() const;
static int getMemFunctionPointerParam(Function* function, std::set<Function*> &brkFunctions, TypeInfo *voidPtrTypeInfo);
static Function* getCustomWrapper(Function* function, Function* stdFunction, Function* stdWrapper, std::vector<unsigned> argMapping,
bool isDealloc);
static bool isCustomWrapper(Function *function);
private:
Module *module;
Function *function;
Function *wrapper;
bool isDealloc;
int allocFlags;
Instruction *instruction;
TypeInfo* aTypeInfo;
std::string allocName;
std::string allocParentName;
Value* typeValue;
Value* allocNameValue;
Value* allocParentNameValue;
std::vector<MagicMemFunction> instructionDeps;
void buildWrapper(std::map<TypeInfo*, Constant*> &magicArrayTypePtrMap, TypeInfo *voidPtrTypeInfo);
static Function *lastAllocWrapper;
static std::map<std::string, Function*> allocWrapperCache;
static std::set<Function*> customWrapperSet;
};
inline raw_ostream &operator<<(raw_ostream &OS, const MagicMemFunction &aMagicMemFunction) {
aMagicMemFunction.print(OS);
return OS;
}
inline void MagicMemFunction::print(raw_ostream &OS) const {
OS << getDescription();
}
inline void MagicMemFunction::printDescription(raw_ostream &OS) const {
OS << "[ function = ";
OS << function->getName() << "(" << TypeUtil::getDescription(function->getFunctionType()) << ")";
OS << ", wrapper = ";
if (wrapper) {
OS << wrapper->getName() << "(" << TypeUtil::getDescription(wrapper->getFunctionType()) << ")";
} else
OS << "NULL";
OS << ", isDeallocFunction = ";
OS << isDealloc;
OS << ", instruction = ";
if (instruction)
instruction->print(OS);
else
OS << "NULL";
OS << ", typeInfo = ";
if (aTypeInfo)
OS << aTypeInfo->getDescription();
else
OS << "NULL";
OS << ", allocName = ";
OS << allocName;
OS << ", allocParentName = ";
OS << allocParentName;
OS << ", typeValue = ";
if (typeValue)
typeValue->print(OS);
else
OS << "NULL";
OS << ", allocNameValue = ";
if (allocNameValue)
allocNameValue->print(OS);
else
OS << "NULL";
OS << ", allocParentNameValue = ";
if (allocParentNameValue)
allocParentNameValue->print(OS);
else
OS << "NULL";
OS << ", instructionDeps = {";
for (unsigned i = 0; i < instructionDeps.size(); i++) {
if (i > 0) {
OS << ", ";
}
instructionDeps[i].print(OS);
}
OS << "}]";
}
inline const std::string MagicMemFunction::getDescription() const {
std::string string;
raw_string_ostream ostream(string);
printDescription(ostream);
ostream.flush();
return string;
}
inline MagicMemFunction::MagicMemFunction(Module &M, Function *function, Function *wrapper, bool isDealloc, int allocFlags) {
this->module = &M;
this->function = function;
this->wrapper = wrapper;
this->isDealloc = isDealloc;
this->allocFlags = allocFlags;
this->instruction = NULL;
this->aTypeInfo = NULL;
this->allocName = "";
this->allocParentName = "";
this->typeValue = NULL;
this->allocNameValue = NULL;
this->allocParentNameValue = NULL;
assert(function);
if (wrapper && !isDealloc) {
lastAllocWrapper = wrapper;
}
if (isDealloc) {
assert(!allocFlags);
}
}
inline Function* MagicMemFunction::getFunction() const {
return function;
}
inline Function* MagicMemFunction::getWrapper() const {
return wrapper;
}
inline bool MagicMemFunction::isDeallocFunction() const {
return isDealloc;
}
inline int MagicMemFunction::getAllocFlags() const {
return allocFlags;
}
inline Instruction* MagicMemFunction::getInstruction() const {
return instruction;
}
inline Function* MagicMemFunction::getInstructionParent() const {
if (!instruction) {
return NULL;
}
return instruction->getParent()->getParent();
}
inline TypeInfo* MagicMemFunction::getInstructionTypeInfo() const {
return aTypeInfo;
}
inline Value* MagicMemFunction::getInstructionTypeValue() const {
return typeValue;
}
inline bool MagicMemFunction::hasInstructionType() const {
return aTypeInfo || typeValue;
}
inline std::vector<MagicMemFunction> MagicMemFunction::getInstructionDeps() const {
return instructionDeps;
}
inline void MagicMemFunction::setInstruction(Instruction* I) {
this->instruction = I;
assert(isa<CallInst>(instruction) || isa<InvokeInst>(instruction));
}
inline void MagicMemFunction::setInstructionTypeInfo(TypeInfo* aTypeInfo, std::string &allocName, std::string &allocParentName) {
this->aTypeInfo = aTypeInfo;
this->allocName = allocName;
this->allocParentName = allocParentName;
}
inline void MagicMemFunction::setInstructionTypeValue(Value* typeValue, Value* allocNameValue, Value* allocParentNameValue) {
this->typeValue = typeValue;
this->allocNameValue = allocNameValue;
this->allocParentNameValue = allocParentNameValue;
}
inline void MagicMemFunction::addInstructionDep(MagicMemFunction &function) {
assert(wrapper == NULL && "Dependencies are resolved at wrapper building time, so wrapper has to be NULL!");
instructionDeps.push_back(function);
allocFlags |= function.getAllocFlags();
}
inline void MagicMemFunction::replaceInstruction(std::map<TypeInfo*, Constant*> &magicArrayTypePtrMap, TypeInfo *voidPtrTypeInfo) {
Instruction *I = getInstruction();
assert(I);
CallSite CS = MagicUtil::getCallSiteFromInstruction(I);
std::vector<Value*> magicMemArgs;
unsigned numMagicArgs = 0;
//if we do not have a wrapper, build one
if (!wrapper) {
buildWrapper(magicArrayTypePtrMap, voidPtrTypeInfo);
}
//inject magic args
if (!isDeallocFunction()) {
std::map<TypeInfo*, Constant*>::iterator it;
if (!typeValue) {
assert(aTypeInfo);
if (aTypeInfo == voidPtrTypeInfo->getContainedType(0)) {
typeValue = ConstantPointerNull::get((TYPECONST PointerType*) (wrapper->arg_begin()->getType()));
} else {
it = magicArrayTypePtrMap.find(aTypeInfo);
assert(it != magicArrayTypePtrMap.end());
typeValue = it->second;
}
assert(allocName.compare(""));
assert(allocParentName.compare(""));
allocNameValue = MagicUtil::getArrayPtr(*module, MagicUtil::getStringRef(*module, allocName));
allocParentNameValue = MagicUtil::getArrayPtr(*module, MagicUtil::getStringRef(*module, allocParentName));
}
magicMemArgs.push_back(typeValue);
magicMemArgs.push_back(allocNameValue);
magicMemArgs.push_back(allocParentNameValue);
numMagicArgs = NUM_MAGIC_ARGS;
}
//push other args
unsigned arg_size = MagicUtil::getCalledFunctionFromCS(CS)->getFunctionType()->getNumContainedTypes() - 1;
for (unsigned i = 0; i < arg_size; i++) {
Value *arg = CS.getArgument(i);
TYPECONST Type* wArgType = wrapper->getFunctionType()->getContainedType(i + numMagicArgs + 1);
if (arg->getType() != wArgType) {
if (arg->getType()->isPointerTy()) {
assert(wArgType->isPointerTy());
arg = CastInst::CreatePointerCast(arg, wArgType, "WrapperCast", I);
}
else {
assert(arg->getType()->isIntegerTy());
assert(wArgType->isIntegerTy());
arg = CastInst::CreateIntegerCast(arg, wArgType, false, "WrapperCast", I);
}
}
magicMemArgs.push_back(arg);
}
//replace function with wrapper
CallInst* newInst = MagicUtil::createCallInstruction(wrapper, magicMemArgs, "", I);
newInst->takeName(I);
MagicUtil::replaceCallInst(I, newInst, NUM_MAGIC_ARGS);
}
inline int MagicMemFunction::getMemFunctionPointerParam(Function* function, std::set<Function*> &brkFunctions, TypeInfo *voidPtrTypeInfo) {
TYPECONST Type *type = function->getReturnType();
if (type == voidPtrTypeInfo->getType()) {
return 0;
} else if (brkFunctions.find(function) != brkFunctions.end()) {
return 1;
} else {
unsigned i;
for (i = 1; i < function->getFunctionType()->getNumContainedTypes(); i++) {
type = function->getFunctionType()->getContainedType(i);
if (type->isPointerTy() && type->getContainedType(0) == voidPtrTypeInfo->getType()) {
return i;
}
}
}
return -1;
}
inline void MagicMemFunction::buildWrapper(std::map<TypeInfo*, Constant*> &magicArrayTypePtrMap, TypeInfo *voidPtrTypeInfo) {
assert(!isDeallocFunction());
assert(lastAllocWrapper);
std::vector<TYPECONST Type*> ArgTypes;
VALUE_TO_VALUE_MAP_TY VMap;
std::map<std::string, Function*>::iterator allocWrapperCacheIt;
// See if the wrapper is in cache, otherwise create a new wrapper using function cloning
allocWrapperCacheIt = allocWrapperCache.find(function->getName());
if (allocWrapperCacheIt != allocWrapperCache.end()) {
wrapper = allocWrapperCacheIt->second;
return;
}
// Build arg types for wrapper
Function::const_arg_iterator E = lastAllocWrapper->arg_begin();
for (unsigned i = 0; i < NUM_MAGIC_ARGS; i++)
E++;
for (Function::const_arg_iterator I = lastAllocWrapper->arg_begin(); I != E; ++I)
ArgTypes.push_back(I->getType());
E = function->arg_end();
for (Function::const_arg_iterator I = function->arg_begin(); I != E; ++I)
ArgTypes.push_back(I->getType());
// Create a new function type...
FunctionType *FTy = FunctionType::get(function->getFunctionType()->getReturnType(), ArgTypes, function->getFunctionType()->isVarArg());
// Create the wrapper
wrapper = Function::Create(FTy, function->getLinkage(), "magic_" + function->getName(), function->getParent());
// Loop over the arguments, copying the names of the mapped arguments over...
Function::arg_iterator DestI = wrapper->arg_begin();
Value *magicTypeValue = DestI;
magicTypeValue->setName("magic_type");
DestI++;
Value *magicNameValue = DestI;
magicNameValue->setName("magic_name");
DestI++;
Value *magicParentNameValue = DestI;
magicParentNameValue->setName("magic_parent_name");
DestI++;
for (Function::const_arg_iterator I = function->arg_begin(), E = function->arg_end(); I != E; ++I) {
DestI->setName(I->getName());
VMap[I] = DestI++;
}
SmallVector<ReturnInst*, 8> Returns; // Ignore returns cloned...
CloneFunctionInto(wrapper, function, VMap, false, Returns, "", NULL);
allocWrapperCache.insert(std::pair<std::string, Function*>(function->getName(), wrapper));
// Create a mapping between the function instruction pointers and the wrapper instruction pointers
std::vector<Instruction *> wrapperInstructionDeps;
for (unsigned i = 0; i < instructionDeps.size(); i++) {
Instruction *instruction = instructionDeps[i].getInstruction();
Instruction *wrapperInstruction = NULL;
unsigned instructionOffset = 0;
for (inst_iterator I = inst_begin(function), E = inst_end(function); I != E; ++I, instructionOffset++) {
if (instruction == &(*I)) {
break;
}
}
assert(instructionOffset > 0);
for (inst_iterator I = inst_begin(wrapper), E = inst_end(wrapper); I != E; ++I, instructionOffset--) {
if (instructionOffset == 0) {
wrapperInstruction = &(*I);
break;
}
}
assert(wrapperInstruction);
wrapperInstructionDeps.push_back(wrapperInstruction);
}
// Forward magic type argument to any dependent instruction and replace it
for (unsigned i = 0; i < wrapperInstructionDeps.size(); i++) {
instructionDeps[i].setInstruction(wrapperInstructionDeps[i]);
instructionDeps[i].setInstructionTypeValue(magicTypeValue, magicNameValue, magicParentNameValue);
instructionDeps[i].replaceInstruction(magicArrayTypePtrMap, voidPtrTypeInfo);
}
}
inline Function* MagicMemFunction::getCustomWrapper(Function* function, Function* stdFunction, Function* stdWrapper, std::vector<unsigned> argMapping,
bool isDealloc) {
Function* wrapper;
std::vector<TYPECONST Type*> ArgTypes;
VALUE_TO_VALUE_MAP_TY VMap;
// Build arg types for wrapper
// add magic arguments
if (!isDealloc) {
Function::const_arg_iterator E = stdWrapper->arg_begin();
for (unsigned i = 0; i < NUM_MAGIC_ARGS; i++)
E++;
for (Function::const_arg_iterator I = stdWrapper->arg_begin(); I != E; ++I) {
ArgTypes.push_back(I->getType());
}
}
// add original function arguments
for (Function::const_arg_iterator I = function->arg_begin(), E = function->arg_end(); I != E; ++I) {
ArgTypes.push_back(I->getType());
}
// Create a new function type...
FunctionType *FTy = FunctionType::get(stdWrapper->getFunctionType()->getReturnType(), ArgTypes, function->getFunctionType()->isVarArg());
// Create the wrapper
wrapper = Function::Create(FTy, function->getLinkage(), "magic_" + function->getName(), function->getParent());
// Loop over the arguments, copying the names of the mapped arguments over...
Function::arg_iterator DestI = wrapper->arg_begin();
std::vector<Value*> wrapperArgs;
if (!isDealloc) {
std::string magicArgs[] = { "magic_type", "magic_name", "magic_parent_name" };
for (unsigned i = 0; i < NUM_MAGIC_ARGS; i++) {
DestI->setName(magicArgs[i]);
wrapperArgs.push_back(DestI);
DestI++;
}
}
for (Function::const_arg_iterator I = function->arg_begin(), E = function->arg_end(); I != E; ++I) {
DestI->setName(I->getName());
wrapperArgs.push_back(DestI);
DestI++;
}
// map the arguments of the standard wrapper to the arguments of the new custom wrapper
if ((!isDealloc) || argMapping.size()) {
Function::const_arg_iterator W = stdWrapper->arg_begin();
if (!isDealloc) {
// magic arguments are in the same position
for (unsigned i = 0; i < NUM_MAGIC_ARGS; i++) {
VMap[W] = wrapperArgs[i];
W++;
}
}
// map the selected arguments of the custom wrapper using the mapping provided as input
unsigned argOffset = isDealloc ? 0 : NUM_MAGIC_ARGS;
for (unsigned i = 0; i < argMapping.size(); i++) {
VMap[W] = wrapperArgs[argOffset + argMapping[i] - 1];
W++;
}
}
SmallVector<ReturnInst*, 8> Returns; // Ignore returns cloned...
CloneFunctionInto(wrapper, stdWrapper, VMap, false, Returns, "", NULL);
// check whether some of the arguments of the custom wrapper need to be casted
// in order to match the basic wrapper implementation
Instruction *FirstInst = MagicUtil::getFirstNonAllocaInst(wrapper);
Function::const_arg_iterator W = stdWrapper->arg_begin();
unsigned argOffset = 0;
if (!isDealloc) {
argOffset = NUM_MAGIC_ARGS;
// skip the magic arguments, they are always the same
for (unsigned i = 0; i < NUM_MAGIC_ARGS; i++) {
W++;
}
}
for (unsigned i = 0; i < argMapping.size(); i++) {
TYPECONST Type* StdParamType = W->getType();
Value* ParamValue = wrapperArgs[argOffset + argMapping[i] - 1];
TYPECONST Type* ParamType = ParamValue->getType();
if (!MagicUtil::isCompatibleType(ParamType, StdParamType)) {
assert(CastInst::isCastable(ParamType, StdParamType) && "The type of the parameter of the custom wrapper "
"cannot be casted to the type of the basic wrapper to which it is corresponding.");
Instruction::CastOps CastOpCode = CastInst::getCastOpcode(ParamValue, false, StdParamType, false);
Instruction *ParamCastInst = CastInst::Create(CastOpCode, ParamValue, StdParamType, "", FirstInst);
for (Value::use_iterator it = ParamValue->use_begin(); it != ParamValue->use_end(); it++) {
if (Constant * C = dyn_cast<Constant>(*it)) {
if (!isa<GlobalValue>(C)) {
C->replaceUsesOfWith(ParamValue, ParamCastInst);
continue;
}
}
Instruction *I = dyn_cast<Instruction>(*it);
if (I && (I != ParamCastInst)) {
// replace all uses, except for the calls to the wrapped function
CallInst *CI = dyn_cast<CallInst>(I);
if (CI && (CI->getCalledFunction() == function)) {
continue;
}
I->replaceUsesOfWith(ParamValue, ParamCastInst);
}
}
}
W++;
}
// replace the call(s) to the standard function with calls to our function
for (Function::iterator BI = wrapper->getBasicBlockList().begin(), BE = wrapper->getBasicBlockList().end(); BI != BE; ++BI) {
unsigned pos = 0;
unsigned bbSize = BI->getInstList().size();
while (pos < bbSize) {
BasicBlock::iterator it = BI->getInstList().begin();
for (unsigned i = 0; i < pos; i++) {
it++;
}
Instruction *inst = &(*it);
// find the calls to the standard function
CallInst *callInst = dyn_cast<CallInst>(inst);
if (callInst && callInst->getCalledFunction() && (callInst->getCalledFunction()->getFunctionType() == stdFunction->getFunctionType())
&& (!callInst->getCalledFunction()->getName().compare(stdFunction->getName()))) {
CallSite CS = MagicUtil::getCallSiteFromInstruction(callInst);
unsigned numStdParams = stdFunction->getFunctionType()->getNumParams();
unsigned numParams = function->getFunctionType()->getNumParams();
// construct the parameter array
std::vector<Value*> callArgs(numParams, NULL);
// first add the arguments that are common to the custom and standard function
// add casts where necessary
for (unsigned i = 0; i < numStdParams; i++) {
Value *argValue = CS.getArgument(i);
TYPECONST Type* paramType = function->getFunctionType()->getParamType(i);
TYPECONST Type* argType = argValue->getType();
if (paramType != argType) {
assert(CastInst::isCastable(argType, paramType) && "The value of the argument cannot be "
"casted to the parameter type required by the function to be called.");
Instruction::CastOps opcode = CastInst::getCastOpcode(argValue, false, paramType, false);
argValue = CastInst::Create(opcode, argValue, paramType, "", callInst);
}
callArgs[argMapping[i] - 1] = argValue;
}
// the other arguments are just forwarded from the wrapper's argument list
// skip the magic arguments of the wrapper from the beginning of the argument list
unsigned argOffset = isDealloc ? 0 : NUM_MAGIC_ARGS;
for (unsigned i = argOffset; i < wrapper->getFunctionType()->getNumParams(); i++) {
if (callArgs[i - argOffset] == NULL) {
Value* arg = wrapperArgs[i];
callArgs[i - argOffset] = arg;
}
}
CallInst* newCallInst = MagicUtil::createCallInstruction(function, callArgs, "", callInst);
newCallInst->takeName(callInst);
MagicUtil::replaceCallInst(callInst, newCallInst, argOffset);
}
pos++;
}
}
customWrapperSet.insert(wrapper);
return wrapper;
}
inline bool MagicMemFunction::isCustomWrapper(Function *function)
{
return customWrapperSet.find(function) != customWrapperSet.end();
}
}
#endif

View file

@ -0,0 +1,130 @@
#ifndef MAGIC_MMAP_CTL_FUNCTION_H
#define MAGIC_MMAP_CTL_FUNCTION_H
#include <pass.h>
#include <magic/support/TypeInfo.h>
using namespace llvm;
namespace llvm {
class MagicMmapCtlFunction {
public:
MagicMmapCtlFunction(Function *function, PointerType *voidPointerType, std::string &ptrArgName, std::string &lenArgName);
Function* getFunction() const;
void fixCalls(Module &M, Function *magicGetPageSizeFunc) const;
void print(raw_ostream &OS) const;
void printDescription(raw_ostream &OS) const;
const std::string getDescription() const;
private:
Function *function;
int ptrArg;
int lenArg;
};
inline raw_ostream &operator<<(raw_ostream &OS, const MagicMmapCtlFunction &aMagicMmapCtlFunction) {
aMagicMmapCtlFunction.print(OS);
return OS;
}
inline void MagicMmapCtlFunction::print(raw_ostream &OS) const {
OS << getDescription();
}
inline void MagicMmapCtlFunction::printDescription(raw_ostream &OS) const {
OS << "[ function = "; OS << function->getName() << "(" << TypeUtil::getDescription(function->getFunctionType()) << ")"
<< ", ptr arg = "; OS << ptrArg
<< ", len arg = "; OS << lenArg
<< "]";
}
inline const std::string MagicMmapCtlFunction::getDescription() const {
std::string string;
raw_string_ostream ostream(string);
printDescription(ostream);
ostream.flush();
return string;
}
inline MagicMmapCtlFunction::MagicMmapCtlFunction(Function *function, PointerType *voidPointerType, std::string &ptrArgName, std::string &lenArgName) {
this->function = function;
this->ptrArg = -1;
this->lenArg = -1;
bool lookupPtrArg = ptrArgName.compare("");
bool lookupLenArg = lenArgName.compare("");
assert((lookupPtrArg || lookupLenArg) && "No valid argument name specified!");
unsigned i=0;
for (Function::arg_iterator it = function->arg_begin(), E = function->arg_end();
it != E; ++it) {
std::string argName = it->getName();
if(lookupPtrArg && !argName.compare(ptrArgName)) {
this->ptrArg = i;
}
else if(lookupLenArg && !argName.compare(lenArgName)) {
this->lenArg = i;
}
i++;
}
if(this->ptrArg >= 0) {
assert(function->getFunctionType()->getContainedType(this->ptrArg+1) == voidPointerType && "Invalid ptr argument specified!");
}
else {
assert(!lookupPtrArg && "Invalid ptr argument name specified!");
}
if(this->lenArg >= 0) {
assert(isa<IntegerType>(function->getFunctionType()->getContainedType(this->lenArg+1)) && "Invalid len argument specified!");
}
else {
assert(!lookupLenArg && "Invalid len argument name specified!");
}
}
inline Function* MagicMmapCtlFunction::getFunction() const {
return function;
}
/* This assumes in-band metadata of 1 page before every mmapped region. */
inline void MagicMmapCtlFunction::fixCalls(Module &M, Function *magicGetPageSizeFunc) const {
std::vector<User*> Users(function->use_begin(), function->use_end());
while (!Users.empty()) {
User *U = Users.back();
Users.pop_back();
if (Instruction *I = dyn_cast<Instruction>(U)) {
Function *parent = I->getParent()->getParent();
if(parent->getName().startswith("magic") || parent->getName().startswith("_magic")) {
continue;
}
CallSite CS = MagicUtil::getCallSiteFromInstruction(I);
std::vector<Value*> args;
CallInst* magicGetPageSizeCall = MagicUtil::createCallInstruction(magicGetPageSizeFunc, args, "", I);
magicGetPageSizeCall->setCallingConv(CallingConv::C);
magicGetPageSizeCall->setTailCall(false);
TYPECONST IntegerType *type = dyn_cast<IntegerType>(magicGetPageSizeCall->getType());
assert(type);
if(this->ptrArg >= 0) {
Value *ptrValue = CS.getArgument(this->ptrArg);
BinaryOperator* negativePageSize = BinaryOperator::Create(Instruction::Sub, ConstantInt::get(M.getContext(), APInt(type->getBitWidth(), 0)), magicGetPageSizeCall, "", I);
GetElementPtrInst* ptrValueWithOffset = GetElementPtrInst::Create(ptrValue, negativePageSize, "", I);
CS.setArgument(this->ptrArg, ptrValueWithOffset);
}
if(this->lenArg >= 0) {
Value *lenValue = CS.getArgument(this->lenArg);
BinaryOperator* lenValuePlusPageSize = BinaryOperator::Create(Instruction::Add, lenValue, magicGetPageSizeCall, "", I);
CS.setArgument(this->lenArg, lenValuePlusPageSize);
}
}
}
}
}
#endif

View file

@ -0,0 +1,72 @@
#ifndef MAGIC_UTIL_H
#define MAGIC_UTIL_H
#include <magic/magic.h>
#include <magic/support/SmartType.h>
#include <cxxabi.h>
using namespace llvm;
namespace llvm {
#define magicUtilLog(M) DEBUG(dbgs() << "MagicUtil: " << M << "\n")
class MagicUtil {
public:
static StringRef getGVSourceName(Module &M, GlobalVariable *GV, DIGlobalVariable **DIGVP=NULL, const std::string &baseDir="");
static StringRef getLVSourceName(Module &M, AllocaInst *V, DIVariable **DIVP=NULL);
static StringRef getFunctionSourceName(Module &M, Function *F, DISubprogram **DISP=NULL, const std::string &baseDir="");
static void putStringRefCache(Module &M, const std::string &str, GlobalVariable *GV);
static Constant* getGetElementPtrConstant(Constant *constant, std::vector<Value*> &indexes);
static GetElementPtrInst* createGetElementPtrInstruction(Value *ptr, std::vector<Value*> &indexes, const Twine &NameStr="", Instruction *InsertBefore=0);
static GetElementPtrInst* createGetElementPtrInstruction(Value *ptr, std::vector<Value*> &indexes, const Twine &NameStr="", BasicBlock *InsertAtEnd=0);
static CallInst* createCallInstruction(Value *F, std::vector<Value*> &args, const Twine &NameStr="", Instruction *InsertBefore=0);
static CallInst* createCallInstruction(Value *F, std::vector<Value*> &args, const Twine &NameStr="", BasicBlock *InsertAtEnd=0);
static Function* getIntrinsicFunction(Module &M, Intrinsic::ID id, TYPECONST Type** types=NULL, unsigned size=0);
static GlobalVariable *getStringRef(Module &M, const std::string &str);
static GlobalVariable *getIntArrayRef(Module &M, unsigned arrSize, std::vector<int> *arr, bool isConstant=true);
static GlobalVariable *getStringArrayRef(Module &M, unsigned arrSize, std::vector<std::string> *arr, bool isConstant=true);
static GlobalVariable *getGenericArrayRef(Module &M, std::vector<Constant*> &arrayElems, bool isConstant=true);
static GlobalVariable *getMagicTypePtrArrayRef(Module &M, Instruction *InsertBefore, std::vector<Value*> &globalTypeIndexes, GlobalVariable *magicTypeArray);
static GlobalVariable* getExportedIntGlobalVar(Module &M, std::string name, int value, bool isConstant=true);
static GlobalVariable* getShadowRef(Module &M, GlobalVariable *GV);
static Value* getMagicStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* array, Value* arrayIndex, const std::string &structFieldName, std::string *structFieldNames);
static Value* getMagicSStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* magicArray, Value* magicArrayIndex, const std::string &structFieldName);
static Value* getMagicTStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* magicTypeArray, Value* magicTypeArrayIndex, const std::string &structFieldName);
static Value* getMagicFStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* magicFunctionArray, Value* magicFunctionArrayIndex, const std::string &structFieldName);
static Value* getMagicRStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* magicVar, const std::string &structFieldName);
static Value* getMagicDStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* magicDsindexArray, Value* magicDsindexArrayIndex, const std::string &structFieldName);
static Constant* getArrayPtr(Module &M, GlobalVariable* array);
static void insertMemcpyInst(Module &M, Instruction *InsertBefore, Value *Dst, Value *Src, Value *Len, unsigned Align);
static void insertCopyInst(Module &M, Instruction *InsertBefore, GlobalVariable *GV, GlobalVariable *SGV, int GVSize, bool forceMemcpy);
static Function* getCalledFunctionFromCS(const CallSite &CS);
static void replaceCallInst(Instruction *originalInst, CallInst *newInst, int argOffset=0, bool removeUnusedFunction=true);
static std::vector<Function*> getGlobalVariablesShadowFunctions(Module &M, std::vector<GlobalVariable*> globalVariables, std::vector<GlobalVariable*> shadowGlobalVariables, std::vector<int> globalVariableSizes, GlobalVariable* magicArray, int magicArraySize, bool forceShadow, bool setDirtyFlag);
static Function* getGlobalVariableShadowFunction(Module &M, GlobalVariable* GV, GlobalVariable* SGV, int GVSize, GlobalVariable* magicArray, int magicArrayIndex, bool forceShadow, bool setDirtyFlag);
static void insertGlobalVariableCleanDirtyFlag(Module &M, GlobalVariable* GV, GlobalVariable* magicArray, int magicArrayIndex, Instruction *InsertBefore);
static void insertShadowTag(Module &M, GlobalVariable *GV, Instruction *InsertBefore);
static bool isShadowTag(Instruction *inst);
static GlobalVariable* getGlobalVariableFromShadowTag(Instruction *inst, std::vector<Instruction*> &instructionsToRemove);
static void cleanupShadowTag(Module &M, std::vector<Instruction*> &instructionsToRemove);
static bool hasAddressTaken(const GlobalValue *GV, bool includeMembers=true);
static bool lookupValueSet(const GlobalVariable *GV, std::vector<int> &valueSet);
static Value* getStringOwner(GlobalVariable *GV);
static Instruction* getFirstNonAllocaInst(Function* F, bool skipAllocaPoint=true);
static void setGlobalVariableSection(GlobalVariable *GV, const std::string &section);
static bool getCallAnnotation(Module &M, const CallSite &CS, int *annotation);
static bool getVarAnnotation(Module &M, const GlobalVariable *GV, int *annotation);
static CallSite getCallSiteFromInstruction(Instruction *I);
static AllocaInst* getAllocaInstFromArgument(Argument *argument);
static Function* getMangledFunction(Module &M, StringRef functionName);
static Function* getFunction(Module &M, StringRef functionName);
static bool isCompatibleType(const Type* type1, const Type* type2);
static void inlinePreHookForwardingCall(Function* function, Function* preHookFunction, std::vector<unsigned> argsMapping, std::vector<Value*> trailingArgs);
static void inlinePostHookForwardingCall(Function* function, Function* postHookFunction, std::vector<unsigned> mapping, std::vector<Value*> trailingArgs);
static int getPointerIndirectionLevel(const Type* type);
static Value* getFunctionParam(Function* function, unsigned index);
static bool isLocalConstant(Module &M, GlobalVariable *GV);
};
}
#endif

View file

@ -0,0 +1,244 @@
#ifndef SMART_TYPE_H
#define SMART_TYPE_H
#include <pass.h>
#include <magic/support/Backports.h>
#include <magic/support/EDIType.h>
#include <magic/support/TypeUtil.h>
#include <magic/support/BitFieldAggregation.h>
using namespace llvm;
namespace llvm {
#define SmartTypeLog(M) DEBUG(dbgs() << "SmartType: " << M << "\n")
#define SmartTypeErr(M) errs() << "SmartType: " << M << "\n"
#if HAVE_EXCEPTIONS
#define THROW(E) throw E
#define TRY(B) try{ B }
#define CATCH(E, B) catch(E){ B }
#else
#define THROW(E) assert(0 && "throw: Exceptions disabled")
#define TRY(B) assert(0 && "try: Exceptions disabled");
#define CATCH(E, B) assert(0 && "catch: Exceptions disabled");
#endif
#define SmartType_assert(X) do { \
if(!(X)) { \
if(useExceptions) { \
THROW(std::exception()); \
} \
errs() << "Assertion failed, dumping object...\n"; \
errs() << "Name is: " << this->aEDIType.getName() << "\n"; \
errs() << *this; \
} \
assert(X); \
} while(0)
class SmartType {
public:
SmartType(const SmartType& et);
SmartType(TYPECONST Type *type, const DIType *aDIType, bool useExceptions=false, bool forceRawTypeRepresentation=false);
SmartType(TYPECONST Type *type, const EDIType *aEDIType, bool useExceptions=false, bool forceRawTypeRepresentation=false);
~SmartType();
SmartType& operator=(const SmartType& et);
void cloneFrom(const SmartType& et);
const std::string getDescription() const;
const SmartType* getContainedType(unsigned i) const;
unsigned getNumContainedTypes() const;
const DIDerivedType& getMember(unsigned i) const;
unsigned getUnionMemberIdx() const;
const SmartType* getTopStructType(unsigned index) const;
TYPECONST Type *getType() const;
const EDIType *getEDIType() const;
bool isTypeConsistent() const;
bool hasInnerPointers() const;
bool isVoidTy() const;
bool isPrimitiveTy() const;
bool isAggregateType() const;
bool isFunctionTy() const;
bool isStructTy() const;
bool isArrayTy() const;
bool isPointerTy() const;
bool isOpaqueTy() const;
bool isPaddedTy() const;
unsigned getNumElements() const;
bool isUseExceptions() const;
void verify() const;
bool verifyTy() const;
void print(raw_ostream &OS) const;
bool equals(const SmartType* other, bool isDebug=false) const;
bool hasRawTypeRepresentation() const;
static const SmartType* getSmartTypeFromGV(Module &M, GlobalVariable *GV, DIGlobalVariable *DIG = NULL);
static const SmartType* getSmartTypeFromLV(Module &M, AllocaInst *AI, DIVariable *DIV = NULL);
static const SmartType* getSmartTypeFromFunction(Module &M, Function *F, DISubprogram *DIS = NULL);
static const SmartType* getStructSmartTypeByName(Module &M, GlobalVariable* GV, std::string &name, bool isUnion=false);
static std::vector<const SmartType*>* getTopStructSmartTypes(Module &M, GlobalVariable* GV);
static bool isTypeConsistent(TYPECONST Type *type, const EDIType *aEDIType, bool useBfas=true, int *weakConsistencyLevel=NULL);
private:
TYPECONST Type *type;
EDIType aEDIType;
bool hasExplicitContainedEDITypes;
bool isInconsistent;
std::vector<EDIType*> explicitContainedEDITypes;
std::vector<BitFieldAggregation> bfas;
bool useExceptions;
bool rawTypeRepresentation;
unsigned unionMemberIdx;
static std::vector<TYPECONST Type*> equalsNestedTypes;
static bool forceRawUnions;
static bool forceRawBitfields;
void init(TYPECONST Type *type, const EDIType *aEDIType, bool useExceptions, bool forceRawTypeRepresentation);
void normalize();
void flattenFunctionTy();
int flattenFunctionArgs(TYPECONST Type *type, const EDIType *aEDIType, unsigned nextContainedType);
bool isTy(bool isTyType, bool isTyEDIType, const char* source) const;
static unsigned getBFAFreeIdx(unsigned i, const std::vector<BitFieldAggregation> &inputBfas);
static bool isRawTypeConsistent(TYPECONST Type *type, const EDIType *aEDIType);
static bool isTypeConsistent2(TYPECONST Type *type, const EDIType *aEDIType);
static bool isTypeConsistent2(std::vector<TYPECONST Type*> &nestedTypes, std::vector<const EDIType*> &nestedEDITypes, const SmartType *aSmartType);
};
inline raw_ostream &operator<<(raw_ostream &OS, const SmartType &aSmartType) {
aSmartType.print(OS);
return OS;
}
inline TYPECONST Type *SmartType::getType() const {
return type;
}
inline const EDIType *SmartType::getEDIType() const {
return &aEDIType;
}
inline bool SmartType::isTypeConsistent() const {
if(isInconsistent) {
return false;
}
if(isFunctionTy() || hasRawTypeRepresentation()) {
return true;
}
return isTypeConsistent(type, &aEDIType);
}
inline bool SmartType::hasInnerPointers() const {
return aEDIType.hasInnerPointers();
}
inline bool SmartType::isVoidTy() const {
return isTy(type->isVoidTy(), aEDIType.isVoidTy(), "isVoidTy");
}
inline bool SmartType::isPrimitiveTy() const {
if(aEDIType.isComplexFloatingPointTy()) {
assert(type->isStructTy());
return true;
}
return isTy(type->isPrimitiveType(), aEDIType.isPrimitiveType(), "isPrimitiveTy");
}
inline bool SmartType::isAggregateType() const {
return isTy(type->isAggregateType(), aEDIType.isAggregateType(), "isAggregateType");
}
inline bool SmartType::isFunctionTy() const {
if(isOpaqueTy()) {
return false;
}
return isTy(type->isFunctionTy(), aEDIType.isFunctionTy(), "isFunctionTy");
}
inline bool SmartType::isStructTy() const {
if(aEDIType.isComplexFloatingPointTy()) {
assert(type->isStructTy());
return false;
}
if(aEDIType.isArrayTy() && TypeUtil::isArrayAsStructTy(type)) {
return false;
}
if(isOpaqueTy()) {
return false;
}
return isTy(type->isStructTy(), aEDIType.isUnionOrStructTy(), "isStructTy");
}
inline bool SmartType::isArrayTy() const {
if(aEDIType.isArrayTy() && TypeUtil::isArrayAsStructTy(type)) {
return true;
}
if (hasRawTypeRepresentation()) { // only possible for structs and bitfields
return false;
}
return isTy(type->isArrayTy(), aEDIType.isArrayTy(), "isArrayTy");
}
inline bool SmartType::isPointerTy() const {
return isTy(type->isPointerTy(), aEDIType.isPointerTy(), "isPointerTy");
}
inline bool SmartType::isOpaqueTy() const {
return TypeUtil::isOpaqueTy(type) || aEDIType.isOpaqueTy();
}
inline bool SmartType::isPaddedTy() const {
if(!isAggregateType() || hasRawTypeRepresentation()) {
return false;
}
return TypeUtil::isPaddedType(type);
}
inline unsigned SmartType::getNumElements() const {
if(!isArrayTy()) {
return 0;
}
unsigned EDINumElements = aEDIType.getNumElements();
unsigned numElements;
if(type->isArrayTy()) {
numElements = ((ArrayType*)type)->getNumElements();
}
else {
assert(type->isStructTy());
numElements = type->getNumContainedTypes();
}
if(numElements == 0) {
assert(EDINumElements <= 1 || EDINumElements==UINT_MAX);
return 0;
}
assert(numElements == EDINumElements);
return numElements;
}
inline bool SmartType::isUseExceptions() const {
return useExceptions;
}
inline bool SmartType::verifyTy() const {
if(isVoidTy()) return true;
if(isPrimitiveTy()) return true;
if(isAggregateType()) return true;
if(isFunctionTy()) return true;
if(isStructTy()) return true;
if(isArrayTy()) return true;
if(isPointerTy()) return true;
if(isOpaqueTy()) return true;
return false;
}
inline bool SmartType::hasRawTypeRepresentation() const {
return rawTypeRepresentation;
}
}
#endif

View file

@ -0,0 +1,636 @@
#ifndef TYPE_INFO_H
#define TYPE_INFO_H
#include <magic/magic.h>
#include <magic_common.h>
#include <magic/support/SmartType.h>
#include <magic/support/TypeUtil.h>
using namespace llvm;
#define TypeInfoErr(M) errs() << "TypeInfo: " << M << "\n"
#define FUNCTIONS_USE_HASH_TYPE_STRINGS 1
#define ROOT_TYPES_HAVE_TYPE_STRINGS 0
#define DEBUG_CAST_LOOKUPS 0
#define TYPEINFO_PERSISTENT 0x01
namespace llvm {
class TypeInfo {
public:
TypeInfo(const SmartType *aSmartType, int persistent=0);
TypeInfo(TYPECONST FunctionType *FT, int persistent=0);
TypeInfo(TYPECONST PointerType *PT, int persistent=0);
TypeInfo(TYPECONST ArrayType *AT, int persistent=0);
TypeInfo(TYPECONST IntegerType *IT, int persistent=0);
TypeInfo(TYPECONST StructType *OpaqueST, int persistent=0);
void init(int persistent);
const SmartType *getSmartType() const;
TYPECONST Type *getType() const;
unsigned getNumContainedTypes() const;
unsigned getNumChildTypes() const;
TypeInfo *getContainedType(unsigned i) const;
std::vector<GlobalValue*> getParents() const;
std::string getTypeString() const;
std::string getDescription() const;
std::string getVerboseDescription() const;
std::string getName() const;
std::vector<std::string> getNames() const;
std::string getNamesString() const;
std::vector<std::string> getMemberNames() const;
std::vector<int> getValueSet() const;
std::vector<TypeInfo*> getCastTypes() const;
unsigned getTypeID() const;
unsigned getFlags() const;
unsigned getBitWidth() const;
bool equals(TYPECONST TypeInfo *other) const;
bool hasRawTypeRepresentation() const;
std::string formatMemberName(const std::string &memberName, unsigned &numAnonMembers);
void setValueSet(const std::vector<int> &valueSet);
void setContainedTypes(const std::vector<TypeInfo*> &containedTypes);
void addParent(GlobalValue* parent);
void addParents(const std::vector<GlobalValue*> &parents);
bool removeParent(GlobalValue* parent);
bool removeAllParents();
void setPersistent();
bool splitByParentValueSet(std::vector<TypeInfo*> &splitTypeInfos, std::set<GlobalVariable*> &globalVariablesWithAddressTaken);
static unsigned getMaxNameLength();
static unsigned getMaxTypeStringLength();
static void setIntCastTypes(std::map<TYPECONST Type*, std::set<int> > &intCastTypes);
static void setBitCastTypes(std::map<TYPECONST Type*, std::set<TYPECONST Type*> > &bitCastTypes);
private:
const SmartType *aSmartType;
TYPECONST Type *aType;
bool forceTypeDescription;
mutable std::string typeDescription;
std::string name;
std::vector<std::string> names;
std::vector<std::string> memberNames;
std::vector<int> valueSet;
std::vector<TypeInfo*> containedTypes;
std::vector<GlobalValue*> parents;
unsigned bitWidth;
unsigned typeID;
unsigned numElements;
unsigned flags;
static unsigned maxNameLength;
static unsigned maxTypeStringLength;
static std::map<TYPECONST Type*, std::set<int> > intCastTypes;
static std::map<TYPECONST Type*, std::set<TYPECONST Type*> > bitCastTypes;
static std::map<TYPECONST Type*, std::set<TypeInfo*> > typeMap;
TypeInfo() {}
};
inline TypeInfo::TypeInfo(const SmartType *aSmartType, int persistent) {
unsigned i;
assert(aSmartType);
this->aSmartType = aSmartType;
this->aType = aSmartType->getType();
bool rawTypeRepresentation = aSmartType->hasRawTypeRepresentation();
forceTypeDescription = aSmartType->isFunctionTy();
name = aSmartType->getEDIType()->getName();
std::vector<StringRef> nameRefs = aSmartType->getEDIType()->getNames();
for(i=0;i<nameRefs.size();i++) {
if(nameRefs[i].size() > maxNameLength) {
maxNameLength = nameRefs[i].size();
}
names.push_back(nameRefs[i]);
}
if(aSmartType->isStructTy()) {
if(!rawTypeRepresentation) {
const EDIType* aEDIType = aSmartType->getEDIType();
unsigned numContainedTypes = aSmartType->getNumContainedTypes();
unsigned numAnonMembers = 0;
if(aEDIType->isUnionTy()) {
assert(numContainedTypes == 1);
i=aSmartType->getUnionMemberIdx();
const DIDerivedType subDIType = aSmartType->getMember(i);
memberNames.push_back(formatMemberName(subDIType.getName(), numAnonMembers));
}
else {
assert(aEDIType->isStructTy());
i=0;
for(;i<numContainedTypes;i++) {
const DIDerivedType subDIType = aSmartType->getMember(i);
memberNames.push_back(formatMemberName(subDIType.getName(), numAnonMembers));
}
}
}
else {
memberNames.push_back("raw");
}
}
if(aSmartType->getEDIType()->isEnumTy()) {
std::vector<unsigned> enumValues = aSmartType->getEDIType()->getEnumValues();
valueSet.push_back(enumValues.size()); //push length as the first value
for(unsigned i=0;i<enumValues.size();i++) {
valueSet.push_back((int)enumValues[i]);
}
}
bitWidth = TypeUtil::typeToBits(aSmartType->getType());
const EDIType *aEDIType = aSmartType->getEDIType();
typeID = 0;
flags = 0;
if(aSmartType->isOpaqueTy()) {
typeID = MAGIC_TYPE_OPAQUE;
}
else if(aEDIType->isVoidTy()) {
typeID = MAGIC_TYPE_VOID;
}
else if(aSmartType->isFunctionTy()) {
typeID = MAGIC_TYPE_FUNCTION;
}
else if(aSmartType->isStructTy()) {
if(aEDIType->isUnionTy()) {
typeID = MAGIC_TYPE_UNION;
}
else if(aEDIType->isStructTy()) {
typeID = MAGIC_TYPE_STRUCT;
#if MAGIC_VARSIZED_STRUCTS_SUPPORT
if(!rawTypeRepresentation) {
assert(this->aType->getNumContainedTypes() > 0);
TYPECONST Type *lastSubType = this->aType->getContainedType(this->aType->getNumContainedTypes()-1);
if(lastSubType->isArrayTy() && ((ArrayType*)lastSubType)->getNumElements() <= 1) {
flags |= MAGIC_TYPE_VARSIZE;
}
}
#endif
}
}
else if(aSmartType->isPointerTy()) {
typeID = MAGIC_TYPE_POINTER;
}
else if(aSmartType->isArrayTy()) {
typeID = MAGIC_TYPE_ARRAY;
}
else if(aEDIType->isFloatingPointTy()) {
typeID = MAGIC_TYPE_FLOAT;
}
else if(aEDIType->isIntegerTy()) {
typeID = MAGIC_TYPE_INTEGER;
}
else if(aEDIType->isEnumTy()) {
typeID = MAGIC_TYPE_ENUM;
}
else if(aEDIType->isVectorTy()) {
typeID = MAGIC_TYPE_VECTOR;
}
assert(typeID);
if(typeID == MAGIC_TYPE_INTEGER || typeID == MAGIC_TYPE_ENUM) {
if(getNamesString().find("unsigned") != std::string::npos) {
flags |= MAGIC_TYPE_UNSIGNED;
}
}
numElements = aSmartType->getNumElements();
init(persistent);
}
inline TypeInfo::TypeInfo(TYPECONST FunctionType *FT, int persistent) {
assert(FT);
aSmartType = NULL;
aType = FT;
forceTypeDescription = true;
bitWidth = 0;
typeID = MAGIC_TYPE_FUNCTION;
numElements = 0;
flags = MAGIC_TYPE_EXTERNAL;
init(persistent);
}
inline TypeInfo::TypeInfo(TYPECONST PointerType *PT, int persistent) {
assert(PT);
aSmartType = NULL;
aType = PT;
forceTypeDescription = false;
bitWidth = 0;
typeID = MAGIC_TYPE_POINTER;
numElements = 0;
flags = MAGIC_TYPE_EXTERNAL;
init(persistent);
}
inline TypeInfo::TypeInfo(TYPECONST ArrayType *AT, int persistent) {
assert(AT);
aSmartType = NULL;
aType = AT;
forceTypeDescription = false;
bitWidth = 0;
typeID = MAGIC_TYPE_ARRAY;
numElements = AT->getNumElements();
flags = MAGIC_TYPE_EXTERNAL;
init(persistent);
}
inline TypeInfo::TypeInfo(TYPECONST IntegerType *IT, int persistent) {
assert(IT);
aSmartType = NULL;
aType = IT;
forceTypeDescription = true;
bitWidth = IT->getBitWidth();
typeID = MAGIC_TYPE_INTEGER;
numElements = 0;
flags = MAGIC_TYPE_EXTERNAL;
init(persistent);
}
inline TypeInfo::TypeInfo(TYPECONST StructType *OpaqueST, int persistent) {
assert(OpaqueST);
assert(TypeUtil::isOpaqueTy(OpaqueST));
aSmartType = NULL;
aType = OpaqueST;
forceTypeDescription = true;
bitWidth = 0;
typeID = MAGIC_TYPE_OPAQUE;
numElements = 0;
flags = MAGIC_TYPE_EXTERNAL;
init(persistent);
}
inline void TypeInfo::init(int persistent) {
std::map<TYPECONST Type*, std::set<int> >::iterator intCastTypesIt;
//set persistent if necessary
if(persistent) {
setPersistent();
}
//initialize value set for pointers casted to int
if(aType->isPointerTy()) {
intCastTypesIt = intCastTypes.find(aType);
if(intCastTypesIt != intCastTypes.end()) {
std::set<int> &pointerValues = intCastTypesIt->second;
assert(pointerValues.size() > 0);
flags |= MAGIC_TYPE_INT_CAST;
if(pointerValues.size() > 1 || *(pointerValues.begin()) != 0) {
valueSet.push_back(pointerValues.size()); //push length as the first value
for(std::set<int>::iterator it=pointerValues.begin() ; it != pointerValues.end(); it++) {
assert(*it != 0);
valueSet.push_back(*it);
}
}
}
}
//adjust flags
bool hasInnerPointers = aSmartType ? aSmartType->hasInnerPointers() : TypeUtil::hasInnerPointers(aType);
if(!hasInnerPointers) {
flags |= MAGIC_TYPE_NO_INNER_PTRS;
}
}
inline const SmartType *TypeInfo::getSmartType() const {
return aSmartType;
}
inline TYPECONST Type *TypeInfo::getType() const {
return aType;
}
inline unsigned TypeInfo::getNumContainedTypes() const {
return containedTypes.size();
}
inline unsigned TypeInfo::getNumChildTypes() const {
return typeID == MAGIC_TYPE_ARRAY ? numElements : containedTypes.size();
}
inline TypeInfo *TypeInfo::getContainedType(unsigned i) const {
assert(i<containedTypes.size());
return containedTypes[i];
}
inline std::vector<GlobalValue*> TypeInfo::getParents() const {
return parents;
}
inline std::string TypeInfo::getTypeString() const {
std::string typeString = forceTypeDescription || aType->getNumContainedTypes() == 0 ? getDescription() : "";
if(MAGIC_SHRINK_TYPE_STR && typeString.size() > MAGIC_MAX_TYPE_STR_LEN) {
typeString = typeString.substr(0, MAGIC_MAX_TYPE_STR_LEN-3) + "...";
}
if(typeString.size() > maxTypeStringLength) {
maxTypeStringLength = typeString.size();
}
return typeString;
}
inline std::string TypeInfo::getDescription() const {
if(typeDescription.size() == 0) {
if(aType->isFunctionTy() && FUNCTIONS_USE_HASH_TYPE_STRINGS) {
unsigned hash = TypeUtil::getHash(aType);
raw_string_ostream ostream(typeDescription);
ostream << "hash_" << hash;
ostream.flush();
}
else {
typeDescription = TypeUtil::getDescription(aType);
}
}
return typeDescription;
}
inline std::string TypeInfo::getVerboseDescription() const {
return aSmartType ? aSmartType->getDescription() : getDescription();
}
inline std::string TypeInfo::getName() const {
return name;
}
inline std::vector<std::string> TypeInfo::getNames() const {
return names;
}
inline std::string TypeInfo::getNamesString() const {
std::string string;
raw_string_ostream ostream(string);
for(unsigned i=0;i<names.size();i++) {
if(i>0) ostream << "|";
ostream << names[i];
}
ostream.flush();
return string;
}
inline std::vector<std::string> TypeInfo::getMemberNames() const {
for(unsigned i=0;i<memberNames.size();i++) {
if(memberNames[i].size() > maxNameLength) {
maxNameLength = memberNames[i].size();
}
}
return memberNames;
}
inline std::vector<int> TypeInfo::getValueSet() const {
return valueSet;
}
inline std::vector<TypeInfo*> TypeInfo::getCastTypes() const {
std::vector<TypeInfo*> castTypes;
std::map<TYPECONST Type*, std::set<TYPECONST Type*> >::iterator bitCastTypesIt;
std::map<TYPECONST Type*, std::set<TypeInfo*> >::iterator typeMapIt;
if(!aType->isPointerTy()) {
return castTypes;
}
//XXX to-do: match only original struct name during lookup by looking at the original bitcast instruction
//the following lookups do not distinguish between struct x = {18} and struct y = {i8}
//the number of false positives generated seems to be fairly small, anyway
bitCastTypesIt = bitCastTypes.find(aType);
if(bitCastTypesIt == bitCastTypes.end()) {
return castTypes;
}
std::set<TYPECONST Type*> bitCastSet = bitCastTypesIt->second;
#if MAGIC_INDEX_TRANSITIVE_BIT_CASTS
std::vector<TYPECONST Type*> bitCasts;
for(std::set<TYPECONST Type*>::iterator it=bitCastSet.begin();it!=bitCastSet.end();it++) {
bitCasts.push_back(*it);
}
while(!bitCasts.empty()) {
TYPECONST Type* bcType = bitCasts.front();
bitCasts.erase(bitCasts.begin());
bitCastTypesIt = bitCastTypes.find(bcType);
if(bitCastTypesIt != bitCastTypes.end()) {
std::set<TYPECONST Type*> set = bitCastTypesIt->second;
for(std::set<TYPECONST Type*>::iterator it=set.begin();it!=set.end();it++) {
unsigned bitCastSetSize = bitCastSet.size();
TYPECONST Type *newBcType = *it;
if(newBcType == aType) {
continue;
}
bitCastSet.insert(newBcType);
if(bitCastSet.size() != bitCastSetSize) {
bitCasts.push_back(newBcType);
}
}
}
}
#endif
#if DEBUG_CAST_LOOKUPS
if(aType->getContainedType(0)->isStructTy()) {
TypeInfoErr("--- type is struct* " << getContainedType(0)->getName());
}
else if(aType->getContainedType(0)->isPointerTy() && aType->getContainedType(0)->getContainedType(0)->isStructTy()) {
TypeInfoErr("--- type is struct** " << getContainedType(0)->getContainedType(0)->getName());
}
else {
TypeInfoErr("--- type is " << getDescription());
}
#endif
for(std::set<TYPECONST Type*>::iterator it=bitCastSet.begin();it!=bitCastSet.end();it++) {
TYPECONST Type* type = *it;
assert(type->isPointerTy());
typeMapIt = typeMap.find(type->getContainedType(0));
if(typeMapIt == typeMap.end()) {
#if DEBUG_CAST_LOOKUPS
TypeInfoErr("*** cast target type not found: " << TypeUtil::getDescription(type->getContainedType(0)));
#endif
continue;
}
std::set<TypeInfo*> *typeInfoSet = &(typeMapIt->second);
for(std::set<TypeInfo*>::iterator it2=typeInfoSet->begin();it2!=typeInfoSet->end();it2++) {
TypeInfo* typeInfo = *it2;
assert(typeInfo->getType() != getType()->getContainedType(0));
#if DEBUG_CAST_LOOKUPS
if(typeInfo->getType()->isStructTy()) {
TypeInfoErr(">>> cast target type info is struct " << typeInfo->getName());
}
else if(typeInfo->getType()->isPointerTy() && typeInfo->getType()->getContainedType(0)->isStructTy()) {
TypeInfoErr(">>> cast target type info is struct* " << typeInfo->getContainedType(0)->getName());
}
else {
TypeInfoErr(">>> cast target type info is " << typeInfo->getDescription());
}
#endif
castTypes.push_back(typeInfo);
#if MAGIC_COMPACT_COMP_TYPES
/* This is safe as long as we check for compatible (LLVM) types at runtime. */
break;
#endif
}
}
if(castTypes.size() > 0) { //push delimiter
castTypes.push_back(NULL);
}
return castTypes;
}
inline unsigned TypeInfo::getTypeID() const {
return typeID;
}
inline unsigned TypeInfo::getFlags() const {
return flags;
}
inline unsigned TypeInfo::getBitWidth() const {
return bitWidth;
}
inline bool TypeInfo::equals(TYPECONST TypeInfo *other) const {
if(aSmartType && other->getSmartType()) {
return aSmartType->equals(other->getSmartType());
}
return (flags & (~MAGIC_TYPE_IS_ROOT)) == (other->getFlags() & (~MAGIC_TYPE_IS_ROOT))
&& !getDescription().compare(other->getDescription());
}
inline bool TypeInfo::hasRawTypeRepresentation() const {
return aSmartType && aSmartType->hasRawTypeRepresentation();
}
inline std::string TypeInfo::formatMemberName(const std::string &memberName, unsigned &numAnonMembers) {
if (memberName.compare("")) {
return memberName;
}
std::string name(memberName);
raw_string_ostream ostream(name);
ostream << MAGIC_ANON_MEMBER_PREFIX << "." << (numAnonMembers+1);
ostream.flush();
numAnonMembers++;
return name;
}
inline void TypeInfo::setValueSet(const std::vector<int> &valueSet) {
this->valueSet = valueSet;
}
inline void TypeInfo::setContainedTypes(const std::vector<TypeInfo*> &containedTypes) {
this->containedTypes = containedTypes;
}
inline void TypeInfo::addParent(GlobalValue* parent) {
assert((typeID == MAGIC_TYPE_FUNCTION && dyn_cast<Function>(parent))
|| (typeID != MAGIC_TYPE_FUNCTION && dyn_cast<GlobalVariable>(parent)));
this->parents.push_back(parent);
flags |= MAGIC_TYPE_IS_ROOT;
#if ROOT_TYPES_HAVE_TYPE_STRINGS
forceTypeDescription = true;
#endif
}
inline void TypeInfo::addParents(const std::vector<GlobalValue*> &parents) {
for(unsigned i=0;i<parents.size();i++) {
addParent(parents[i]);
}
}
inline bool TypeInfo::removeParent(GlobalValue* parent)
{
std::vector<GlobalValue*> originalParents = this->parents;
this->parents.clear();
for(unsigned i=0;i<originalParents.size();i++) {
if(originalParents[i] != parent) {
this->parents.push_back(originalParents[i]);
}
}
int sizeDiff = originalParents.size() - this->parents.size();
assert(sizeDiff == 0 || sizeDiff == 1);
return (sizeDiff == 1);
}
inline bool TypeInfo::removeAllParents()
{
if(this->parents.size() > 0) {
this->parents.clear();
return true;
}
return false;
}
inline void TypeInfo::setPersistent() {
std::map<TYPECONST Type*, std::set<TypeInfo*> >::iterator typeMapIt;
typeMapIt = typeMap.find(aType);
if(typeMapIt == typeMap.end()) {
std::set<TypeInfo*> set;
set.insert(this);
typeMap.insert(std::pair<TYPECONST Type*, std::set<TypeInfo*> >(aType, set));
}
else {
std::set<TypeInfo*> *set;
set = &(typeMapIt->second);
set->insert(this);
}
}
inline bool TypeInfo::splitByParentValueSet(std::vector<TypeInfo*> &splitTypeInfos, std::set<GlobalVariable*> &globalVariablesWithAddressTaken) {
std::map<std::vector<int>, std::vector<GlobalVariable*> > valueSetMap;
std::map<std::vector<int>, std::vector<GlobalVariable*> >::iterator valueSetMapIt;
std::vector<int> valueSet;
splitTypeInfos.push_back(this);
if(!isa<IntegerType>(aType)) {
return false;
}
assert(valueSet.size() == 0);
for(unsigned i=0;i<parents.size();i++) {
if(GlobalVariable *GV = dyn_cast<GlobalVariable>(parents[i])) {
bool hasAddressTaken = globalVariablesWithAddressTaken.find(GV) != globalVariablesWithAddressTaken.end();
if(hasAddressTaken) {
continue;
}
valueSet.clear();
bool valueSetFound = MagicUtil::lookupValueSet(GV, valueSet);
if(!valueSetFound) {
continue;
}
valueSetMapIt = valueSetMap.find(valueSet);
if(valueSetMapIt == valueSetMap.end()) {
std::vector<GlobalVariable*> vector;
valueSetMap.insert(std::pair<std::vector<int>, std::vector<GlobalVariable*> >(valueSet, vector));
valueSetMapIt = valueSetMap.find(valueSet);
assert(valueSetMapIt != valueSetMap.end());
}
std::vector<GlobalVariable*> *globalsVector = &valueSetMapIt->second;
globalsVector->push_back(GV);
}
}
if(valueSetMap.size() == 0) {
return false;
}
for(valueSetMapIt = valueSetMap.begin(); valueSetMapIt!=valueSetMap.end(); valueSetMapIt++) {
const std::vector<int> &values = valueSetMapIt->first;
const std::vector<GlobalVariable*> &globalVariables = valueSetMapIt->second;
TypeInfo *aTypeInfo = new TypeInfo(*this);
aTypeInfo->setValueSet(values);
aTypeInfo->removeAllParents();
for(unsigned i=0;i<globalVariables.size();i++) {
GlobalVariable* GV = globalVariables[i];
bool parentRemoved = this->removeParent(GV);
assert(parentRemoved);
aTypeInfo->addParent(GV);
}
splitTypeInfos.push_back(aTypeInfo);
}
return true;
}
inline unsigned TypeInfo::getMaxNameLength() {
return TypeInfo::maxNameLength;
}
inline unsigned TypeInfo::getMaxTypeStringLength() {
return TypeInfo::maxTypeStringLength;
}
inline void TypeInfo::setIntCastTypes(std::map<TYPECONST Type*, std::set<int> > &intCastTypes) {
TypeInfo::intCastTypes = intCastTypes;
}
inline void TypeInfo::setBitCastTypes(std::map<TYPECONST Type*, std::set<TYPECONST Type*> > &bitCastTypes) {
TypeInfo::bitCastTypes = bitCastTypes;
}
}
#endif

View file

@ -0,0 +1,52 @@
#ifndef TYPE_UTIL_H
#define TYPE_UTIL_H
#include <pass.h>
#include <magic/support/EDIType.h>
using namespace llvm;
namespace llvm {
#define TypeUtilLog(M) DEBUG(dbgs() << "TypeUtil: " << M << "\n")
class TypeUtil {
public:
static int VERBOSE_LEVEL;
static int PRINT_SKIP_UNIONS;
static int PRINT_SKIP_STRUCTS;
static int PRINT_USE_BUILTIN_PRINTING;
static int PRINT_MULTI_NAMES;
static const unsigned TYPE_STRUCT = 0x01;
static const unsigned TYPE_UNION = 0x02;
static const unsigned TYPE_ANONYMOUS = 0x04;
static const unsigned TYPE_UNNAMED = 0x08;
static bool isPaddedType(TYPECONST Type *type);
static TYPECONST Type* lookupTopStructType(TYPECONST Type *type, unsigned index);
static void parseTopStructTypes(Module &M, TYPECONST Type *type, std::vector<std::string> *names, std::vector<unsigned> *flags);
static int findTopStructTypeIndex(Module &M, TYPECONST Type *type, std::string &name, unsigned flagsToAccept);
static TYPECONST Type* getRecursiveElementType(TYPECONST Type *type);
static TYPECONST Type* getArrayFreePointerType(TYPECONST Type *type);
static bool hasInnerPointers(TYPECONST Type *type);
static bool isArrayAsStructTy(TYPECONST Type *type);
static bool isOpaqueTy(TYPECONST Type *type);
static unsigned getHash(TYPECONST Type* type);
static const std::string getDescription(TYPECONST Type* type, size_t max_chars = 0, size_t max_levels = 0);
static const std::string getDescription(const EDIType* aEDIType);
static const std::string getDescription(TYPECONST Type* type, const EDIType* aEDIType, size_t max_chars = 0, size_t max_levels = 0);
static const std::string getFormattedDescription(std::string &description);
static void printFormattedTypeString(raw_ostream &OS, std::string &typeStr, int start, int length);
static void printTypeString(raw_ostream &OS, TYPECONST Type* type, size_t max_chars = 0, size_t max_levels = 0);
static unsigned typeToBits(TYPECONST Type *type);
};
inline bool TypeUtil::isOpaqueTy(TYPECONST Type *type) {
return PassUtil::isOpaqueTy(type);
}
}
#endif

View file

@ -0,0 +1,30 @@
#ifndef VARIABLE_REFS_H
#define VARIABLE_REFS_H
#include <pass.h>
using namespace llvm;
namespace llvm {
class VariableRefs {
public:
VariableRefs();
bool isUnnecessaryInstruction(Instruction* inst) const;
Instruction* getInstruction() const;
bool isInstructionInEntryBlock() const;
void addInstruction(Instruction* inst);
void clear();
private:
Instruction* instruction;
bool instructionInEntryBlock;
void setFunctionEntryInstruction(Function* function);
};
}
#endif

View file

@ -2,8 +2,8 @@
#ifndef _PASS_H
#define _PASS_H
#import <set>
#import <map>
#include <set>
#include <map>
#include <llvm/Pass.h>
#include <llvm/Support/raw_ostream.h>

File diff suppressed because it is too large Load diff

View file

@ -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

View file

@ -0,0 +1,172 @@
#include <pass.h>
#include <magic/support/Backports.h>
#include <magic/support/EDIType.h>
#include <magic/support/SmartType.h>
using namespace llvm;
namespace llvm {
//===----------------------------------------------------------------------===//
// Public static methods
//===----------------------------------------------------------------------===//
/// Find the debug info descriptor corresponding to this global variable.
Value *Backports::findDbgGlobalDeclare(GlobalVariable *V) {
return PassUtil::findDbgGlobalDeclare(V);
}
/// Find the debug info descriptor corresponding to this function.
Value *Backports::findDbgSubprogramDeclare(Function *V) {
return PassUtil::findDbgSubprogramDeclare(V);
}
/// Finds the llvm.dbg.declare intrinsic corresponding to this value if any.
/// It looks through pointer casts too.
const DbgDeclareInst *Backports::findDbgDeclare(const Value *V) {
V = V->stripPointerCasts();
if (!isa<Instruction>(V) && !isa<Argument>(V))
return 0;
const Function *F = NULL;
if (const Instruction *I = dyn_cast<Instruction>(V))
F = I->getParent()->getParent();
else if (const Argument *A = dyn_cast<Argument>(V))
F = A->getParent();
for (Function::const_iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI)
for (BasicBlock::const_iterator BI = (*FI).begin(), BE = (*FI).end();
BI != BE; ++BI)
if (const DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(BI))
if (DDI->getAddress() == V)
return DDI;
return 0;
}
/// FindAllocaDbgDeclare - Finds the llvm.dbg.declare intrinsic describing the
/// alloca 'V', if any.
DbgDeclareInst *Backports::FindAllocaDbgDeclare(Value *V) {
#if LLVM_VERSION >= 33
if (MDNode *DebugNode = MDNode::getIfExists(V->getContext(), V))
for (Value::use_iterator UI = DebugNode->use_begin(),
E = DebugNode->use_end(); UI != E; ++UI)
if (DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(*UI))
return DDI;
return 0;
#else
///
/// There is an unfixed bug (http://llvm.org/bugs/show_bug.cgi?id=10887)
/// that drops debug information references for local variables at linking time.
/// This is way the method FindAllocaDbgDeclare() will always return NULL and
/// we need to resort to some ugly workaround.
///
AllocaInst *AI = dyn_cast<AllocaInst>(V);
if(!AI) {
return NULL;
}
BasicBlock *varParent = AI->getParent();
Function *varFunc = varParent->getParent();
if(!AI->hasName() || !AI->getName().compare("retval")) {
return NULL;
}
StringRef varName = AI->getName();
bool isInlinedVar = false;
bool isScopedVar = false;
DIType aDIType, aAddrDIType, tmpDIType;
DbgDeclareInst *DDI = NULL, *addrDDI = NULL;
SmallVector< StringRef, 8 > vector;
varName.split(vector, ".");
if(vector.size() >= 2 && vector[1][0] == 'i') {
isInlinedVar = true;
varName = vector[0];
}
if(!isInlinedVar) {
//for non-inlined variables we have to look in the first bb first.
for(BasicBlock::iterator i=varParent->begin(), e=varParent->end();i!=e;i++) {
if(DbgDeclareInst *DI = dyn_cast<DbgDeclareInst>(i)) {
MDNode *node = DI->getVariable();
assert(node);
DIVariable DIV(node);
if(!DIV.getName().compare(varName)) {
aDIType = DIV.getType();
DDI = DI;
break;
}
StringRef addrVarName(DIV.getName().str() + "_addr");
if(!addrVarName.compare(varName)) {
aAddrDIType = DIV.getType();
addrDDI = DI;
break;
}
}
}
if(!DDI && !addrDDI) {
//not found? probably a scoped variable, look anywhere else.
isScopedVar = true;
}
}
if(isInlinedVar || isScopedVar) {
//for inlined/scoped variables we have to look everywhere in the function and name clashing could also occur.
bool isDuplicate = false;
for (inst_iterator it = inst_begin(varFunc), et = inst_end(varFunc); it != et; ++it) {
Instruction *inst = &(*it);
if(DbgDeclareInst *DI = dyn_cast<DbgDeclareInst>(inst)) {
MDNode *node = DI->getVariable();
assert(node);
DIVariable DIV(node);
StringRef addrVarName(DIV.getName().str() + "_addr");
if(!DIV.getName().compare(varName) || !addrVarName.compare(varName)) {
tmpDIType = DIV.getType();
EDIType tmpEDIType(tmpDIType);
if(!SmartType::isTypeConsistent(AI->getAllocatedType(), &tmpEDIType)) {
continue;
}
bool skipDIType = false;
if(DDI) {
EDIType aEDIType(aDIType);
skipDIType = true;
if(!aEDIType.equals(&tmpEDIType)) {
isDuplicate = true;
}
}
if(addrDDI) {
EDIType aAddrEDIType(aAddrDIType);
skipDIType = true;
if(!aAddrEDIType.equals(&tmpEDIType)) {
isDuplicate = true;
}
}
if(!skipDIType && !DIV.getName().compare(varName)) {
aDIType = tmpDIType;
DDI = DI;
continue;
}
if(!skipDIType && !addrVarName.compare(varName)) {
aAddrDIType = tmpDIType;
addrDDI = DI;
continue;
}
}
}
}
if(isDuplicate) {
//name clashing problem with inline/scoped variables, pretend nothing was found
DDI = NULL;
addrDDI = NULL;
}
}
if(!DDI && !addrDDI) {
return (DbgDeclareInst*)-1;
}
assert((DDI && !addrDDI) || (!DDI && addrDDI));
DDI = DDI ? DDI : addrDDI;
return DDI;
#endif
}
}

View file

@ -0,0 +1,171 @@
#include <magic/support/BitFieldAggregation.h>
using namespace llvm;
namespace llvm {
#define DEBUG_BFA 0
#define BitFieldAggregation_assert_or_return(R,RV,T,ET,X) do { \
if(!(X)) { \
if(R) return RV; \
errs() << "Assertion failed, dumping types...\n"; \
errs() << TypeUtil::getDescription(T, ET); \
} \
assert(X); \
} while(0)
//===----------------------------------------------------------------------===//
// Constructors, destructor, and operators
//===----------------------------------------------------------------------===//
BitFieldAggregation::BitFieldAggregation(TYPECONST Type* type, std::vector<EDIType> EDITypes, unsigned typeIndex, unsigned EDITypeIndex, std::vector<DIDerivedType> members, unsigned counter) {
init(type, EDITypes, typeIndex, EDITypeIndex, members, counter);
}
BitFieldAggregation::BitFieldAggregation() {
type = NULL;
typeIndex = 0;
EDITypeIndex = 0;
name = "";
}
void BitFieldAggregation::init(TYPECONST Type* type, std::vector<EDIType> EDITypes, unsigned typeIndex, unsigned EDITypeIndex, std::vector<DIDerivedType> members, unsigned counter) {
assert(members.size() == EDITypes.size());
assert(typeIndex <= EDITypeIndex);
size = members.size();
assert(size > 0);
this->type = type;
this->EDITypes = EDITypes;
this->typeIndex = typeIndex;
this->EDITypeIndex = EDITypeIndex;
this->members = members;
raw_string_ostream ostream(name);
ostream << bfaNamePrefix << counter;
ostream.flush();
}
//===----------------------------------------------------------------------===//
// Getters
//===----------------------------------------------------------------------===//
const std::string BitFieldAggregation::getDescription() const {
std::string string;
raw_string_ostream ostream(string);
ostream << "[\nname = " << name << "\nmembers = ";
for(unsigned i=0;i<size;i++) {
ostream << (i==0 ? "" : ", ") << members[i].getName();
}
ostream << "\ntype = \n" << TypeUtil::getDescription(getType());
std::vector<EDIType> EDITypes = getEDITypes();
for(unsigned i=0;i<EDITypes.size();i++) {
ostream << "\nEDIType" << i << " =\n" << TypeUtil::getDescription(&EDITypes[i]);
}
ostream << "\n]";
ostream.flush();
return string;
}
//===----------------------------------------------------------------------===//
// Public static methods
//===----------------------------------------------------------------------===//
bool BitFieldAggregation::getBitFieldAggregations(TYPECONST Type *type, const EDIType *aEDIType, std::vector<BitFieldAggregation> &bfas, bool returnOnError) {
std::vector<BitFieldAggregation> emptyBfas;
if(!hasBitFields(type, aEDIType)) {
return true;
}
unsigned typeIndex = 0;
unsigned EDITypeIndex = 0;
unsigned typeContainedTypes = type->getNumContainedTypes();
unsigned aEDITypeContainedTypes = aEDIType->getNumContainedTypes();
unsigned counter = 1;
const EDIType privateEDIType(*aEDIType);
aEDIType = &privateEDIType;
while(typeIndex < typeContainedTypes) {
TYPECONST Type *containedType = type->getContainedType(typeIndex);
if(EDITypeIndex >= aEDITypeContainedTypes && typeIndex == typeContainedTypes-1 && TypeUtil::isPaddedType(type)) {
break;
}
BitFieldAggregation_assert_or_return(returnOnError, false, type, aEDIType, EDITypeIndex < aEDITypeContainedTypes);
const EDIType containedEDIType = aEDIType->getContainedType(EDITypeIndex);
unsigned typeBits = TypeUtil::typeToBits(containedType);
if(typeBits > 0 && containedEDIType.isIntegerTy()) {
unsigned EDITypeBits = aEDIType->getMember(EDITypeIndex).getSizeInBits();
assert(typeBits >= EDITypeBits);
if(typeBits > EDITypeBits) {
unsigned lastTypeIndex = typeIndex;
unsigned lastEDITypeIndex = EDITypeIndex;
while(lastEDITypeIndex+1 < aEDITypeContainedTypes && isBitField(type, aEDIType, lastEDITypeIndex+1)) { // grab all the bitfields following the first one found
lastEDITypeIndex++;
EDITypeBits += aEDIType->getMember(lastEDITypeIndex).getSizeInBits();
}
while(lastTypeIndex+1 < typeContainedTypes && EDITypeBits > typeBits) { // grab all the necessary fields to cover all the bits found in the bitfields
lastTypeIndex++;
typeBits += TypeUtil::typeToBits(type->getContainedType(lastTypeIndex));
}
BitFieldAggregation *bfa = BitFieldAggregation::getBitFieldAggregation(type, aEDIType, returnOnError, typeIndex, EDITypeIndex, lastTypeIndex, lastEDITypeIndex, counter++);
BitFieldAggregation_assert_or_return(returnOnError, false, type, aEDIType, bfa != NULL);
if(bfa->getSize() > 1) {
//we don't care about single-element aggregates
bfas.push_back(*bfa);
}
typeIndex++;
EDITypeIndex += bfa->getSize();
continue;
}
}
typeIndex++;
EDITypeIndex++;
}
return true;
}
BitFieldAggregation *BitFieldAggregation::getBitFieldAggregation(TYPECONST Type *type, const EDIType *aEDIType, bool returnOnError, unsigned typeIndex, unsigned EDITypeIndex, unsigned lastTypeIndex, unsigned lastEDITypeIndex, unsigned counter) {
static BitFieldAggregation bfa;
TYPECONST Type *containedType = type->getContainedType(typeIndex);
unsigned typeBits = TypeUtil::typeToBits(containedType);
assert(typeBits > 0);
unsigned nextTypeBits = 0;
if (typeIndex < lastTypeIndex) {
nextTypeBits = TypeUtil::typeToBits(type->getContainedType(typeIndex+1));
}
const int maxNumMembers = (lastEDITypeIndex - EDITypeIndex) - (lastTypeIndex - typeIndex) + 1;
unsigned index = EDITypeIndex;
std::vector<DIDerivedType> members;
std::vector<EDIType> containedEDITypes;
BitFieldAggregation_assert_or_return(returnOnError, NULL, type, aEDIType, maxNumMembers > 0);
#if DEBUG_BFA
BitFieldAggregationErr("getBitFieldAggregation(): typeIndex = " << typeIndex << ", EDITypeIndex = " << EDITypeIndex << ", maxNumMembers = " << maxNumMembers);
BitFieldAggregationErr("getBitFieldAggregation(): lastTypeIndex = " << lastTypeIndex << ", lastEDITypeIndex = " << lastEDITypeIndex);
BitFieldAggregationErr("getBitFieldAggregation(): " << TypeUtil::getDescription(type) << " VS " << TypeUtil::getDescription(aEDIType));
#endif
while(index <= lastEDITypeIndex && members.size() < (unsigned)maxNumMembers) {
const EDIType containedEDIType = aEDIType->getContainedType(index);
#if DEBUG_BFA
BitFieldAggregationErr("Examining type " << TypeUtil::getDescription(&containedEDIType));
#endif
BitFieldAggregation_assert_or_return(returnOnError, NULL, type, aEDIType, containedEDIType.isIntegerTy());
DIDerivedType member = aEDIType->getMember(index);
unsigned EDITypeBits = member.getSizeInBits();
#if DEBUG_BFA
BitFieldAggregationErr("Type bits = " << typeBits << ", next type bits = " << nextTypeBits << ", index = " << index);
BitFieldAggregationErr("This is member " << member.getName() << " with bits " << EDITypeBits);
#endif
if((index > EDITypeIndex && EDITypeBits == nextTypeBits) || EDITypeBits > typeBits) {
break;
}
typeBits -= EDITypeBits;
members.push_back(member);
containedEDITypes.push_back(containedEDIType);
index++;
}
bfa.init(containedType, containedEDITypes, typeIndex, EDITypeIndex, members, counter);
return &bfa;
}
std::string BitFieldAggregation::bfaNamePrefix = BFA_NAME_PREFIX;
}

View file

@ -0,0 +1,520 @@
#include <magic/support/EDIType.h>
using namespace llvm;
namespace llvm {
#define DEBUG_EDI_EQUALS 0
int debugEDIEquals = 0;
//===----------------------------------------------------------------------===//
// Constructors, destructor, and operators
//===----------------------------------------------------------------------===//
EDIType::EDIType(const MDNode *N, bool norm, bool checkOpaqueTypes) : aDIType(N) {
init(norm, checkOpaqueTypes);
}
EDIType::EDIType(bool norm, bool checkOpaqueTypes) : aDIType() {
init(norm, checkOpaqueTypes);
}
EDIType::EDIType(const DIType aDIType, bool norm, bool checkOpaqueTypes) : aDIType(aDIType) {
init(norm, checkOpaqueTypes);
}
bool EDIType::operator == (const EDIType& aEDIType) const {
const DIType oDIType = *(aEDIType.getDIType());
return (aDIType == oDIType);
}
//===----------------------------------------------------------------------===//
// Getters
//===----------------------------------------------------------------------===//
const std::string EDIType::getDescription(int skipUnions, int skipStructs, int allowMultiNames) const {
std::string string;
raw_string_ostream ostream(string);
printDescription(ostream, skipUnions, skipStructs, allowMultiNames);
ostream.flush();
return string;
}
const EDIType& EDIType::getContainedType(unsigned i, bool norm) const {
static EDIType subType;
EDIType_assert(!isBasicType() && !isVoidTy() && !isEnumTy());
bool isArrayOrVectorTy = isArrayTy() || isVectorTy();
if(isDerivedType() || isArrayOrVectorTy) {
EDIType_assert(i == 0);
if(isArrayOrVectorTy && getCurrentDimension() < getNumDimensions()-1) {
subType = *this;
subType.setCurrentDimension(getCurrentDimension() + 1);
}
else {
subType = getTypeDerivedFrom();
}
return subType;
}
DIArray aDIArray = getTypeArray();
unsigned numContainedTypes = aDIArray.getNumElements();
assert(i < numContainedTypes);
EDIType tmpType((const DIType) aDIArray.getElement(i), norm);
subType = tmpType;
return subType;
}
unsigned EDIType::getNumContainedTypes() const {
if(isBasicType() || isVoidTy() || isEnumTy()) {
return 0;
}
bool isArrayOrVectorTy = isArrayTy() || isVectorTy();
if(isDerivedType() || isArrayOrVectorTy) {
return 1;
}
DIArray aDIArray = getTypeArray();
unsigned numContainedTypes = aDIArray.getNumElements();
return numContainedTypes;
}
const DIDerivedType& EDIType::getMember(unsigned i) const {
static DIDerivedType aDIDerivedType;
EDIType_assert(isUnionOrStructTy());
DIArray aDIArray = getTypeArray();
DIDescriptor aDIDescriptor = aDIArray.getElement(i);
assert(aDIDescriptor.getTag() == dwarf::DW_TAG_member);
aDIDerivedType = (DIDerivedType) aDIDescriptor;
return aDIDerivedType;
}
bool EDIType::isUnionOrStructTy(bool isStruct, bool isUnion) const {
if(isOpaqueTy()) {
return false;
}
if((isStruct && getTag() == dwarf::DW_TAG_structure_type) ||
(isUnion && getTag() == dwarf::DW_TAG_union_type)) {
EDIType_assert(isCompositeType());
return true;
}
return false;
}
bool EDIType::hasInnerPointers() const {
if(isOpaqueTy() || isFunctionTy()) {
return false;
}
if(isPointerTy()) {
return true;
}
unsigned numContainedTypes = getNumContainedTypes();
if(numContainedTypes == 0) {
return false;
}
else if(isArrayTy() || isVectorTy()) {
const EDIType subType = getContainedType(0);
return subType.hasInnerPointers();
}
else {
assert(isUnionOrStructTy());
for(unsigned i=0;i<numContainedTypes;i++) {
const EDIType subType = getContainedType(i);
if(subType.hasInnerPointers()) {
return true;
}
}
}
return false;
}
DIArray EDIType::getTypeArray() const {
static std::set<std::string> nonOpaqueEmptyTypes;
static std::set<std::string>::iterator nonOpaqueEmptyTypesIt;
EDIType_assert(isCompositeType());
DIArray aDIArray = ((const DICompositeType)aDIType).getTypeArray();
if(aDIArray.getNumElements() == 0 && checkOpaqueTypes && myNames.size() > 0) {
const EDIType *aType = NULL;
std::string name;
for(int i=myNames.size()-1;i>=0;i--) {
name = myNames[i];
aType = getStructEDITypeByName(name);
if(aType) {
break;
}
}
if(aType) {
aDIArray = ((const DICompositeType *)aType->getDIType())->getTypeArray();
nonOpaqueEmptyTypesIt = nonOpaqueEmptyTypes.find(name);
if(nonOpaqueEmptyTypesIt == nonOpaqueEmptyTypes.end()) {
EDITypeLog("Found a non-opaque composite type with 0 members! Name is: " << name);
nonOpaqueEmptyTypes.insert(name);
}
}
}
return aDIArray;
}
const EDIType* EDIType::getTopStructType(unsigned index) const {
static unsigned level = 0;
static unsigned structsLeft;
static EDIType targetType;
if(level == 0) {
structsLeft = index;
}
if(isUnionOrStructTy() || isOpaqueTy()) {
if(structsLeft == 0) {
targetType = *this;
return &targetType;
}
else {
structsLeft--;
return NULL;
}
}
unsigned numContainedTypes = getNumContainedTypes();
for(unsigned i=0;i<numContainedTypes;i++) {
const EDIType containedType(getContainedType(i));
level++;
const EDIType *topStructType = containedType.getTopStructType(index);
level--;
if(topStructType != NULL) {
return topStructType;
}
}
return NULL;
}
//===----------------------------------------------------------------------===//
// Other public methods
//===----------------------------------------------------------------------===//
void EDIType::print(raw_ostream &OS) const {
OS << getDescription();
}
void EDIType::printDescription(raw_ostream &OS, int skipUnions, int skipStructs, int allowMultiNames) const {
static std::vector<const EDIType*> nestedTypes;
int printMultiNames = allowMultiNames && myNames.size() > 1;
if(allowMultiNames && !printMultiNames && isPointerTy() && myName.compare("")) {
printMultiNames = 1;
}
if(isOpaqueTy()) {
OS << "opaque";
return;
}
unsigned numContainedTypes = getNumContainedTypes();
if(numContainedTypes == 0) {
OS << (printMultiNames ? getNamesString() : getName());
return;
}
if(isPointerTy() && getContainedType(0).isUnionOrStructTy()) {
bool isNestedType = false;
unsigned j;
for(j=0;j<nestedTypes.size();j++) {
if(nestedTypes[j]->equals(this)) {
isNestedType = true;
break;
}
}
if(isNestedType) {
OS << "\\" << nestedTypes.size() - j;
return;
}
}
nestedTypes.push_back(this);
if(isPointerTy()) {
const EDIType subType = getContainedType(0);
subType.printDescription(OS, skipUnions, skipStructs, allowMultiNames);
OS << "*";
if(printMultiNames) {
OS << "|" << getNamesString();
}
}
else if(isArrayTy() || isVectorTy()) {
const EDIType subType = getContainedType(0);
unsigned numElements = getNumElements();
char startSep = isArrayTy() ? '[' : '<';
char endSep = isArrayTy() ? ']' : '>';
OS << startSep;
if(numElements) {
OS << numElements << " x ";
}
subType.printDescription(OS, skipUnions, skipStructs, allowMultiNames);
OS << endSep;
}
else if(isUnionOrStructTy()) {
if(skipUnions && isUnionTy()) {
OS << "(U) $" << (printMultiNames ? getNamesString() : (myName.compare("") ? myName : "ANONYMOUS"));
nestedTypes.pop_back();
return;
}
if(skipStructs && isStructTy()) {
OS << "$" << (printMultiNames ? getNamesString() : (myName.compare("") ? myName : "ANONYMOUS"));
nestedTypes.pop_back();
return;
}
unsigned numContainedTypes = getNumContainedTypes();
OS << "{ ";
if(isUnionTy()) {
OS << "(U) ";
}
OS << "$" << (printMultiNames ? getNamesString() : (myName.compare("") ? myName : "ANONYMOUS")) << " ";
for(unsigned i=0;i<numContainedTypes;i++) {
if(i > 0) {
OS << ", ";
}
EDIType subType = getContainedType(i);
subType.printDescription(OS, skipUnions, skipStructs, allowMultiNames);
}
OS << " }";
}
else if(isFunctionTy()) {
unsigned numContainedTypes = getNumContainedTypes();
assert(numContainedTypes > 0);
EDIType subType = getContainedType(0);
subType.printDescription(OS, skipUnions, skipStructs, allowMultiNames);
numContainedTypes--;
OS << " (";
for(unsigned i=0;i<numContainedTypes;i++) {
if(i > 0) {
OS << ", ";
}
subType = getContainedType(i+1);
subType.printDescription(OS, skipUnions, skipStructs, allowMultiNames);
}
OS << ")";
}
else {
OS << "???";
}
nestedTypes.pop_back();
}
bool EDIType::equals(const EDIType *other) const {
static std::set<std::pair<MDNode*, MDNode*> > compatibleMDNodes;
static std::set<std::pair<MDNode*, MDNode*> >::iterator compatibleMDNodesIt;
static int max_recursive_steps = -1;
#if DEBUG_EDI_EQUALS
if(debugEDIEquals>1) EDITypeErr("COMPARING :" << getTag() << ":" << getName() << " VS " << other->getTag() << ":" << other->getName());
#endif
if(isOpaqueTy() || other->isOpaqueTy()) {
#if DEBUG_EDI_EQUALS
if(debugEDIEquals) EDITypeErr("----> ???1");
#endif
return isOpaqueTy() && other->isOpaqueTy();
}
if(getTag() != other->getTag()) {
#if DEBUG_EDI_EQUALS
if(debugEDIEquals) EDITypeErr("----> false1");
#endif
return false;
}
unsigned numContainedTypes = getNumContainedTypes();
unsigned numOtherContainedTypes = other->getNumContainedTypes();
if(numContainedTypes != numOtherContainedTypes) {
#if DEBUG_EDI_EQUALS
if(debugEDIEquals) EDITypeErr("----> false2");
#endif
return false;
}
if(getNumElements() != other->getNumElements()) {
#if DEBUG_EDI_EQUALS
if(debugEDIEquals) EDITypeErr("----> false3");
#endif
return false;
}
if(myName.compare(other->getName())) {
#if DEBUG_EDI_EQUALS
if(debugEDIEquals) EDITypeErr("----> false4");
#endif
return false;
}
if((myNames.size() > 0 || other->getNames().size() > 0) && getNamesString().compare(other->getNamesString())) {
#if DEBUG_EDI_EQUALS
if(debugEDIEquals) EDITypeErr("----> false5");
#endif
return false;
}
if(numContainedTypes == 0) {
#if DEBUG_EDI_EQUALS
if(debugEDIEquals) EDITypeErr("----> true1");
#endif
return true;
}
MDNode *aNode = *(&aDIType);
MDNode *otherNode = *(other->getDIType());
if(aNode == otherNode) {
#if DEBUG_EDI_EQUALS
if(debugEDIEquals) EDITypeErr("----> true2");
#endif
return true;
}
int isUnionOrStruct = isUnionOrStructTy();
int isNonAnonUnionOrStruct = isUnionOrStruct && myName.size() > 0;
int saved_max_recursive_steps = max_recursive_steps;
if(max_recursive_steps == -1 && isNonAnonUnionOrStruct) {
//A simple way to break recursion for recursive non-anonymous structs/unions.
max_recursive_steps = 10;
}
else if(max_recursive_steps == 0) {
#if DEBUG_EDI_EQUALS
if(debugEDIEquals) EDITypeErr("----> true4");
#endif
return true;
}
else {
max_recursive_steps--;
}
for(unsigned i=0;i<numContainedTypes;i++) {
const EDIType &subEDIType = getContainedType(i);
const EDIType &subOtherEDIType = other->getContainedType(i);
if(!subEDIType.equals(&subOtherEDIType)) {
max_recursive_steps = saved_max_recursive_steps;
return false;
}
}
max_recursive_steps = saved_max_recursive_steps;
return true;
}
//===----------------------------------------------------------------------===//
// Public static methods
//===----------------------------------------------------------------------===//
std::string EDIType::lookupTypedefName(std::string &typedefName) {
static std::string noName;
for (DebugInfoFinder::iterator I = DIFinder.type_begin(),
E = DIFinder.type_end(); I != E; ++I) {
DIType aDIType(*I);
if(aDIType.getTag() == dwarf::DW_TAG_typedef && aDIType.getName().compare(typedefName)) {
while(aDIType.getTag() == dwarf::DW_TAG_typedef) {
aDIType = PassUtil::getDITypeDerivedFrom((const DIDerivedType)aDIType);
}
if(aDIType.getName().compare("")) {
return aDIType.getName();
}
}
}
return noName;
}
std::string EDIType::lookupUnionMemberName(TYPECONST Type* type) {
std::string string;
std::string error;
if(!type->isStructTy() || type->getNumContainedTypes() != 1) {
return "";
}
raw_string_ostream ostream(string);
writeTypeSymbolic(ostream, type->getContainedType(0), EDIType::module);
ostream.flush();
Regex unionRegex("%(union|struct)\\.([^ ]+)", 0);
assert(unionRegex.isValid(error));
SmallVector<StringRef, 8> unionMatches;
if(unionRegex.match(string, &unionMatches)) {
return unionMatches[2];
}
return "";
}
const EDIType* EDIType::getStructEDITypeByName(std::string &typeName) {
static EDIType aEDIType;
assert(module);
for (DebugInfoFinder::iterator I = DIFinder.type_begin(),
E = DIFinder.type_end(); I != E; ++I) {
const DIType aDIType(*I);
//skip zero-element stuct types, necessary to avoid infinite recursion during opaque type lookup
//xxx opaque type lookup should not be necessary but is there a bug in the frontend that leaves certain concrete types unnecessarily opaque?
const EDIType tmpEDIType(aDIType, NORMALIZE, DO_NOT_CHECK_OPAQUE_TYPES);
aEDIType = tmpEDIType;
if(typeName.compare(aEDIType.getName())) {
continue;
}
if(aEDIType.isUnionOrStructTy()) {
return &aEDIType;
}
}
return NULL;
}
void EDIType::setModule(Module *M) {
assert(module == NULL);
module = M;
DIFinder.processModule(*module);
}
//===----------------------------------------------------------------------===//
// Private methods
//===----------------------------------------------------------------------===//
void EDIType::init(bool norm, bool checkOpaqueTypes) {
EDIType_assert(isType());
currentDimension = 0;
this->checkOpaqueTypes = checkOpaqueTypes;
myName = "";
if(norm) {
normalize();
}
if(myNames.size() == 0) {
//nobody assigned names yet, do it here
myName = isVoidTy() ? voidName : aDIType.getName();
if(myName.compare("")) {
myNames.push_back(myName);
}
}
}
void EDIType::normalize() {
if(getTag() == dwarf::DW_TAG_typedef) {
normalizeTypedef();
}
if(isBasicType() || isVoidTy() || isEnumTy() || isOpaqueTy()) {
return;
}
if(isDerivedType()) {
if(isPointerTy() || isUnionOrStructTy()) {
return;
}
aDIType = PassUtil::getDITypeDerivedFrom((const DIDerivedType)aDIType);
normalize();
return;
}
EDIType_assert(isCompositeType());
if(isAggregateType() || isVectorTy() || isFunctionTy()) {
return;
}
EDIType_assert(getNumContainedTypes() == 1);
aDIType = *(getContainedType(0, DO_NOT_NORMALIZE).getDIType());
normalize();
}
void EDIType::normalizeTypedef() {
myNames.clear();
while(aDIType.getTag() == dwarf::DW_TAG_typedef) {
if(aDIType.getName().compare("")) {
myNames.push_back(aDIType.getName());
}
aDIType = PassUtil::getDITypeDerivedFrom((const DIDerivedType)aDIType);
}
myName = isVoidTy() ? voidName : aDIType.getName();
if(!myName.compare("")) {
//anonymous typedefed type, use the deepest typedef name
assert(!isBasicType());
assert(myNames.size() > 0);
myName = myNames[myNames.size()-1];
}
else {
myNames.push_back(myName);
}
}
StringRef EDIType::voidName("void");
Module *EDIType::module = NULL;
DebugInfoFinder EDIType::DIFinder;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,780 @@
#include <magic/support/SmartType.h>
#include <limits.h>
using namespace llvm;
namespace llvm {
#define DEBUG_EQUALS 0
#define DEBUG_BFAS 0
#define DEBUG_UNIONS 0
int debugEquals = 0;
//===----------------------------------------------------------------------===//
// Constructors, destructor, and operators
//===----------------------------------------------------------------------===//
SmartType::SmartType(const SmartType& et) {
cloneFrom(et);
}
SmartType::SmartType(TYPECONST Type *type, const DIType *aDIType, bool useExceptions, bool forceRawTypeRepresentation) {
EDIType tmp(*aDIType);
init(type, &tmp, useExceptions, forceRawTypeRepresentation);
normalize();
}
SmartType::SmartType(TYPECONST Type *type, const EDIType *aEDIType, bool useExceptions, bool forceRawTypeRepresentation) {
init(type, aEDIType, useExceptions, forceRawTypeRepresentation);
normalize();
}
SmartType::~SmartType() {
if(hasExplicitContainedEDITypes) {
for(unsigned i=0;i<explicitContainedEDITypes.size();i++) {
const EDIType* aEDIType = explicitContainedEDITypes[i];
delete aEDIType;
}
}
}
SmartType& SmartType::operator=(const SmartType& et) {
if (this != &et) {
cloneFrom(et);
}
return *this;
}
void SmartType::cloneFrom(const SmartType& et) {
init(et.type, &et.aEDIType, et.useExceptions, false);
if(et.hasExplicitContainedEDITypes) {
hasExplicitContainedEDITypes = true;
for(unsigned i=0;i<et.explicitContainedEDITypes.size();i++) {
const EDIType* aEDIType = et.explicitContainedEDITypes[i];
explicitContainedEDITypes.push_back(new EDIType(*aEDIType));
}
}
isInconsistent = et.isInconsistent;
rawTypeRepresentation = et.rawTypeRepresentation;
bfas = et.bfas;
}
//===----------------------------------------------------------------------===//
// Getters
//===----------------------------------------------------------------------===//
const std::string SmartType::getDescription() const {
return TypeUtil::getDescription(type, &aEDIType);
}
const SmartType* SmartType::getContainedType(unsigned i) const {
assert(!rawTypeRepresentation);
bool hasBitFields = false;
TYPECONST Type *subType = type->getContainedType(i);
const SmartType* retSmartType = NULL;
if(hasExplicitContainedEDITypes) {
const EDIType subEDIType(*(explicitContainedEDITypes[i]));
retSmartType = new SmartType(subType, &subEDIType, useExceptions);
}
else {
if(aEDIType.isUnionTy()) {
assert(i == 0);
i = unionMemberIdx;
}
else if(bfas.size() > 0) {
i = getBFAFreeIdx(i, bfas);
hasBitFields = true;
}
const EDIType subEDIType(aEDIType.getContainedType(i));
retSmartType = new SmartType(subType, &subEDIType, useExceptions, hasBitFields && subEDIType.isIntegerTy() && subType->isArrayTy());
}
return retSmartType;
}
unsigned SmartType::getNumContainedTypes() const {
if(rawTypeRepresentation || aEDIType.isComplexFloatingPointTy() || isOpaqueTy()) {
return 0;
}
unsigned numContainedTypes = type->getNumContainedTypes();
unsigned numContainedEDITypes;
if(hasExplicitContainedEDITypes) {
numContainedEDITypes = explicitContainedEDITypes.size();
}
else {
if(aEDIType.isUnionTy()) {
numContainedEDITypes = 1;
}
else {
numContainedEDITypes = aEDIType.getNumContainedTypes();
if(bfas.size() > 0) {
for(unsigned i=0;i<bfas.size();i++) {
numContainedEDITypes -= (bfas[i].getSize() - 1);
}
}
}
}
if(numContainedTypes == numContainedEDITypes+1 && isPaddedTy()) {
numContainedTypes--;
}
if(numContainedTypes != numContainedEDITypes) {
if(isArrayTy() && TypeUtil::isArrayAsStructTy(type)) {
numContainedTypes = 1;
}
}
SmartType_assert(numContainedTypes == numContainedEDITypes);
return numContainedTypes;
}
const DIDerivedType& SmartType::getMember(unsigned i) const {
assert(!rawTypeRepresentation);
if(bfas.size() > 0) {
i = getBFAFreeIdx(i, bfas);
}
return aEDIType.getMember(i);
}
unsigned SmartType::getUnionMemberIdx() const {
assert(!rawTypeRepresentation);
SmartType_assert(isTy(type->isStructTy(), aEDIType.isUnionTy(), "getUnionMemberIdx"));
SmartType_assert(getNumContainedTypes() == 1);
TYPECONST Type* uMemberType = type->getContainedType(0);
unsigned numSubEDITypes = aEDIType.getNumContainedTypes();
std::vector<unsigned> indexes;
int maxWeakConsistencyLevel = -1;
unsigned maxWeakConsistencyIndex = -1;
int maxWeakConsistencyLevelEntries;
unsigned index;
for(unsigned i=0;i<numSubEDITypes;i++) {
int weakConsistencyLevel;
EDIType subEDIType = aEDIType.getContainedType(i);
if(isTypeConsistent(uMemberType, &subEDIType, true, &weakConsistencyLevel)) {
indexes.push_back(i);
if(weakConsistencyLevel > maxWeakConsistencyLevel) {
maxWeakConsistencyLevel = weakConsistencyLevel;
maxWeakConsistencyIndex = i;
maxWeakConsistencyLevelEntries = 1;
}
else if(weakConsistencyLevel == maxWeakConsistencyLevel) {
maxWeakConsistencyLevelEntries++;
}
}
}
if(indexes.size() == 0) {
//try to match names if we failed before
std::string name = EDIType::lookupUnionMemberName(type);
if(name.compare("")) {
for(unsigned i=0;i<numSubEDITypes;i++) {
EDIType subEDIType = aEDIType.getContainedType(i);
if(!subEDIType.getName().compare(name)) {
indexes.push_back(i);
maxWeakConsistencyIndex = i;
}
}
}
}
if(indexes.size() == 0) {
//No valid union member found
#if DEBUG_UNIONS
SmartTypeErr("getUnionMemberIdx: resorting to a raw type. No valid union member found for: " << getDescription());
#endif
return UINT_MAX;
}
index = maxWeakConsistencyIndex;
if(indexes.size() > 1) {
SmartTypeLog("getUnionMemberIdx: warning: multiple valid union members found, automatically selecting the first most-consistent member:");
SmartTypeLog(" - target member type is: " << TypeUtil::getDescription(uMemberType));
SmartTypeLog(" - selected index is: " << index);
for(unsigned i=0;i<indexes.size();i++) {
EDIType subEDIType = aEDIType.getContainedType(indexes[i]);
SmartTypeLog(" - " << indexes[i] << ". " << TypeUtil::getDescription(&subEDIType));
}
}
return index;
}
const SmartType* SmartType::getTopStructType(unsigned index) const {
TYPECONST Type *topType = TypeUtil::lookupTopStructType(type, index);
const EDIType *topEDIType = aEDIType.getTopStructType(index);
assert((topType && topEDIType) || (!topType && !topEDIType));
if(topType) {
const SmartType* retSmartType = new SmartType(topType, topEDIType);
return retSmartType;
}
return NULL;
}
//===----------------------------------------------------------------------===//
// Other public methods
//===----------------------------------------------------------------------===//
void SmartType::verify() const {
SmartType_assert(isTypeConsistent());
}
void SmartType::print(raw_ostream &OS) const {
OS << getDescription();
}
bool SmartType::equals(const SmartType* other, bool isDebug) const {
static std::set<std::pair<MDNode*, MDNode*> > compatibleMDNodes;
static std::set<std::pair<MDNode*, MDNode*> >::iterator compatibleMDNodesIt;
#if DEBUG_EQUALS
if(debugEquals) SmartTypeErr("COMPARING :" << getDescription() << " VS " << other->getDescription());
#endif
if(type != other->getType()) {
#if DEBUG_EQUALS
if(debugEquals) SmartTypeErr("----> false1");
#endif
return false;
}
if(isOpaqueTy() || other->isOpaqueTy()) {
return isOpaqueTy() && other->isOpaqueTy();
}
if(aEDIType.getTag() != other->getEDIType()->getTag()) {
#if DEBUG_EQUALS
if(debugEquals) SmartTypeErr("----> false1b");
#endif
return false;
}
if(isFunctionTy() && (!isTypeConsistent() || !other->isTypeConsistent())) {
//we just compare the types for inconsistent functions types
return true;
}
if(hasRawTypeRepresentation() || other->hasRawTypeRepresentation()) {
return !aEDIType.getNamesString().compare(other->getEDIType()->getNamesString());
}
unsigned numContainedTypes = getNumContainedTypes();
unsigned otherNumContainedTypes = other->getNumContainedTypes();
if(numContainedTypes != otherNumContainedTypes) {
#if DEBUG_EQUALS
if(debugEquals) SmartTypeErr("----> false2");
#endif
return false;
}
unsigned numElements = aEDIType.getNumElements();
unsigned otherNumElements = other->getEDIType()->getNumElements();
if(numElements != otherNumElements) {
#if DEBUG_EQUALS
if(debugEquals) SmartTypeErr("----> false2b");
#endif
return false;
}
std::string name = aEDIType.getName();
std::string otherName = other->getEDIType()->getName();
if(name.compare(otherName)) {
#if DEBUG_EQUALS
if(debugEquals) SmartTypeErr("----> false3: " << name << " vs " << otherName);
#endif
return false;
}
if(aEDIType.getNames().size() > 1 || other->getEDIType()->getNames().size() > 1) {
std::string namesString = aEDIType.getNamesString();
std::string otherNamesString = other->getEDIType()->getNamesString();
if(namesString.compare(otherNamesString)) {
#if DEBUG_EQUALS
if(debugEquals) SmartTypeErr("----> false4: " << namesString << " vs " << otherNamesString);
#endif
return false;
}
}
if(numContainedTypes == 0) {
#if DEBUG_EQUALS
if(debugEquals) SmartTypeErr("----> true4");
#endif
return true;
}
MDNode *node = *(aEDIType.getDIType());
MDNode *otherNode = *(other->getEDIType()->getDIType());
if(node == otherNode) {
return true;
}
for(unsigned i=0;i<SmartType::equalsNestedTypes.size();i++) {
if(type == SmartType::equalsNestedTypes[i]) {
#if DEBUG_EQUALS
if(debugEquals) SmartTypeErr("----> true5");
#endif
return true;
}
}
//before digging the type tree, see if we have these 2 metadata nodes in cache
//this gives us an impressive speedup
MDNode *minNode = node < otherNode ? node : otherNode;
MDNode *maxNode = node < otherNode ? otherNode : node;
compatibleMDNodesIt = compatibleMDNodes.find(std::pair<MDNode*, MDNode*>(minNode, maxNode));
if(compatibleMDNodesIt != compatibleMDNodes.end()) {
return true;
}
SmartType::equalsNestedTypes.push_back(type);
const SmartType* containedType = NULL;
const SmartType* otherContainedType = NULL;
bool sameContainedTypes = true;
for(unsigned i=0;i<numContainedTypes;i++) {
containedType = getContainedType(i);
otherContainedType = other->getContainedType(i);
sameContainedTypes = containedType->equals(otherContainedType);
delete containedType;
delete otherContainedType;
if(!sameContainedTypes) {
break;
}
}
SmartType::equalsNestedTypes.pop_back();
if(!sameContainedTypes) {
#if DEBUG_EQUALS
if(debugEquals) SmartTypeErr("----> false6");
#endif
return false;
}
#if DEBUG_EQUALS
if(debugEquals) SmartTypeErr("----> true7");
#endif
compatibleMDNodes.insert(std::pair<MDNode*, MDNode*>(minNode, maxNode));
return true;
}
//===----------------------------------------------------------------------===//
// Public static methods
//===----------------------------------------------------------------------===//
const SmartType* SmartType::getSmartTypeFromGV(Module &M, GlobalVariable *GV, DIGlobalVariable *DIG) {
//ignore anonymous strings
if(GV->getName().startswith(".str")) {
return NULL;
}
Value *DIGV = Backports::findDbgGlobalDeclare(GV);
if (!DIGV) {
return NULL;
}
DIGlobalVariable Var(cast<MDNode>(DIGV));
DIType aDIType = Var.getType();
const SmartType* retSmartType = new SmartType(GV->getType()->getElementType(), &aDIType);
if(DIG) {
*DIG = Var;
}
return retSmartType;
}
const SmartType* SmartType::getSmartTypeFromLV(Module &M, AllocaInst *AI, DIVariable *DIV) {
const DbgDeclareInst *DDI = Backports::FindAllocaDbgDeclare(AI);
if (!DDI) {
return NULL;
}
if(DDI == (const DbgDeclareInst *) -1) {
return (const SmartType*)-1;
}
DIVariable Var(cast<MDNode>(DDI->getVariable()));
DIType aDIType = Var.getType();
if(DIV) {
*DIV = Var;
}
const SmartType* aSmartType = new SmartType(AI->getAllocatedType(), &aDIType);
return aSmartType;
}
const SmartType* SmartType::getSmartTypeFromFunction(Module &M, Function *F, DISubprogram *DIS) {
Value *DIF = Backports::findDbgSubprogramDeclare(F);
if (!DIF) {
return NULL;
}
DISubprogram Sub(cast<MDNode>(DIF));
DIType aDIType = Sub.getType();
const SmartType* retSmartType = new SmartType(F->getType()->getElementType(), &aDIType);
if(DIS) {
*DIS = Sub;
}
return retSmartType;
}
const SmartType* SmartType::getStructSmartTypeByName(Module &M, GlobalVariable* GV, std::string &name, bool isUnion) {
std::string structName((isUnion ? "union." : "struct.") + name);
TYPECONST Type *targetType = M.getTypeByName(structName);
const EDIType *targetEDIType = EDIType::getStructEDITypeByName(name);
const SmartType *retSmartType = NULL;
if(targetType && targetEDIType) {
retSmartType = new SmartType(targetType, targetEDIType);
}
return retSmartType;
}
std::vector<const SmartType*>* SmartType::getTopStructSmartTypes(Module &M, GlobalVariable* GV) {
std::vector<std::string> names;
std::vector<unsigned> flags;
TypeUtil::parseTopStructTypes(M, GV->getType()->getElementType(), &names, &flags);
std::vector<const SmartType*> *vector = new std::vector<const SmartType*>;
for(unsigned i=0;i<names.size();i++) {
std::string entryName = names[i];
unsigned entryFlags = flags[i];
const SmartType *aSmartType = NULL;
if(!(entryFlags & TypeUtil::TYPE_ANONYMOUS) && !(entryFlags & TypeUtil::TYPE_UNNAMED)) {
aSmartType = getStructSmartTypeByName(M, GV, entryName, (entryFlags & TypeUtil::TYPE_UNION));
}
if(aSmartType == NULL) {
//this method can fail due to name clashing but is the only one possible for anonymous or unnamed struct types
const SmartType *GVSmartType = getSmartTypeFromGV(M, GV);
assert(GVSmartType && "Unable to find a match for anonymous or unnamed struct type");
aSmartType = GVSmartType->getTopStructType(i);
delete GVSmartType;
assert(aSmartType != NULL);
}
vector->push_back(aSmartType);
}
return vector;
}
//===----------------------------------------------------------------------===//
// Private methods
//===----------------------------------------------------------------------===//
void SmartType::init(TYPECONST Type *type, const EDIType *aEDIType, bool useExceptions, bool forceRawTypeRepresentation) {
this->type = type;
this->aEDIType = *aEDIType;
this->useExceptions = useExceptions;
hasExplicitContainedEDITypes = false;
isInconsistent = false;
rawTypeRepresentation = false;
unionMemberIdx = 0;
if(aEDIType->isUnionTy()) {
if(forceRawUnions) {
rawTypeRepresentation = true;
}
else {
unionMemberIdx = getUnionMemberIdx();
if(unionMemberIdx == UINT_MAX) {
rawTypeRepresentation = true;
unionMemberIdx = 0;
}
}
}
else if(forceRawTypeRepresentation || (forceRawBitfields && BitFieldAggregation::hasBitFields(type, &(this->aEDIType)))) {
rawTypeRepresentation = true;
}
}
void SmartType::normalize() {
if(isFunctionTy() && !hasExplicitContainedEDITypes) {
flattenFunctionTy();
hasExplicitContainedEDITypes = true;
}
if(!hasExplicitContainedEDITypes && !rawTypeRepresentation) {
if(!BitFieldAggregation::getBitFieldAggregations(type, &aEDIType, bfas, true)) {
//failed to determine bfas
#if DEBUG_BFAS
SmartTypeErr("normalize: resorting to a raw type. Cannot determine bfas for: " << getDescription());
#endif
rawTypeRepresentation = true;
}
}
}
void SmartType::flattenFunctionTy() {
SmartType_assert(isFunctionTy() && !hasExplicitContainedEDITypes);
SmartType_assert(explicitContainedEDITypes.size() == 0);
#if MAGIC_FLATTEN_FUNCTION_ARGS
int ret = flattenFunctionArgs(type, &aEDIType, 0);
if(ret < 0 || explicitContainedEDITypes.size() != type->getNumContainedTypes()) {
SmartTypeLog("Warning: function flattening produced an inconsistent type!");
isInconsistent = true;
}
#else
isInconsistent = true;
#endif
}
int SmartType::flattenFunctionArgs(TYPECONST Type *type, const EDIType *aEDIType, unsigned nextContainedType) {
unsigned containedTypes = type->getNumContainedTypes();
unsigned containedEDITypes = aEDIType->isUnionTy() ? 1 : aEDIType->getNumContainedTypes();
unsigned containedEDIOptions = aEDIType->isUnionTy() ? aEDIType->getNumContainedTypes() : 1;
int ret;
unsigned nextContainedEDIType = 0;
while(nextContainedEDIType < containedEDITypes) {
SmartType_assert(nextContainedType < containedTypes);
TYPECONST Type *containedType = type->getContainedType(nextContainedType);
unsigned currExplicitEDITypes = explicitContainedEDITypes.size();
unsigned i;
for(i=nextContainedEDIType;i<nextContainedEDIType+containedEDIOptions;i++) {
const EDIType containedEDIType = aEDIType->getContainedType(i);
if(isTypeConsistent(containedType, &containedEDIType)) {
explicitContainedEDITypes.push_back(new EDIType(containedEDIType));
break;
}
if(!containedEDIType.isAggregateType()) {
continue;
}
ret = flattenFunctionArgs(type, &containedEDIType, nextContainedType);
if(ret == 0) {
break;
}
}
if(i >= nextContainedEDIType+containedEDIOptions) {
while(explicitContainedEDITypes.size() > currExplicitEDITypes) {
EDIType* aEDIType = explicitContainedEDITypes[explicitContainedEDITypes.size()-1];
explicitContainedEDITypes.pop_back();
delete aEDIType;
}
return -1;
}
nextContainedType += (explicitContainedEDITypes.size() - currExplicitEDITypes);
nextContainedEDIType++;
}
return 0;
}
bool SmartType::isTy(bool isTyType, bool isTyEDIType, const char* source) const {
bool check = (isTyType && isTyEDIType) || (!isTyType && !isTyEDIType);
if(!check) {
SmartTypeErr(source << " failed");
}
SmartType_assert(check);
return isTyType;
}
//===----------------------------------------------------------------------===//
// Private static methods
//===----------------------------------------------------------------------===//
unsigned SmartType::getBFAFreeIdx(unsigned i, const std::vector<BitFieldAggregation> &inputBfas) {
for(unsigned j=0;j<inputBfas.size();j++) {
if(i<inputBfas[j].getEDITypeIndex()) {
break;
}
else if(i>inputBfas[j].getEDITypeIndex()) {
i += (inputBfas[j].getSize() - 1);
}
else {
i = inputBfas[j].getRepresentativeEDITypeIndex();
break;
}
}
return i;
}
bool SmartType::isRawTypeConsistent(TYPECONST Type *type, const EDIType *aEDIType) {
if(aEDIType->isVoidTy()) {
return type->isVoidTy() || (type->isIntegerTy() && ((IntegerType*)type)->getBitWidth() == 8);
}
if(type->isFloatingPointTy()) {
return aEDIType->isFloatingPointTy();
}
if(type->isIntegerTy()) {
if(aEDIType->isCharTy() || aEDIType->isBoolTy()) {
return (((IntegerType*)type)->getBitWidth() <= 8);
}
return aEDIType->isIntegerTy() || aEDIType->isEnumTy();
}
if(type->isFunctionTy()) {
return aEDIType->isFunctionTy();
}
if(TypeUtil::isOpaqueTy(type)) {
return (aEDIType->isOpaqueTy());
}
return false;
}
bool SmartType::isTypeConsistent2(std::vector<TYPECONST Type*> &nestedTypes, std::vector<const EDIType*> &nestedEDITypes, const SmartType *aSmartType) {
assert(aSmartType->isUseExceptions());
TYPECONST Type *type = aSmartType->getType();
const EDIType *aEDIType = aSmartType->getEDIType();
if(aEDIType->isPointerTy() || aEDIType->isUnionOrStructTy()) {
for(unsigned j=0;j<nestedTypes.size();j++) {
if(nestedTypes[j] == type && nestedEDITypes[j]->equals(aEDIType)) {
return true;
}
}
}
unsigned nTypes = type->getNumContainedTypes();
unsigned nEDITypes = aEDIType->getNumContainedTypes();
if(nTypes == 0 || nEDITypes == 0) {
if(nTypes != 0 || nEDITypes != 0) {
return false;
}
return isRawTypeConsistent(type, aEDIType);
}
if(!aSmartType->verifyTy()) {
return false;
}
unsigned numContainedTypes = aSmartType->getNumContainedTypes();
nestedTypes.push_back(type);
nestedEDITypes.push_back(aEDIType);
for(unsigned i=0;i<numContainedTypes;i++) {
const SmartType *containedSmartType = aSmartType->getContainedType(i);
assert(containedSmartType->isUseExceptions());
SmartType clonedSmartType(*containedSmartType);
assert(clonedSmartType.isUseExceptions());
delete containedSmartType;
if(!isTypeConsistent2(nestedTypes, nestedEDITypes, &clonedSmartType)) {
return false;
}
}
nestedTypes.pop_back();
nestedEDITypes.pop_back();
return true;
}
bool SmartType::isTypeConsistent2(TYPECONST Type *type, const EDIType *aEDIType) {
/* Exception-handling based isTypeConsistent(). Broken with -fno-exceptions. */
static std::vector<TYPECONST Type*> nestedTypes;
static std::vector<const EDIType*> nestedEDITypes;
static unsigned level = 0;
if(level == 0) {
nestedTypes.clear();
nestedEDITypes.clear();
}
bool checkTypeConsistent = false;
bool useExceptions = true;
level++;
assert(useExceptions);
TRY(
const SmartType aSmartType(type, aEDIType, useExceptions);
checkTypeConsistent = isTypeConsistent2(nestedTypes, nestedEDITypes, &aSmartType);
)
CATCH(std::exception& e,
checkTypeConsistent = false;
)
level--;
return checkTypeConsistent;
}
bool SmartType::isTypeConsistent(TYPECONST Type *type, const EDIType *aEDIType, bool useBfas, int *weakConsistencyLevel) {
static std::vector<TYPECONST Type*> nestedTypes;
static std::vector<const EDIType*> nestedEDITypes;
static unsigned level = 0;
if(level == 0) {
if(weakConsistencyLevel) {
*weakConsistencyLevel = INT_MAX;
}
}
if(aEDIType->isPointerTy() || aEDIType->isUnionOrStructTy()) {
for(unsigned j=0;j<nestedTypes.size();j++) {
if(nestedTypes[j] == type && nestedEDITypes[j]->equals(aEDIType)) {
return true;
}
}
}
unsigned nTypes = type->getNumContainedTypes();
unsigned nEDITypes = aEDIType->getNumContainedTypes();
if(nTypes == 0 || nEDITypes == 0) {
if(nTypes != 0 || nEDITypes != 0) {
return false;
}
return isRawTypeConsistent(type, aEDIType);
}
if(aEDIType->isOpaqueTy()) {
return (TypeUtil::isOpaqueTy(type));
}
bool isArrayOrVectorTy = aEDIType->isArrayTy() || aEDIType->isVectorTy();
unsigned nEDINumElements = aEDIType->getNumElements();
if(aEDIType->isDerivedType() || isArrayOrVectorTy) {
TYPECONST Type *nextType = type;
if(aEDIType->isPointerTy()) {
if(!type->isPointerTy()) {
return false;
}
nextType = type->getContainedType(0);
}
else if(aEDIType->isArrayTy()) {
if(!type->isArrayTy() || ((ArrayType*)type)->getNumElements() != nEDINumElements) {
return false;
}
nextType = type->getContainedType(0);
}
else if(aEDIType->isVectorTy()) {
if(!type->isVectorTy() || ((VectorType*)type)->getNumElements() != nEDINumElements) {
return false;
}
nextType = type->getContainedType(0);
}
const EDIType aEDISubType(aEDIType->getContainedType(0));
nestedEDITypes.push_back(aEDIType);
nestedTypes.push_back(type);
level++;
bool ret = isTypeConsistent(nextType, &aEDISubType, useBfas, weakConsistencyLevel);
level--;
nestedTypes.pop_back();
nestedEDITypes.pop_back();
return ret;
}
else if(aEDIType->isCompositeType()) {
if(!aEDIType->isUnionOrStructTy() && !aEDIType->isVectorTy() && !aEDIType->isFunctionTy()) {
return false;
}
if(aEDIType->isUnionOrStructTy() && !type->isStructTy()) {
return false;
}
if(aEDIType->isVectorTy() && !type->isVectorTy()) {
return false;
}
if(aEDIType->isFunctionTy() && !type->isFunctionTy()) {
return false;
}
if(aEDIType->isUnionTy() || aEDIType->isFunctionTy()) {
if(weakConsistencyLevel) {
*weakConsistencyLevel = level;
}
return true; //xxx we should be less conservative here
}
unsigned numContainedEDITypes = aEDIType->getNumContainedTypes();
std::vector<BitFieldAggregation> myBfas;
if(numContainedEDITypes != type->getNumContainedTypes()) {
if(!useBfas) {
return false;
}
if(!BitFieldAggregation::getBitFieldAggregations(type, aEDIType, myBfas, true)) {
return false;
}
for(unsigned i=0;i<myBfas.size();i++) {
numContainedEDITypes -= (myBfas[i].getSize() - 1);
}
if(numContainedEDITypes != type->getNumContainedTypes()) {
return false;
}
nestedEDITypes.push_back(aEDIType);
nestedTypes.push_back(type);
level++;
for(unsigned i=0;i<numContainedEDITypes;i++) {
const EDIType aEDISubType(aEDIType->getContainedType(getBFAFreeIdx(i, myBfas)));
if(!isTypeConsistent(type->getContainedType(i), &aEDISubType, useBfas, weakConsistencyLevel)) {
level--;
nestedTypes.pop_back();
nestedEDITypes.pop_back();
return false;
}
}
level--;
nestedTypes.pop_back();
nestedEDITypes.pop_back();
return true;
}
nestedEDITypes.push_back(aEDIType);
nestedTypes.push_back(type);
level++;
for(unsigned i=0;i<numContainedEDITypes;i++) {
const EDIType aEDISubType(aEDIType->getContainedType(i));
if(!isTypeConsistent(type->getContainedType(i), &aEDISubType, useBfas, weakConsistencyLevel)) {
level--;
nestedTypes.pop_back();
nestedEDITypes.pop_back();
return false;
}
}
level--;
nestedTypes.pop_back();
nestedEDITypes.pop_back();
return true;
}
return false;
}
std::vector<TYPECONST Type*> SmartType::equalsNestedTypes;
}

View file

@ -0,0 +1,388 @@
#include <magic/support/TypeUtil.h>
using namespace llvm;
namespace llvm {
//===----------------------------------------------------------------------===//
// Public static methods
//===----------------------------------------------------------------------===//
bool TypeUtil::isPaddedType(TYPECONST Type *type) {
if(type->getNumContainedTypes() < 2) {
return false;
}
TYPECONST Type *lastContainedType = type->getContainedType(type->getNumContainedTypes() - 1);
bool paddedTy = lastContainedType->isIntegerTy() || (lastContainedType->isArrayTy() &&
lastContainedType->getContainedType(0)->isIntegerTy());
return paddedTy;
}
TYPECONST Type* TypeUtil::lookupTopStructType(TYPECONST Type *type, unsigned index) {
static unsigned level = 0;
static unsigned structsLeft;
if(level == 0) {
structsLeft = index;
}
if(type->isStructTy() || TypeUtil::isOpaqueTy(type)) {
if(structsLeft == 0) {
return type;
}
else {
structsLeft--;
return NULL;
}
}
unsigned numContainedTypes = type->getNumContainedTypes();
for(unsigned i=0;i<numContainedTypes;i++) {
TYPECONST Type *containedType = type->getContainedType(i);
level++;
TYPECONST Type *topStructType = lookupTopStructType(containedType, index);
level--;
if(topStructType != NULL) {
return topStructType;
}
}
return NULL;
}
void TypeUtil::parseTopStructTypes(Module &M, TYPECONST Type *type, std::vector<std::string> *names, std::vector<unsigned> *flags) {
std::string string;
raw_string_ostream ostream(string);
EDIType::writeTypeSymbolic(ostream, type, &M);
ostream.flush();
Regex anonRegex("%(union|struct)\\.(\\.*[0-9]*anon)", 0);
Regex regularRegex("%(union|struct)\\.([^{}(), *]+)", 0);
Regex unnamedRegex("%(%)?([0-9]+)", 0);
std::string error;
assert(anonRegex.isValid(error) && regularRegex.isValid(error) && unnamedRegex.isValid(error));
size_t index = -1;
while((index=string.find("%", index+1))!=std::string::npos) {
std::string entryString = string.substr(index);
if(entryString[entryString.size()-1] == ']') {
entryString = entryString.substr(0, entryString.size()-1);
}
StringRef entryStringRef(entryString);
SmallVector<StringRef, 8> entryMatches;
unsigned entryFlags;
entryMatches.clear();
entryFlags = 0;
if(anonRegex.match(entryString, &entryMatches)) {
entryFlags |= TypeUtil::TYPE_ANONYMOUS;
}
else if(unnamedRegex.match(entryString, &entryMatches)) {
entryFlags |= TypeUtil::TYPE_UNNAMED;
}
else {
assert(regularRegex.match(entryString, &entryMatches) && "Unsupported struct type");
}
assert(entryStringRef.startswith(entryMatches[0]));
std::string prefix = entryMatches[1];
std::string name = entryMatches[2];
entryFlags |= !prefix.compare("union") ? TypeUtil::TYPE_UNION : TypeUtil::TYPE_STRUCT;
if(names) names->push_back(name);
if(flags) flags->push_back(entryFlags);
}
}
int TypeUtil::findTopStructTypeIndex(Module &M, TYPECONST Type *type, std::string &name, unsigned flagsToAccept) {
std::vector<std::string> names;
std::vector<unsigned> flags;
parseTopStructTypes(M, type, &names, &flags);
int index = -1;
for(unsigned i=0;i<names.size();i++) {
if(!name.compare(names[i]) && (flagsToAccept | flags[i]) == flagsToAccept) {
index = i;
break;
}
}
return index;
}
TYPECONST Type* TypeUtil::getRecursiveElementType(TYPECONST Type *type) {
TYPECONST PointerType* pointerType = dyn_cast<PointerType>(type);
if(!pointerType) {
return type;
}
return getRecursiveElementType(pointerType->getElementType());
}
TYPECONST Type* TypeUtil::getArrayFreePointerType(TYPECONST Type *type) {
if(type->isPointerTy() || type->isArrayTy()) {
TYPECONST Type* elementType = getArrayFreePointerType(type->getContainedType(0));
type = PointerType::get(elementType, 0);
}
return type;
}
bool TypeUtil::hasInnerPointers(TYPECONST Type *type) {
if(TypeUtil::isOpaqueTy(type) || type->isFunctionTy()) {
return false;
}
if(type->isPointerTy()) {
return true;
}
unsigned numContainedTypes = type->getNumContainedTypes();
if(numContainedTypes == 0) {
return false;
}
else if(type->isArrayTy() || type->isVectorTy()) {
return hasInnerPointers(type->getContainedType(0));
}
else {
assert(type->isStructTy());
for(unsigned i=0;i<numContainedTypes;i++) {
if(hasInnerPointers(type->getContainedType(i))) {
return true;
}
}
}
return false;
}
bool TypeUtil::isArrayAsStructTy(TYPECONST Type *type) {
if(!type->isStructTy()) {
return false;
}
return type->getNumContainedTypes() == 1 || type->getContainedType(0) == type->getContainedType(1);
}
unsigned TypeUtil::getHash(TYPECONST Type* type) {
return (unsigned) PassUtil::getTypeHash(type);
}
const std::string TypeUtil::getDescription(TYPECONST Type* type,
size_t max_chars /*= 0*/, size_t max_levels /*= 0*/) {
std::string string;
if(!PRINT_SKIP_UNIONS && !PRINT_SKIP_STRUCTS && PRINT_USE_BUILTIN_PRINTING) {
string = PassUtil::getTypeDescription(type);
}
else {
raw_string_ostream ostream(string);
printTypeString(ostream, type, max_chars, max_levels);
ostream.flush();
}
if(VERBOSE_LEVEL > 0) {
string = getFormattedDescription(string);
}
return string;
}
const std::string TypeUtil::getDescription(const EDIType* aEDIType) {
std::string string;
string = aEDIType->getDescription(PRINT_SKIP_UNIONS, PRINT_SKIP_STRUCTS, PRINT_MULTI_NAMES);
if(VERBOSE_LEVEL > 0) {
string = getFormattedDescription(string);
}
if(VERBOSE_LEVEL > 1) {
raw_string_ostream ostream(string);
ostream << "\n\t";
aEDIType->getDIType()->print(ostream);
ostream.flush();
}
return string;
}
const std::string TypeUtil::getDescription(TYPECONST Type* type, const EDIType* aEDIType,
size_t max_chars /*= 0*/, size_t max_levels /*= 0*/) {
std::string string;
string = "[\ntype = \n";
string.append(TypeUtil::getDescription(type, max_chars, max_levels));
string.append("\nEDIType =\n");
string.append(TypeUtil::getDescription(aEDIType));
string.append("\n]");
return string;
}
const std::string TypeUtil::getFormattedDescription(std::string &description) {
std::string string;
raw_string_ostream ostream(string);
printFormattedTypeString(ostream, description, 0, description.size());
ostream.flush();
return string;
}
void TypeUtil::printFormattedTypeString(raw_ostream &OS, std::string &typeStr, int start, int length) {
static int indent = 0;
for(int k=0;k<indent;k++) OS << " ";
for(int i=start;i<start+length;i++) {
OS << typeStr[i];
if(typeStr[i] == '{') {
int newLength = 0;
int structsFound = 0;
int j;
for(j=i+2;j<start+length;j++) {
switch(typeStr[j]) {
case '{':
structsFound++;
break;
case '}':
if(structsFound == 0) {
newLength = j-i-3;
}
else {
structsFound--;
}
break;
}
if(newLength != 0) {
break;
}
}
assert(newLength > 0);
OS << "\n";
indent += 2;
printFormattedTypeString(OS, typeStr, i+2, newLength);
indent -= 2;
OS << "\n";
for(int k=0;k<indent;k++) OS << " ";
i = j;
OS << typeStr[i];
}
}
}
void TypeUtil::printTypeString(raw_ostream &OS, TYPECONST Type* type,
size_t max_chars /*= 0*/, size_t max_levels /*= 0*/) {
static std::vector<TYPECONST Type*> nestedTypes;
static unsigned level = 0;
static unsigned counter;
if (level == 0) {
counter = 0;
}
else if(max_chars && counter >= max_chars) {
OS << "%%";
return;
}
else if(max_levels && level >= max_levels) {
OS << "%%";
return;
}
if(TypeUtil::isOpaqueTy(type)) {
OS << "opaque";
counter += 6;
return;
}
unsigned numContainedTypes = type->getNumContainedTypes();
if(numContainedTypes == 0) {
assert(!type->isStructTy());
type->print(OS);
counter += 2;
return;
}
if(type->isPointerTy() && type->getContainedType(0)->isStructTy()) {
bool isNestedType = false;
unsigned j;
for(j=0;j<nestedTypes.size();j++) {
if(nestedTypes[j] == type) {
isNestedType = true;
break;
}
}
if(isNestedType) {
OS << "\\" << nestedTypes.size() - j;
counter += 2;
return;
}
}
nestedTypes.push_back(type);
if(type->isPointerTy()) {
TYPECONST Type* subType = type->getContainedType(0);
level++;
printTypeString(OS, subType);
level--;
OS << "*";
counter++;
}
else if(type->isArrayTy() || type->isVectorTy()) {
TYPECONST Type* subType = type->getContainedType(0);
unsigned numElements = type->isArrayTy() ? ((TYPECONST ArrayType*) type)->getNumElements() : ((TYPECONST VectorType*) type)->getNumElements();
char startSep = type->isArrayTy() ? '[' : '<';
char endSep = type->isArrayTy() ? ']' : '>';
OS << startSep;
if(numElements) {
OS << numElements << " x ";
}
level++;
printTypeString(OS, subType);
level--;
OS << endSep;
counter += 4;
}
else if(type->isStructTy()) {
if(PRINT_SKIP_STRUCTS || PRINT_SKIP_UNIONS) {
OS << "$STRUCT/UNION";
counter += 13;
nestedTypes.pop_back();
return;
}
unsigned numContainedTypes = type->getNumContainedTypes();
OS << "{ ";
OS << "$STRUCT/UNION ";
for(unsigned i=0;i<numContainedTypes;i++) {
if(i > 0) {
OS << ", ";
}
TYPECONST Type* subType = type->getContainedType(i);
level++;
printTypeString(OS, subType);
level--;
}
OS << " }";
counter += 18 + 2*numContainedTypes;
}
else if(type->isFunctionTy()) {
unsigned numContainedTypes = type->getNumContainedTypes();
assert(numContainedTypes > 0);
TYPECONST Type* subType = type->getContainedType(0);
level++;
printTypeString(OS, subType);
level--;
numContainedTypes--;
OS << " (";
for(unsigned i=0;i<numContainedTypes;i++) {
if(i > 0) {
OS << ", ";
}
subType = type->getContainedType(i+1);
level++;
printTypeString(OS, subType);
level--;
}
OS << ")";
counter += 3 + 2*numContainedTypes;
}
else {
OS << "???";
counter +=3;
}
nestedTypes.pop_back();
}
unsigned TypeUtil::typeToBits(TYPECONST Type *type) {
if (type->isIntegerTy()) {
return ((IntegerType*)type)->getBitWidth();
}
else if (type->isArrayTy() && type->getContainedType(0)->isIntegerTy()) {
TYPECONST Type *containedType = type->getContainedType(0);
return ((IntegerType*)containedType)->getBitWidth() * ((ArrayType*)containedType)->getNumElements();
}
return 0;
}
int TypeUtil::VERBOSE_LEVEL = 1;
int TypeUtil::PRINT_SKIP_UNIONS = 0;
int TypeUtil::PRINT_SKIP_STRUCTS = 0;
int TypeUtil::PRINT_USE_BUILTIN_PRINTING = 0;
int TypeUtil::PRINT_MULTI_NAMES = 0;
}

View file

@ -0,0 +1,68 @@
#include <magic/support/VariableRefs.h>
using namespace llvm;
namespace llvm {
//===----------------------------------------------------------------------===//
// Constructors, destructor, and operators
//===----------------------------------------------------------------------===//
VariableRefs::VariableRefs() {
clear();
}
//===----------------------------------------------------------------------===//
// Getters
//===----------------------------------------------------------------------===//
bool VariableRefs::isUnnecessaryInstruction(Instruction* inst) const {
//have already instruction in the entry block, skip
if(instructionInEntryBlock) {
return true;
}
//have already instruction in the same block, skip
if(instruction && inst->getParent() == instruction->getParent()) {
return true;
}
return false;
}
Instruction* VariableRefs::getInstruction() const {
return instruction;
}
bool VariableRefs::isInstructionInEntryBlock() const {
return instructionInEntryBlock;
}
//===----------------------------------------------------------------------===//
// Other public methods
//===----------------------------------------------------------------------===//
void VariableRefs::addInstruction(Instruction* inst) {
//no instruction yet, update instruction
if(!instruction) {
instruction = inst;
return;
}
//have already instruction in another block, give up and resort to a single instruction in the entry block
setFunctionEntryInstruction(inst->getParent()->getParent());
}
void VariableRefs::clear() {
instruction = NULL;
instructionInEntryBlock = false;
}
//===----------------------------------------------------------------------===//
// Private methods
//===----------------------------------------------------------------------===//
void VariableRefs::setFunctionEntryInstruction(Function* function) {
this->instruction = function->front().getFirstNonPHI();
this->instructionInEntryBlock = true;
}
}