#include using namespace llvm; PASS_COMMON_INIT_ONCE(); // command-line arguments static cl::opt DLLFName("magic-dll-function", cl::desc("Specify the name of the deepest long-lived function whose stack " "needs to be instrumented"), cl::init(MAGIC_ENTRY_POINT), cl::NotHidden, cl::ValueRequired); static cl::opt LibPathRegex("magic-lib-path-regex", cl::desc("Specify all the colon-separated path regexes that identify directories containing " "libraries. Deprecated. Use -magic-ext-lib-sections instead."), cl::init(""), cl::NotHidden, cl::ValueRequired); static cl::opt VoidTypeAlias("magic-void-alias", cl::desc("Specify all the colon-separated type names that are to be treated as void, typically " "used in custom memory management implementations"), cl::init(""), cl::NotHidden, cl::ValueRequired); static cl::opt MMFuncPrefix("magic-mmfunc-prefix", cl::desc("Specify all the colon-separated prefixes that are to be used when extracting " "memory management functions used in custom memory management implementations"), cl::init(""), cl::NotHidden, cl::ValueRequired); static cl::opt MMFuncPair("magic-mmfunc-pair", cl::desc("Specify all the colon-separated pairs of malloc/free style memory management functions " "used in custom memory management implementations. Each function is to be listed together " "with a number indicating which of the input parameters is the one corresponding to its " "malloc(size)/free(pointer) counterpart. Example: " "\"my_smart_alloc/3;my_smart_free/3:my_custom_alloc/2;my_custom_free/1\". " "The counter for arguments starts from 1."), cl::init(""), cl::NotHidden, cl::ValueRequired); static cl::opt MMPoolFunc("magic-mm-poolfunc", cl::desc("Specify a pool memory management set of functions for creating pools, destroying pools, " "managing the pool buffers, reseting (reusing) pools and allocating memory blocks from the pool. " "All the functions are to be listed together with a number indicating which of the input parameters" "(numbering starts at 1) corresponds to the pool object. For the creation function, the pool object " "can be the return value (specify 0 for return value). The block allocation function additionally " "requires the number of the parameter denoting the size. Separate sets of functions using ':' and " "separate multiple functions of the same type using ';'. " "Example: \"my_pool_block_alloc/1/2:my_pool_create/0:my_pool_destroy/1:my_pool_alloc/1;" "another_pool_alloc/1;my_pool_free/1:my_pool_reset/1\"." "If there are no additional management functions, skip them. " "Example: \"pool_block_alloc/1/2:pool_create:pool_destroy/1\"."), cl::init(""), cl::NotHidden, cl::ValueRequired); static cl::opt EnablePoolMemReuse("magic-mpool-enable-reuse", cl::desc("Enable memory reuse across pools."), cl::init(false), cl::NotHidden); static cl::opt MMAPCtlFunction("magic-mmap-ctlfunc", cl::desc("Specify all the colon-separated mmap control functions that change low-level properties" "of memory-mapped memory regions taking the start address as an argument"), cl::init(""), cl::NotHidden, cl::ValueRequired); static cl::opt MagicDataSections("magic-data-sections", cl::desc("Specify all the colon-separated magic data section regexes not to instrument"), cl::init("^" MAGIC_STATIC_VARS_SECTION_PREFIX ".*$:^" UNBL_SECTION_PREFIX ".*$"), cl::NotHidden, cl::ValueRequired); static cl::opt MagicFunctionSections("magic-function-sections", cl::desc("Specify all the colon-separated magic function section regexes not to instrument"), cl::init("^" MAGIC_STATIC_FUNCTIONS_SECTION ".*$:^" UNBL_SECTION_PREFIX ".*$"), cl::NotHidden, cl::ValueRequired); static cl::opt ExtLibSections("magic-ext-lib-sections", cl::desc("Specify all the colon-separated external lib section regexes"), cl::init(MAGIC_DEFAULT_EXT_LIB_SECTION_REGEX), cl::NotHidden, cl::ValueRequired); static cl::opt baseBuildDir("magic-base-build-dir", cl::desc("Specify the base build directory from which the pass derives relative directories for debug symbols"), cl::init(""), cl::NotHidden, cl::ValueRequired); static cl::opt EnableShadowing("magic-enable-shadowing", cl::desc("Enable state shadowing"), cl::init(false), cl::NotHidden); static cl::opt SkipAll("magic-skip-all", cl::desc("Exit immediately"), cl::init(false), cl::NotHidden); #if MAGIC_USE_QPROF_INSTRUMENTATION QPROF_DECLARE_ALL_OPTS(magic, magicLLSitestacks, magicDeepestLLLoops, magicDeepestLLLibs, magicTaskClasses ); #endif #define DEBUG_TYPE_INFOS 0 #define DEBUG_FILL_TYPE_INFOS 0 #define DEBUG_FILL_EXT_TYPE_INFOS 0 #define DEBUG_ALLOC_LEVEL 0 #define DEBUG_ALLOC_BAD_TYPES 0 #define DEBUG_CASTS 0 #define DEBUG_DUPLICATED_TYPE_INFOS 0 #define DEBUG_VALUE_SET 0 #define DEBUG_QPROF 0 namespace llvm { //===----------------------------------------------------------------------===// // Constructors, destructor, and operators //===----------------------------------------------------------------------===// MagicPass::MagicPass() : ModulePass(ID) {} unsigned TypeInfo::maxNameLength = 0; unsigned TypeInfo::maxTypeStringLength = 0; std::map > TypeInfo::intCastTypes; std::map > TypeInfo::bitCastTypes; std::map > TypeInfo::typeMap; bool SmartType::forceRawUnions = MAGIC_FORCE_RAW_UNIONS; bool SmartType::forceRawBitfields = MAGIC_FORCE_RAW_BITFIELDS; Function *MagicMemFunction::lastAllocWrapper = NULL; std::map MagicMemFunction::allocWrapperCache; std::set MagicMemFunction::customWrapperSet; //===----------------------------------------------------------------------===// // Public methods //===----------------------------------------------------------------------===// bool MagicPass::runOnModule(Module &M) { unsigned i; if (SkipAll) { return false; } magicPassLog("Running..."); EDIType::setModule(&M); PassUtil::setModule(&M); // initialize qprof instrumentation qprofInstrumentationInit(M); //look up magic entry point function Function *magicEntryPointFunc = M.getFunction(MAGIC_ENTRY_POINT); if( !magicEntryPointFunc ){ //if no valid entry point, we are not compiling a valid program, skip pass magicPassLog("Error: no " << MAGIC_ENTRY_POINT << "() found"); return false; } //look up magic enabled variable GlobalVariable* magicEnabled = M.getNamedGlobal(MAGIC_ENABLED); if(!magicEnabled) { magicPassErr("Error: no " << MAGIC_ENABLED << " variable found"); exit(1); } //look up magic root variable GlobalVariable* magicRootVar = M.getNamedGlobal(MAGIC_ROOT_VAR_NAME); if(!magicRootVar) { magicPassErr("Error: no " << MAGIC_ROOT_VAR_NAME << " variable found"); exit(1); } //look up magic data init function and get the last instruction to add stuff in it Function *magicDataInitFunc = M.getFunction(MAGIC_DATA_INIT_FUNC_NAME); if(!magicDataInitFunc){ magicPassErr("Error: no " << MAGIC_DATA_INIT_FUNC_NAME << "() found"); exit(1); } Instruction *magicArrayBuildFuncInst = magicDataInitFunc->back().getTerminator(); //look up pointer to magic array and magic struct type Value* magicArrayPtr = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_SENTRIES); if(!magicArrayPtr) { magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_SENTRIES << " field found"); exit(1); } TYPECONST StructType* magicStructType = (TYPECONST StructType*) ((TYPECONST PointerType*)((TYPECONST PointerType*)magicArrayPtr->getType())->getElementType())->getElementType(); //look up pointer to magic array size Value *magicArraySize = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_SENTRIES_NUM); if(!magicArraySize) { magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_SENTRIES_NUM << " field found"); exit(1); } //look up pointer to magic array string size Value *magicArrayStrSize = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_SENTRIES_STR_NUM); if(!magicArrayStrSize) { magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_SENTRIES_STR_NUM << " field found"); exit(1); } //look up pointer to magic next id Value *magicNextId = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_SENTRIES_NEXT_ID); if(!magicNextId) { magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_SENTRIES_NEXT_ID << " field found"); exit(1); } //look up pointer to magic dsindex array and magic dsindex struct type Value* magicDsindexArrayPtr = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_DSINDEXES); if(!magicDsindexArrayPtr) { magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_DSINDEXES << " field found"); exit(1); } TYPECONST StructType* magicDsindexStructType = (TYPECONST StructType*) ((TYPECONST PointerType*)((TYPECONST PointerType*)magicDsindexArrayPtr->getType())->getElementType())->getElementType(); //look up pointer to magic dsindex array size Value *magicDsindexArraySize = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_DSINDEXES_NUM); if(!magicDsindexArraySize) { magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_DSINDEXES_NUM << " field found"); exit(1); } //look up pointer to magic type array and magic type struct type Value *magicTypeArrayPtr = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_TYPES); if(!magicTypeArrayPtr) { magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_TYPES << " field found"); exit(1); } TYPECONST StructType* magicTypeStructType = (TYPECONST StructType*) ((TYPECONST PointerType*)((TYPECONST PointerType*)magicTypeArrayPtr->getType())->getElementType())->getElementType(); //look up pointer to magic type array size Value *magicTypeArraySize = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_TYPES_NUM); if(!magicTypeArraySize) { magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_TYPES_NUM << " field found"); exit(1); } //look up pointer to magic type next id Value *magicTypeNextId = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_TYPES_NEXT_ID); if(!magicTypeNextId) { magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_TYPES_NEXT_ID << " field found"); exit(1); } //look up pointer to magic function array and magic function struct type Value *magicFunctionArrayPtr = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_FUNCTIONS); if(!magicFunctionArrayPtr) { magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_FUNCTIONS << " field found"); exit(1); } TYPECONST StructType* magicFunctionStructType = (TYPECONST StructType*) ((TYPECONST PointerType*)((TYPECONST PointerType*)magicFunctionArrayPtr->getType())->getElementType())->getElementType(); //look up pointer to magic function array size Value *magicFunctionArraySize = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_FUNCTIONS_NUM); if(!magicFunctionArraySize) { magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_FUNCTIONS_NUM << " field found"); exit(1); } //look up pointer to magic function next id Value *magicFunctionNextId = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_FUNCTIONS_NEXT_ID); if(!magicFunctionNextId) { magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_FUNCTIONS_NEXT_ID << " field found"); exit(1); } //look up magic dsentry struct type Value *magicFirstDsentyPtr = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_FIRST_DSENTRY); if(!magicFirstDsentyPtr) { magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_FIRST_DSENTRY << " field found"); exit(1); } TYPECONST StructType* magicDsentryStructType = (TYPECONST StructType*) ((TYPECONST PointerType*)((TYPECONST PointerType*)magicFirstDsentyPtr->getType())->getElementType())->getElementType(); //look up magic init function Function *magicInitFunc = M.getFunction(MAGIC_INIT_FUNC_NAME); if( !magicInitFunc ){ magicPassErr("Error: no " << MAGIC_INIT_FUNC_NAME << "() found"); exit(1); } //look up magic dsentry stack functions Function *magicStackDsentryCreateFunc = M.getFunction(MAGIC_STACK_DSENTRIES_CREATE_FUNC_NAME); if (!magicStackDsentryCreateFunc) { magicPassErr("Error: no " << MAGIC_STACK_DSENTRIES_CREATE_FUNC_NAME << "() found"); exit(1); } Function *magicStackDsentryDestroyFunc = M.getFunction(MAGIC_STACK_DSENTRIES_DESTROY_FUNC_NAME); if (!magicStackDsentryDestroyFunc) { magicPassErr("Error: no " << MAGIC_STACK_DSENTRIES_DESTROY_FUNC_NAME << "() found"); exit(1); } //look up deepest long-lived function Function *deepestLLFunction = M.getFunction(DLLFName); if (!deepestLLFunction) { magicPassErr("Error: no " << DLLFName << "() found"); exit(1); } //lookup magic get page size function Function *magicGetPageSizeFunc = M.getFunction(MAGIC_GET_PAGE_SIZE_FUNC_NAME); if(!magicGetPageSizeFunc){ magicPassErr("Error: no " << MAGIC_GET_PAGE_SIZE_FUNC_NAME << "() found"); exit(1); } //look up magic void pointer GlobalVariable *magicVoidPtr = M.getNamedGlobal(MAGIC_VOID_PTR_NAME); if(!magicVoidPtr) { magicPassErr("Error: no " << MAGIC_VOID_PTR_NAME << "variable found"); exit(1); } assert(!isMagicGV(M, magicVoidPtr)); //look up magic void array GlobalVariable *magicVoidArr = M.getNamedGlobal(MAGIC_VOID_ARRAY_NAME); if(!magicVoidArr) { magicPassErr("Error: no " << MAGIC_VOID_ARRAY_NAME << "variable found"); exit(1); } assert(!isMagicGV(M, magicVoidArr)); //look up magic void * type pointer GlobalVariable *magicVoidPtrTypePtr = M.getNamedGlobal(MAGIC_VOID_PTR_TYPE_PTR_NAME); if(!magicVoidPtrTypePtr) { magicPassErr("Error: no " << MAGIC_VOID_PTR_TYPE_PTR_NAME << "variable found"); exit(1); } //determine lib path regexes PassUtil::parseStringListOpt(libPathRegexes, LibPathRegex); //determine void type aliases PassUtil::parseStringListOpt(voidTypeAliases, VoidTypeAlias); std::copy( voidTypeAliases.begin(), voidTypeAliases.end(), std::inserter( voidTypeAliasesSet, voidTypeAliasesSet.end() ) ); //determine mm function prefixes PassUtil::parseStringListOpt(mmFuncPrefixes, MMFuncPrefix); //determine custom malloc/free style custom mm functions PassUtil::parseStringPairListOpt(mmFuncPairs, MMFuncPair); //determine the pool management sets of functions PassUtil::parseStringListOpt(mmPoolFunctions, MMPoolFunc); //determine mmap ctl functions PassUtil::parseStringListOpt(mmapCtlFunctions, MMAPCtlFunction); //determine magic data section regexes PassUtil::parseRegexListOpt(magicDataSectionRegexes, MagicDataSections); //determine magic function section regexes PassUtil::parseRegexListOpt(magicFunctionSectionRegexes, MagicFunctionSections); //determine magic ext lib section regexes PassUtil::parseRegexListOpt(extLibSectionRegexes, ExtLibSections); //look up inttoptr type casts Module::GlobalListType &globalList = M.getGlobalList(); Module::FunctionListType &functionList = M.getFunctionList(); std::vector intCastTypes; std::vector intCastValues; std::map > bitCastMap; for (Module::iterator it = functionList.begin(); it != functionList.end(); ++it) { Function *F = it; if(isMagicFunction(M, F)) { continue; } for (inst_iterator I2 = inst_begin(F), E2 = inst_end(F); I2 != E2; ++I2) { indexCasts(M, &(*I2), intCastTypes, intCastValues, bitCastMap); } } for (Module::global_iterator it = globalList.begin(); it != globalList.end(); ++it) { GlobalVariable *GV = it; StringRef GVName = GV->getName(); if(isMagicGV(M, GV) || GVName.startswith(".str") || GVName.startswith(".arr") || GVName.startswith("C.")) { continue; } if(GV->hasInitializer()) { indexCasts(M, GV->getInitializer(), intCastTypes, intCastValues, bitCastMap); } } //index and set cast maps std::map > intCastMap; std::map >::iterator intCastMapIt; for(i=0;i valueSet; intCastMap.insert(std::pair >(type, valueSet)); intCastMapIt = intCastMap.find(type); } assert(intCastMapIt != intCastMap.end()); std::set *setPtr = &(intCastMapIt->second); if(setPtr->size() == 1 && *(setPtr->begin()) == 0) { continue; } if(value == 0) { setPtr->clear(); } setPtr->insert(value); } TypeInfo::setIntCastTypes(intCastMap); TypeInfo::setBitCastTypes(bitCastMap); #if MAGIC_INSTRUMENT_MEM_FUNCS //look up magic memory functions and corresponding wrappers #define __X(P) #P std::string magicMemFuncNames[] = { MAGIC_MEM_FUNC_NAMES }; std::string magicMemDeallocFuncNames[] = { MAGIC_MEMD_FUNC_NAMES }; #undef __X int magicMemFuncAllocFlags[] = { MAGIC_MEM_FUNC_ALLOC_FLAGS }; std::string magicMemPrefixes[] = { MAGIC_MEM_PREFIX_STRS }; std::vector llvmCallPrefixes; for (std::vector::iterator it = mmFuncPrefixes.begin(); it != mmFuncPrefixes.end(); ++it) { llvmCallPrefixes.push_back(*it); } llvmCallPrefixes.push_back(""); llvmCallPrefixes.push_back("\01"); //llvm uses odd prefixes for some functions, sometimes (e.g. mmap64) std::vector magicMemFunctions; std::set originalMagicMemFunctions; for(i=0;magicMemFuncNames[i].compare("");i++) { int allocFlags = magicMemFuncAllocFlags[i]; for(unsigned j=0;jgetFunctionType(); if(fType->getNumParams() == 0 && fType->isVarArg()) { //missing function prototype, i.e. no realistic caller. Skip. continue; } if(!magicMemFuncNames[i].compare("brk")) { brkFunctions.insert(f); } if(!magicMemFuncNames[i].compare("sbrk")) { sbrkFunctions.insert(f); } std::string wName, wName2; Function *w = NULL, *w2 = NULL; for(unsigned k=0;magicMemPrefixes[k].compare("");k++) { wName = magicMemPrefixes[k] + magicMemFuncNames[i]; w = M.getFunction(wName); if(w) { wName2 = wName + "_"; break; } } if(!w) { magicPassErr("Error: no wrapper function found for " << magicMemFuncNames[i] << "()"); exit(1); } while(!isCompatibleMagicMemFuncType(f->getFunctionType(), w->getFunctionType()) && (w2 = M.getFunction(wName2))) { w = w2; wName2.append("_"); } if(!isCompatibleMagicMemFuncType(f->getFunctionType(), w->getFunctionType())) { magicPassErr("Error: wrapper function with incompatible type " << wName << "() found"); magicPassErr(TypeUtil::getDescription(f->getFunctionType(), MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL) << " != " << TypeUtil::getDescription(w->getFunctionType(), MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL)); exit(1); } bool isDeallocFunction = false; for(unsigned j=0;magicMemDeallocFuncNames[j].compare("");j++) { if(!magicMemDeallocFuncNames[j].compare(magicMemFuncNames[i])) { isDeallocFunction = true; break; } } MagicMemFunction memFunction(M, f, w, isDeallocFunction, allocFlags); magicMemFunctions.push_back(memFunction); originalMagicMemFunctions.insert(f); #if DEBUG_ALLOC_LEVEL >= 1 magicPassErr("Memory management function/wrapper found: " << f->getName() << "()/" << w->getName() << "()"); #endif } } //look up custom memory management functions and build the corresponding wrappers int stdAllocFlags = 0; Function *stdAllocFunc, *stdAllocWrapperFunc; stdAllocFunc = M.getFunction(MAGIC_MALLOC_FUNC_NAME); assert(stdAllocFunc && "Could not find the standard allocation function."); for(i=0;magicMemFuncNames[i].compare("");i++) { if (!magicMemFuncNames[i].compare(MAGIC_MALLOC_FUNC_NAME)) { stdAllocFlags = magicMemFuncAllocFlags[i]; break; } } assert(magicMemFuncNames[i].compare("") && "Could not find the flags for the standard allocation function."); std::string wName; for(i=0;magicMemPrefixes[i].compare("");i++) { wName = magicMemPrefixes[i] + MAGIC_MALLOC_FUNC_NAME; stdAllocWrapperFunc = M.getFunction(wName); if (stdAllocWrapperFunc) { break; } } assert(stdAllocWrapperFunc && "Could not find a wrapper for the standard allocation function."); for (std::set >::iterator it = mmFuncPairs.begin(); it != mmFuncPairs.end(); ++it) { std::vector allocTokens; PassUtil::parseStringListOpt(allocTokens, (*it).first, "/"); assert((allocTokens.size() == stdAllocFunc->getFunctionType()->getNumParams() + 1) && "Bad option format, format is: customFuncName/stdFuncArg1Mapping/.../stdFuncArgNMapping"); // build custom wrapper for the allocation function Function *allocFunction = MagicUtil::getFunction(M, allocTokens[0]); if (!allocFunction) { continue; } std::vector allocArgMapping; int param; for (unsigned i = 0; i < stdAllocFunc->getFunctionType()->getNumParams(); i++) { int ret = StringRef(allocTokens[i + 1]).getAsInteger(10, param); assert(!ret && "Bad option format, format is: customFuncName/stdFuncArg1Mapping/.../stdFuncArgNMapping"); assert(param > 0 && "The numbering of function parameters starts from 1."); allocArgMapping.push_back(param); } FunctionType *allocFuncType = getFunctionType(allocFunction->getFunctionType(), allocArgMapping); if(!isCompatibleMagicMemFuncType(allocFuncType, stdAllocWrapperFunc->getFunctionType())) { magicPassErr("Error: standard wrapper function " << stdAllocWrapperFunc->getName() << " has incompatible type."); magicPassErr(TypeUtil::getDescription(allocFuncType, MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL) << " != " << TypeUtil::getDescription(stdAllocWrapperFunc->getFunctionType(), MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL)); exit(1); } Function *allocWrapper = MagicMemFunction::getCustomWrapper(allocFunction, stdAllocFunc, stdAllocWrapperFunc, allocArgMapping, false); // register the wrapper MagicMemFunction memFunctionAlloc(M, allocFunction, allocWrapper, false, stdAllocFlags); magicMemFunctions.push_back(memFunctionAlloc); originalMagicMemFunctions.insert(allocFunction); #if DEBUG_ALLOC_LEVEL >= 1 magicPassErr("Allocation function/custom wrapper added: " << allocFunction->getName() << "()/" << allocWrapper->getName() << "()"); #endif } //lookup memory pool management functions and add the corresponding wrapper calls int mempoolAllocFlags = MAGIC_STATE_HEAP; Function *mempoolBlockAllocTemplate, *mempoolBlockAllocTemplateWrapper; mempoolBlockAllocTemplate = MagicUtil::getFunction(M, MAGIC_MEMPOOL_BLOCK_ALLOC_TEMPLATE_FUNC_NAME); assert(mempoolBlockAllocTemplate && "Could not find the pool block allocation template function."); for(i = 0; magicMemPrefixes[i].compare(""); i++) { wName = magicMemPrefixes[i] + MAGIC_MEMPOOL_BLOCK_ALLOC_TEMPLATE_FUNC_NAME; mempoolBlockAllocTemplateWrapper = MagicUtil::getFunction(M, wName); if (mempoolBlockAllocTemplateWrapper) { break; } } assert(mempoolBlockAllocTemplateWrapper && "Could not find a wrapper for the pool block allocation template function."); #define __X(P) #P // C++11 Initializer Lists are not yet supported as of Clang 3.0 ... std::pair magicMempoolFuncNames[] = { std::pair(MAGIC_MEMPOOL_CREATE_FUNCS), std::pair(MAGIC_MEMPOOL_DESTROY_FUNCS), std::pair(MAGIC_MEMPOOL_MGMT_FUNCS), std::pair(MAGIC_MEMPOOL_RESET_FUNCS) }; #undef __X int magicMempoolFuncFlags[] = { MAGIC_MEMPOOL_FUNC_FLAGS }; unsigned numMagicMempoolFuncPairs = sizeof(magicMempoolFuncNames) / sizeof(magicMempoolFuncNames[0]); std::vector > magicMempoolFuncs(numMagicMempoolFuncPairs, std::pair()); for (i = 0; i < numMagicMempoolFuncPairs; i++) { magicMempoolFuncs[i].first = MagicUtil::getFunction(M, magicMempoolFuncNames[i].first); if (!magicMempoolFuncs[i].first) { magicPassErr("Could not find one of the memory pool wrapper functions: " + magicMempoolFuncNames[i].first); exit(1); } magicMempoolFuncs[i].second = MagicUtil::getFunction(M, magicMempoolFuncNames[i].second); if (!magicMempoolFuncs[i].second) { magicPassErr("Could not find one of the memory pool wrapper functions: " + magicMempoolFuncNames[i].second); exit(1); } } std::vector magicDebugFunctions; if (mmPoolFunctions.size()) { assert(mmPoolFunctions.size() >= 3 && mmPoolFunctions.size() <= 5 && "Specify at least 3 and at most 5 of the pool management types of functions: block alloc,pool create,pool destroy,pool management functions,pool reset functions."); std::vector::iterator mmPoolFuncsIt = mmPoolFunctions.begin(); std::vector mempoolMagicMemFunctions; // memory pool block allocation functions std::vector mempoolBlockAllocFuncs; PassUtil::parseStringListOpt(mempoolBlockAllocFuncs, *(mmPoolFuncsIt++), ";"); for (std::vector::iterator funcIt = mempoolBlockAllocFuncs.begin(); funcIt != mempoolBlockAllocFuncs.end(); ++funcIt) { std::vector funcTokens; PassUtil::parseStringListOpt(funcTokens, *funcIt, "/"); assert(funcTokens.size() == 3 && "Bad option format, format is: block_alloc_func/pool_ptr_arg_number/size_arg_number"); Function* blockAllocFunc = MagicUtil::getFunction(M, funcTokens[0]); if (!blockAllocFunc) { magicPassErr("Memory pool block allocation function not found - " + funcTokens[0] + ". Skipping instrumentation!"); mempoolMagicMemFunctions.clear(); break; } std::vector argMapping; unsigned param; for (unsigned i = 1; i < funcTokens.size(); i++) { assert(!StringRef(funcTokens[i]).getAsInteger(10, param) && "Bad option format, format is: block_alloc_func/pool_ptr_arg_number/size_arg_number"); assert(param > 0 && param <= blockAllocFunc->getFunctionType()->getNumParams() && "Bad option format. The function parameter number is not valid."); argMapping.push_back(param); } FunctionType *blockAllocFuncType = getFunctionType(mempoolBlockAllocTemplate->getFunctionType(), argMapping); if(!isCompatibleMagicMemFuncType(blockAllocFuncType, mempoolBlockAllocTemplateWrapper->getFunctionType())) { magicPassErr("Error: standard wrapper function " << mempoolBlockAllocTemplateWrapper->getName() << " has incompatible type."); magicPassErr(TypeUtil::getDescription(blockAllocFuncType, MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL) << " != " << TypeUtil::getDescription(mempoolBlockAllocTemplateWrapper->getFunctionType(), MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL)); exit(1); } Function *blockAllocWrapper = MagicMemFunction::getCustomWrapper(blockAllocFunc, mempoolBlockAllocTemplate, mempoolBlockAllocTemplateWrapper, argMapping, false); MagicMemFunction memFunctionBlockAlloc(M, blockAllocFunc, blockAllocWrapper, false, mempoolAllocFlags); mempoolMagicMemFunctions.push_back(memFunctionBlockAlloc); } if (!mempoolMagicMemFunctions.empty()) { // only if the block allocation functions have been successfully processed // continue with the rest of the memory pool management functions, which do not require a magic wrapper std::vector >::iterator magicMempoolFuncIt; std::vector >::iterator magicMempoolFuncFlagsIt; for (unsigned magicMempoolFuncIndex = 1; mmPoolFuncsIt != mmPoolFunctions.end(); ++mmPoolFuncsIt, ++magicMempoolFuncIndex) { std::vector mempoolMgmtFuncs; PassUtil::parseStringListOpt(mempoolMgmtFuncs, *mmPoolFuncsIt, ";"); for (std::vector::iterator funcIt = mempoolMgmtFuncs.begin(); funcIt != mempoolMgmtFuncs.end(); ++funcIt) { std::vector funcTokens; PassUtil::parseStringListOpt(funcTokens, *funcIt, "/"); assert(funcTokens.size() == 2 && "Bad option format, format is: mempool_mgmt_func/pool_ptr_arg_number"); Function* mempoolMgmtFunc = MagicUtil::getFunction(M, funcTokens[0]); assert(mempoolMgmtFunc && "Bad memory pool configuration, instrumentation aborted!"); std::vector argMapping; unsigned param; for (unsigned i = 1; i < funcTokens.size(); i++) { assert(!StringRef(funcTokens[i]).getAsInteger(10, param) && "Bad option format, format is: mempool_mgmt_func/pool_ptr_arg_number"); assert(param <= mempoolMgmtFunc->getFunctionType()->getNumParams() && "Bad option format. The function parameter number is not valid."); argMapping.push_back(param); } std::vector trailingArgs; if (magicMempoolFuncIndex == 1) { // pool create funcs TYPECONST Type* poolType = mempoolMgmtFunc->getFunctionType()->getContainedType(argMapping[0]); int level = MagicUtil::getPointerIndirectionLevel(poolType); trailingArgs.push_back(ConstantInt::get(Type::getInt32Ty(M.getContext()), (level > 1))); } else if (magicMempoolFuncIndex == 2) { // pool destroy funcs trailingArgs.push_back(ConstantInt::get(Type::getInt32Ty(M.getContext()), (EnablePoolMemReuse ? 1 : 0))); } if (magicMempoolFuncFlags[magicMempoolFuncIndex - 1] & MAGIC_HOOK_DEBUG_MASK) { MagicDebugFunction magicDebugFunction(mempoolMgmtFunc); magicDebugFunction.addHooks(magicMempoolFuncs[magicMempoolFuncIndex - 1], magicMempoolFuncFlags[magicMempoolFuncIndex - 1], argMapping, trailingArgs); magicDebugFunctions.push_back(magicDebugFunction); } else { bool ret = MagicDebugFunction::inlineHookCalls(mempoolMgmtFunc, magicMempoolFuncs[magicMempoolFuncIndex - 1], magicMempoolFuncFlags[magicMempoolFuncIndex - 1], argMapping, trailingArgs); if (!ret) { magicPassErr("Unable to inline wrapper function calls for " + funcTokens[0]); exit(1); } } } } for (std::vector::iterator magicIt = mempoolMagicMemFunctions.begin(); magicIt != mempoolMagicMemFunctions.end(); ++magicIt) { magicMemFunctions.push_back(*magicIt); originalMagicMemFunctions.insert(magicIt->getFunction()); } } } //lookup mmap ctl functions whose call arguments need to be fixed std::vector magicMmapCtlFunctions; for (std::vector::iterator it = mmapCtlFunctions.begin(); it != mmapCtlFunctions.end(); ++it) { std::vector tokens; tokens.clear(); PassUtil::parseStringListOpt(tokens, *it, "/"); assert(tokens.size() == 3 && "Bad option format, format is: function/[ptr_arg_name]/[len_arg_name]"); Function *function = M.getFunction(tokens[0]); if(!function) { continue; } std::string &ptrArgName = tokens[1]; std::string &lenArgName = tokens[2]; MagicMmapCtlFunction magicMmapCtlFunction(function, PointerType::get(IntegerType::get(M.getContext(), 8), 0), ptrArgName, lenArgName); magicMmapCtlFunctions.push_back(magicMmapCtlFunction); } #endif //everything as expected, set magic enabled variable to TRUE magicEnabled->setInitializer(ConstantInt::get(M.getContext(), APInt(32, 1))); //scan the list of global variables unsigned strGlobalVariables = 0; unsigned constGlobalVariables = 0; for (Module::global_iterator it = globalList.begin(); it != globalList.end(); ++it) { GlobalVariable *GV = it; StringRef GVName = GV->getName(); TYPECONST Type *GVType = GV->getType()->getElementType(); bool isPrimitiveOrPointerType = !GVType->isAggregateType(); DATA_LAYOUT_TY DL = DATA_LAYOUT_TY(&M); bool isExternal = GV->hasExternalLinkage() || GV->hasExternalWeakLinkage(); int typeSize = isExternal ? 0 : DL.getTypeSizeInBits(GVType)/8; int align = MAGIC_FORCE_ALIGN; if(isMagicGV(M, GV)) { magicPassLog("Skipping magic variable: " << GVName); continue; } assert(!MAGIC_STRINGREF_HAS_MAGIC_HIDDEN_PREFIX(GVName)); if(GVName.startswith("C.")) { //LLVM code we are not interested in continue; } if(MagicUtil::isLocalConstant(M, GV)) { //Local constants we are not interested in continue; } #if GLOBAL_VARS_IN_SECTION MagicUtil::setGlobalVariableSection(GV, GV->isConstant() ? GLOBAL_VARS_SECTION_RO : GLOBAL_VARS_SECTION_DATA); #endif if(GVName.startswith(".str")) { assert(GV->hasInitializer()); #if LLVM_VERSION >= 31 /* XXX Check. */ ConstantDataArray *initializer = dyn_cast(GV->getInitializer()); #else ConstantArray *initializer = dyn_cast(GV->getInitializer()); #endif if(initializer) { assert(initializer->isString()); MagicUtil::putStringRefCache(M, initializer->getAsString(), GV); } else { MagicUtil::putStringRefCache(M, "", GV); } strGlobalVariables++; Value *stringOwner = MagicUtil::getStringOwner(GV); if(stringOwner) { GlobalVariable *GVOwner = dyn_cast(stringOwner); AllocaInst *AIOwner = dyn_cast(stringOwner); assert(GVOwner || AIOwner); bool stringOwnerFound = false; std::string ownerName; raw_string_ostream ostream(ownerName); if(GVOwner && !isMagicGV(M, GVOwner)) { ostream << "#" << MagicUtil::getGVSourceName(M, GVOwner, NULL, baseBuildDir); stringOwnerFound = true; } else if(AIOwner && !isMagicFunction(M, AIOwner->getParent()->getParent())) { ostream << MagicUtil::getFunctionSourceName(M, AIOwner->getParent()->getParent(), NULL, baseBuildDir) << "#" << MagicUtil::getLVSourceName(M, AIOwner); stringOwnerFound = true; } if(stringOwnerFound) { ostream.flush(); stringOwnerMapIt = stringOwnerMap.find(ownerName); if(stringOwnerMapIt == stringOwnerMap.end()) { stringOwnerMap.insert(std::pair(ownerName, GV)); stringOwnerInvertedMap.insert(std::pair(GV, ownerName)); } else { stringOwnerInvertedMapIt = stringOwnerInvertedMap.find(stringOwnerMapIt->second); if(stringOwnerInvertedMapIt != stringOwnerInvertedMap.end()) { stringOwnerInvertedMap.erase(stringOwnerInvertedMapIt); } } } } } else if(GV->isConstant()) { constGlobalVariables++; } if(!isPrimitiveOrPointerType && align) { GV->setAlignment(align); if(typeSize % align) { typeSize = typeSize - (typeSize % align) + align; } } else if(MAGIC_OFF_BY_N_PROTECTION_N && GVType->isArrayTy() && typeSize>0) { unsigned alignment = typeSize + (DL.getTypeSizeInBits(GVType->getContainedType(0))/8) * MAGIC_OFF_BY_N_PROTECTION_N; unsigned a = 2; while(a < alignment) a = a << 1; GV->setAlignment(a); } globalVariableSizes.push_back(typeSize); globalVariables.push_back(GV); if(MagicUtil::hasAddressTaken(GV)) { globalVariablesWithAddressTaken.insert(GV); } } magicPassLog(">>>> Number of global variables found: " << globalVariables.size() << " of which " << strGlobalVariables << " .str variables, " << constGlobalVariables << " constants, and " << globalVariables.size()-strGlobalVariables-constGlobalVariables << " regular variables"); //build the list of functions having their address taken (include the last function no matter what to get the function ranges right) std::vector functionTypes; std::vector functionTypeParents; std::vector externalFunctionTypes; std::vector externalFunctionTypeParents; for (Module::iterator it = functionList.begin(); it != functionList.end(); ++it) { Function *F = it; if(F->hasAddressTaken() || it == --functionList.end() || F->getName().startswith(MAGIC_EVAL_FUNC_PREFIX)) { if(isMagicFunction(M, F)) { continue; } functions.push_back(F); const SmartType *FSmartType = SmartType::getSmartTypeFromFunction(M, F); if(FSmartType && !FSmartType->isTypeConsistent()) { delete FSmartType; //pretend the function is external if an invalid type has been found. FSmartType = NULL; } if(!FSmartType) { externalFunctionTypes.push_back(F->getFunctionType()); externalFunctionTypeParents.push_back(F); } else { functionTypes.push_back(FSmartType); functionTypeParents.push_back(F); } } } magicPassLog(">>>> Number of functions with address taken found: " << functions.size() << ", of which " << functionTypes.size() << " internal and " << externalFunctionTypes.size() << " external..."); //build the list of global types std::vector smartTypes; std::vector smartTypeParents; std::vector externalTypes; std::vector externalTypeParents; for(i=0;igetType()->getElementType(); const SmartType *GVSmartType = SmartType::getSmartTypeFromGV(M, GV); if(!GV->hasAppendingLinkage()){ // llvm.global_ctors and llvm.global_dtors have appending linkage, don't have compile unit debug info, and therefore cannot be linked to GV debug info, and so are skipped. if(!GVSmartType) { bool isExternal = GV->hasExternalLinkage() || GV->hasExternalWeakLinkage(); if (!isExternal && !GV->isConstant()) { magicPassErr("var is: " << GV->getName()); magicPassErr("type is: " << TypeUtil::getDescription(GV->getType()->getElementType(), MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL)); } assert(isExternal || GV->isConstant()); externalTypes.push_back(GVType); externalTypeParents.push_back(GV); } else { smartTypes.push_back(GVSmartType); smartTypeParents.push_back(GV); } } } magicPassLog(">>>> Number of global types found: " << globalVariables.size() << ", of which " << smartTypes.size() << " internal and " << externalTypes.size() << " external..."); //build type infos TypeInfo* magicVoidPtrTypeInfo = NULL; TypeInfo* magicVoidArrTypeInfo = NULL; TypeInfo* magicVoidTypeInfo = NULL; for(i=0;igetTypeID() == MAGIC_TYPE_POINTER); magicVoidTypeInfo = magicVoidPtrTypeInfo->getContainedType(0); assert(magicVoidTypeInfo->getTypeID() == MAGIC_TYPE_VOID); } else if(smartTypeParents[i] == magicVoidArr) { //get a pointer to void array types magicVoidArrTypeInfo = aTypeInfo; assert(magicVoidArrTypeInfo->getTypeID() == MAGIC_TYPE_ARRAY); } } assert(magicVoidPtrTypeInfo && magicVoidTypeInfo && magicVoidArrTypeInfo); std::vector magicVoidTypeInfoArr; magicVoidTypeInfoArr.push_back(magicVoidTypeInfo); magicVoidArrTypeInfo->setContainedTypes(magicVoidTypeInfoArr); magicPassLog(">>>> Number of types found: " << globalTypeInfos.size()); for(i=0;i>>> Number of types + function types found: " << globalTypeInfos.size()); //add external function types for(i=0;i>>> Number of types + function types + external function types found: " << globalTypeInfos.size()); //add external variable types for(i=0;igetName()); magicPassErr("type is: " << TypeUtil::getDescription(externalTypes[i], MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL)); } assert(aTypeInfo != NULL && "External type not supported!"); } magicPassLog(">>>> Number of types + external types + function types + external function types found: " << globalTypeInfos.size()); //process types, split them when some parent has a valid value set std::vector splitTypeInfos; for(i=0;isplitByParentValueSet(splitTypeInfos, globalVariablesWithAddressTaken); if(isTypeInfoSplit) { #if DEBUG_VALUE_SET unsigned splitTypeInfosSize = splitTypeInfos.size(); errs() << "MagicPass: Found type info split with different parents and value sets: original type is: " << globalTypeInfos[i]->getDescription() << ", type splits are:\n"; for(unsigned j=splitTypeInfosSize;j valueSet = splitTypeInfos[j]->getValueSet(); for(unsigned k=1;k parents = splitTypeInfos[j]->getParents(); for(unsigned k=0;kgetName(); } errs() << " ]\n"; } #endif } } //index type parents globalTypeInfos.clear(); for(i=0;i parents = aTypeInfo->getParents(); for(unsigned j=0;j(parents[j], aTypeInfo)); } globalTypeInfos.push_back(aTypeInfo); } std::vector< TypeInfo* > magicDsindexTypeInfoList; std::vector< std::pair > magicDsindexNamesList; std::vector magicDsindexFlagsList; #if MAGIC_INSTRUMENT_MEM_FUNCS //gather magic memory function calls to replace and figure out the type (adding more (local) types if needed) std::vector magicMemFunctionCalls; std::map< std::pair, int> namesMap; int allocFlags; std::set extendedMagicMemFunctions; for (std::set::iterator it = originalMagicMemFunctions.begin(); it != originalMagicMemFunctions.end(); ++it) { PassUtil::getFunctionsInDirectBUCallgraph(*it, extendedMagicMemFunctions); } while(!magicMemFunctions.empty()) { MagicMemFunction magicMemFunction = magicMemFunctions.front(); magicMemFunctions.erase(magicMemFunctions.begin()); std::vector Users(magicMemFunction.getFunction()->use_begin(), magicMemFunction.getFunction()->use_end()); std::vector EqPointers; while (!Users.empty()) { int annotation; User *U = Users.back(); Users.pop_back(); if (Instruction *I = dyn_cast(U)) { Function *parent = I->getParent()->getParent(); if (isMagicFunction(M, parent) || MagicMemFunction::isCustomWrapper(parent)) { continue; } CallSite CS = MagicUtil::getCallSiteFromInstruction(I); if (CS.getInstruction() && (!CS.arg_empty() || magicMemFunction.getWrapper() == NULL) && (MagicUtil::getCalledFunctionFromCS(CS) == magicMemFunction.getFunction() || std::find(EqPointers.begin(), EqPointers.end(), CS.getCalledValue()) != EqPointers.end())) { bool isDeallocFunction = magicMemFunction.isDeallocFunction(); bool wrapParent = false; TypeInfo *typeInfo = magicVoidTypeInfo; std::string allocName = ""; std::string allocParentName = ""; //check if we have to skip if(extendedMagicMemFunctions.find(CS.getInstruction()->getParent()->getParent()) != extendedMagicMemFunctions.end()) { //this call site is only called from some predefined mem function. skip. continue; } if(sbrkFunctions.find(MagicUtil::getCalledFunctionFromCS(CS)) != sbrkFunctions.end()) { ConstantInt *arg = dyn_cast(CS.getArgument(0)); if(arg && arg->getZExtValue() == 0) { //ignore sbrk(0) calls. This does not skip calls with a variable argument (when arg == NULL) #if DEBUG_ALLOC_LEVEL >= 1 magicPassErr("Skipping instrumentation of sbrk(0) MM call found in " << parent->getName() << "():"); I->print(errs()); errs() << "\n"; #endif continue; } } else if(MagicUtil::getCallAnnotation(M, CS, &annotation) && annotation == MAGIC_CALL_MEM_SKIP_INSTRUMENTATION) { //ignore calls we are supposed to skip #if DEBUG_ALLOC_LEVEL >= 1 magicPassErr("Skipping instrumentation of annotated MM call found in " << parent->getName() << "():"); I->print(errs()); errs() << "\n"; #endif continue; } //figure out the type and the names if(!isDeallocFunction) { int allocCounter = 1; int ret; std::map< std::pair, int>::iterator namesMapIt; //get alloc types and names TypeInfo *allocTypeInfo = getAllocTypeInfo(M, magicVoidPtrTypeInfo, CS, allocName, allocParentName); #if !MAGIC_INSTRUMENT_MEM_CUSTOM_WRAPPERS if(!allocTypeInfo) { allocTypeInfo = voidTypeInfo; } #endif if(allocTypeInfo) { typeInfo = allocTypeInfo; } else { int pointerParam = MagicMemFunction::getMemFunctionPointerParam(I->getParent()->getParent(), brkFunctions, magicVoidPtrTypeInfo); if(pointerParam >= 0 /* && !I->getParent()->getParent()->hasAddressTaken() */) { //the parent is a valid magic mem function to wrap wrapParent = true; } } if(!wrapParent) { assert(allocParentName.compare("") && "Empty parent name!"); if(!allocName.compare("")) { allocName = MAGIC_ALLOC_NONAME; } #if (MAGIC_NAMED_ALLOC_USE_DBG_INFO || (MAGIC_MEM_USAGE_OUTPUT_CTL == 1)) //extend names with debug information when requested if (MDNode *N = I->getMetadata("dbg")) { DILocation Loc(N); std::string string; raw_string_ostream ostream(string); ostream << allocName << MAGIC_ALLOC_NAME_SEP << Loc.getFilename() << MAGIC_ALLOC_NAME_SEP << Loc.getLineNumber(); ostream.flush(); allocName = string; } #endif #if MAGIC_FORCE_ALLOC_EXT_NAMES if (isExtLibrary(parent, NULL)) { allocName = MAGIC_ALLOC_EXT_NAME; allocName = MAGIC_ALLOC_EXT_PARENT_NAME; } #endif //avoid duplicates namesMapIt = namesMap.find(std::pair(allocParentName, allocName)); if(namesMapIt != namesMap.end()) { allocCounter = namesMapIt->second + 1; ret = namesMap.erase(std::pair(allocParentName, allocName)); assert(ret == 1); namesMap.insert(std::pair, int>(std::pair(allocParentName, allocName), allocCounter)); std::string string; raw_string_ostream ostream(string); ostream << allocName << MAGIC_ALLOC_NAME_SUFFIX << allocCounter; ostream.flush(); allocName = string; } else { namesMap.insert(std::pair, int>(std::pair(allocParentName, allocName), allocCounter)); allocName += MAGIC_ALLOC_NAME_SUFFIX; } magicMemFunction.setInstructionTypeInfo(typeInfo, allocName, allocParentName); //add dsindex entries magicDsindexTypeInfoList.push_back(typeInfo); magicDsindexNamesList.push_back(std::pair(allocParentName, allocName)); allocFlags = magicMemFunction.getAllocFlags(); assert(allocFlags); magicDsindexFlagsList.push_back(allocFlags); } } magicMemFunction.setInstruction(I); Function *instructionParent = I->getParent()->getParent(); //see if we can find the parent in our lists MagicMemFunction *magicMemParent = NULL; for(unsigned k=0;kaddInstructionDep(magicMemFunction); assert(magicMemParent->getAllocFlags()); } else { //if there is no parent, add it to the call queue magicMemFunctionCalls.push_back(magicMemFunction); } } } else if (GlobalValue *GV = dyn_cast(U)) { Users.insert(Users.end(), GV->use_begin(), GV->use_end()); EqPointers.push_back(GV); } else if (ConstantExpr *CE = dyn_cast(U)) { if (CE->isCast()) { Users.insert(Users.end(), CE->use_begin(), CE->use_end()); EqPointers.push_back(CE); } } } } #endif #if MAGIC_INSTRUMENT_STACK std::vector > > localTypeInfoMaps; std::map > localTypeInfoMap; std::vector stackIntrumentedFuncs; fillStackInstrumentedFunctions(stackIntrumentedFuncs, deepestLLFunction); std::string stackIntrumentedFuncsStr; for(i=0;igetName().str() + "()"; } magicPassLog(">>>> Set of stack-instrumented functions expanded from function " << deepestLLFunction->getName() << "(): " << stackIntrumentedFuncsStr); magicPassLog(">>>> Number of types + external types + function types + external function types + local types found: " << globalTypeInfos.size()); #endif //add raw types std::vector rawTypeInfos; for(i=0;ihasRawTypeRepresentation()) { continue; } assert(aTypeInfo->getNumContainedTypes() == 0); TypeInfo* aRawTypeInfo = new TypeInfo(*magicVoidArrTypeInfo); aRawTypeInfo->setPersistent(); aRawTypeInfo->removeAllParents(); rawTypeInfos.push_back(aRawTypeInfo); std::vector aTypeInfoContainedTypes; aTypeInfoContainedTypes.push_back(aRawTypeInfo); aTypeInfo->setContainedTypes(aTypeInfoContainedTypes); assert(aTypeInfo->getContainedType(0)->getContainedType(0) == magicVoidTypeInfo); } for(i=0;igetNumContainedTypes() == 1); } magicPassLog(">>>> Number of types + external types + function types + external function types + local types found + raw types: " << globalTypeInfos.size()); //find max recursive sequence length unsigned length, maxRecursiveSequenceLength = 0; for(i=0;igetParents().size() > 0) { length = getMaxRecursiveSequenceLength(globalTypeInfos[i]); if(length > maxRecursiveSequenceLength) { maxRecursiveSequenceLength = length; } } } magicPassLog(">>>> Max recursive sequence length: " << maxRecursiveSequenceLength); //debug type infos when needed #if DEBUG_TYPE_INFOS for(i=0;i parents = globalTypeInfos[i]->getParents(); if(parents.size() > 0) { std::string parentString, typeString; for(unsigned j=0;j0 ? ", " : "") + parents[j]->getName().str()); } typeString = globalTypeInfos[i]->getDescription(); magicPassErr(" Global type group found, parents=( " << parentString << "), type=" << typeString << ", name=" << globalTypeInfos[i]->getName() << ", names_string=" << globalTypeInfos[i]->getNamesString()); if(DEBUG_TYPE_INFOS >= 2) { printInterestingTypes(globalTypeInfos[i]); } } } for(i=0;igetName(); if(name.compare("")) { magicPassErr(" Named type found: " << name << " (names string: " << globalTypeInfos[i]->getNamesString() << ", id: " << i << ")"); } } #endif #if DEBUG_DUPLICATED_TYPE_INFOS std::map duplicatedTypeInfoMap; std::map::iterator duplicatedTypeInfoMapIt; for(i=0;igetType()->isStructTy()) { std::string name = globalTypeInfos[i]->getName(); if(!name.compare("")) { continue; } duplicatedTypeInfoMapIt = duplicatedTypeInfoMap.find(name); if(duplicatedTypeInfoMapIt != duplicatedTypeInfoMap.end()) { magicPassErr("Duplicated struct name found: " << name << ": " << globalTypeInfos[i]->getVerboseDescription() << " != " << (duplicatedTypeInfoMapIt->second)->getVerboseDescription()); } else { duplicatedTypeInfoMap.insert(std::pair(name, globalTypeInfos[i])); } } } #endif //allocate magic type array ArrayType* magicTypeArrayType = ArrayType::get(magicTypeStructType, globalTypeInfos.size()); magicTypeArray = new GlobalVariable(M, magicTypeArrayType, false, GlobalValue::InternalLinkage, ConstantAggregateZero::get(magicTypeArrayType), MAGIC_TYPE_ARRAY_NAME); MagicUtil::setGlobalVariableSection(magicTypeArray, MAGIC_STATIC_VARS_SECTION_DATA); //allocate magic array ArrayType* magicArrayType = ArrayType::get(magicStructType, globalVariables.size()); magicArray = new GlobalVariable(M, magicArrayType, false, GlobalValue::InternalLinkage, ConstantAggregateZero::get(magicArrayType), MAGIC_ARRAY_NAME); MagicUtil::setGlobalVariableSection(magicArray, MAGIC_STATIC_VARS_SECTION_DATA); //allocate magic function array ArrayType* magicFunctionArrayType = ArrayType::get(magicFunctionStructType, functions.size()); magicFunctionArray = new GlobalVariable(M, magicFunctionArrayType, false, GlobalValue::InternalLinkage, ConstantAggregateZero::get(magicFunctionArrayType), MAGIC_FUNC_ARRAY_NAME); MagicUtil::setGlobalVariableSection(magicFunctionArray, MAGIC_STATIC_VARS_SECTION_DATA); //build magic type array in build function i=0; std::map magicArrayTypePtrMap; std::map::iterator magicArrayTypePtrMapIt; std::map magicArrayTypeIndexMap; std::map::iterator magicArrayTypeIndexMapIt; std::vector arrayIndexes; for(;igetType(); arrayIndexes.clear(); arrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(64, 0, 10))); //pointer to A[] arrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(64, i, 10))); //pointer to A[index] Constant* magicTypeArrayPtr = MagicUtil::getGetElementPtrConstant(magicTypeArray, arrayIndexes); magicArrayTypePtrMap.insert(std::pair(aTypeInfo, magicTypeArrayPtr)); magicArrayTypeIndexMap.insert(std::pair(aTypeInfo, i)); //storing id field Value* structIdField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_ID); Constant* idValue = ConstantInt::get(M.getContext(), APInt(32, i+1, 10)); new StoreInst(idValue, structIdField, false, magicArrayBuildFuncInst); //storing name field Value* structNameField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_NAME); Constant* nameValue = MagicUtil::getArrayPtr(M, MagicUtil::getStringRef(M, aTypeInfo->getName())); new StoreInst(nameValue, structNameField, false, magicArrayBuildFuncInst); //storing names field std::vector names = aTypeInfo->getNames(); Value* structNamesField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_NAMES); Constant* namesValue; if(names.size() > 0) { namesValue = MagicUtil::getArrayPtr(M, MagicUtil::getStringArrayRef(M, names.size(), &names)); } else { namesValue = ConstantPointerNull::get((TYPECONST PointerType*) ((TYPECONST PointerType*)structNamesField->getType())->getElementType()); } new StoreInst(namesValue, structNamesField, false, magicArrayBuildFuncInst); //storing num_names field Value* structNumNamesField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_NUM_NAMES); Constant* numNamesValue = ConstantInt::get(M.getContext(), APInt(32, names.size(), 10)); new StoreInst(numNamesValue, structNumNamesField, false, magicArrayBuildFuncInst); //storing type_str field Value* structTypeStrField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_TYPE_STR); Constant* typeStrValue = MagicUtil::getArrayPtr(M, MagicUtil::getStringRef(M, aTypeInfo->getTypeString())); new StoreInst(typeStrValue, structTypeStrField, false, magicArrayBuildFuncInst); //filling size field Value* structSizeField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_SIZE); Value* typeSizeValue; if(aType->isFunctionTy() || TypeUtil::isOpaqueTy(aType) || aType->isVoidTy()) { typeSizeValue = ConstantInt::get(M.getContext(), APInt(32, 1, 10)); } else { assert(aType->isSized()); typeSizeValue = ConstantExpr::getIntegerCast(ConstantExpr::getSizeOf(aType), (TYPECONST IntegerType*)((TYPECONST PointerType*)structSizeField->getType())->getElementType(), true); } new StoreInst(typeSizeValue, structSizeField, false, magicArrayBuildFuncInst); //storing num_child_types field Value* structNumChildTypesField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_NUM_CHILD_TYPES); Constant* numChildTypesValue = ConstantInt::get(M.getContext(), APInt(32, aTypeInfo->getNumChildTypes(), 10)); new StoreInst(numChildTypesValue, structNumChildTypesField, false, magicArrayBuildFuncInst); //storing member_names field std::vector memberNames = aTypeInfo->getMemberNames(); Value* structMemberNamesField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_MEMBER_NAMES); Constant* memberNamesValue; if(memberNames.size() > 0) { assert(aType->isStructTy()); assert(aTypeInfo->getNumContainedTypes() == memberNames.size()); memberNamesValue = MagicUtil::getArrayPtr(M, MagicUtil::getStringArrayRef(M, memberNames.size(), &memberNames)); } else { memberNamesValue = ConstantPointerNull::get((TYPECONST PointerType*) ((TYPECONST PointerType*)structMemberNamesField->getType())->getElementType()); } new StoreInst(memberNamesValue, structMemberNamesField, false, magicArrayBuildFuncInst); //storing member_offsets field Value* structMemberOffsetsField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_MEMBER_OFFSETS); Constant* memberOffsetsValue; if(memberNames.size() > 0) { assert(aType->isStructTy()); assert(aTypeInfo->getNumContainedTypes() == aTypeInfo->getNumChildTypes()); bool isConstant = false; GlobalVariable *memberOffsetArray = MagicUtil::getIntArrayRef(M, aTypeInfo->getNumChildTypes(), NULL, isConstant); for(unsigned j=0;jgetNumChildTypes();j++) { std::vector arrayIndexes; arrayIndexes.clear(); arrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(64, 0, 10))); //pointer to A[] arrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(64, j, 10))); //pointer to A[j] Constant* memberOffsetArrayPtr = MagicUtil::getGetElementPtrConstant(memberOffsetArray, arrayIndexes); Value* memberOffsetValue = ConstantExpr::getIntegerCast(ConstantExpr::getOffsetOf((TYPECONST StructType*) aTypeInfo->getType(), j), (TYPECONST IntegerType*)((TYPECONST PointerType*)memberOffsetArrayPtr->getType())->getElementType(), true); new StoreInst(memberOffsetValue, memberOffsetArrayPtr, false, magicArrayBuildFuncInst); } memberOffsetsValue = MagicUtil::getArrayPtr(M, memberOffsetArray); } else { memberOffsetsValue = ConstantPointerNull::get((TYPECONST PointerType*) ((TYPECONST PointerType*)structMemberOffsetsField->getType())->getElementType()); } new StoreInst(memberOffsetsValue, structMemberOffsetsField, false, magicArrayBuildFuncInst); //storing value set field (for enum values and value set analysis) std::vector valueSet = aTypeInfo->getValueSet(); Value* structValueSetField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_VALUE_SET); Constant* valueSetValue; if(valueSet.size() > 0) { valueSetValue = ConstantExpr::getCast(Instruction::BitCast, MagicUtil::getArrayPtr(M, MagicUtil::getIntArrayRef(M, valueSet.size(), &valueSet)), magicVoidPtrTypeInfo->getType()); } else { valueSetValue = ConstantPointerNull::get((TYPECONST PointerType*)magicVoidPtrTypeInfo->getType()); } new StoreInst(valueSetValue, structValueSetField, false, magicArrayBuildFuncInst); //storing type_id field Value* structTypeIDField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_TYPE_ID); Constant* typeIDValue = ConstantInt::get(M.getContext(), APInt(32, aTypeInfo->getTypeID(), 10)); new StoreInst(typeIDValue, structTypeIDField, false, magicArrayBuildFuncInst); //storing flags field Value* structFlagsField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_FLAGS); Constant* flagsValue = ConstantInt::get(M.getContext(), APInt(32, aTypeInfo->getFlags(), 10)); new StoreInst(flagsValue, structFlagsField, false, magicArrayBuildFuncInst); //storing bit_width field Value* structBitWidthField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_BIT_WIDTH); Constant* bitWidthValue = ConstantInt::get(M.getContext(), APInt(32, aTypeInfo->getBitWidth(), 10)); new StoreInst(bitWidthValue, structBitWidthField, false, magicArrayBuildFuncInst); } i=0; //build contained types pointers unsigned dstIndex, voidTypeIndex; magicArrayTypeIndexMapIt = magicArrayTypeIndexMap.find(magicVoidTypeInfo); assert(magicArrayTypeIndexMapIt != magicArrayTypeIndexMap.end()); voidTypeIndex = magicArrayTypeIndexMapIt->second; for(;i containedTypePtrs; for(unsigned j=0;jgetNumContainedTypes();j++) { TypeInfo* containedType = aTypeInfo->getContainedType(j); magicArrayTypePtrMapIt = magicArrayTypePtrMap.find(containedType); assert(magicArrayTypePtrMapIt != magicArrayTypePtrMap.end()); containedTypePtrs.push_back(magicArrayTypePtrMapIt->second); } Value* structContainedTypesField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_CONTAINED_TYPES); Constant *containedTypesValue; if(containedTypePtrs.size() > 0) { containedTypesValue = MagicUtil::getArrayPtr(M, MagicUtil::getGenericArrayRef(M, containedTypePtrs)); } else { containedTypesValue = ConstantPointerNull::get((TYPECONST PointerType*) ((TYPECONST PointerType*)structContainedTypesField->getType())->getElementType()); } new StoreInst(containedTypesValue, structContainedTypesField, false, magicArrayBuildFuncInst); if(!aTypeInfo->hasRawTypeRepresentation()) { continue; } //handle raw array types assert(aTypeInfo->getNumContainedTypes() == 1 && aTypeInfo->getContainedType(0)->getType()->isArrayTy()); magicArrayTypeIndexMapIt = magicArrayTypeIndexMap.find(aTypeInfo->getContainedType(0)); assert(magicArrayTypeIndexMapIt != magicArrayTypeIndexMap.end()); dstIndex = magicArrayTypeIndexMapIt->second; //fix size field (inherited by parent type) Value* srcStructSizeField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_SIZE); Value* dstStructSizeField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, dstIndex, 10)), MAGIC_TSTRUCT_FIELD_SIZE); Value* srcStructSizeValue = new LoadInst(srcStructSizeField, "", false, magicArrayBuildFuncInst); new StoreInst(srcStructSizeValue, dstStructSizeField, false, magicArrayBuildFuncInst); //fix num_child_types field Value* dstStructNumChildTypesField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, dstIndex, 10)), MAGIC_TSTRUCT_FIELD_NUM_CHILD_TYPES); Value* voidStructSizeField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, voidTypeIndex, 10)), MAGIC_TSTRUCT_FIELD_SIZE); Value* voidStructSizeValue = new LoadInst(voidStructSizeField, "", false, magicArrayBuildFuncInst); BinaryOperator* numChildTypesValue = BinaryOperator::Create(Instruction::SDiv, srcStructSizeValue, voidStructSizeValue, "", magicArrayBuildFuncInst); new StoreInst(numChildTypesValue, dstStructNumChildTypesField, false, magicArrayBuildFuncInst); } i=0; //build cast types pointers for(;i castTypePtrs; std::vector castTypes = aTypeInfo->getCastTypes(); Value* structCompatibleTypesField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_COMPATIBLE_TYPES); TYPECONST PointerType* nullArrayType = (TYPECONST PointerType*) ((TYPECONST PointerType*)structCompatibleTypesField->getType())->getElementType(); for(unsigned j=0;jgetContainedType(0))); } else { magicArrayTypePtrMapIt = magicArrayTypePtrMap.find(castType); assert(magicArrayTypePtrMapIt != magicArrayTypePtrMap.end()); castTypePtrs.push_back(magicArrayTypePtrMapIt->second); } } Constant *compatibleTypesValue; if(castTypePtrs.size() > 0) { compatibleTypesValue = MagicUtil::getArrayPtr(M, MagicUtil::getGenericArrayRef(M, castTypePtrs)); } else { compatibleTypesValue = ConstantPointerNull::get(nullArrayType); } new StoreInst(compatibleTypesValue, structCompatibleTypesField, false, magicArrayBuildFuncInst); } //build magic array in build function i=0; strGlobalVariables = 0; PointerType* voidPointerType = PointerType::get(IntegerType::get(M.getContext(), 8), 0); for(;igetName().startswith(".str"); isNamedString = false; if(isString) { stringOwnerInvertedMapIt = stringOwnerInvertedMap.find(GV); if(stringOwnerInvertedMapIt != stringOwnerInvertedMap.end()) { isNamedString = true; DIGV = NULL; GVName = ".str#" + stringOwnerInvertedMapIt->second; } } if(!isNamedString) { GVName = MagicUtil::getGVSourceName(M, GV, &DIGV, baseBuildDir); } isFromLibrary = isExtLibrary(GV, DIGV); hasAddressTaken = globalVariablesWithAddressTaken.find(GV) != globalVariablesWithAddressTaken.end(); std::string GVNameStr(GVName.str()); //storing id field Value* structIdField = MagicUtil::getMagicSStructFieldPtr(M, magicArrayBuildFuncInst, magicArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_SSTRUCT_FIELD_ID); Constant* idValue = ConstantInt::get(M.getContext(), APInt(32, i+1, 10)); new StoreInst(idValue, structIdField, false, magicArrayBuildFuncInst); //storing name field Value* structNameField = MagicUtil::getMagicSStructFieldPtr(M, magicArrayBuildFuncInst, magicArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_SSTRUCT_FIELD_NAME); Constant* nameValue = MagicUtil::getArrayPtr(M, MagicUtil::getStringRef(M, GVNameStr)); new StoreInst(nameValue, structNameField, false, magicArrayBuildFuncInst); //storing type field parentMapIt = globalParentMap.find(GV); if(parentMapIt == globalParentMap.end()) { continue; } assert(parentMapIt != globalParentMap.end()); TypeInfo* aTypeInfo = parentMapIt->second; magicArrayTypePtrMapIt = magicArrayTypePtrMap.find(aTypeInfo); assert(magicArrayTypePtrMapIt != magicArrayTypePtrMap.end()); Value* structTypeField = MagicUtil::getMagicSStructFieldPtr(M, magicArrayBuildFuncInst, magicArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_SSTRUCT_FIELD_TYPE); Constant* typeValue = magicArrayTypePtrMapIt->second; new StoreInst(typeValue, structTypeField, false, magicArrayBuildFuncInst); //filling flags field int annotation, flags = MAGIC_STATE_DATA; if(GV->hasExternalLinkage() || GV->hasExternalWeakLinkage()) { flags |= MAGIC_STATE_EXTERNAL; } if(GV->isConstant()) { flags |= MAGIC_STATE_CONSTANT; } if(GV->isThreadLocal()) { flags |= MAGIC_STATE_THREAD_LOCAL; } if(isFromLibrary) { flags |= MAGIC_STATE_LIB; } if(!hasAddressTaken) { flags |= MAGIC_STATE_ADDR_NOT_TAKEN; } if(isString) { flags |= MAGIC_STATE_STRING; if(isNamedString) { flags |= MAGIC_STATE_NAMED_STRING; } strGlobalVariables++; } if(MagicUtil::getVarAnnotation(M, GV, &annotation)) { magicPassLog("Magic annotation found for global variable: " << GV->getName()); flags |= (annotation & MAGIC_STATE_ANNOTATION_MASK); } Value* structFlagsField = MagicUtil::getMagicSStructFieldPtr(M, magicArrayBuildFuncInst, magicArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_SSTRUCT_FIELD_FLAGS); Constant* flagsValue = ConstantInt::get(M.getContext(), APInt(32, flags, 10)); new StoreInst(flagsValue, structFlagsField, false, magicArrayBuildFuncInst); //filling address field Value* structAddressField = MagicUtil::getMagicSStructFieldPtr(M, magicArrayBuildFuncInst, magicArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_SSTRUCT_FIELD_ADDRESS); Constant* varAddressValue = ConstantExpr::getCast(Instruction::BitCast, GV, voidPointerType); new StoreInst(varAddressValue, structAddressField, false, magicArrayBuildFuncInst); //filling shadow address field Value* structShadowAddressField = MagicUtil::getMagicSStructFieldPtr(M, magicArrayBuildFuncInst, magicArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_SSTRUCT_FIELD_SHADOW_ADDRESS); Constant* varShadowAddressValue; if(EnableShadowing && !GV->isConstant()) { GlobalVariable* varShadow = MagicUtil::getShadowRef(M, GV); shadowGlobalVariables.push_back(varShadow); varShadowAddressValue = ConstantExpr::getCast(Instruction::BitCast, varShadow, voidPointerType); } else { varShadowAddressValue = ConstantPointerNull::get((TYPECONST PointerType*) ((TYPECONST PointerType*)structShadowAddressField->getType())->getElementType()); } new StoreInst(varShadowAddressValue, structShadowAddressField, false, magicArrayBuildFuncInst); } //build magic function array in build function i=0; for(;isecond; magicArrayTypePtrMapIt = magicArrayTypePtrMap.find(aTypeInfo); assert(magicArrayTypePtrMapIt != magicArrayTypePtrMap.end()); Value* structTypeField = MagicUtil::getMagicFStructFieldPtr(M, magicArrayBuildFuncInst, magicFunctionArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_FSTRUCT_FIELD_TYPE); Constant* typeValue = magicArrayTypePtrMapIt->second; new StoreInst(typeValue, structTypeField, false, magicArrayBuildFuncInst); //filling flags field int flags = MAGIC_STATE_TEXT|MAGIC_STATE_CONSTANT; if(isFromLibrary) { flags |= MAGIC_STATE_LIB; } if(!F->hasAddressTaken()) { flags |= MAGIC_STATE_ADDR_NOT_TAKEN; } Value* structFlagsField = MagicUtil::getMagicFStructFieldPtr(M, magicArrayBuildFuncInst, magicFunctionArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_FSTRUCT_FIELD_FLAGS); Constant* flagsValue = ConstantInt::get(M.getContext(), APInt(32, flags, 10)); new StoreInst(flagsValue, structFlagsField, false, magicArrayBuildFuncInst); //filling address field Value* structAddressField = MagicUtil::getMagicFStructFieldPtr(M, magicArrayBuildFuncInst, magicFunctionArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_FSTRUCT_FIELD_ADDRESS); Constant* varAddressValue = ConstantExpr::getCast(Instruction::BitCast, F, voidPointerType); new StoreInst(varAddressValue, structAddressField, false, magicArrayBuildFuncInst); } #if MAGIC_INSTRUMENT_MEM_FUNCS //replace magic memory function calls with their wrappers for(i=0;ireplaceInstruction(magicArrayTypePtrMap, magicVoidPtrTypeInfo); } //fix debug function calls and their arguments for (i=0;ifixCalls(M, baseBuildDir); } //fix mmap ctl function calls and their arguments for (i=0;ifixCalls(M, magicGetPageSizeFunc); } #endif #if MAGIC_INSTRUMENT_STACK //instrument the stack for the relevant set of functions and add dsindex entries for(i=0;isecond; new StoreInst(typeValue, structTypeField, false, magicArrayBuildFuncInst); //storing name field Value* structNameField = MagicUtil::getMagicDStructFieldPtr(M, magicArrayBuildFuncInst, magicDsindexArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_DSTRUCT_FIELD_NAME); Constant* nameValue = MagicUtil::getArrayPtr(M, MagicUtil::getStringRef(M, magicDsindexNamesList[i].second)); new StoreInst(nameValue, structNameField, false, magicArrayBuildFuncInst); //storing parent name field Value* structParentNameField = MagicUtil::getMagicDStructFieldPtr(M, magicArrayBuildFuncInst, magicDsindexArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_DSTRUCT_FIELD_PARENT_NAME); Constant* parentNameValue = MagicUtil::getArrayPtr(M, MagicUtil::getStringRef(M, magicDsindexNamesList[i].first)); new StoreInst(parentNameValue, structParentNameField, false, magicArrayBuildFuncInst); //storing flags field Value* structFlagsField = MagicUtil::getMagicDStructFieldPtr(M, magicArrayBuildFuncInst, magicDsindexArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_DSTRUCT_FIELD_FLAGS); Constant* flagsValue = ConstantInt::get(M.getContext(), APInt(32, magicDsindexFlagsList[i], 10)); new StoreInst(flagsValue, structFlagsField, false, magicArrayBuildFuncInst); } // apply qprof instrumentation qprofInstrumentationApply(M); //set pointer to magic type array in build function new StoreInst(MagicUtil::getArrayPtr(M, magicTypeArray), magicTypeArrayPtr, false, magicArrayBuildFuncInst); //set magic type array size in build function new StoreInst(ConstantInt::get(M.getContext(), APInt(32, globalTypeInfos.size())), magicTypeArraySize, false, magicArrayBuildFuncInst); //set magic type next id in build function new StoreInst(ConstantInt::get(M.getContext(), APInt(32, globalTypeInfos.size()+1)), magicTypeNextId, false, magicArrayBuildFuncInst); //set pointer to magic array in build function new StoreInst(MagicUtil::getArrayPtr(M, magicArray), magicArrayPtr, false, magicArrayBuildFuncInst); //set magic array size in build function new StoreInst(ConstantInt::get(M.getContext(), APInt(32, globalVariables.size())), magicArraySize, false, magicArrayBuildFuncInst); //set magic array string size in build function new StoreInst(ConstantInt::get(M.getContext(), APInt(32, strGlobalVariables)), magicArrayStrSize, false, magicArrayBuildFuncInst); //set magic next id in build function new StoreInst(ConstantInt::get(M.getContext(), APInt(32, globalVariables.size()+1)), magicNextId, false, magicArrayBuildFuncInst); //set pointer to magic function array in build function new StoreInst(MagicUtil::getArrayPtr(M, magicFunctionArray), magicFunctionArrayPtr, false, magicArrayBuildFuncInst); //set magic function array size in build function new StoreInst(ConstantInt::get(M.getContext(), APInt(32, functions.size())), magicFunctionArraySize, false, magicArrayBuildFuncInst); //set magic function next id in build function new StoreInst(ConstantInt::get(M.getContext(), APInt(32, functions.size()+1)), magicFunctionNextId, false, magicArrayBuildFuncInst); //set pointer to magic dsindex array in build function new StoreInst(MagicUtil::getArrayPtr(M, magicDsindexArray), magicDsindexArrayPtr, false, magicArrayBuildFuncInst); //set magic dsindex array size in build function new StoreInst(ConstantInt::get(M.getContext(), APInt(32, magicDsindexTypeInfoList.size())), magicDsindexArraySize, false, magicArrayBuildFuncInst); //set magic void type pointer in build function magicArrayTypePtrMapIt = magicArrayTypePtrMap.find(magicVoidPtrTypeInfo); assert(magicArrayTypePtrMapIt != magicArrayTypePtrMap.end()); Constant* magicVoidPtrTypeValue = magicArrayTypePtrMapIt->second; new StoreInst(magicVoidPtrTypeValue, magicVoidPtrTypePtr, false, magicArrayBuildFuncInst); //inject magic init call at the beginning of magic entry point function std::vector args; MagicUtil::createCallInstruction(magicInitFunc, args, "", magicEntryPointFunc->getBasicBlockList().begin()->begin()); //check invariants #if MAGIC_CHECK_INVARIANTS if(maxRecursiveSequenceLength > MAGIC_MAX_RECURSIVE_TYPES) { magicPassErr("Max recursive sequence length is: " << maxRecursiveSequenceLength); } assert(maxRecursiveSequenceLength <= MAGIC_MAX_RECURSIVE_TYPES && "MAGIC_MAX_RECURSIVE_TYPES is too small!"); if(TypeInfo::getMaxNameLength() > MAGIC_MAX_NAME_LEN) { magicPassErr("Max name length is: " << TypeInfo::getMaxNameLength()); } assert(TypeInfo::getMaxNameLength() <= MAGIC_MAX_NAME_LEN && "MAGIC_MAX_NAME_LEN is too small!"); if(TypeInfo::getMaxTypeStringLength() > MAGIC_MAX_TYPE_STR_LEN) { magicPassErr("Max type string length is: " << TypeInfo::getMaxTypeStringLength()); } assert(TypeInfo::getMaxTypeStringLength() <= MAGIC_MAX_TYPE_STR_LEN && "MAGIC_MAX_TYPE_STR_LEN is too small!"); #endif return true; } //===----------------------------------------------------------------------===// // Private methods //===----------------------------------------------------------------------===// static std::vector currPtrVarIndexes; static std::set< std::pair > > visitedValues; bool MagicPass::checkPointerVariableIndexes(TYPECONST Type *type, std::vector &ptrVarIndexes, unsigned offset) { if(offset >= ptrVarIndexes.size()) { return true; } unsigned ptrVarIndex = (unsigned) ptrVarIndexes[ptrVarIndexes.size()-1 - offset]; if(ptrVarIndex >= type->getNumContainedTypes()) { return false; } return checkPointerVariableIndexes(type->getContainedType(ptrVarIndex), ptrVarIndexes, offset+1); } void MagicPass::findPointerVariables(Function* function, Value *value, std::vector &ptrVars, std::vector > &ptrVarIndexes, Value *parent, bool isUser) { #define RETURN_IF(X) do{ if(X){ return; } } while(0) #define DEBUG_VALUE(M, V) do{ if(DEBUG_ALLOC_LEVEL >= 2) { errs() << M; V->print(errs()); errs() << "\n"; } } while(0) #define DEBUG_INDEXES() do{ if(DEBUG_ALLOC_LEVEL >= 3) { errs() << ">>> Indexes: "; for(unsigned i=0;i > visitedPair(value, currPtrVarIndexes); if(visitedValues.find(visitedPair) != visitedValues.end()) { return; } DEBUG_VALUE(" >>>> findPointerVariables: Value is: ", value); DEBUG_VALUE(" >>>> findPointerVariables: Parent value is: ", parent); DEBUG_INDEXES(); std::vector savedPtrVarIndexes; visitedValues.insert(visitedPair); ConstantExpr *constantExpr = dyn_cast(value); if(currPtrVarIndexes.size() == 0) { if(DEBUG_ALLOC_LEVEL >= 2) { magicPassErr("Empty indexes, skipping search path!"); } RETURN_IF(true); } else if(GlobalVariable *GV = dyn_cast(value)) { if(DEBUG_ALLOC_LEVEL >= 2) { magicPassErr("Found global variable!"); } ptrVars.push_back(GV); ptrVarIndexes.push_back(currPtrVarIndexes); assert(!isUser); if(GV->getType()->getElementType() != PointerType::get(IntegerType::get(function->getParent()->getContext(), 8), 0)) { RETURN_IF(true); } } else if(AllocaInst *AI = dyn_cast(value)) { if(DEBUG_ALLOC_LEVEL >= 2) { magicPassErr("Found local variable!"); } ptrVars.push_back(AI); ptrVarIndexes.push_back(currPtrVarIndexes); assert(!isUser); if(AI->getAllocatedType() != PointerType::get(IntegerType::get(function->getParent()->getContext(), 8), 0)) { RETURN_IF(true); } } else if(dyn_cast(value)) { if(DEBUG_ALLOC_LEVEL >= 2) { magicPassErr("Found return variable!"); } assert(isUser); RETURN_IF(true); } else if(StoreInst *SI = dyn_cast(value)) { DEBUG_VALUE(" >>>> findPointerVariables: Digging store instruction: ", value); assert(isUser); if(parent == SI->getOperand(1)) { assert(currPtrVarIndexes.size() > 0 && currPtrVarIndexes[currPtrVarIndexes.size()-1] == 0); currPtrVarIndexes.pop_back(); findPointerVariables(function, SI->getOperand(0), ptrVars, ptrVarIndexes, value); currPtrVarIndexes.push_back(0); } else { currPtrVarIndexes.push_back(0); findPointerVariables(function, SI->getOperand(1), ptrVars, ptrVarIndexes, value); currPtrVarIndexes.pop_back(); } } else if(LoadInst *LI = dyn_cast(value)) { DEBUG_VALUE(" >>>> findPointerVariables: Digging load instruction: ", value); if(isUser) { assert(currPtrVarIndexes.size() > 0 && currPtrVarIndexes[currPtrVarIndexes.size()-1] == 0); savedPtrVarIndexes.push_back(currPtrVarIndexes.back()); currPtrVarIndexes.pop_back(); } else { currPtrVarIndexes.push_back(0); findPointerVariables(function, LI->getOperand(0), ptrVars, ptrVarIndexes, value); currPtrVarIndexes.pop_back(); } } else if(GetElementPtrInst *GEPI = dyn_cast(value)) { if(GEPI->getNumIndices() == 1) { DEBUG_VALUE(" >>>> findPointerVariables: Digging GEP instruction: ", value); findPointerVariables(function, GEPI->getOperand(0), ptrVars, ptrVarIndexes, value); } else { RETURN_IF(isUser); DEBUG_VALUE(" >>>> findPointerVariables: Digging GEP instruction: ", value); unsigned k = 0; int index; assert(currPtrVarIndexes.size() > 0 && currPtrVarIndexes[currPtrVarIndexes.size()-1] == 0); currPtrVarIndexes.pop_back(); //pop 0 for(GetElementPtrInst::const_op_iterator i=GEPI->idx_end()-1, b=GEPI->idx_begin();i>b;i--,k++) { index = 0; if(ConstantInt *CI = dyn_cast(*i)) { index = CI->getSExtValue(); } currPtrVarIndexes.push_back(index); } currPtrVarIndexes.push_back(0); //push 0 findPointerVariables(function, GEPI->getOperand(0), ptrVars, ptrVarIndexes, value); currPtrVarIndexes.pop_back(); //pop 0 while(k-->0) { currPtrVarIndexes.pop_back(); } currPtrVarIndexes.push_back(0); //push 0 } } else if(constantExpr && constantExpr->getOpcode() == Instruction::GetElementPtr) { assert(constantExpr->getNumOperands() >= 2); if(constantExpr->getNumOperands() == 2) { DEBUG_VALUE(" >>>> findPointerVariables: Digging GEP expression: ", value); findPointerVariables(function, constantExpr->getOperand(0), ptrVars, ptrVarIndexes, value); } else { RETURN_IF(isUser); DEBUG_VALUE(" >>>> findPointerVariables: Digging GEP expression: ", value); unsigned k = 0; int index; assert(currPtrVarIndexes.size() > 0 && currPtrVarIndexes[currPtrVarIndexes.size()-1] == 0); currPtrVarIndexes.pop_back(); //pop 0 for(unsigned i=constantExpr->getNumOperands()-1;i>1;i--,k++) { index = 0; if(ConstantInt *CI = dyn_cast(constantExpr->getOperand(i))) { index = CI->getSExtValue(); } currPtrVarIndexes.push_back(index); } currPtrVarIndexes.push_back(0); //push 0 findPointerVariables(function, constantExpr->getOperand(0), ptrVars, ptrVarIndexes, value); currPtrVarIndexes.pop_back(); //pop 0 while(k-->0) { currPtrVarIndexes.pop_back(); } currPtrVarIndexes.push_back(0); //push 0 } } else if(BitCastInst *CI = dyn_cast(value)) { if((isUser && !checkPointerVariableIndexes(CI->getType(), currPtrVarIndexes)) || (!isUser && !checkPointerVariableIndexes(CI->getOperand(0)->getType(), currPtrVarIndexes))) { DEBUG_VALUE(" >>>> findPointerVariables: Skipping unsafe cast instruction: ", value); RETURN_IF(true); } DEBUG_VALUE(" >>>> findPointerVariables: Digging cast instruction: ", value); findPointerVariables(function, CI->getOperand(0), ptrVars, ptrVarIndexes, value); } else if(dyn_cast(value) || dyn_cast(value)) { RETURN_IF(isUser); DEBUG_VALUE(" >>>> findPointerVariables: found call instruction: ", value); } else if(CmpInst *CI = dyn_cast(value)) { assert(isUser); DEBUG_VALUE(" >>>> findPointerVariables: Digging cmp instruction: ", value); findPointerVariables(function, CI->getOperand(0), ptrVars, ptrVarIndexes, value); findPointerVariables(function, CI->getOperand(1), ptrVars, ptrVarIndexes, value); RETURN_IF(true); } else if(SelectInst *SI = dyn_cast(value)) { DEBUG_VALUE(" >>>> findPointerVariables: Digging select instruction: ", value); findPointerVariables(function, SI->getOperand(1), ptrVars, ptrVarIndexes, value); findPointerVariables(function, SI->getOperand(2), ptrVars, ptrVarIndexes, value); } else if(constantExpr && constantExpr->getOpcode() == Instruction::Select) { DEBUG_VALUE(" >>>> findPointerVariables: Digging select expression: ", value); findPointerVariables(function, constantExpr->getOperand(1), ptrVars, ptrVarIndexes, value); findPointerVariables(function, constantExpr->getOperand(2), ptrVars, ptrVarIndexes, value); } else if(PHINode *PN = dyn_cast(value)) { DEBUG_VALUE(" >>>> findPointerVariables: Digging PHI instruction: ", value); for(unsigned i=0;igetNumIncomingValues();i++) { findPointerVariables(function, PN->getIncomingValue(i), ptrVars, ptrVarIndexes, value); } } else if(Argument *ARG = dyn_cast(value)) { DEBUG_VALUE(" >>>> findPointerVariables: Digging Argument: ", value); AllocaInst *AI = MagicUtil::getAllocaInstFromArgument(ARG); assert(AI); currPtrVarIndexes.push_back(0); findPointerVariables(function, AI, ptrVars, ptrVarIndexes, value); currPtrVarIndexes.pop_back(); RETURN_IF(true); } else { DEBUG_VALUE(" ************************************************************ findPointerVariables: Unknown value: ", value); RETURN_IF(true); } for (Value::use_iterator i = value->use_begin(), e = value->use_end(); i != e; ++i) { User *user = *i; Instruction *instruction = dyn_cast(user); if(!instruction || instruction->getParent()->getParent() != function) { continue; } DEBUG_VALUE(" >>>> findPointerVariables: Found user: ", user); findPointerVariables(function, user, ptrVars, ptrVarIndexes, value, true); } while(savedPtrVarIndexes.size() > 0) { currPtrVarIndexes.push_back(savedPtrVarIndexes.back()); savedPtrVarIndexes.pop_back(); } } TypeInfo* MagicPass::typeInfoFromPointerVariables(Module &M, TypeInfo *voidPtrTypeInfo, std::vector &ptrVars, std::vector > &ptrVarIndexes, std::string &allocName) { std::vector validTypeInfos; std::set validTypeInfoSet; std::vector validTypeTags; std::vector voidTypeTags; std::vector indexes; TypeInfo *aTypeInfo = NULL; TypeInfo *voidTypeInfo = voidPtrTypeInfo->getContainedType(0); allocName = ""; if(ptrVars.size()==0) { return voidTypeInfo; } for(unsigned i=0;i(ptrVars[i])) { parentMapIt = globalParentMap.find(GV); assert(parentMapIt != globalParentMap.end()); aTypeInfo = parentMapIt->second; tag = dwarf::DW_TAG_variable; varName = MagicUtil::getGVSourceName(M, GV, NULL, baseBuildDir); } else { AllocaInst *AI = dyn_cast(ptrVars[i]); assert(AI); if(DEBUG_ALLOC_LEVEL >= 4) { AI->print(errs()); errs() << "\n"; } const SmartType *aSmartType = SmartType::getSmartTypeFromLV(M, AI, &DIV); if(aSmartType == (const SmartType *)-1) { //a temporary variable if(DEBUG_ALLOC_LEVEL >= 4) { magicPassErr("typeInfoFromPointerVariables: Skipping temporary variable"); } continue; } else if(!aSmartType) { //a return variable if(DEBUG_ALLOC_LEVEL >= 4) { magicPassErr("typeInfoFromPointerVariables: Processing return variable"); } if(AI->getAllocatedType() == voidPtrTypeInfo->getType()) { aTypeInfo = voidPtrTypeInfo; } else { aTypeInfo = fillExternalTypeInfos(AI->getAllocatedType(), NULL, globalTypeInfos); if(aTypeInfo == NULL) { magicPassErr("typeInfoFromPointerVariables: type is: " << TypeUtil::getDescription(AI->getAllocatedType(), MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL)); if(!MAGIC_ABORT_ON_UNSUPPORTED_LOCAL_EXTERNAL_TYPE) { magicPassErr("typeInfoFromPointerVariables: Warning: Local external type not supported, resorting to void* type..."); aTypeInfo = voidPtrTypeInfo; } else { assert(aTypeInfo != NULL && "Local external type not supported!"); } } } tag = dwarf::DW_TAG_unspecified_type; } else { //a regular variable (potentially returning a value to the caller) if(DEBUG_ALLOC_LEVEL >= 4) { magicPassErr("typeInfoFromPointerVariables: Processing regular variable"); } TypeInfo newTypeInfo(aSmartType); aTypeInfo = fillTypeInfos(newTypeInfo, globalTypeInfos); if(aTypeInfo->getSmartType() != aSmartType) { delete aSmartType; } if (PassUtil::isReturnedValue(AI->getParent()->getParent(), AI)) { // treat this variable as a return variable tag = dwarf::DW_TAG_unspecified_type; } else { tag = DIV.getTag(); } } varName = DIV.getName(); } //see if the target type is an alias for void* assert(aTypeInfo); if(aTypeInfo->getType()->isPointerTy()) { stringSetIt = voidTypeAliasesSet.find(aTypeInfo->getContainedType(0)->getName()); if(stringSetIt != voidTypeAliasesSet.end()) { aTypeInfo = voidPtrTypeInfo; } } //fix tag if needed if(tag == dwarf::DW_TAG_unspecified_type) { TYPECONST Type *type = aTypeInfo->getType(); if(!type->isPointerTy() || type->getContainedType(0)->isPointerTy()) { //not a good return type, switch to a regular variable tag = dwarf::DW_TAG_auto_variable; } } if(tag == dwarf::DW_TAG_arg_variable) { TYPECONST Type *type = aTypeInfo->getType(); if(!type->isPointerTy() || !type->getContainedType(0)->isPointerTy() || type->getContainedType(0)->getContainedType(0)->isPointerTy()) { //not a good arg type, switch to a regular variable tag = dwarf::DW_TAG_auto_variable; } } if(DEBUG_ALLOC_LEVEL >= 3) { switch(tag) { case dwarf::DW_TAG_unspecified_type: magicPassErr("typeInfoFromPointerVariables: Found return variable: " << varName); break; case dwarf::DW_TAG_variable: magicPassErr("typeInfoFromPointerVariables: Found global variable:" << varName); break; case dwarf::DW_TAG_auto_variable: magicPassErr("typeInfoFromPointerVariables: Found local variable:" << varName); break; case dwarf::DW_TAG_arg_variable: magicPassErr("typeInfoFromPointerVariables: Found argument variable:" << varName); break; default: assert(0 && "Should never get here!"); break; } } indexes = ptrVarIndexes[i]; assert(indexes.back() == 0); indexes.pop_back(); if(DEBUG_ALLOC_LEVEL >= 4) { magicPassErr("typeInfoFromPointerVariables: " << indexes.size() << " indexes to process."); } while(!indexes.empty()) { int index = indexes.back(); if(aTypeInfo->hasRawTypeRepresentation()) { if(DEBUG_ALLOC_LEVEL >= 4) { magicPassErr("typeInfoFromPointerVariables: Skipping index (raw type representation): " << index << ", type is: " << aTypeInfo->getVerboseDescription()); } aTypeInfo = voidTypeInfo; break; } if(!aTypeInfo->getType()->isStructTy()) { index = 0; } aTypeInfo = aTypeInfo->getContainedType(index); if(DEBUG_ALLOC_LEVEL >= 4) { magicPassErr("typeInfoFromPointerVariables: Processing index: " << index << ", type is: " << aTypeInfo->getVerboseDescription()); } indexes.pop_back(); } if(aTypeInfo == voidTypeInfo) { voidTypeTags.push_back(tag); } else { validTypeInfos.push_back(aTypeInfo); validTypeInfoSet.insert(aTypeInfo); validTypeTags.push_back(tag); } if(!allocName.compare("")) { allocName = varName; } } //see if we have a valid void return type bool hasValidVoidReturnType = false; for(unsigned i=0;i::iterator it=validTypeInfoSet.begin() ; it != validTypeInfoSet.end(); it++ ) { if((*it)->getType() == voidTypeInfo->getType()) { numWeakLocalTypes++; } else { nonWeakTypeIndex = index; } index++; } bool hasOnlyWeakLocalTypes = (numWeakLocalTypes == validTypeInfoSet.size()); bool hasOnlyOneNonWeakLocalType = (validTypeInfoSet.size() - numWeakLocalTypes == 1); if(DEBUG_ALLOC_LEVEL >= 3) { magicPassErr("typeInfoFromPointerVariables: Status: voidTypeTagsSize=" << voidTypeTags.size() << ", hasValidVoidReturnType=" << hasValidVoidReturnType << ", hasOnlyWeakLocalTypes=" << hasOnlyWeakLocalTypes << ", hasOnlyOneNonWeakLocalType=" << hasOnlyOneNonWeakLocalType); } //return NULL (treat the function as a wrapper) if we have a valid return type and only weak local types if(hasValidVoidReturnType && hasOnlyWeakLocalTypes) { if(DEBUG_ALLOC_LEVEL >= 3) { magicPassErr("typeInfoFromPointerVariables: Returning no type at all: treat the function as a wrapper"); } return NULL; } //a single valid type has been found, return it if(hasOnlyOneNonWeakLocalType || (hasOnlyWeakLocalTypes && validTypeInfoSet.size() > 0)) { if(validTypeTags[nonWeakTypeIndex] == dwarf::DW_TAG_unspecified_type) { if(DEBUG_ALLOC_BAD_TYPES) { magicPassErr("typeInfoFromPointerVariables: warning: non-void return type"); } } if(validTypeTags[nonWeakTypeIndex] == dwarf::DW_TAG_arg_variable) { if(DEBUG_ALLOC_BAD_TYPES) { magicPassErr("typeInfoFromPointerVariables: warning: non-void arg type"); } } if(DEBUG_ALLOC_LEVEL >= 3) { magicPassErr("typeInfoFromPointerVariables: Returning single valid type"); } return validTypeInfos[nonWeakTypeIndex]; } //multiple valid types found, print warning and resort to void else if(validTypeInfoSet.size() > 1 && DEBUG_ALLOC_BAD_TYPES) { magicPassErr("typeInfoFromPointerVariables: warning: multiple valid types found:"); for (std::set::iterator it=validTypeInfoSet.begin() ; it != validTypeInfoSet.end(); it++ ) { magicPassErr(" - " << (*it)->getVerboseDescription()); } if(DEBUG_ALLOC_LEVEL >= 3) { magicPassErr("typeInfoFromPointerVariables: Multiple valid types found"); } } if(DEBUG_ALLOC_LEVEL >= 3) { magicPassErr("typeInfoFromPointerVariables: Returning default void type"); } return voidTypeInfo; } TypeInfo* MagicPass::getAllocTypeInfo(Module &M, TypeInfo *voidPtrTypeInfo, const CallSite &CS, std::string &allocName, std::string &allocParentName) { Value *allocPointer = NULL; Function *function = MagicUtil::getCalledFunctionFromCS(CS); Function *parentFunction = CS.getInstruction()->getParent()->getParent(); if(DEBUG_ALLOC_LEVEL >= 1) { magicPassErr("Function is: " << function->getName()); magicPassErr("Parent is: " << parentFunction->getName()); } std::vector ptrVars; std::vector > ptrVarIndexes; currPtrVarIndexes.clear(); visitedValues.clear(); int pointerParam = MagicMemFunction::getMemFunctionPointerParam(function, brkFunctions, voidPtrTypeInfo); assert(pointerParam >= 0 && "Invalid wrapper function!"); if(pointerParam == 0) { allocPointer = CS.getInstruction(); currPtrVarIndexes.push_back(0); } else { allocPointer = CS.getArgument(pointerParam-1); currPtrVarIndexes.push_back(0); //brk is a special case and takes the pointer by value if(brkFunctions.find(function) == brkFunctions.end()) { currPtrVarIndexes.push_back(0); } } findPointerVariables(parentFunction, allocPointer, ptrVars, ptrVarIndexes); TypeInfo* aTypeInfo = typeInfoFromPointerVariables(M, voidPtrTypeInfo, ptrVars, ptrVarIndexes, allocName); allocParentName = MagicUtil::getFunctionSourceName(M, parentFunction, NULL, baseBuildDir); if(DEBUG_ALLOC_LEVEL >= 1) { magicPassErr("**************** type found: " << (aTypeInfo ? aTypeInfo->getType()->isStructTy() ? "struct " + aTypeInfo->getName() : aTypeInfo->getVerboseDescription() : "NULL")); } return aTypeInfo; } TypeInfo* MagicPass::fillTypeInfos(TypeInfo &sourceTypeInfo, std::vector &typeInfos) { static std::vector nestedTypes; static unsigned level = 0; if(DEBUG_FILL_TYPE_INFOS) { magicPassErr("Entering level: " << level << ", Examining type: " << sourceTypeInfo.getDescription() << ", types so far: " << typeInfos.size()); } if(sourceTypeInfo.getType()) { TYPECONST Type* type = sourceTypeInfo.getType(); for(unsigned i=0;igetType()) { const SmartType *nestedSType = nestedTypes[i]->getSmartType(); const SmartType *sourceSType = sourceTypeInfo.getSmartType(); if((!nestedSType && !sourceSType) || (nestedSType && sourceSType && nestedSType->getEDIType()->equals(sourceSType->getEDIType()))) { nestedTypes[i]->addParents(sourceTypeInfo.getParents()); return nestedTypes[i]; } } } } assert(sourceTypeInfo.getParents().size() <= 1); for(unsigned i=0;iequals(&sourceTypeInfo)) { typeInfos[i]->addParents(sourceTypeInfo.getParents()); return typeInfos[i]; } } TypeInfo *aTypeInfo = new TypeInfo(sourceTypeInfo); aTypeInfo->setPersistent(); const SmartType *aSmartType = aTypeInfo->getSmartType(); unsigned numContainedTypes = aSmartType ? aSmartType->getNumContainedTypes() : 0; const SmartType* containedSmartType = NULL; TypeInfo* addedTypeInfo = NULL; std::vector aTypeInfoContainedTypes; nestedTypes.push_back(aTypeInfo); level++; for(unsigned i=0;igetContainedType(i); if(!containedSmartType->isFunctionTy() || containedSmartType->isTypeConsistent()) { TypeInfo containedTypeInfo(containedSmartType); addedTypeInfo = fillTypeInfos(containedTypeInfo, typeInfos); } else { TYPECONST FunctionType* type = (TYPECONST FunctionType*) containedSmartType->getType(); TypeInfo containedTypeInfo(type); addedTypeInfo = fillTypeInfos(containedTypeInfo, typeInfos); } if(addedTypeInfo->getSmartType() != containedSmartType) { delete containedSmartType; } aTypeInfoContainedTypes.push_back(addedTypeInfo); } level--; nestedTypes.pop_back(); aTypeInfo->setContainedTypes(aTypeInfoContainedTypes); typeInfos.push_back(aTypeInfo); if(DEBUG_FILL_TYPE_INFOS) { magicPassErr("Exiting level: " << level << ", types so far: " << typeInfos.size()); } return aTypeInfo; } TypeInfo* MagicPass::fillExternalTypeInfos(TYPECONST Type *sourceType, GlobalValue* parent, std::vector &typeInfos) { static std::map externalTypeInfoCache; std::map::iterator externalTypeInfoCacheIt; TypeInfo* aTypeInfo = NULL; std::vector compatibleTypeInfos; //see if we already have the type in the cache first externalTypeInfoCacheIt = externalTypeInfoCache.find(sourceType); if(externalTypeInfoCacheIt != externalTypeInfoCache.end()) { aTypeInfo = externalTypeInfoCacheIt->second; if(parent) { aTypeInfo->addParent(parent); } return aTypeInfo; } for(unsigned i=0;igetSmartType() && typeInfos[i]->getSmartType()->getType() == sourceType && (!sourceType->isArrayTy() || typeInfos[i]->getTypeID() == MAGIC_TYPE_ARRAY)) { compatibleTypeInfos.push_back(typeInfos[i]); } } if(compatibleTypeInfos.size() > 0) { unsigned minStringTypeInfo = 0; if(compatibleTypeInfos.size() > 1) { /* Select the first type in alphabetical order to ensure deterministic behavior. */ for(unsigned i=1;igetSmartType()->getEDIType()->getDescription().compare(compatibleTypeInfos[minStringTypeInfo]->getSmartType()->getEDIType()->getDescription()) < 0) { minStringTypeInfo = i; } } } aTypeInfo = compatibleTypeInfos[minStringTypeInfo]; } if(DEBUG_FILL_EXT_TYPE_INFOS && compatibleTypeInfos.size() > 1) { std::string typeString; for(unsigned i=0;igetSmartType()); typeString += (i==0 ? "" : ", ") + compatibleTypeInfos[i]->getSmartType()->getEDIType()->getDescription(); } magicPassErr("Multiple compatible types found for external type " << TypeUtil::getDescription(sourceType, MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL) << ": " << typeString << "; selecting the first type in alphabetical order: " << aTypeInfo->getSmartType()->getEDIType()->getDescription()); } if(aTypeInfo == NULL) { TypeInfo *targetTypeInfo = NULL; if(TypeUtil::isOpaqueTy(sourceType)) { aTypeInfo = new TypeInfo((TYPECONST StructType*) sourceType, TYPEINFO_PERSISTENT); typeInfos.push_back(aTypeInfo); } else if(sourceType->isPointerTy()) { TYPECONST Type *targetType = sourceType->getContainedType(0); targetTypeInfo = fillExternalTypeInfos(targetType, NULL, typeInfos); if(targetTypeInfo == NULL) { return NULL; } aTypeInfo = new TypeInfo((TYPECONST PointerType*) sourceType, TYPEINFO_PERSISTENT); } else if(sourceType->isArrayTy()) { TYPECONST Type *targetType = sourceType->getContainedType(0); targetTypeInfo = fillExternalTypeInfos(targetType, NULL, typeInfos); if(targetTypeInfo == NULL) { return NULL; } aTypeInfo = new TypeInfo((TYPECONST ArrayType*) sourceType, TYPEINFO_PERSISTENT); } else if(sourceType->isIntegerTy()) { aTypeInfo = new TypeInfo((TYPECONST IntegerType*) sourceType, TYPEINFO_PERSISTENT); typeInfos.push_back(aTypeInfo); } else if(sourceType->isFunctionTy()) { aTypeInfo = new TypeInfo((TYPECONST FunctionType*) sourceType, TYPEINFO_PERSISTENT); typeInfos.push_back(aTypeInfo); } if(targetTypeInfo != NULL) { std::vector containedTypes; containedTypes.push_back(targetTypeInfo); aTypeInfo->setContainedTypes(containedTypes); typeInfos.push_back(aTypeInfo); } } if(aTypeInfo && parent) { aTypeInfo->addParent(parent); } externalTypeInfoCache.insert(std::pair(sourceType, aTypeInfo)); return aTypeInfo; } void MagicPass::printInterestingTypes(TYPECONST TypeInfo *aTypeInfo) { static std::vector nestedTypes; static std::vector nestedIndexes; static std::vector interestingTypesSoFar; static std::string typeName; static unsigned level = 0; for(unsigned i=0;igetSmartType(); if(aSmartType) { if(aSmartType->isStructTy() && !aTypeInfo->getName().compare("")) { isInterestingType = true; typeName = "Anonymous"; } if(aSmartType->getEDIType()->isEnumTy()) { isInterestingType = true; typeName = "Enum"; } if(aSmartType->isOpaqueTy()) { isInterestingType = true; typeName = "Opaque"; } } if(isInterestingType) { bool isNewInterestingType = true; for(unsigned i=0;igetDescription(); aSmartType->getEDIType()->getDIType()->print(dbgs()); } else { dbgs() << "**** " << typeName << " type found, printing path: \n"; dbgs() << "**************** LEVEL 0\n"; dbgs() << "**************** NAME: " << nestedTypes[0]->getName() << "\n"; dbgs() << nestedTypes[0]->getSmartType()->getDescription(); unsigned i; for(i=1;igetName() << "\n"; dbgs() << "**************** PARENT INDEX " << nestedIndexes[i-1] << "\n"; dbgs() << nestedTypes[i]->getSmartType()->getDescription(); } dbgs() << "**************** LAST LEVEL " << i << "\n"; dbgs() << "**************** PARENT INDEX " << nestedIndexes[i-1] << "\n"; dbgs() << aSmartType->getDescription(); aSmartType->getEDIType()->getDIType()->print(dbgs()); dbgs() << "*****************************************\n"; } } } unsigned numContainedTypes = aTypeInfo->getNumContainedTypes(); nestedTypes.push_back(aTypeInfo); level++; for(unsigned i=0;igetContainedType(i)); nestedIndexes.pop_back(); } level--; nestedTypes.pop_back(); } unsigned MagicPass::getMaxRecursiveSequenceLength(TYPECONST TypeInfo *aTypeInfo) { static std::vector nestedTypes; static unsigned level = 0; for(unsigned i=0;igetNumContainedTypes(); unsigned length, maxLength = 0; nestedTypes.push_back(aTypeInfo); level++; for(unsigned i=0;igetContainedType(i)); if(length > maxLength) { maxLength = length; } } level--; nestedTypes.pop_back(); return maxLength; } FunctionType* MagicPass::getFunctionType(TYPECONST FunctionType *baseType, std::vector selectedArgs) { std::vector ArgTypes; for (unsigned i = 0; i < selectedArgs.size(); i++) { ArgTypes.push_back(baseType->getParamType(selectedArgs[i] - 1)); } // Create a new function type... FunctionType *FTy = FunctionType::get(baseType->getReturnType(), ArgTypes, baseType->isVarArg()); return FTy; } bool MagicPass::isCompatibleMagicMemFuncType(TYPECONST FunctionType *type, TYPECONST FunctionType* magicType) { if(type->getReturnType() != magicType->getReturnType()) { return false; } unsigned numContainedTypes = type->getNumContainedTypes(); unsigned numContainedMagicTypes = magicType->getNumContainedTypes(); if(numContainedTypes > numContainedMagicTypes) { return false; } for(unsigned i=0;igetContainedType(numContainedTypes-1-i); TYPECONST Type* cMagicType = magicType->getContainedType(numContainedMagicTypes-1-i); if (!MagicUtil::isCompatibleType(cType, cMagicType)) { return false; } } return true; } void MagicPass::indexCasts(Module &M, User *U, std::vector &intCastTypes, std::vector &intCastValues, std::map > &bitCastMap) { unsigned i; std::map >::iterator bitCastMapIt; TYPECONST Type* voidPtrType = PointerType::get(IntegerType::get(M.getContext(), 8), 0); //look at instructions first #if MAGIC_INDEX_INT_CAST if(CastInst* CI = dyn_cast(U)) { TYPECONST Type* type = TypeUtil::getArrayFreePointerType(CI->getDestTy()); TYPECONST Type* elType = TypeUtil::getRecursiveElementType(type); if((MAGIC_INDEX_FUN_PTR_INT_CAST && elType->isFunctionTy()) || (MAGIC_INDEX_STR_PTR_INT_CAST && elType->isStructTy()) || MAGIC_INDEX_OTH_PTR_INT_CAST) { if(MAGIC_INDEX_VOID_PTR_INT_CAST || type != voidPtrType) { intCastTypes.push_back(type); ConstantInt *value = dyn_cast(CI->getOperand(0)); intCastValues.push_back(value ? value->getSExtValue() : 0); #if DEBUG_CASTS CI->print(errs()); errs() << "\n"; #endif } } } #endif #if MAGIC_INDEX_BIT_CAST if(BitCastInst* CI = dyn_cast(U)) { TYPECONST Type* type = TypeUtil::getArrayFreePointerType(CI->getDestTy()); TYPECONST Type* elType = TypeUtil::getRecursiveElementType(type); if((MAGIC_INDEX_FUN_PTR_BIT_CAST && elType->isFunctionTy()) || (MAGIC_INDEX_STR_PTR_BIT_CAST && elType->isStructTy()) || MAGIC_INDEX_OTH_PTR_BIT_CAST) { if(MAGIC_INDEX_VOID_PTR_BIT_CAST || type != voidPtrType) { TYPECONST Type* srcType = TypeUtil::getArrayFreePointerType(CI->getSrcTy()); if(srcType != type && (!MAGIC_SKIP_TOVOID_PTR_BIT_CAST || srcType != voidPtrType)) { #if DEBUG_CASTS CI->print(errs()); errs() << "\n"; #endif bitCastMapIt = bitCastMap.find(type); if(bitCastMapIt == bitCastMap.end()) { std::set typeSet; typeSet.insert(srcType); bitCastMap.insert(std::pair >(type, typeSet)); } else { std::set *typeSet = &(bitCastMapIt->second); typeSet->insert(srcType); } } } } } #endif //now dig looking for constant expressions std::vector users; users.push_back(U); while(!users.empty()) { User *user = users.front(); users.erase(users.begin()); ConstantExpr *CE = dyn_cast(user); #if MAGIC_INDEX_INT_CAST if(CE && CE->getOpcode() == Instruction::IntToPtr) { TYPECONST Type* type = TypeUtil::getArrayFreePointerType(CE->getType()); TYPECONST Type* elType = TypeUtil::getRecursiveElementType(type); if((MAGIC_INDEX_FUN_PTR_INT_CAST && elType->isFunctionTy()) || (MAGIC_INDEX_STR_PTR_INT_CAST && elType->isStructTy()) || MAGIC_INDEX_OTH_PTR_INT_CAST) { if(MAGIC_INDEX_VOID_PTR_INT_CAST || type != voidPtrType) { #if DEBUG_CASTS CE->print(errs()); errs() << "\n"; #endif intCastTypes.push_back(type); ConstantInt *value = dyn_cast(CE->getOperand(0)); intCastValues.push_back(value ? value->getSExtValue() : 0); } } } #endif #if MAGIC_INDEX_BIT_CAST if(CE && CE->getOpcode() == Instruction::BitCast) { TYPECONST Type* type = TypeUtil::getArrayFreePointerType(CE->getType()); TYPECONST Type* elType = TypeUtil::getRecursiveElementType(type); if((MAGIC_INDEX_FUN_PTR_BIT_CAST && elType->isFunctionTy()) || (MAGIC_INDEX_STR_PTR_BIT_CAST && elType->isStructTy()) || MAGIC_INDEX_OTH_PTR_BIT_CAST) { if(MAGIC_INDEX_VOID_PTR_BIT_CAST || type != voidPtrType) { TYPECONST Type* srcType = TypeUtil::getArrayFreePointerType(CE->getOperand(0)->getType()); if(srcType != type && (!MAGIC_SKIP_TOVOID_PTR_BIT_CAST || srcType != voidPtrType)) { #if DEBUG_CASTS CE->print(errs()); errs() << "\n"; #endif bitCastMapIt = bitCastMap.find(type); if(bitCastMapIt == bitCastMap.end()) { std::set typeSet; typeSet.insert(srcType); bitCastMap.insert(std::pair >(type, typeSet)); } else { std::set *typeSet = &(bitCastMapIt->second); typeSet->insert(srcType); } } } } } #endif for(i=0;igetNumOperands();i++) { User *operand = dyn_cast(user->getOperand(i)); if(operand && !isa(operand) && !isa(operand)) { users.push_back(operand); } } } } void MagicPass::fillStackInstrumentedFunctions(std::vector &stackIntrumentedFuncs, Function *deepestLLFunction) { assert(!deepestLLFunction->hasAddressTaken() && "Indirect calls not supported for detection of long-lived functions"); for(unsigned i=0;iuse_begin(), e = deepestLLFunction->use_end(); i != e; ++i) { User *user = *i; if(Instruction *I = dyn_cast(user)) { fillStackInstrumentedFunctions(stackIntrumentedFuncs, I->getParent()->getParent()); } } } void MagicPass::indexLocalTypeInfos(Module &M, Function *F, std::map > &localMap) { DIVariable DIV; for (inst_iterator it = inst_begin(F), et = inst_end(F); it != et; ++it) { AllocaInst *AI = dyn_cast(&(*it)); if(!AI) { break; } const SmartType *aSmartType = SmartType::getSmartTypeFromLV(M, AI, &DIV); if(!aSmartType || aSmartType == (const SmartType *)-1) { // skip return and temporary variables continue; } TypeInfo newTypeInfo(aSmartType); TypeInfo *aTypeInfo = fillTypeInfos(newTypeInfo, globalTypeInfos); if(aTypeInfo->getSmartType() != aSmartType) { delete aSmartType; } std::string name = MagicUtil::getLVSourceName(M, AI).data(); std::pair infoNamePair(aTypeInfo, name); localMap.insert(std::pair >(AI, infoNamePair)); } } void MagicPass::addMagicStackDsentryFuncCalls(Module &M, Function *insertCallsInFunc, Function *localsFromFunc, Function *dsentryCreateFunc, Function *dsentryDestroyFunc, TYPECONST StructType *dsentryStructType, std::map > localTypeInfoMap, std::map &magicArrayTypePtrMap, TypeInfo *voidPtrTypeInfo, std::vector &typeInfoList, std::vector > &namesList, std::vector &flagsList) { std::vector locals; std::map >::iterator localTypeInfoMapIt; std::map::iterator magicArrayTypePtrMapIt; std::vector localTypeInfos; std::vector localTypeInfoValues; std::vector localDsentryValues; std::string allocName, allocParentName; Instruction *allocaI = NULL, *dsentryCreateI = NULL, *dsentryDestroyI = NULL; // find local variables and types for (inst_iterator it = inst_begin(localsFromFunc), et = inst_end(localsFromFunc); it != et; ++it) { AllocaInst *AI = dyn_cast(&(*it)); if(!AI) { break; } localTypeInfoMapIt = localTypeInfoMap.find(AI); if(localTypeInfoMapIt != localTypeInfoMap.end()) { assert(AI->hasName()); TypeInfo *aTypeInfo = localTypeInfoMapIt->second.first; magicArrayTypePtrMapIt = magicArrayTypePtrMap.find(aTypeInfo); assert(magicArrayTypePtrMapIt != magicArrayTypePtrMap.end()); Constant *aTypeInfoValue = magicArrayTypePtrMapIt->second; localTypeInfos.push_back(aTypeInfo); localTypeInfoValues.push_back(aTypeInfoValue); locals.push_back(AI); } } // find the first and the last valid instruction to place a call and the alloca point dsentryCreateI = MagicUtil::getFirstNonAllocaInst(insertCallsInFunc); dsentryDestroyI = insertCallsInFunc->back().getTerminator(); allocaI = MagicUtil::getFirstNonAllocaInst(insertCallsInFunc, false); // create one dsentry for each local variable for(unsigned i=0;ihasName() ? locals[i]->getName() : "anon"), allocaI); localDsentryValues.push_back(AI); } assert(localTypeInfoValues.size() == localDsentryValues.size()); // create one dsentry and value set array for the return address localTypeInfos.push_back(voidPtrTypeInfo); localTypeInfoValues.push_back(new AllocaInst(ArrayType::get(IntegerType::get(M.getContext(), 32), 2), "dsentry_ret_addr_value_set", allocaI)); //pass the value set pointer as though it were a type pointer localDsentryValues.push_back(new AllocaInst(dsentryStructType, "dsentry_ret_addr", allocaI)); // create one dsentry pointer to remember the last stack dsentry AllocaInst *prevLastStackDsentry = new AllocaInst(PointerType::get(dsentryStructType, 0), "prev_last_stack_dsentry", allocaI); // get the frame address of the function and pass the value as though it were a data pointer Function *frameAddrIntrinsic = MagicUtil::getIntrinsicFunction(M, Intrinsic::frameaddress); std::vector frameAddrArgs; frameAddrArgs.push_back(ConstantInt::get(M.getContext(), APInt(32, 0))); CallInst *callInst = MagicUtil::createCallInstruction(frameAddrIntrinsic, frameAddrArgs, "", dsentryCreateI); locals.push_back(callInst); // place calls std::vector dsentryCreateArgs; std::vector dsentryDestroyArgs; dsentryCreateArgs.push_back(prevLastStackDsentry); dsentryDestroyArgs.push_back(prevLastStackDsentry); dsentryCreateArgs.push_back(ConstantInt::get(M.getContext(), APInt(32, locals.size()))); dsentryDestroyArgs.push_back(ConstantInt::get(M.getContext(), APInt(32, locals.size()))); allocParentName = MagicUtil::getFunctionSourceName(M, insertCallsInFunc, NULL, baseBuildDir); int allocFlags = MAGIC_STATE_STACK; for(unsigned i=0;i(locals[i])) { // local variable localTypeInfoMapIt = localTypeInfoMap.find(AI); assert(localTypeInfoMapIt != localTypeInfoMap.end()); allocName = localTypeInfoMapIt->second.second; } else { // return address allocName = MAGIC_ALLOC_RET_ADDR_NAME; } //add args dsentryCreateArgs.push_back(localDsentryValues[i]); dsentryCreateArgs.push_back(localTypeInfoValues[i]); dsentryCreateArgs.push_back(locals[i]); dsentryCreateArgs.push_back(MagicUtil::getStringRef(M, allocParentName)); dsentryCreateArgs.push_back(MagicUtil::getStringRef(M, allocName)); dsentryDestroyArgs.push_back(localDsentryValues[i]); //add elements to type and names lists typeInfoList.push_back(localTypeInfos[i]); namesList.push_back(std::pair(allocParentName, allocName)); flagsList.push_back(allocFlags); } MagicUtil::createCallInstruction(dsentryCreateFunc, dsentryCreateArgs, "", dsentryCreateI); if(isa(dsentryDestroyI)) { MagicUtil::createCallInstruction(dsentryDestroyFunc, dsentryDestroyArgs, "", dsentryDestroyI); } } bool MagicPass::isExtLibrary(GlobalValue *GV, DIDescriptor *DID) { static bool regexesInitialized = false; static std::vector regexes; if(!regexesInitialized) { std::vector::iterator it; for (it = libPathRegexes.begin(); it != libPathRegexes.end(); ++it) { Regex* regex = new Regex(*it, 0); std::string error; assert(regex->isValid(error)); regexes.push_back(regex); } regexesInitialized = true; } if (DID) { std::string relPath; PassUtil::getDbgLocationInfo(*DID, baseBuildDir, NULL, NULL, &relPath); for(unsigned i=0;imatch(relPath, NULL)) { return true; } } } return PassUtil::matchRegexes(GV->getSection(), extLibSectionRegexes); } bool MagicPass::isMagicGV(Module &M, GlobalVariable *GV) { if (GV->isThreadLocal() && (GV->getName().startswith(MAGIC_PREFIX_STR) || GV->getName().startswith("rcu"))) { return true; } if (!GV->getSection().compare(MAGIC_LLVM_METADATA_SECTION)) { return true; } if (GV->getName().startswith("__start") || GV->getName().startswith("__stop") || GV->getName().startswith("llvm.")) { return true; } return PassUtil::matchRegexes(GV->getSection(), magicDataSectionRegexes); } bool MagicPass::isMagicFunction(Module &M, Function *F) { if (F->getName().startswith("llvm.")) return true; return PassUtil::matchRegexes(F->getSection(), magicFunctionSectionRegexes); } #if MAGIC_USE_QPROF_INSTRUMENTATION void MagicPass::qprofInstrumentationInit(Module &M) { // look up qprof configuration qprofConf = QProfConf::get(M, &magicLLSitestacks, &magicDeepestLLLoops, &magicDeepestLLLibs, &magicTaskClasses); qprofConf->mergeAllTaskClassesWithSameDeepestLLLoops(); #if DEBUG_QPROF qprofConf->print(errs()); #endif } void MagicPass::qprofInstrumentationApply(Module &M) { Function *hook; std::vector hookParams; QProfSite* site; std::vectorfunctionTyArgs; FunctionType *hookFunctionTy; /* * Instrument deepest long-lived loops. This creates a function * pointer of the form void (*MAGIC_DEEPEST_LL_LOOP_HOOK_NAME)(char*, int) * called (if set by instrumentation libraries) at the top of every loop. */ functionTyArgs.push_back(PointerType::get(IntegerType::get(M.getContext(), 8), 0)); functionTyArgs.push_back(IntegerType::get(M.getContext(), 32)); hookFunctionTy = PassUtil::getFunctionType(Type::getVoidTy(M.getContext()), functionTyArgs, false); std::vector deepestLLLoops = qprofConf->getDeepestLLLoops(); hook = PassUtil::getOrInsertFunction(M, MAGIC_DEEPEST_LL_LOOP_HOOK_NAME, hookFunctionTy, PASS_UTIL_LINKAGE_WEAK_POINTER, PASS_UTIL_FLAG(PASS_UTIL_PROP_PRESERVE)); assert(hook); for (unsigned i=0;itoString())); hookParams.push_back(siteString); hookParams.push_back(ConstantInt::get(M.getContext(), APInt(32, site->taskClassID, 10))); PassUtil::createCallInstruction(hook, hookParams, "", site->siteInstruction); } /* * Instrument deepest long-lived library calls. This creates a function * pointer of the form void (*MAGIC_DEEPEST_LL_LIB_HOOK_NAME)(char*, int, int, int) * called (if set by instrumentation libraries) before every library call. */ functionTyArgs.clear(); functionTyArgs.push_back(PointerType::get(IntegerType::get(M.getContext(), 8), 0)); functionTyArgs.push_back(IntegerType::get(M.getContext(), 32)); functionTyArgs.push_back(IntegerType::get(M.getContext(), 32)); functionTyArgs.push_back(IntegerType::get(M.getContext(), 32)); hookFunctionTy = PassUtil::getFunctionType(Type::getVoidTy(M.getContext()), functionTyArgs, false); std::vector deepestLLLibs = qprofConf->getDeepestLLLibs(); hook = PassUtil::getOrInsertFunction(M, MAGIC_DEEPEST_LL_LIB_HOOK_NAME, hookFunctionTy, PASS_UTIL_LINKAGE_WEAK_POINTER, PASS_UTIL_FLAG(PASS_UTIL_PROP_PRESERVE)); assert(hook); for (unsigned i=0;itoString())); hookParams.push_back(siteString); hookParams.push_back(ConstantInt::get(M.getContext(), APInt(32, site->taskClassID, 10))); hookParams.push_back(ConstantInt::get(M.getContext(), APInt(32, site->taskSiteID, 10))); hookParams.push_back(ConstantInt::get(M.getContext(), APInt(32, site->libFlags, 10))); PassUtil::createCallInstruction(hook, hookParams, "", site->siteInstruction); } /* * Create relevant exported variables in use by the libraries. */ MagicUtil::getExportedIntGlobalVar(M, MAGIC_NUM_LL_TASK_CLASSES_NAME, qprofConf->getNumLLTaskClasses()); MagicUtil::getExportedIntGlobalVar(M, MAGIC_NUM_LL_BLOCK_EXT_TASK_CLASSES_NAME, qprofConf->getNumLLBlockExtTaskClasses()); MagicUtil::getExportedIntGlobalVar(M, MAGIC_NUM_LL_BLOCK_INT_TASK_CLASSES_NAME, qprofConf->getNumLLBlockIntTaskClasses()); MagicUtil::getExportedIntGlobalVar(M, MAGIC_NUM_LL_BLOCK_EXT_LIBS_NAME, qprofConf->getNumLLBlockExtLibs()); MagicUtil::getExportedIntGlobalVar(M, MAGIC_NUM_LL_BLOCK_INT_LIBS_NAME, qprofConf->getNumLLBlockIntLibs()); } #else void MagicPass::qprofInstrumentationInit(Module &M) {} void MagicPass::qprofInstrumentationApply(Module &M) {} #endif } // end namespace char MagicPass::ID = 0; RegisterPass MP("magic", "Magic Pass to Build a Table of Global Variables");