bool canSpecialize(Function* f) { if (f->isDeclaration()) return false; for (inst_iterator I = inst_begin(f), E = inst_end(f); I != E; ++I) { if (CallInst* ci = dyn_cast<CallInst>(&*I)) { if (ci->isInlineAsm()) { return false; } } } return true; }
virtual bool runOnFunction(Function& F) { int num_changed = 0; for (inst_iterator inst_it = inst_begin(F), _inst_end = inst_end(F); inst_it != _inst_end; ++inst_it) { if (!isMallocCall(dyn_cast<CallInst>(&*inst_it))) continue; if (VERBOSITY("opt") >= 2) { errs() << "\nFound malloc call:\n" << *inst_it << '\n'; } num_changed += ComparisonFinder(cast<CallInst>(&*inst_it)).elide_comparisons(); } return num_changed > 0; }
void FIInstSelector::getInitFIInsts(Module &M, std::set<Instruction*> *fiinsts) { for (Module::iterator m_it = M.begin(); m_it != M.end(); ++m_it) { if (!m_it->isDeclaration()) { //m_it is a function for (inst_iterator f_it = inst_begin(m_it); f_it != inst_end(m_it); ++f_it) { Instruction *inst = &(*f_it); if (isInstFITarget(inst)) { fiinsts->insert(inst); } } } } }
std::string CodeGeneratorTest::GenerateCode() { // create worklist containing all instructions of the function std::vector<Instruction*> worklist; for (inst_iterator I = inst_begin(*F), E = inst_end(*F); I != E; ++I) worklist.push_back(&*I); // remove parameter initialization from the instruction vector unsigned int paramCount = 0; for (std::vector<Instruction*>::iterator instrIt = worklist.begin(); instrIt != worklist.end(); ++instrIt) if (isa<AllocaInst>(*instrIt)) paramCount++; worklist.erase(worklist.begin(), worklist.begin()+2*paramCount); // run C code generator return getCodeGenerator()->createCCode(*F, worklist); }
void dumpPrettyIR(llvm::Function* f) { std::unique_ptr<llvm::Module> tmp_module(llvm::CloneModule(f->getParent())); // std::unique_ptr<llvm::Module> tmp_module(new llvm::Module("tmp", g.context)); llvm::Function* new_f = tmp_module->begin(); llvm::ValueToValueMapTy VMap; PrettifyingMaterializer materializer(tmp_module.get()); for (llvm::Function::iterator I = new_f->begin(), E = new_f->end(); I != E; ++I) { VMap[I] = I; } for (llvm::inst_iterator it = inst_begin(new_f), end = inst_end(new_f); it != end; ++it) { llvm::RemapInstruction(&*it, VMap, llvm::RF_None, NULL, &materializer); } tmp_module->begin()->dump(); // tmp_module->dump(); }
void DataDependence::getDataDependencies(Function &F, MemoryDependenceAnalysis &MDA, AliasAnalysis &AA) { // Since MemoryDependenceAnalysis is a function pass, we need to pass the // function we are looking at to the pass //MemoryDependenceAnalysis &MDA = getAnalysis<MemoryDependenceAnalysis>(F); for (inst_iterator i = inst_begin(F); i != inst_end(F); ++i) { Instruction *inst; inst = &*i; // skip non memory accesses if (!inst->mayReadFromMemory() && !inst->mayWriteToMemory()) continue; processDepResult(inst, MDA, AA); } // end for (inst_iterator) }
unsigned int designScorer::getDesignSizeInGates(Function* F) { unsigned int totalGateSize = 0; map<string, unsigned int> resourceMap = machineResourceConfig::getResourceTable(); unsigned int mul_count = resourceMap["mul"]; unsigned int div_count = resourceMap["div"]; unsigned int shl_count = resourceMap["shl"]; totalGateSize += mul_count*1088 + div_count*1500 + shl_count*1000; for (inst_iterator i = inst_begin(*F), e = inst_end(*F); i != e; ++i) { totalGateSize += getInstructionSize(&*i); } return totalGateSize; }
void EncoderPass::initAssertCalls() { bool hasAsserts = false; inst_iterator ii0; for (ii0 = inst_begin(targetFun); ii0!=inst_end(targetFun); ii0++) { Instruction &I = *ii0; if (CallInst *C = dyn_cast<CallInst>(&I)) { StringRef calledFunName; Function *F = C->getCalledFunction(); // Direct call if (F) { calledFunName = F->getName(); } // Indirect function call else { F = dyn_cast<Function>(C->getCalledValue()->stripPointerCasts()); if (F) { calledFunName = F->getName(); } } if (calledFunName==Frontend::SNIPER_ASSERT_FUN_NAME || calledFunName=="sniper_reportAssert") { hasAsserts = true; if (MDNode *N = I.getMetadata("dbg")) { DILocation Loc(N); unsigned line = Loc.getLineNumber(); ctx->setAssertCallLine(line); } } // TODO: put assume line numbers in a differente vector else if (calledFunName==Frontend::SNIPER_ASSUME_FUN_NAME || calledFunName=="sniper_reportAssume") { if (MDNode *N = I.getMetadata("dbg")) { DILocation Loc(N); unsigned line = Loc.getLineNumber(); ctx->setAssertCallLine(line); } } } } // No post-condition and no oracle? assert((hasAsserts || !options->getGoldenOutputsFileName().empty()) && "No call to assert function nor oracle!"); }
void getProgramExitInsts(Module &M, std::set<Instruction*> &exitinsts) { for (Module::iterator m_it = M.begin(); m_it != M.end(); ++m_it) { if (!m_it->isDeclaration()) { //m_it is a function for (inst_iterator f_it = inst_begin(m_it); f_it != inst_end(m_it); ++f_it) { Instruction *inst = &(*f_it); if (CallInst *ci = dyn_cast<CallInst>(inst)) { Function *calledFunc = ci->getCalledFunction(); if (calledFunc && calledFunc->hasName() && calledFunc->getName().str() == "exit") { exitinsts.insert(inst); } } } } } Function* mainfunc = M.getFunction("main"); exitinsts.insert(getTermInstofFunction(mainfunc)); }
bool Frontend::inlineForProcessFct(Function* F) { for(inst_iterator i = inst_begin(F); i != inst_end(F); ++i) { Function* calledFunction = NULL; Instruction* currentInst = &*i; BasicBlock* bb = currentInst->getParent(); bool isInvoke = false; if (CallInst *callInst = dyn_cast < CallInst > (currentInst)) { calledFunction = callInst->getCalledFunction(); } else if(InvokeInst *invokeInst = dyn_cast < InvokeInst > (currentInst)) { calledFunction = invokeInst->getCalledFunction(); isInvoke = true; } if (! calledFunction) { TRACE_6("Encountered call to function pointer. Not parsing it.\n"); } else if (! this->sccfactory->handlerExists(F, bb, currentInst, calledFunction)) { TRACE_6("CallInst : " << currentInst << "\n"); TRACE_6("CalledFct : " << calledFunction << "\n"); PRINT_6(currentInst->dump()); TRACE_4("Call not handled : " << calledFunction->getName().str() << "\n"); TRACE_4("Inlining function : " << calledFunction->getName().str() << "\n"); bool isInlined = false; llvm::InlineFunctionInfo ifi; if (isInvoke) { isInlined = llvm::InlineFunction(dyn_cast<InvokeInst>(currentInst), ifi); } else { isInlined = llvm::InlineFunction(dyn_cast<CallInst>(currentInst), ifi); } // InlineFunction invalidates iterators => restart loop. if (isInlined) { return true; } } } return false; }
void PointerTracking::print(raw_ostream &OS, const Module* M) const { // Calling some PT methods may cause caches to be updated, however // this should be safe for the same reason its safe for SCEV. PointerTracking &PT = *const_cast<PointerTracking*>(this); for (inst_iterator I=inst_begin(*FF), E=inst_end(*FF); I != E; ++I) { if (!isa<PointerType>(I->getType())) continue; Value *Base; const SCEV *Limit, *Offset; getPointerOffset(&*I, Base, Limit, Offset); if (!Base) continue; if (Base == &*I) { const SCEV *S = getAllocationElementCount(Base); OS << *Base << " ==> " << *S << " elements, "; OS << *Limit << " bytes allocated\n"; continue; } OS << &*I << " -- base: " << *Base; OS << " offset: " << *Offset; enum SolverResult res = PT.checkLimits(Offset, Limit, I->getParent()); switch (res) { case AlwaysTrue: OS << " always safe\n"; break; case AlwaysFalse: OS << " always unsafe\n"; break; case Unknown: OS << " <<unknown>>\n"; break; } } }
bool EscapeAnalysis::runOnFunction(Function& F) { return false; // This analysis is currently broken and not maintained if (VERBOSITY("opt") >= 1) outs() << "Running escape analysis on " << F.getName() << '\n'; for (inst_iterator inst_it = inst_begin(F), _inst_end = inst_end(F); inst_it != _inst_end; ++inst_it) { CallInst* alloc = dyn_cast<CallInst>(&*inst_it); if (!alloc || !isAllocCall(alloc)) continue; ChainInfo* chain = new ChainInfo(alloc); chains.push_back(chain); if (VERBOSITY("opt") >= 2) { errs() << "Found chain " << chain << " starting at " << *alloc; } // Calculating derived pointers, and finding escape points { // Instructions in the queue to be visited: std::deque<Instruction*> queue; // Instructions we've fully visited: std::unordered_set<Instruction*> checked; queue.push_back(alloc); while (queue.size()) { Instruction* next = queue.back(); queue.pop_back(); if (checked.count(next)) continue; checked.insert(next); for (User* user : next->users()) { if (GetElementPtrInst* gep = dyn_cast<GetElementPtrInst>(user)) { queue.push_back(gep); chain->derived.insert(gep); chain_by_pointer[gep] = chain; continue; } if (CastInst* bc = dyn_cast<CastInst>(user)) { queue.push_back(bc); chain->derived.insert(bc); chain_by_pointer[bc] = chain; continue; } if (PHINode* phi = dyn_cast<PHINode>(user)) { queue.push_back(phi); chain->derived.insert(phi); chain_by_pointer[phi] = chain; continue; } if (isa<LoadInst>(user)) { continue; } if (ReturnInst* ret = dyn_cast<ReturnInst>(user)) { if (VERBOSITY() >= 2) errs() << "Not dead; used here: " << *ret << '\n'; chain->escape_points.insert(ret); continue; } if (StoreInst* si = dyn_cast<StoreInst>(user)) { if (si->getPointerOperand() == next) { } else { assert(si->getValueOperand() == next); if (VERBOSITY() >= 2) errs() << "Escapes here: " << *si << '\n'; chain->escape_points.insert(si); } continue; } if (llvm::isa<CallInst>(user) || llvm::isa<InvokeInst>(user)) { if (VERBOSITY() >= 2) errs() << "Escapes here: " << *user << '\n'; chain->escape_points.insert(dyn_cast<Instruction>(user)); continue; } user->dump(); RELEASE_ASSERT(0, ""); } } } // Calculating BB-level escape-ness { std::deque<const BasicBlock*> queue; for (const auto I : chain->escape_points) { chain->bb_escapes[I->getParent()] = BBPartialEscape; queue.insert(queue.end(), succ_begin(I->getParent()), succ_end(I->getParent())); } while (queue.size()) { const BasicBlock* bb = queue.back(); queue.pop_back(); if (chain->bb_escapes[bb] == BBFullEscape) continue; chain->bb_escapes[bb] = BBFullEscape; queue.insert(queue.end(), succ_begin(bb), succ_end(bb)); } for (BasicBlock& bb : F) { if (chain->bb_escapes.count(&bb) == 0) chain->bb_escapes[&bb] = BBNoEscape; // outs() << bb.getName() << ' ' << chain->bb_escapes[&bb] << '\n'; } } } return false; }
/** * Finds those allocas that are only used to store some value from ebp and then * this value is stored back to ebp. */ bool StackPointerOpsRemove::removePreservationStores() { bool changed = false; for (auto& f : _module->getFunctionList()) { for (inst_iterator I = inst_begin(f), E = inst_end(f); I != E; ++I) { auto* a = dyn_cast<AllocaInst>(&*I); if (a == nullptr) { continue; } bool remove = true; Value* storedVal = nullptr; std::set<llvm::Instruction*> toRemove; for (auto* u : a->users()) { if (auto* s = dyn_cast<StoreInst>(u)) { auto* l = dyn_cast<LoadInst>(s->getValueOperand()); if (l && storedVal == nullptr && (l->getPointerOperand()->getName() == "ebp" || l->getPointerOperand()->getName() == "rbp")) { storedVal = l->getPointerOperand(); toRemove.insert(s); } else if (l && l->getPointerOperand() == storedVal) { toRemove.insert(s); } else { remove = false; break; } } else if (isa<LoadInst>(u) || isa<CastInst>(u)) { for (auto* uu : u->users()) { auto* s = dyn_cast<StoreInst>(uu); if (s && storedVal == nullptr && (s->getPointerOperand()->getName() == "ebp" || s->getPointerOperand()->getName() == "rbp")) { storedVal = s->getPointerOperand(); toRemove.insert(s); } else if (s && s->getPointerOperand() == storedVal) { toRemove.insert(s); } else { remove = false; break; } } if (!remove) { break; } } else { remove = false; break; } } if (remove) { for (auto* i : toRemove) { i->eraseFromParent(); changed = true; } } } } return changed; }
bool runOnFunction(Function &Func) override { if (Func.isDeclaration()) { return false; } vector<BranchInst *> BIs; for (inst_iterator I = inst_begin(Func); I != inst_end(Func); I++) { Instruction *Inst = &(*I); if (BranchInst *BI = dyn_cast<BranchInst>(Inst)) { BIs.push_back(BI); } } // Finish collecting branching conditions Value *zero = ConstantInt::get(Type::getInt32Ty(Func.getParent()->getContext()), 0); for (BranchInst *BI : BIs) { IRBuilder<> IRB(BI); vector<BasicBlock *> BBs; // We use the condition's evaluation result to generate the GEP // instruction False evaluates to 0 while true evaluates to 1. So here // we insert the false block first if (BI->isConditional()) { BBs.push_back(BI->getSuccessor(1)); } BBs.push_back(BI->getSuccessor(0)); ArrayType *AT = ArrayType::get( Type::getInt8PtrTy(Func.getParent()->getContext()), BBs.size()); vector<Constant *> BlockAddresses; for (unsigned i = 0; i < BBs.size(); i++) { BlockAddresses.push_back(BlockAddress::get(BBs[i])); } GlobalVariable *LoadFrom = NULL; if (BI->isConditional() || indexmap.find(BI->getSuccessor(0))==indexmap.end()) { // Create a new GV Constant *BlockAddressArray = ConstantArray::get(AT, ArrayRef<Constant *>(BlockAddresses)); LoadFrom = new GlobalVariable(*Func.getParent(), AT, false, GlobalValue::LinkageTypes::PrivateLinkage, BlockAddressArray); } else { LoadFrom = Func.getParent()->getGlobalVariable("IndirectBranchingGlobalTable",true); } Value *index = NULL; if (BI->isConditional()) { Value *condition = BI->getCondition(); index = IRB.CreateZExt( condition, Type::getInt32Ty(Func.getParent()->getContext())); } else { index = ConstantInt::get(Type::getInt32Ty(Func.getParent()->getContext()), indexmap[BI->getSuccessor(0)]); } Value *GEP = IRB.CreateGEP(LoadFrom, {zero, index}); LoadInst *LI = IRB.CreateLoad(GEP, "IndirectBranchingTargetAddress"); IndirectBrInst *indirBr = IndirectBrInst::Create(LI, BBs.size()); for (BasicBlock *BB : BBs) { indirBr->addDestination(BB); } ReplaceInstWithInst(BI, indirBr); } return true; }
bool ProfilingPass::doInitialization(Module &M) { LLVMContext& context = M.getContext(); Function* mainFunc = M.getFunction("main"); const string moduleName = M.getModuleIdentifier(); if (mainFunc!=NULL) { //BasicBlock* entryBlock = &mainFunc->front(); Constant* Init = ConstantArray::get(context,moduleName,true); // Convert it to an LLVM Type GlobalVariable* nameStr = new GlobalVariable(Init->getType(), true, GlobalValue::InternalLinkage, Init, "NameStr" ); M.getGlobalList().push_back( nameStr ); // Insert it into the list of globals for module std::vector<Constant*>IndicesC(2); IndicesC[0] = Constant::getNullValue(Type::getInt32Ty(context)); IndicesC[1] = ConstantInt::get(Type::getInt32Ty(context),0); Constant *getElemExpr = ConstantExpr::getGetElementPtr(nameStr, &IndicesC[0], IndicesC.size()); vector<Value*> initInjectArgs; initInjectArgs.push_back( getElemExpr ); FunctionType* initInjectionFuncType = FunctionType::get(Type::getVoidTy(context), vector<const Type*>(1, PointerType::get(Type::getInt8Ty(context),0)),0); //BasicBlock *exitBlock = &mainFunc->back(); Instruction *I; for (inst_iterator fi = inst_begin(mainFunc), fe = inst_end(mainFunc); fi!=fe; ++fi){ I = &*fi; if(isa<ReturnInst>(I)) break; } BasicBlock *retblock = I->getParent(); //*retpred = retblock->getSinglePredecessor(); Instruction *term = retblock->getTerminator(); Constant *endFunc = M.getOrInsertFunction("endProfiling", initInjectionFuncType); vector<Value*> countArgs(1); //const IntegerType* itype = IntegerType::get(context,32); //Value* branchVal = ConstantInt::get(itype, BRANCH ); CallInst::Create(endFunc, initInjectArgs.begin(), initInjectArgs.end(), "", term); } else { Constant* Init = ConstantArray::get(context,moduleName,true); // Convert it to an LLVM Type GlobalVariable* nameStr = new GlobalVariable(Init->getType(), true, GlobalValue::InternalLinkage, Init, "NameStr" ); M.getGlobalList().push_back( nameStr ); } //*********************************************************************************************************** //code for loading configure file should be here ifstream config ("llfi_configure.txt"); if (config.is_open()) { // we need to extract information from config file here Qining // this loop is used to know if the file is end while ( config.good() ) { string line; getline (config,line); if(line.empty()) continue; //if the line is empty, just skip. //Any block of configure is started with one specific function unsigned found = line.find("FUNCTION_NAME:"); if (found < line.length()) { //std::cout << "\nfound FUNCTION_NAME at " << found << '\n'; std::string func_name = line.substr (found + string("FUNCTION_NAME:").length(),line.length() - found - string("FUNCTION_NAME:").length()); //first, I need to trim it while(func_name[0] == ' ') { func_name.erase(0, 1); } while(func_name[func_name.length() - 1] == ' ') { func_name.erase(func_name.length() - 1, 0); } //so now I've got the name of the function if(func_name.empty()) continue; std::cout << "The func_name is " << func_name << "\n"; map_func_argu[func_name] = set<unsigned int>(); // create entry //map_func_fault_type[func_name] = set<unsigned int>(); //second, I need to load argument set and type set do { line.clear(); getline(config,line); // get the next line if(!config.good()) break; // if the new line is the end of file, our job is done. if(line.find("ARGUMENT:") < line.length()) { //insert argument id to argument set std::string arg_set = line.substr(line.find("ARGUMENT:")+string("ARGUMENT:").length(), line.length() - line.find("ARGUMENT:")-string("ARGUMENT:").length()); std::string arg; while(!arg_set.empty()) { while(arg_set[0] <= '9' && arg_set[0] >= '0') { arg.append(arg_set.substr(0,1)); if(!arg_set.empty()) arg_set.erase(0,1); } if(!arg.empty()) { unsigned int arg_num = atoi(arg.c_str()) - 1; map_func_argu[func_name].insert(arg_num); std::cout << "\tinclude arg: " << arg_num+1 << "\n"; } arg.clear(); if(!arg_set.empty()) arg_set.erase(0,1); } } }while(line.find("FUNC_DEF_END") != 0); } } // The file is end, we should have already finished our work, now close the file config.close(); } else errs()<<"Unable to open config file, use default config: all instructions, one bit flip\n"; //*********************************************************************************************************** return FunctionPass::doInitialization(M); }
// ============================================================================= // replaceCallsInProcess // // Replace indirect calls to write() or read() by direct calls // in the given process. // ============================================================================= void TLMBasicPassImpl::replaceCallsInProcess(sc_core::sc_module *initiatorMod, sc_core::sc_process_b *proc) { // Get associate function std::string fctName = proc->func_process; std::string modType = typeid(*initiatorMod).name(); std::string mainFctName = "_ZN" + modType + utostr(fctName.size()) + fctName + "Ev"; Function *oldProcf = this->llvmMod->getFunction(mainFctName); if (oldProcf==NULL) return; // We do not modifie the original function // Instead, we create a clone. Function *procf = createProcess(oldProcf, initiatorMod); void *funPtr = this->engine->getPointerToFunction(procf); sc_core::SC_ENTRY_FUNC_OPT scfun = reinterpret_cast<sc_core::SC_ENTRY_FUNC_OPT>(funPtr); proc->m_semantics_p = scfun; std::string procfName = procf->getName(); MSG(" Replace in the process's function : "+procfName+"\n"); std::ostringstream oss; sc_core::sc_module *targetMod; std::vector<CallInfo*> *work = new std::vector<CallInfo*>; inst_iterator ii; for (ii = inst_begin(procf); ii!=inst_end(procf); ii++) { Instruction &i = *ii; CallSite cs(&i); if (cs.getInstruction()) { // Candidate for a replacement Function *oldfun = cs.getCalledFunction(); if (oldfun!=NULL && !oldfun->isDeclaration()) { std::string name = oldfun->getName(); // === Write === if (!strcmp(name.c_str(), wFunName.c_str())) { CallInfo *info = new CallInfo(); info->oldcall = dyn_cast<CallInst>(cs.getInstruction()); MSG(" Checking adress : "); // Retrieve the adress argument by executing // the appropriated piece of code SCJit *scjit = new SCJit(this->llvmMod, this->elab); Process *irProc = this->elab->getProcess(proc); scjit->setCurrentProcess(irProc); bool jitErr = false; info->addrArg = cs.getArgument(1); int value = scjit->jitInt(procf, info->oldcall, info->addrArg, &jitErr); if(jitErr) { std::cout << " cannot get the address value!" << std::endl; } else { oss.str(""); oss << std::hex << value; MSG("0x"+oss.str()+"\n"); basic::addr_t a = static_cast<basic::addr_t>(value); // Checking address alignment if(value % sizeof(basic::data_t)) { std::cerr << " unaligned write : " << std::hex << value << std::endl; abort(); } // Retreive the target module using the address targetMod = getTargetModule(initiatorMod, a); // Save informations to build a new call later FunctionType *writeFunType = this->basicWriteFun->getFunctionType(); info->targetType = writeFunType->getParamType(0); LLVMContext &context = getGlobalContext(); IntegerType *intType; if (this->is64Bit) { intType = Type::getInt64Ty(context); } else { intType = Type::getInt32Ty(context); } info->targetModVal = ConstantInt::getSigned(intType, reinterpret_cast<intptr_t>(targetMod)); info->dataArg = cs.getArgument(2); work->push_back(info); } } else // === Read === if (!strcmp(name.c_str(), rFunName.c_str())) { // Not yet supported } } } } // Before //procf->dump(); // Replace calls std::vector<CallInfo*>::iterator it; for (it = work->begin(); it!=work->end(); ++it) { CallInfo *i = *it; LLVMContext &context = getGlobalContext(); FunctionType *writeFunType = this->writeFun->getFunctionType(); IntegerType *i64 = Type::getInt64Ty(context); // Get a pointer to the target module basic::target_module_base *tmb = dynamic_cast<basic::target_module_base*>(targetMod); Value *ptr = ConstantInt::getSigned(i64, reinterpret_cast<intptr_t>(tmb)); IntToPtrInst *modPtr = new IntToPtrInst(ptr, writeFunType->getParamType(0), "myitp", i->oldcall); // Get a the address value LoadInst *addr = new LoadInst(i->addrArg, "", i->oldcall); // Create the new call Value *args[] = {modPtr, addr, i->dataArg}; i->newcall = CallInst::Create(this->writeFun, ArrayRef<Value*>(args, 3)); // Replace the old call BasicBlock::iterator it(i->oldcall); ReplaceInstWithInst(i->oldcall->getParent()->getInstList(), it, i->newcall); i->oldcall->replaceAllUsesWith(i->newcall); // Inline the new call DataLayout *td = new DataLayout(this->llvmMod); InlineFunctionInfo ifi(NULL, td); bool success = InlineFunction(i->newcall, ifi); if(!success) { MSG(" The call cannot be inlined (it's not an error :D)"); } MSG(" Call optimized (^_-)\n"); callOptCounter++; } //std::cout << "==================================\n"; // Run preloaded passes on the function to propagate constants funPassManager->run(*procf); // After //procf->dump(); // Check if the function is corrupt verifyFunction(*procf); this->engine->recompileAndRelinkFunction(procf); }
// // Method: addGetActualValues() // // Description: // Search for comparison or pointer to integer cast instructions which will // need to turn an OOB pointer back into the original pointer value. Insert // calls to getActualValue() to do the conversion. // // Inputs: // M - The module in which to add calls to getActualValue(). // // Return value: // true - The module was modified. // false - The module was not modified. // bool RewriteOOB::addGetActualValues (Module & M) { // Assume that we don't modify anything bool modified = false; // Worklist of instructions to modify std::vector<Instruction *> Worklist; for (Module::iterator F = M.begin(); F != M.end(); ++F) { // // Clear the worklist. // Worklist.clear(); // // Scan through all the instructions in the given function for those that // need to be modified. Add them to the worklist. // for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) { // // Integer comparisons need to be processed. // if (ICmpInst *CmpI = dyn_cast<ICmpInst>(&*I)) { CmpInst::Predicate Pred = CmpI->getUnsignedPredicate(); if ((Pred >= CmpInst::FIRST_ICMP_PREDICATE) && (Pred <= CmpInst::LAST_ICMP_PREDICATE)) { Worklist.push_back (CmpI); } } // // Casts from pointers to integers must also be processed. // if (PtrToIntInst * CastInst = dyn_cast<PtrToIntInst>(&*I)) { Worklist.push_back (CastInst); } } // // Now scan through the worklist and process each instruction. Note that, // since we're using a worklist, we won't pick up casts introduced by // addGetActualValue(). // for (unsigned index = 0; index < Worklist.size(); ++index) { // // Get the proper element from the worklist. // Instruction * I = Worklist[index]; if (ICmpInst *CmpI = dyn_cast<ICmpInst>(I)) { // // Replace all pointer operands with a call to getActualValue(). // This will convert an OOB pointer back into the real pointer value. // if (isa<PointerType>(CmpI->getOperand(0)->getType())) { // Rewrite both operands and flag that we modified the code addGetActualValue(CmpI, 0); modified = true; } if (isa<PointerType>(CmpI->getOperand(1)->getType())) { // Rewrite both operands and flag that we modified the code addGetActualValue(CmpI, 1); modified = true; } } if (PtrToIntInst * CastInst = dyn_cast<PtrToIntInst>(&*I)) { // // Replace all pointer operands with a call to getActualValue(). // This will convert an OOB pointer back into the real pointer value. // if (isa<PointerType>(CastInst->getOperand(0)->getType())) { // Rewrite both operands and flag that we modified the code addGetActualValue(CastInst, 0); modified = true; } } } } // Return whether we modified anything return modified; }
bool ProfilingPass::runOnFunction(Function &F) { LLVMContext& context = F.getContext(); Module *m = F.getParent(); string funcname = F.getNameStr(); string injectfunc("injectFault"); if((profileoption == 'p' || profileoption == 'c' || profileoption == 'i') && (funcname.find(injectfunc) != string::npos)) return false; std::vector<Instruction*> insert_worklist; for (inst_iterator In = inst_begin(F), E = inst_end(F); In != E; ++In) { Instruction *I = dyn_cast<Instruction>(&*In); //errs()<<*I<<"\n"; if(profileoption == 'b') { if(CmpInst *ci = dyn_cast<CmpInst>(I)) if(is_used_by_branch(ci)){ vector<const Type*> argTypes(1); argTypes[0] = Type::getInt32Ty(context); // enum for the options FunctionType* countFuncType = FunctionType::get( Type::getVoidTy(context), argTypes, 0 ); Constant* countFunc = m->getOrInsertFunction("doProfiling", countFuncType); // get the injection function vector<Value*> countArgs(1); const IntegerType* itype = IntegerType::get(context,32); Value* branchVal = ConstantInt::get(itype, BRANCH ); countArgs[0] = branchVal; //enum for branch CallInst::Create( countFunc, countArgs.begin(),countArgs.end(), "", I); } } else if(profileoption == 'd') { //see if the current instruction is a cmp instruction that leads to a conditional branch //add the instrumentation to the defs of this cmp instruction //--> Static time deduction since branch not known if executed or not CmpInst *ci = dyn_cast<CmpInst>(I); //errs() <<"reached here:\n"; if(!ci) continue; //traverse def-use chain //int is_used_by_branch = 0; if(!is_used_by_branch(I)) continue; //the defines of this instruction I --> would be injectFaultCalls. for (User::op_iterator i = I->op_begin(), e = I->op_end(); i != e; ++i) { Instruction *v = dyn_cast<Instruction>(*i); if(!v) continue; //errs() <<"reached here:"<< *v << "\n"; //do profiling for the def vector<const Type*> argTypes(1); argTypes[0] = Type::getInt32Ty(context); // enum for the options FunctionType* countFuncType = FunctionType::get( Type::getVoidTy(context), argTypes, 0 ); Constant* countFunc = m->getOrInsertFunction("doProfiling", countFuncType); // get the injection function vector<Value*> countArgs(1); const IntegerType* itype = IntegerType::get(context,32); Value* defVal = ConstantInt::get(itype, DEF ); countArgs[0] = defVal; //enum for branch Instruction *beforeInst; if(isa<PHINode>(v)) { BasicBlock *bb = v->getParent(); beforeInst = bb->getFirstNonPHI(); } else beforeInst = v; CallInst::Create( countFunc, countArgs.begin(),countArgs.end(), "", beforeInst); // insert the profiling call before the def:v } } else if(profileoption == 'a' ) { Instruction *beforeInst; //consider all instructions profiling vector<const Type*> argTypes(1); argTypes[0] = Type::getInt32Ty(context); // enum for the options FunctionType* countFuncType = FunctionType::get( Type::getVoidTy(context), argTypes, 0 ); Constant* countFunc = m->getOrInsertFunction("doProfiling", countFuncType); // get the injection function vector<Value*> countArgs(1); const IntegerType* itype = IntegerType::get(context,32); Value* allVal = ConstantInt::get(itype, ALL ); if(isa<PHINode>(I)) { BasicBlock *bb = I->getParent(); beforeInst = bb->getFirstNonPHI(); } else beforeInst = I; countArgs[0] = allVal; //enum for All inst CallInst::Create( countFunc, countArgs.begin(),countArgs.end(), "", beforeInst); // Insert the inject call before the instruction } //in fact, here we only use backwardslice ('s') else if(profileoption == 's') { const Type* returnType = I->getType(); if (returnType->isVoidTy() || !filter(I))//Here we can insert a new filter /////////////////////////////////////////////// { //errs()<<"filter not passed\n"; continue; } //for injection into all instructions except invoke instructions (these are same as unconditional branch instructions with exception handling mechanism) if((isa<InvokeInst>(I)) #ifdef EXCLUDE_CASTINST || (isa<CastInst>(I)) #endif ) // cast instruction added by Jiesheng continue; //errs()<<"filter passed\n"; Instruction *beforeInst; if(isa<PHINode>(I)) { BasicBlock *bb = I->getParent(); beforeInst = bb->getFirstNonPHI(); } else beforeInst = I; insert_worklist.push_back(beforeInst); } } while(!insert_worklist.empty()) { Instruction* beforeInst = insert_worklist.back(); insert_worklist.pop_back(); vector<const Type*> argTypes(1); argTypes[0] = Type::getInt32Ty(context); // enum for the options FunctionType* countFuncType = FunctionType::get( Type::getVoidTy(context), argTypes, 0 ); Constant* countFunc = m->getOrInsertFunction("doProfiling", countFuncType); vector<Value*> countArgs(1); const IntegerType* itype = IntegerType::get(context,32); Value* allVal = ConstantInt::get(itype, BACKWARD_SLICE ); countArgs[0] = allVal; //enum for All inst CallInst::Create( countFunc, countArgs.begin(),countArgs.end(), "", beforeInst); } return true; }
bool NullDerefProtectionTransformer::runOnFunction(llvm::Function &F) { std::vector<llvm::Instruction*> WorkList; for (llvm::inst_iterator i = inst_begin(F), e = inst_end(F); i != e; ++i) { llvm::Instruction* I = &*i; if (llvm::isa<llvm::LoadInst>(I)) WorkList.push_back(I); } for (std::vector<llvm::Instruction*>::iterator i = WorkList.begin(), e = WorkList.end(); i != e; ++i) { Inst = *i; Builder->SetInsertPoint(Inst); llvm::LoadInst* I = llvm::cast<llvm::LoadInst>(*i); // Find all the instructions that uses the instruction I. for (llvm::Value::use_iterator UI = I->use_begin(), UE = I->use_end(); UI != UE; ++UI) { // Check whether I is used as the first argument for a load instruction. // If it is, then instrument the load instruction. if (llvm::LoadInst* LI = llvm::dyn_cast<llvm::LoadInst>(*UI)) { llvm::Value* Arg = LI->getOperand(0); if (Arg == I) instrumentInst(LI, Arg); } // Check whether I is used as the second argument for a store // instruction. If it is, then instrument the store instruction. else if (llvm::StoreInst* SI = llvm::dyn_cast<llvm::StoreInst>(*UI)) { llvm::Value* Arg = SI->getOperand(1); if (Arg == I) instrumentInst(SI, Arg); } // Check whether I is used as the first argument for a GEP instruction. // If it is, then instrument the GEP instruction. else if (llvm::GetElementPtrInst* GEP = llvm::dyn_cast< llvm::GetElementPtrInst>(*UI)) { llvm::Value* Arg = GEP->getOperand(0); if (Arg == I) instrumentInst(GEP, Arg); } else { // Check whether I is used as the first argument for a call instruction. // If it is, then instrument the call instruction. llvm::CallSite CS(*UI); if (CS) { llvm::CallSite::arg_iterator i = CS.arg_begin(), e = CS.arg_end(); if (i != e) { llvm::Value *Arg = *i; if (Arg == I) instrumentInst(CS.getInstruction(), Arg); } } } } } return true; }
Function * futamurize( const Function * orig_func, DenseMap<const Value*, Value*> &argmap, std::set<const unsigned char *> &constant_addresses_set ) { LLVMContext &context = getGlobalContext(); // Make a copy of the function, removing constant arguments Function * specialized_func = CloneFunction( orig_func, argmap ); specialized_func->setName( orig_func->getNameStr() + "_1" ); // add it to our module LLVM_Module->getFunctionList().push_back( specialized_func ); printf("\nspecialized_func = %p <%s>\n", specialized_func, specialized_func->getName().data()); //~ specialized_func->dump(); // Optimize it FunctionPassManager PM( LLVM_Module ); createStandardFunctionPasses( &PM, 3 ); PM.add(createScalarReplAggregatesPass()); // Break up aggregate allocas PM.add(createInstructionCombiningPass()); // Cleanup for scalarrepl. PM.add(createJumpThreadingPass()); // Thread jumps. PM.add(createCFGSimplificationPass()); // Merge & remove BBs PM.add(createInstructionCombiningPass()); // Combine silly seq's PM.add(createTailCallEliminationPass()); // Eliminate tail calls PM.add(createCFGSimplificationPass()); // Merge & remove BBs PM.add(createReassociatePass()); // Reassociate expressions PM.add(createLoopRotatePass()); // Rotate Loop PM.add(createLICMPass()); // Hoist loop invariants PM.add(createLoopUnswitchPass( false )); PM.add(createInstructionCombiningPass()); PM.add(createIndVarSimplifyPass()); // Canonicalize indvars PM.add(createLoopDeletionPass()); // Delete dead loops PM.add(createLoopUnroll2Pass()); // Unroll small loops PM.add(createInstructionCombiningPass()); // Clean up after the unroller PM.add(createGVNPass()); // Remove redundancies PM.add(createMemCpyOptPass()); // Remove memcpy / form memset PM.add(createSCCPPass()); // Constant prop with SCCP PM.add(createPromoteMemoryToRegisterPass()); PM.add(createConstantPropagationPass()); PM.add(createDeadStoreEliminationPass()); PM.add(createAggressiveDCEPass()); PM.add(new MemoryDependenceAnalysis()); //~ PM.add(createAAEvalPass()); const PassInfo * pinfo = Pass::lookupPassInfo( "print-alias-sets" ); if( !pinfo ) { printf( "print-alias-sets not found\n" ); exit(-1); } PM.add( pinfo->createPass() ); FunctionPassManager PM_Inline( LLVM_Module ); PM_Inline.add(createSingleFunctionInliningPass()); bool Changed = false; int iterations = 2; int inline_iterations = 6; do { Changed = false; // first do some optimizations PM.doInitialization(); PM.run( *specialized_func ); PM.doFinalization(); // Load from Constant Memory detection const TargetData *TD = LLVM_EE->getTargetData(); for (inst_iterator I = inst_begin(specialized_func), E = inst_end(specialized_func); I != E; ++I) { Instruction * inst = (Instruction *) &*I; // get all Load instructions LoadInst * load = dyn_cast<LoadInst>( inst ); if( !load ) continue; if( load->isVolatile() ) continue; if (load->use_empty()) continue; // Don't muck with dead instructions... // get the address loaded by load instruction Value *ptr_value = load->getPointerOperand(); // we're only interested in constant addresses ConstantExpr * ptr_constant_expr = dyn_cast<ConstantExpr>( ptr_value ); if( !ptr_constant_expr ) continue; ptr_constant_expr->dump(); // compute real address of constant pointer expression Constant * ptr_constant = ConstantFoldConstantExpression( ptr_constant_expr, TD ); if( !ptr_constant ) continue; ptr_constant->dump(); // convert to int constant ConstantInt *int_constant = dyn_cast<ConstantInt>( ConstantExpr::getPtrToInt( ptr_constant, Type::getInt64Ty( context ))); if( !int_constant ) continue; int_constant->dump(); // get data size int data_length = TD->getTypeAllocSize( load->getType() ); ptr_value->getType()->dump(); // get real address (at last !) const unsigned char * c_ptr = (const unsigned char *) int_constant->getLimitedValue(); printf( "%ld %d %d\n", c_ptr, constant_addresses_set.count( c_ptr ), data_length ); // check what's in this address int isconst = 1; for( int offset=0; offset<data_length; offset++ ) isconst &= constant_addresses_set.count( c_ptr + offset ); if( !isconst ) continue; printf( "It is constant.\n" ); // make a LLVM const with the data Constant *new_constant = NULL; switch( data_length ) { case 1: new_constant = ConstantInt::get( Type::getInt8Ty( context ), *(uint8_t*)c_ptr, false /* signed */ ); break; case 2: new_constant = ConstantInt::get( Type::getInt16Ty( context ), *(uint16_t*)c_ptr, false /* signed */ ); break; case 4: new_constant = ConstantInt::get( Type::getInt32Ty( context ), *(uint32_t*)c_ptr, false /* signed */ ); break; case 8: new_constant = ConstantInt::get( Type::getInt64Ty( context ), *(uint64_t*)c_ptr, false /* signed */ ); break; default: { StringRef const_data ( (const char *) c_ptr, data_length ); new_constant = ConstantArray::get( context, const_data, false /* dont add terminating null */ ); } } if( !new_constant ) continue; new_constant->dump(); //~ // get the type that is loaded const Type *Ty = load->getType(); // do we need a cast ? if( load->getType() != new_constant->getType() ) { new_constant = ConstantExpr::getBitCast( new_constant, Ty ); new_constant->dump(); } // zap the load and replace with constant address load->replaceAllUsesWith( new_constant ); printf( "\nREPLACED :...\n" ); load->dump(); new_constant->dump(); Changed = true; } if( Changed ) continue; // re-optimize and do another pass of constant load elimination // if we can't do anything else, do an inlining pass if( inline_iterations > 0 ) { inline_iterations --; PM_Inline.doInitialization(); Changed |= PM_Inline.run( *specialized_func ); PM_Inline.doFinalization(); //~ for( int i=0; i<3; i++ ) { PM.doInitialization(); Changed |= PM.run( *specialized_func ); PM.doFinalization(); } } if( iterations>0 && !Changed ) iterations--; } while( Changed || iterations>0 ); return specialized_func; }