bool ImageSorter::_msort(const Info& a, const Info& b, FuncList criteria) { for (size_t n = 0; n < criteria.size(); ++n) { const int diff = criteria[n](a, b); if (diff != 0) return diff < 0; } return 0; }
void StructuredModuleEditor::dumpFuncsWithSameSignature(Function *Func) { FuncList *Funcs = getFuncsWithSameSignature(Func); OS << Funcs->size() << " functions with the following signature:\n"; OS << "*** RETURN TYPE: " << *(Func->getFunctionType()) << "\n"; for (Function::arg_iterator AI = Func->arg_begin(), AE = Func->arg_end(); AI != AE; ++AI) { OS << "*** ARG TYPE: " << *AI << "\n"; } OS << "\n"; for (FuncList::iterator FI = Funcs->begin(), FE = Funcs->end(); FI != FE; ++FI) { OS << (*FI)->getName() << "\n"; } }
bool ICFGBuilder::runOnModule(Module &M) { MicroBasicBlockBuilder &MBBB = getAnalysis<MicroBasicBlockBuilder>(); forallbb(M, bb) { for (mbb_iterator mi = MBBB.begin(bb), E = MBBB.end(bb); mi != E; ++mi) getOrInsertMBB(mi); } forallbb(M, bb) { for (mbb_iterator mi = MBBB.begin(bb), E = MBBB.end(bb); mi != E; ++mi) { // The ICFG will not contain any inter-thread edge. // It's also difficult to handle them. How to deal with the return // edges? They are supposed to go to the pthread_join sites. if (mi->end() != bb->end() && !is_pthread_create(mi->end())) { FPCallGraph &CG = getAnalysis<FPCallGraph>(); FuncList callees = CG.getCalledFunctions(mi->end()); bool calls_decl = false; for (size_t i = 0; i < callees.size(); ++i) { Function *callee = callees[i]; if (callee->isDeclaration()) { calls_decl = true; } else { MicroBasicBlock *entry_mbb = MBBB.begin(callee->begin()); addEdge(mi, entry_mbb); } } if (calls_decl) { mbb_iterator next_mbb = mi; ++next_mbb; addEdge(mi, next_mbb); } } else { for (succ_iterator si = succ_begin(bb); si != succ_end(bb); ++si) { MicroBasicBlock *succ_mbb = MBBB.begin(*si); addEdge(mi, succ_mbb); } TerminatorInst *ti = bb->getTerminator(); if (is_ret(ti)) { FPCallGraph &CG = getAnalysis<FPCallGraph>(); InstList call_sites = CG.getCallSites(bb->getParent()); for (size_t i = 0; i < call_sites.size(); ++i) { Instruction *call_site = call_sites[i]; // Ignore inter-thread edges. if (is_pthread_create(call_site)) continue; MicroBasicBlock *next_mbb; if (isa<CallInst>(call_site)) { BasicBlock::iterator next = call_site; ++next; next_mbb = MBBB.parent(next); } else { assert(isa<InvokeInst>(call_site)); InvokeInst *inv = dyn_cast<InvokeInst>(call_site); if (isa<ReturnInst>(ti)) { next_mbb = MBBB.begin(inv->getNormalDest()); } else { next_mbb = MBBB.begin(inv->getUnwindDest()); } } addEdge(mi, next_mbb); } } } } } return false; }
void StructuredModuleEditor::instrumentCallsToFunction(Function *Callee) { if (Callee == NULL) { OS << "Function not found!\n"; return; } InstList Calls = getCallsToFunction(Callee); FuncList Callers; for (InstList::iterator II = Calls.begin(), IE = Calls.end(); II != IE; ++II) { Function *Caller = (*II)->getParent()->getParent(); if (std::find(Callers.begin(), Callers.end(), Caller) == Callers.end()) Callers.push_back(Caller); } OS << Callers.size() << " functions call '" << Callee->getName() << "'...\n"; OS << "=================================\n"; for (FuncList::iterator FI = Callers.begin(), FE = Callers.end(); FI != FE; ++FI) { OS << (*FI)->getName() << "\n"; } OS << "=================================\n"; std::vector<Value*> PreArgs; std::vector<Type*> PreArgTypes; for (Function::arg_iterator I = Callee->arg_begin(), E = Callee->arg_end(); I != E; ++I) { PreArgTypes.push_back(I->getType()); PreArgs.push_back(I); } std::vector<Type*> PostArgTypes; if (!Callee->getReturnType()->isVoidTy()) { PostArgTypes.push_back(Callee->getReturnType()); } FuncList Clones; Clones.push_back(Callee); for (uint64_t i = 0; i < Callers.size() - 1; i++) { Function *Clone = cloneFunc(Callee); Clones.push_back(Clone); } for (uint64_t i = 0; i < Clones.size(); i++) { Constant *PreConst = M->getOrInsertFunction("", FunctionType::get(Type::getVoidTy(getGlobalContext()), PreArgTypes, false)); Function *Pre = cast<Function>(PreConst); Pre->setName("pre"); CG->getOrInsertFunction(Pre); Constant *PostConst = M->getOrInsertFunction("", FunctionType::get(Type::getVoidTy(getGlobalContext()), PostArgTypes, false)); Function *Post = cast<Function>(PostConst); Post->setName("post"); CG->getOrInsertFunction(Post); /* OS << "\n"; OS << "Wrapping '" << Clones.at(i)->getName() << "'...\n\n"; OS << "Pre-invocation function = " << Pre->getName() << "\n"; OS << *Pre; OS << "Post-invocation function = " << Post->getName() << "\n"; OS << *Post; OS << "**************************************\n";*/ Function *Wrapper = wrapFunc(Clones.at(i), Pre, Post); if (i == 0) Callee = Wrapper; Function *Caller = Callers.at(i); for (Function::iterator BBI = Caller->begin(), BBE = Caller->end(); BBI != BBE; ++BBI) { for (BasicBlock::iterator II = BBI->begin(), IE = BBI->end(); II != IE; ++II) { CallSite CS(cast<Value>(II)); // If this isn't a call, or it is a call to an intrinsic... if (!CS || isa<IntrinsicInst>(II)) continue; if (Callee == CS.getCalledFunction()) { CS.setCalledFunction(Wrapper); // Creates an edge from the calling node to its new destination node CallGraphNode *CallingNode = (*CG)[CS.getCaller()]; CallGraphNode *NewCalleeNode = (*CG)[Wrapper]; CallingNode->replaceCallEdge(CS, CS, NewCalleeNode); } } } } OS << "Functions successfully wrapped!\n"; }
void StructuredModuleEditor::instrumentFunctionsThatCallFunction( Function *Callee) { if (Callee == NULL) { OS << "Function not found!\n"; return; } InstList Calls = getCallsToFunction(Callee); FuncList Callers; for (InstList::iterator II = Calls.begin(), IE = Calls.end(); II != IE; ++II) { Function *Caller = (*II)->getParent()->getParent(); if (std::find(Callers.begin(), Callers.end(), Caller) == Callers.end()) Callers.push_back(Caller); } OS << Callers.size() << " functions call '" << Callee->getName() << "'...\n"; OS << "=================================\n"; for (FuncList::iterator FI = Callers.begin(), FE = Callers.end(); FI != FE; ++FI) { OS << (*FI)->getName() << "\n"; } OS << "=================================\n"; for (FuncList::iterator FI = Callers.begin(), FE = Callers.end(); FI != FE; ++FI) { std::vector<Value*> PreArgs; std::vector<Type*> PreArgTypes; Function *Caller = *FI; for (Function::arg_iterator AI = Caller->arg_begin(), AE = Caller->arg_end(); AI != AE; ++AI) { PreArgTypes.push_back(AI->getType()); PreArgs.push_back(AI); } std::vector<Type*> PostArgTypes; if (!Caller->getReturnType()->isVoidTy()) { PostArgTypes.push_back(Caller->getReturnType()); } Constant *PreConst = M->getOrInsertFunction("", FunctionType::get(Type::getVoidTy(getGlobalContext()), PreArgTypes, false)); Function *Pre = cast<Function>(PreConst); Pre->setName("pre"); CG->getOrInsertFunction(Pre); Constant *PostConst = M->getOrInsertFunction("", FunctionType::get(Type::getVoidTy(getGlobalContext()), PostArgTypes, false)); Function *Post = cast<Function>(PostConst); Post->setName("post"); CG->getOrInsertFunction(Post); Function *Wrapper = wrapFunc(Caller, Pre, Post); /* OS << "\n"; OS << "Function '" << Caller->getName() << "' returns " << *(Caller->getReturnType()) << "\n"; int ArgCount = 0; for (Function::arg_iterator AI = Caller->arg_begin(), AE = Caller->arg_end(); AI != AE; ++AI) { OS << "Arg #" << ArgCount++ << ": " << *AI << "\n"; } OS << "\n"; OS << "Wrapping '" << Caller->getName() << "' with '" << Wrapper->getName() << "'...\n\n"; OS << "Pre-invocation function = " << Pre->getName() << "\n"; OS << *Pre << "\n"; OS << "Post-invocation function = " << Post->getName() << "\n"; OS << *Post; OS << "**************************************\n";*/ } OS << "Functions successfully wrapped!\n"; }
bool CallGraphChecker::runOnModule(Module &M) { unsigned NumMissingCallEdges = 0; 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) { CallSite CS(Ins); if (CS && CS.getCalledFunction() == NULL) { Value *FP = CS.getCalledValue(); // Get all the targets of <FP>. FuncList Callees; #if 0 // Use DynamicPointerAnalysis if not fine-grained. PointerAnalysis &PA = getAnalysis<DynamicPointerAnalysis>(); ValueList Pointees; PA.getPointees(FP, Pointees); for (size_t j = 0; j < Pointees.size(); ++j) { assert(Pointees[j]); Callees.push_back(cast<Function>(Pointees[j])); } #endif // Use DynamicAliasAnalysis if fine-grained. // <Callees> contains real callees in the execution. AliasAnalysis &AA = getAnalysis<DynamicAliasAnalysis>(); for (Module::iterator PotentialCallee = M.begin(); PotentialCallee != M.end(); ++PotentialCallee) { if (AA.alias(FP, PotentialCallee)) Callees.push_back(PotentialCallee); } // Check whether these targets are captured in the call graph. for (size_t j = 0; j < Callees.size(); ++j) { Function *Callee = Callees[j]; assert(Callee); if (!existsInCallGraph(Ins, Callee)) { ++NumMissingCallEdges; errs().changeColor(raw_ostream::RED); errs() << "Call edge does not exist in the call graph:\n"; errs().resetColor(); DynAAUtils::PrintValue(errs(), Ins); errs() << "\n"; errs() << " " << Callee->getName() << "\n"; } } } } } } if (NumMissingCallEdges == 0) { errs().changeColor(raw_ostream::GREEN); errs() << "Congrats! You passed all the tests.\n"; errs().resetColor(); } else { errs().changeColor(raw_ostream::RED); errs() << "Detected " << NumMissingCallEdges << " missing call edges.\n"; errs().resetColor(); } return false; }