bool LLPE::runOnModule(Module &M) { vector<int> argv = readInputFile(); for (Module::iterator F = M.begin(), F_end = M.end(); F != F_end; ++F) { for (Function::arg_iterator A = F->arg_begin(), A_end = F->arg_end(); A != A_end; ++A) { //Search for variables referencing argv if (A->getName() == "argv") { //Iterate through uses of argv for (Value::use_iterator U = A->use_begin(), U_end = A->use_end(); U != U_end; ++U) { Instruction *User = dyn_cast<Instruction>(*U); StoreInst *SI = dyn_cast<StoreInst>(User); AllocaInst *OrigAlloca = dyn_cast<AllocaInst>(SI->getOperand(1)); for (Value::use_iterator U2 = OrigAlloca->use_begin(), U2_end = OrigAlloca->use_end(); U2 != U2_end; ++U2) { Instruction *User2 = dyn_cast<Instruction>(*U2); for (Value::use_iterator U3 = User2->use_begin(), U3_end = OrigAlloca->use_end(); U3 != U3_end; ++U3) { searchForStoreInstruction(dyn_cast<Instruction>(*U3)->getParent(), argv); } } } } } } return true; }
/* * Build information about functions that store on pointer arguments * For simplification, we only consider a function to store on an argument * if it has exactly one StoreInst to that argument and the arg has no other use. */ int DeadStoreEliminationPass::getFnThatStoreOnArgs(Module &M) { int numStores = 0; DEBUG(errs() << "Getting functions that store on arguments...\n"); for (Module::iterator F = M.begin(); F != M.end(); ++F) { if (F->arg_empty() || F->isDeclaration()) continue; // Get args std::set<Value*> args; for (Function::arg_iterator formalArgIter = F->arg_begin(); formalArgIter != F->arg_end(); ++formalArgIter) { Value *formalArg = formalArgIter; if (formalArg->getType()->isPointerTy()) { args.insert(formalArg); } } // Find stores on arguments for (Function::iterator BB = F->begin(); BB != F->end(); ++BB) { for (BasicBlock::iterator I = BB->begin(); I != BB->end(); ++I) { Instruction *inst = I; if (!isa<StoreInst>(inst)) continue; StoreInst *SI = dyn_cast<StoreInst>(inst); Value *ptrOp = SI->getPointerOperand(); if (args.count(ptrOp) && ptrOp->hasNUses(1)) { fnThatStoreOnArgs[F].insert(ptrOp); numStores++; DEBUG(errs() << " " << F->getName() << " stores on argument " << ptrOp->getName() << "\n"); } } } } DEBUG(errs() << "\n"); return numStores; }
bool llvm::ValueCounter::runOnModule(Module& M) { std::set<Value*> values; for(Module::iterator Fit = M.begin(), Fend = M.end(); Fit != Fend; Fit++){ if (!values.count(Fit)) values.insert(Fit); for(Function::arg_iterator Arg = Fit->arg_begin(), aEnd = Fit->arg_end(); Arg != aEnd; Arg++) { if (!values.count(Arg)) values.insert(Arg); } for (Function::iterator BBit = Fit->begin(), BBend = Fit->end(); BBit != BBend; BBit++) { for (BasicBlock::iterator Iit = BBit->begin(), Iend = BBit->end(); Iit != Iend; Iit++) { if (!values.count(Iit)) values.insert(Iit); for(unsigned int i = 0; i < Iit->getNumOperands(); i++){ if (!values.count(Iit->getOperand(i))) values.insert(Iit->getOperand(i)); } } } } TotalValues = values.size(); //We don't modify anything, so we must return false; return false; }
void MemoryInstrumenter::checkFeatures(Module &M) { // Check whether any memory allocation function can // potentially be pointed by function pointers. // Also, all intrinsic functions will be called directly, // i.e. not via function pointers. for (Module::iterator F = M.begin(); F != M.end(); ++F) { if (DynAAUtils::IsMalloc(F) || F->isIntrinsic()) { for (Value::use_iterator UI = F->use_begin(); UI != F->use_end(); ++UI) { User *Usr = *UI; assert(isa<CallInst>(Usr) || isa<InvokeInst>(Usr)); CallSite CS(cast<Instruction>(Usr)); for (unsigned i = 0; i < CS.arg_size(); ++i) assert(CS.getArgument(i) != F); } } } // Check whether memory allocation functions are captured. for (Module::iterator F = M.begin(); F != M.end(); ++F) { // 0 is the return, 1 is the first parameter. if (F->isDeclaration() && F->doesNotAlias(0) && !DynAAUtils::IsMalloc(F)) { errs().changeColor(raw_ostream::RED); errs() << F->getName() << "'s return value is marked noalias, "; errs() << "but the function is not treated as malloc.\n"; errs().resetColor(); } } // Global variables shouldn't be of the array type. for (Module::global_iterator GI = M.global_begin(), E = M.global_end(); GI != E; ++GI) { assert(!GI->getType()->isArrayTy()); } // A function parameter or an instruction can be an array, but we don't // instrument such constructs for now. Issue a warning on such cases. for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { for (Function::arg_iterator AI = F->arg_begin(); AI != F->arg_end(); ++AI) { if (AI->getType()->isArrayTy()) { errs().changeColor(raw_ostream::RED); errs() << F->getName() << ":" << *AI << " is an array\n"; errs().resetColor(); } } } for (Module::iterator F = M.begin(); F != M.end(); ++F) { for (Function::iterator BB = F->begin(); BB != F->end(); ++BB) { for (BasicBlock::iterator Ins = BB->begin(); Ins != BB->end(); ++Ins) { if (Ins->getType()->isArrayTy()) { errs().changeColor(raw_ostream::RED); errs() << F->getName() << ":" << *Ins << " is an array\n"; errs().resetColor(); } } } } }
void MemoryInstrumenter::checkFeatures(Module &M) { // Check whether any memory allocation function can // potentially be pointed by function pointers. // Also, all intrinsic functions will be called directly, // i.e. not via function pointers. for (Module::iterator F = M.begin(); F != M.end(); ++F) { if (DynAAUtils::IsMalloc(F) || F->isIntrinsic()) { for (Value::use_iterator UI = F->use_begin(); UI != F->use_end(); ++UI) { User *Usr = *UI; assert(isa<CallInst>(Usr) || isa<InvokeInst>(Usr)); CallSite CS(cast<Instruction>(Usr)); for (unsigned i = 0; i < CS.arg_size(); ++i) assert(CS.getArgument(i) != F); } } } // Check whether memory allocation functions are captured. for (Module::iterator F = M.begin(); F != M.end(); ++F) { // 0 is the return, 1 is the first parameter. if (F->isDeclaration() && F->doesNotAlias(0) && !DynAAUtils::IsMalloc(F)) { errs().changeColor(raw_ostream::RED); errs() << F->getName() << "'s return value is marked noalias, "; errs() << "but the function is not treated as malloc.\n"; errs().resetColor(); } } // Sequential types except pointer types shouldn't be used as the type of // an instruction, a function parameter, or a global variable. for (Module::global_iterator GI = M.global_begin(), E = M.global_end(); GI != E; ++GI) { if (isa<SequentialType>(GI->getType())) assert(GI->getType()->isPointerTy()); } for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { for (Function::arg_iterator AI = F->arg_begin(); AI != F->arg_end(); ++AI) { if (isa<SequentialType>(AI->getType())) assert(AI->getType()->isPointerTy()); } } for (Module::iterator F = M.begin(); F != M.end(); ++F) { for (Function::iterator BB = F->begin(); BB != F->end(); ++BB) { for (BasicBlock::iterator Ins = BB->begin(); Ins != BB->end(); ++Ins) { if (isa<SequentialType>(Ins->getType())) assert(Ins->getType()->isPointerTy()); } } } // We don't support multi-process programs for now. if (!HookFork) assert(M.getFunction("fork") == NULL); }
void IntrinsicLowering::AddPrototypes(Module &M) { LLVMContext &Context = M.getContext(); for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) if (I->isDeclaration() && !I->use_empty()) switch (I->getIntrinsicID()) { default: break; case Intrinsic::setjmp: EnsureFunctionExists(M, "setjmp", I->arg_begin(), I->arg_end(), Type::getInt32Ty(M.getContext())); break; case Intrinsic::longjmp: EnsureFunctionExists(M, "longjmp", I->arg_begin(), I->arg_end(), Type::getVoidTy(M.getContext())); break; case Intrinsic::siglongjmp: EnsureFunctionExists(M, "abort", I->arg_end(), I->arg_end(), Type::getVoidTy(M.getContext())); break; case Intrinsic::memcpy: M.getOrInsertFunction("memcpy", Type::getInt8PtrTy(Context), Type::getInt8PtrTy(Context), Type::getInt8PtrTy(Context), DL.getIntPtrType(Context), nullptr); break; case Intrinsic::memmove: M.getOrInsertFunction("memmove", Type::getInt8PtrTy(Context), Type::getInt8PtrTy(Context), Type::getInt8PtrTy(Context), DL.getIntPtrType(Context), nullptr); break; case Intrinsic::memset: M.getOrInsertFunction("memset", Type::getInt8PtrTy(Context), Type::getInt8PtrTy(Context), Type::getInt32Ty(M.getContext()), DL.getIntPtrType(Context), nullptr); break; case Intrinsic::sqrt: EnsureFPIntrinsicsExist(M, I, "sqrtf", "sqrt", "sqrtl"); break; case Intrinsic::sin: EnsureFPIntrinsicsExist(M, I, "sinf", "sin", "sinl"); break; case Intrinsic::cos: EnsureFPIntrinsicsExist(M, I, "cosf", "cos", "cosl"); break; case Intrinsic::pow: EnsureFPIntrinsicsExist(M, I, "powf", "pow", "powl"); break; case Intrinsic::log: EnsureFPIntrinsicsExist(M, I, "logf", "log", "logl"); break; case Intrinsic::log2: EnsureFPIntrinsicsExist(M, I, "log2f", "log2", "log2l"); break; case Intrinsic::log10: EnsureFPIntrinsicsExist(M, I, "log10f", "log10", "log10l"); break; case Intrinsic::exp: EnsureFPIntrinsicsExist(M, I, "expf", "exp", "expl"); break; case Intrinsic::exp2: EnsureFPIntrinsicsExist(M, I, "exp2f", "exp2", "exp2l"); break; } }
/*! * This method identify which is value sym and which is object sym */ void SymbolTableInfo::buildMemModel(llvm::Module& module) { analysisUtil::increaseStackSize(); prePassSchedule(module); mod = &module; maxFieldLimit = maxFieldNumLimit; // Object #0 is black hole the object that may point to any object assert(totalSymNum == BlackHole && "Something changed!"); symTyMap.insert(std::make_pair(totalSymNum++, BlackHole)); createBlkOrConstantObj(BlackHole); // Object #1 always represents the constant assert(totalSymNum == ConstantObj && "Something changed!"); symTyMap.insert(std::make_pair(totalSymNum++, ConstantObj)); createBlkOrConstantObj(ConstantObj); // Pointer #2 always represents the pointer points-to black hole. assert(totalSymNum == BlkPtr && "Something changed!"); symTyMap.insert(std::make_pair(totalSymNum++, BlkPtr)); // Pointer #3 always represents the null pointer. assert(totalSymNum == NullPtr && "Something changed!"); symTyMap.insert(std::make_pair(totalSymNum, NullPtr)); // Add symbols for all the globals . for (Module::global_iterator I = module.global_begin(), E = module.global_end(); I != E; ++I) { collectSym(&*I); } // Add symbols for all the global aliases for (Module::alias_iterator I = module.alias_begin(), E = module.alias_end(); I != E; I++) { collectSym(&*I); } // Add symbols for all of the functions and the instructions in them. for (Module::iterator F = module.begin(), E = module.end(); F != E; ++F) { collectSym(&*F); collectRet(&*F); if (F->getFunctionType()->isVarArg()) collectVararg(&*F); // Add symbols for all formal parameters. for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I) { collectSym(&*I); } // collect and create symbols inside the function body for (inst_iterator II = inst_begin(&*F), E = inst_end(&*F); II != E; ++II) { const Instruction *inst = &*II; collectSym(inst); // initialization for some special instructions //{@ if (const StoreInst *st = dyn_cast<StoreInst>(inst)) { collectSym(st->getPointerOperand()); collectSym(st->getValueOperand()); } else if (const LoadInst *ld = dyn_cast<LoadInst>(inst)) { collectSym(ld->getPointerOperand()); } else if (const PHINode *phi = dyn_cast<PHINode>(inst)) { for (u32_t i = 0; i < phi->getNumIncomingValues(); ++i) { collectSym(phi->getIncomingValue(i)); } } else if (const GetElementPtrInst *gep = dyn_cast<GetElementPtrInst>( inst)) { collectSym(gep->getPointerOperand()); } else if (const SelectInst *sel = dyn_cast<SelectInst>(inst)) { collectSym(sel->getTrueValue()); collectSym(sel->getFalseValue()); } else if (const CastInst *cast = dyn_cast<CastInst>(inst)) { collectSym(cast->getOperand(0)); } else if (const ReturnInst *ret = dyn_cast<ReturnInst>(inst)) { if(ret->getReturnValue()) collectSym(ret->getReturnValue()); } else if (isCallSite(inst) && isInstrinsicDbgInst(inst)==false) { CallSite cs = analysisUtil::getLLVMCallSite(inst); callSiteSet.insert(cs); for (CallSite::arg_iterator it = cs.arg_begin(); it != cs.arg_end(); ++it) { collectSym(*it); } // Calls to inline asm need to be added as well because the callee isn't // referenced anywhere else. const Value *Callee = cs.getCalledValue(); collectSym(Callee); //TODO handle inlineAsm ///if (isa<InlineAsm>(Callee)) } //@} } } }
bool StdLibDataStructures::runOnModule (Module &M) { // // Get the results from the local pass. // init (&getAnalysis<LocalDataStructures>(), true, true, false, false); AllocWrappersAnalysis = &getAnalysis<AllocIdentify>(); // // Fetch the DSGraphs for all defined functions within the module. // for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) if (!I->isDeclaration()) getOrCreateGraph(&*I); // // Erase direct calls to functions that don't return a pointer and are marked // with the readnone annotation. // for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) if (I->isDeclaration() && I->doesNotAccessMemory() && !isa<PointerType>(I->getReturnType())) eraseCallsTo(I); // // Erase direct calls to external functions that are not varargs, do not // return a pointer, and do not take pointers. // for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) if (I->isDeclaration() && !I->isVarArg() && !isa<PointerType>(I->getReturnType())) { bool hasPtr = false; for (Function::arg_iterator ii = I->arg_begin(), ee = I->arg_end(); ii != ee; ++ii) if (isa<PointerType>(ii->getType())) { hasPtr = true; break; } if (!hasPtr) eraseCallsTo(I); } if(!DisableStdLib) { // // Scan through the function summaries and process functions by summary. // for (int x = 0; recFuncs[x].name; ++x) if (Function* F = M.getFunction(recFuncs[x].name)) if (F->isDeclaration()) { processFunction(x, F); } std::set<std::string>::iterator ai = AllocWrappersAnalysis->alloc_begin(); std::set<std::string>::iterator ae = AllocWrappersAnalysis->alloc_end(); int x; for (x = 0; recFuncs[x].name; ++x) { if(recFuncs[x].name == std::string("malloc")) break; } for(;ai != ae; ++ai) { if(Function* F = M.getFunction(*ai)) processFunction(x, F); } ai = AllocWrappersAnalysis->dealloc_begin(); ae = AllocWrappersAnalysis->dealloc_end(); for (x = 0; recFuncs[x].name; ++x) { if(recFuncs[x].name == std::string("free")) break; } for(;ai != ae; ++ai) { if(Function* F = M.getFunction(*ai)) processFunction(x, F); } // // Merge return values and checked pointer values for SAFECode run-time // checks. // processRuntimeCheck (M, "boundscheck", 2); processRuntimeCheck (M, "boundscheckui", 2); processRuntimeCheck (M, "exactcheck2", 1); processRuntimeCheck (M, "boundscheck_debug", 2); processRuntimeCheck (M, "boundscheckui_debug", 2); processRuntimeCheck (M, "exactcheck2_debug", 1); processRuntimeCheck (M, "pchk_getActualValue", 1); } // // In the Local DSA Pass, we marked nodes passed to/returned from 'StdLib' // functions as External because, at that point, they were. However, they no // longer are necessarily External, and we need to update accordingly. // GlobalsGraph->maskIncompleteMarkers(); GlobalsGraph->computeExternalFlags(DSGraph::ResetExternal); for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) if (!I->isDeclaration()) { DSGraph * G = getDSGraph(*I); unsigned EFlags = 0 | DSGraph::ResetExternal | DSGraph::DontMarkFormalsExternal | DSGraph::ProcessCallSites; G->maskIncompleteMarkers(); G->markIncompleteNodes(DSGraph::MarkFormalArgs |DSGraph::IgnoreGlobals); G->computeExternalFlags(EFlags); DEBUG(G->AssertGraphOK()); } GlobalsGraph->markIncompleteNodes(DSGraph::MarkFormalArgs |DSGraph::IgnoreGlobals); GlobalsGraph->computeExternalFlags(DSGraph::ProcessCallSites); DEBUG(GlobalsGraph->AssertGraphOK()); for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) if (!I->isDeclaration()) { DSGraph *Graph = getOrCreateGraph(I); Graph->maskIncompleteMarkers(); cloneGlobalsInto(Graph, DSGraph::DontCloneCallNodes | DSGraph::DontCloneAuxCallNodes); Graph->markIncompleteNodes(DSGraph::MarkFormalArgs |DSGraph::IgnoreGlobals); } return false; }