bool PrintCgTree::runOnModule(Module &M) { #if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR == 4 CallGraph CG; CG.runOnModule(M); CallGraphNode* root = CG.getRoot(); #else CallGraph CG(M); Function* Main = M.getFunction("main"); CallGraphNode* root = Main?CG[Main]:CG.getExternalCallingNode(); #endif Assert(root->getFunction()==Main, ""); errs()<<root->getFunction()->getName()<<"\n"; print_cg(root); return false; }
/// removeDeadFunctions - Remove dead functions that are not included in /// DNR (Do Not Remove) list. bool Inliner::removeDeadFunctions(CallGraph &CG, bool AlwaysInlineOnly) { SmallVector<CallGraphNode*, 16> FunctionsToRemove; // Scan for all of the functions, looking for ones that should now be removed // from the program. Insert the dead ones in the FunctionsToRemove set. for (CallGraph::iterator I = CG.begin(), E = CG.end(); I != E; ++I) { CallGraphNode *CGN = I->second; Function *F = CGN->getFunction(); if (!F || F->isDeclaration()) continue; // Handle the case when this function is called and we only want to care // about always-inline functions. This is a bit of a hack to share code // between here and the InlineAlways pass. if (AlwaysInlineOnly && !F->getFnAttributes().hasAttribute(Attributes::AlwaysInline)) continue; // If the only remaining users of the function are dead constants, remove // them. F->removeDeadConstantUsers(); if (!F->isDefTriviallyDead()) continue; // Remove any call graph edges from the function to its callees. CGN->removeAllCalledFunctions(); // Remove any edges from the external node to the function's call graph // node. These edges might have been made irrelegant due to // optimization of the program. CG.getExternalCallingNode()->removeAnyCallEdgeTo(CGN); // Removing the node for callee from the call graph and delete it. FunctionsToRemove.push_back(CGN); } if (FunctionsToRemove.empty()) return false; // Now that we know which functions to delete, do so. We didn't want to do // this inline, because that would invalidate our CallGraph::iterator // objects. :( // // Note that it doesn't matter that we are iterating over a non-stable order // here to do this, it doesn't matter which order the functions are deleted // in. array_pod_sort(FunctionsToRemove.begin(), FunctionsToRemove.end()); FunctionsToRemove.erase(std::unique(FunctionsToRemove.begin(), FunctionsToRemove.end()), FunctionsToRemove.end()); for (SmallVectorImpl<CallGraphNode *>::iterator I = FunctionsToRemove.begin(), E = FunctionsToRemove.end(); I != E; ++I) { delete CG.removeFunctionFromModule(*I); ++NumDeleted; } return true; }
bool AnalysisEngine::runOnSCC(CallGraphSCC &scc) { for (CallGraphSCC::iterator i = scc.begin(), e = scc.end(); i != e; ++i) { CallGraphNode *cgnode = *i; Function *f = cgnode->getFunction(); FunctionSimulator fsimulator(f); fsimulator.simulate(); } }
/// removeDeadFunctions - Remove dead functions that are not included in /// DNR (Do Not Remove) list. bool Inliner::removeDeadFunctions(CallGraph &CG, SmallPtrSet<const Function *, 16> *DNR) { std::set<CallGraphNode*> FunctionsToRemove; // Scan for all of the functions, looking for ones that should now be removed // from the program. Insert the dead ones in the FunctionsToRemove set. for (CallGraph::iterator I = CG.begin(), E = CG.end(); I != E; ++I) { CallGraphNode *CGN = I->second; if (Function *F = CGN ? CGN->getFunction() : 0) { // If the only remaining users of the function are dead constants, remove // them. F->removeDeadConstantUsers(); if (DNR && DNR->count(F)) continue; if ((F->hasLinkOnceLinkage() || F->hasLocalLinkage()) && F->use_empty()) { // Remove any call graph edges from the function to its callees. CGN->removeAllCalledFunctions(); // Remove any edges from the external node to the function's call graph // node. These edges might have been made irrelegant due to // optimization of the program. CG.getExternalCallingNode()->removeAnyCallEdgeTo(CGN); // Removing the node for callee from the call graph and delete it. FunctionsToRemove.insert(CGN); } } } // Now that we know which functions to delete, do so. We didn't want to do // this inline, because that would invalidate our CallGraph::iterator // objects. :( bool Changed = false; for (std::set<CallGraphNode*>::iterator I = FunctionsToRemove.begin(), E = FunctionsToRemove.end(); I != E; ++I) { resetCachedCostInfo((*I)->getFunction()); delete CG.removeFunctionFromModule(*I); ++NumDeleted; Changed = true; } return Changed; }
void CallGraph::verify() const { #ifndef NDEBUG // For every function in the module, add it to our SILFunction set. llvm::DenseSet<SILFunction *> Functions; for (auto &F : M) Functions.insert(&F); // For every pair (SILFunction, CallGraphNode) in the // function-to-node map, verify: // // a. The function is in the current module. // b. The call graph node is for that same function. // // In addition, call the verify method for the function. unsigned numEdges = 0; for (auto &P : FunctionToNodeMap) { SILFunction *F = P.first; CallGraphNode *Node = P.second; assert(Functions.count(F) && "Function in call graph but not in module!?"); assert(Node->getFunction() == F && "Func mapped to node, but node has different Function inside?!"); verify(F); numEdges += Node->getCalleeEdges().size(); } assert(InstToEdgeMap.size() == numEdges && "Some edges in InstToEdgeMap are not contained in any node"); // Verify the callee sets. for (auto Iter : CalleeSetCache) { auto *CalleeSet = Iter.second.getPointer(); for (CallGraphNode *Node : *CalleeSet) { SILFunction *F = Node->getFunction(); assert(tryGetCallGraphNode(F) && "Callee set contains dangling node poiners"); } } #endif }
bool CallGraphCFG::findBBPath(CallGraphNode *n, std::vector<BasicBlock*> &path, std::string srcFile, int srcLine) { if (n == NULL) return false; Function *F = n->getFunction(); std::cerr << "Processing " << F->getNameStr() << "\n"; // Are we on a leaf? if (n->size() == 0) { BasicBlock *bb=NULL; if (findLineInFunction(F,&bb,srcFile,srcLine)) { path.push_back(bb); return true; } } for (CallGraphNode::iterator it = n->begin(); it != n->end(); ++it) { CallSite cs = it->first; CallGraphNode *tCGN = it->second; Instruction *tI = cs.getInstruction(); if (tI == NULL) return false; BasicBlock *bb = tI->getParent(); Function *tF = tCGN->getFunction(); path.push_back(bb); if (findLineInBB(bb,srcFile,srcLine)) return true; if (tF != F) { // Dont get stuck in recursion if (findBBPath(tCGN,path,srcFile,srcLine)) return true; } std::cerr << " Dead end, reverting...\n"; // FIX: This is misleading, not really correct. path.pop_back(); } return false; }
/// Remove dead functions that are not included in DNR (Do Not Remove) list. bool Inliner::removeDeadFunctions(CallGraph &CG, bool AlwaysInlineOnly) { SmallVector<CallGraphNode*, 16> FunctionsToRemove; SmallVector<CallGraphNode *, 16> DeadFunctionsInComdats; SmallDenseMap<const Comdat *, int, 16> ComdatEntriesAlive; auto RemoveCGN = [&](CallGraphNode *CGN) { // Remove any call graph edges from the function to its callees. CGN->removeAllCalledFunctions(); // Remove any edges from the external node to the function's call graph // node. These edges might have been made irrelegant due to // optimization of the program. CG.getExternalCallingNode()->removeAnyCallEdgeTo(CGN); // Removing the node for callee from the call graph and delete it. FunctionsToRemove.push_back(CGN); }; // Scan for all of the functions, looking for ones that should now be removed // from the program. Insert the dead ones in the FunctionsToRemove set. for (CallGraph::iterator I = CG.begin(), E = CG.end(); I != E; ++I) { CallGraphNode *CGN = I->second; Function *F = CGN->getFunction(); if (!F || F->isDeclaration()) continue; // Handle the case when this function is called and we only want to care // about always-inline functions. This is a bit of a hack to share code // between here and the InlineAlways pass. if (AlwaysInlineOnly && !F->hasFnAttribute(Attribute::AlwaysInline)) continue; // If the only remaining users of the function are dead constants, remove // them. F->removeDeadConstantUsers(); if (!F->isDefTriviallyDead()) continue; // It is unsafe to drop a function with discardable linkage from a COMDAT // without also dropping the other members of the COMDAT. // The inliner doesn't visit non-function entities which are in COMDAT // groups so it is unsafe to do so *unless* the linkage is local. if (!F->hasLocalLinkage()) { if (const Comdat *C = F->getComdat()) { --ComdatEntriesAlive[C]; DeadFunctionsInComdats.push_back(CGN); continue; } } RemoveCGN(CGN); } if (!DeadFunctionsInComdats.empty()) { // Count up all the entities in COMDAT groups auto ComdatGroupReferenced = [&](const Comdat *C) { auto I = ComdatEntriesAlive.find(C); if (I != ComdatEntriesAlive.end()) ++(I->getSecond()); }; for (const Function &F : CG.getModule()) if (const Comdat *C = F.getComdat()) ComdatGroupReferenced(C); for (const GlobalVariable &GV : CG.getModule().globals()) if (const Comdat *C = GV.getComdat()) ComdatGroupReferenced(C); for (const GlobalAlias &GA : CG.getModule().aliases()) if (const Comdat *C = GA.getComdat()) ComdatGroupReferenced(C); for (CallGraphNode *CGN : DeadFunctionsInComdats) { Function *F = CGN->getFunction(); const Comdat *C = F->getComdat(); int NumAlive = ComdatEntriesAlive[C]; // We can remove functions in a COMDAT group if the entire group is dead. assert(NumAlive >= 0); if (NumAlive > 0) continue; RemoveCGN(CGN); } } if (FunctionsToRemove.empty()) return false; // Now that we know which functions to delete, do so. We didn't want to do // this inline, because that would invalidate our CallGraph::iterator // objects. :( // // Note that it doesn't matter that we are iterating over a non-stable order // here to do this, it doesn't matter which order the functions are deleted // in. array_pod_sort(FunctionsToRemove.begin(), FunctionsToRemove.end()); FunctionsToRemove.erase(std::unique(FunctionsToRemove.begin(), FunctionsToRemove.end()), FunctionsToRemove.end()); for (SmallVectorImpl<CallGraphNode *>::iterator I = FunctionsToRemove.begin(), E = FunctionsToRemove.end(); I != E; ++I) { delete CG.removeFunctionFromModule(*I); ++NumDeleted; } return true; }
bool Strator::runOnModule(Module &m) { errs() << "Strator started!\n"; /// Get previous analysis results // multithreadedFunctionMap = &(getAnalysis<MultithreadFinder>().multithreadedFunctionMap); // if(UseLocalValueInfo) // localValueInfo = &(getAnalysis<LocalIdentifier>().localValueInfo); if(UseAliasAnalysis || DebugAliasAnalysis) aa = &getAnalysis<AliasAnalysis>(); //aa = getAnalysis<LocalIdentifier>().aa; //useDefMap = &(getAnalysis<UseDefBuilder>().useDefMap); CallGraph& callGraph = getAnalysis<CallGraph>(); GEPFactory = new GEPValueFactory(&m); if(PrintPrevPasses){ printLocalModificationInfo(); } CallGraphNode* externalNode = callGraph.getExternalCallingNode(); if (DirectedRaceDetection){ /// This is the first and default race detection strategy /// that only tracks a main function (like the /// unit test case). We call this directed race detection /// There is no thread pool in this case but a single worker threadPoolSize = 0; /// We use this simply to mark all the external entry point functions as initially not analyzed CallGraphNode::iterator it; for(it = externalNode->begin(); it != externalNode->end(); ++it){ Function* f = 0; if((f = it->second->getFunction())) if(f->size() > 0){ functionMap[f->getName().str()] = false; ++functionCount; } } // cerr << "Total entry point count: " << functionCount << endl; CallGraphNode* root = callGraph.getRoot(); assert(root->size() && "Size of the call graph root is 0! Something is wrong"); cerr << "Root calls: " << root->size() << " functions"<< endl; if(!root->getFunction()){ cerr << "The root represents an external node" << endl; assert(false && "You need to switch to global race detection!"); } // cerr << root->getFunction()->getName().str() << endl; /// Initialize all functions to not-multithreaded workers.push_back(new StratorWorker(this)); for(it = root->begin(); it != root->end(); ++it){ Function* f = 0; if((f = it->second->getFunction())){ if(f->size() > 0){ workers[0]->multithreadedFunctionMap[it->second->getFunction()->getName().str()] = false; } } } Strator::StratorWorker::LockSet* lockSet = new Strator::StratorWorker::LockSet(); workers[0]->traverseFunction(*(root->getFunction()), *lockSet); } else { /// This is the second variant of race detection. Here all the external /// functions with definitions are considered as root and race detection /// is performed over all their childeren. this variant is called global /// race detection pthread_t tids[50]; threadPoolSize = 50; if(externalNode){ /// TODO: We should investigate the following: Some static functions (thus /// having internal linkage) are considered as external nodes as they are /// used as parameters to some functions (like pthread_create). We should /// understand if it is necessary to add such functions as external nodes. CallGraphNode::iterator it; for(it = externalNode->begin(); it != externalNode->end(); ++it){ Function* f = 0; if((f = it->second->getFunction())) if(f->size() > 0){ cerr << "adding function \"" << it->second->getFunction()->getName().str() << "\" to task list" << endl; tasks.push_back(f); ++functionCount; } } /// Create the thread pool threadPoolSize = (threadPoolSize < functionCount) ? threadPoolSize : functionCount; /// Create as many workers as the pool size // threadPoolSize = 1; cerr << "Thread pool size:" << threadPoolSize << endl; for(unsigned i=0; i<threadPoolSize; ++i) workers.push_back(new StratorWorker(this)); /// trigger the for(unsigned i=0; i<threadPoolSize; ++i){ int retVal = pthread_create(&tids[i], 0, stratorWorkerHelper, workers[i]); assert(retVal == 0 && "Problem with creating the threads"); } /// Synchronize the threads for(unsigned i=0; i<threadPoolSize; ++i){ int retVal = pthread_join(tids[i], 0); assert(retVal == 0 && "Problem with joining the threads"); } } } if(ReportUnprocessed){ /// list all the unprocessed entry point functions cerr << "Following entry point functions were not processed: " << endl; FunctionMap::iterator fMIt; for(fMIt = functionMap.begin(); fMIt != functionMap.end(); ++fMIt){ if(!fMIt->second) cerr << fMIt->first << endl; } } /// We have gathered race detection data, now report reportRaces(); /// We did not modify the module, return false return false; }
/// Remove dead functions that are not included in DNR (Do Not Remove) list. bool LegacyInlinerBase::removeDeadFunctions(CallGraph &CG, bool AlwaysInlineOnly) { SmallVector<CallGraphNode *, 16> FunctionsToRemove; SmallVector<Function *, 16> DeadFunctionsInComdats; auto RemoveCGN = [&](CallGraphNode *CGN) { // Remove any call graph edges from the function to its callees. CGN->removeAllCalledFunctions(); // Remove any edges from the external node to the function's call graph // node. These edges might have been made irrelegant due to // optimization of the program. CG.getExternalCallingNode()->removeAnyCallEdgeTo(CGN); // Removing the node for callee from the call graph and delete it. FunctionsToRemove.push_back(CGN); }; // Scan for all of the functions, looking for ones that should now be removed // from the program. Insert the dead ones in the FunctionsToRemove set. for (const auto &I : CG) { CallGraphNode *CGN = I.second.get(); Function *F = CGN->getFunction(); if (!F || F->isDeclaration()) continue; // Handle the case when this function is called and we only want to care // about always-inline functions. This is a bit of a hack to share code // between here and the InlineAlways pass. if (AlwaysInlineOnly && !F->hasFnAttribute(Attribute::AlwaysInline)) continue; // If the only remaining users of the function are dead constants, remove // them. F->removeDeadConstantUsers(); if (!F->isDefTriviallyDead()) continue; // It is unsafe to drop a function with discardable linkage from a COMDAT // without also dropping the other members of the COMDAT. // The inliner doesn't visit non-function entities which are in COMDAT // groups so it is unsafe to do so *unless* the linkage is local. if (!F->hasLocalLinkage()) { if (F->hasComdat()) { DeadFunctionsInComdats.push_back(F); continue; } } RemoveCGN(CGN); } if (!DeadFunctionsInComdats.empty()) { // Filter out the functions whose comdats remain alive. filterDeadComdatFunctions(CG.getModule(), DeadFunctionsInComdats); // Remove the rest. for (Function *F : DeadFunctionsInComdats) RemoveCGN(CG[F]); } if (FunctionsToRemove.empty()) return false; // Now that we know which functions to delete, do so. We didn't want to do // this inline, because that would invalidate our CallGraph::iterator // objects. :( // // Note that it doesn't matter that we are iterating over a non-stable order // here to do this, it doesn't matter which order the functions are deleted // in. array_pod_sort(FunctionsToRemove.begin(), FunctionsToRemove.end()); FunctionsToRemove.erase( std::unique(FunctionsToRemove.begin(), FunctionsToRemove.end()), FunctionsToRemove.end()); for (CallGraphNode *CGN : FunctionsToRemove) { delete CG.removeFunctionFromModule(CGN); ++NumDeleted; } return true; }
bool InlineModule::runOnModule( Module & M ) { std::vector<std::string> leafNames; //File *file = fopen("inline_info.txt", "r"); //if (!file) { // errs() << "Error: Could not open inline_info file.\n"; // retrun true; //} std::string line; std::ifstream file ("inline_info.txt"); if(file.is_open()) { while(std::getline(file, line)) leafNames.push_back(line); file.close(); } else errs() << "Error: Could not open inline_info file.\n"; //makeLeaf.push_back(M.getFunction("ORACLE_0")); //makeLeaf.push_back(M.getFunction("ORACLE_1")); //makeLeaf.push_back(M.getFunction("ORACLE_2")); //makeLeaf.push_back(M.getFunction("ORACLE_3")); for (std::vector<std::string>::iterator i = leafNames.begin(), e = leafNames.end(); i!=e; ++i) { if (debugInlining) errs() << "inline_info: " << *i << "\n"; makeLeaf.push_back(M.getFunction(*i)); } // First, get a pointer to previous analysis results CallGraph & CG = getAnalysis<CallGraph>(); CallGraphNode * entry = CG.getRoot(); if( entry && entry->getFunction() && debugInlining) errs() << "Entry is function: " << entry->getFunction()->getName() << "\n"; // Iterate over all SCCs in the module in bottom-up order for( scc_iterator<CallGraph*> si=scc_begin( &CG ), se=scc_end( &CG ); si != se; ++si ) { runOnSCC( *si ); } //reverse the vector for preorder std::reverse(vectPostOrder.begin(),vectPostOrder.end()); for(std::vector<Function*>::iterator vit = vectPostOrder.begin(), vitE = vectPostOrder.end(); vit!=vitE; ++vit) { Function *f = *vit; runOnFunction(*f); } // now we have all the call sites which need to be inlined // inline from the leaves all the way up const TargetData *TD = getAnalysisIfAvailable<TargetData>(); InlineFunctionInfo InlineInfo(&CG, TD); std::reverse(inlineCallInsts.begin(),inlineCallInsts.end()); for (std::vector<CallInst*>::iterator i = inlineCallInsts.begin(), e = inlineCallInsts.end(); i!=e; ++i) { CallInst* CI = *i; bool success = InlineFunction(CI, InlineInfo, false); if(!success) { if (debugInlining) errs() << "Error: Could not inline callee function " << CI->getCalledFunction()->getName() << " into caller function " << "\n"; continue; } if (debugInlining) errs() << "Successfully inlined callee function " << CI->getCalledFunction()->getName() << "into caller function " << "\n"; } return false; }
bool PathList::runOnModule(Module &M) { module = &M; llvm::dbgs() << "[runOnModule]: Moduel M has " << M.getFunctionList().size() << " Functions in all.\n"; // for test Function *f1 = M.getFunction("fprintf"); if (!f1) dbgs() << "[Test]: can not find function fprintf.\n"; else dbgs() << "[Test]: find function fprintf.\n"; CallGraph &CG = getAnalysis<CallGraph>(); // CG.dump(); CallGraphNode *cgNode = CG.getRoot(); cgNode->dump(); // errs()<<node->getFunction()->getName()<<'\n'; Function *startFunc; Function *endFunc; startFunc = M.getFunction("__user_main"); //std::string fileName("/home/xqx/data/xqx/projects/benckmarks-klee/texinfo-4.8/build-shit/makeinfo/../../makeinfo/insertion.c"); //int lineNo = 407; BB = getBB(fileName, lineNo); *targetBbpp = getBB(fileName, lineNo); if (BB) { endFunc = BB->getParent(); if (!endFunc) { errs()<<"Error: get endFunc failed.\n"; return false; } if (!startFunc) { errs()<<"Error: get startFunc failed.\n"; return false; } errs()<<startFunc->getName()<<'\n'; } else { errs()<<"Error: get BB failed.\n"; return false; } //read start and end from xml files // defectList enStart, enEnd; // getEntryList("/tmp/entrys.xml", &enStart, "start"); // getEntryList("/tmp/entrys.xml", &enEnd, "end"); // getEntryList("/tmp/entrys.xml", &dl, "end"); // dumpEntryList(&enStart); // dumpEntryList(&enEnd); // dumpEntryList(&dl); //read bug information from xml file /* for (defectList::iterator dit = dl.begin(); dit != dl.end(); dit++) { StringRef file(dit->first.c_str()); std::vector<int> lines = dit->second; BasicBlock *BB = getBB(file, *(lines.begin())); if (BB) { endFunc = BB->getParent(); } } */ //to store temporary path std::vector<BasicBlock*> p; // a counter int map_count = 0; for (Module::iterator i = M.begin(), e = M.end(); i != e; ++i) { Function *F = i; if (!F) { llvm::errs() << "***NULL Function***\n"; continue; } cgNode = CG.getOrInsertFunction(F); F = cgNode->getFunction(); // for (CallGraphNode::iterator I = cgNode->begin(), E = cgNode->end(); I != E; ++I){ CallGraphNode::CallRecord *cr = &*I; // llvm::errs() << "\tCS<" << cr->first << "> calls"; // check if the CallInst is existed if(cr->first){ Instruction *TmpIns = dyn_cast<Instruction>(cr->first); if(TmpIns) { // errs() << "\t" << *TmpIns << "\n"; //unsigned int l, c; //std::string cfi_path = getInstPath(TmpIns, l, c); //if (!cfi_path.empty()) { // if (cfi_path.find("uclibc") != std::string::npos) { // dbgs() << "[Filter Uclib]: find an instruction from uclibc.\n"; // continue; // } else if (cfi_path.find("POSIX") != std::string::npos) { // dbgs() << "[Filter Uclib]: find an instruction from POSIX.\n"; // continue; // } //} } else continue; } // get the funciton pointer which is called by current CallRecord cr Function *FI = cr->second->getFunction(); if (!FI) continue; // create a new CalledFunctions element and push it into calledFunctionMap. calledFunctionMap[FI].push_back(std::make_pair(F, dyn_cast<Instruction>(cr->first))); // for debuging map_count++; } } dbgs() << "[Count Number of calledFunctionMap]: "<< calledFunctionMap.size() <<'\n'; // analyze the global function pointer table if(function_pointer_analysis()) { errs() << "[Analyze global function pointer table success]\n"; } else { errs() << "[Analyze global function pointer table failed]\n"; } dbgs() << "[Count Number of calledFunctionMap]: "<< calledFunctionMap.size() <<'\n'; // filter the instructions from uclibc //filter_uclibc(); llvm::errs() << "=================================hh\n"; llvm::errs() << "get Function Path: " << endFunc->getName() << " to " << startFunc->getName() << " \n"; // printCalledFuncAndCFGPath(endFunc, startFunc, BB, p); // modification by wh evo_paths = new entire_path; //filter_paths = new func_bbs_type; //BB_paths_map = new std::map<std::pair<Function*, BasicBlock*>, std::vector<BasicBlock*> >; std::vector<std::pair< Function*, Instruction*> > tmp_func_path; // std::vector<BasicBlock*> tmp_bb_path; // explore_function_paths(endFunc, startFunc, bug_Inst, &tmp_func_path); collect_funcitons(endFunc, startFunc, bug_Inst, &tmp_func_path); // dbgs() << "++++++Found " << evo_paths->size() << " function paths.\n"; // for (entire_path::iterator ep_it = evo_paths->begin(); ep_it != evo_paths->end(); ep_it++) { // for (std::vector<std::pair< Function*, Instruction*> >::iterator pair_it = ep_it->begin(); pair_it != ep_it->end(); pair_it++) { // if (filter_paths->size() != 0) { // std::vector<Instruction*>::iterator inst_it = std::find((*filter_paths)[pair_it->first].begin(), (*filter_paths)[pair_it->first].end(), pair_it->second); // if (inst_it != (*filter_paths)[pair_it->first].end()) { // continue; // } // } // (*filter_paths)[pair_it->first].push_back(pair_it->second); // } // } dbgs() << "[filter_paths]: contain " << filter_paths->size() << " functions in all.\n"; for (func_bbs_type::iterator fbs_it = filter_paths->begin(); fbs_it != filter_paths->end(); fbs_it++) { for (std::vector<Instruction*>::iterator bb_it2 = fbs_it->second.begin(); bb_it2 != fbs_it->second.end(); bb_it2++) { dbgs() << "^^^^^^ " << fbs_it->first->getName() << ": " << (*bb_it2)->getParent()->getName() << '\n'; // to expand functions call_insts.push_back((*bb_it2)); explore_basicblock_paths(fbs_it->first, (*bb_it2)->getParent(), &(*BB_paths_map)[std::make_pair(fbs_it->first, *bb_it2)]); dbgs() << "^^^^^^ found " << (*BB_paths_map)[std::make_pair(fbs_it->first, *bb_it2)].size() << " basicblocks.\n"; } } llvm::dbgs() << "!!!!!!!! Found " << call_insts.size() << " call instructions.\n"; llvm::dbgs() << "!!!!!!!! Found " << path_basicblocks.size() << " path basicblocks.\n"; // expand functions for (std::vector<Instruction*>::iterator ci_it = call_insts.begin(); ci_it != call_insts.end(); ci_it++) { BasicBlock *call_bb = (*ci_it)->getParent(); if (!call_bb) { continue; } for (BasicBlock::iterator inst = call_bb->begin(); inst != call_bb->end(); inst++) { if (&*inst == *ci_it) { break; } if (isa<CallInst>(&*inst)) { std::vector<Instruction*>::iterator ci = std::find(path_call_insts.begin(), path_call_insts.end(), &*inst); if (ci != path_call_insts.end()) continue; path_call_insts.push_back(&*inst); } } } llvm::dbgs() << "@@@@@@@@ After search call_insts, found " << path_call_insts.size() << " call instructions.\n"; for (std::vector<BasicBlock*>::iterator p_bb_it = path_basicblocks.begin(); p_bb_it != path_basicblocks.end(); p_bb_it++) { for (BasicBlock::iterator inst = (*p_bb_it)->begin(); inst != (*p_bb_it)->end(); inst++) { if (isa<CallInst>(&*inst)) { std::vector<Instruction*>::iterator ci = std::find(path_call_insts.begin(), path_call_insts.end(), &*inst); if (ci != path_call_insts.end()) continue; path_call_insts.push_back(&*inst); } } } llvm::dbgs() << "@@@@@@@@ After search path_basicblocks, found " << path_call_insts.size() << " call instructions.\n"; for (std::vector<Instruction*>::iterator iit = path_call_insts.begin(); iit != path_call_insts.end(); iit++) { CallInst *ci = dyn_cast<CallInst>(*iit); if (!ci) continue; Function *ff = ci->getCalledFunction(); if (!ff) { //ci->dump(); //dbgs() << "\t[called value] " << ci->getOperand(0)->getName() << '\n'; continue; } std::vector<Function*>::iterator fit = std::find(otherCalledFuncs->begin(), otherCalledFuncs->end(), ff); if (fit == otherCalledFuncs->end()) otherCalledFuncs->push_back(ff); } llvm::dbgs() << "((((((((( Found " << otherCalledFuncs->size() << " functions.\n"; for (int index = 0; index < otherCalledFuncs->size(); index++) { Function *f = otherCalledFuncs->at(index); /* if (!f) { //f->dump(); llvm::dbgs() << "?????? index = " << index << " size = " << otherCalledFuncs->size()<< '\n'; continue; } */ for (inst_iterator f_it = inst_begin(f); f_it != inst_end(f); f_it++) { CallInst *ci = dyn_cast<CallInst>(&*f_it); if (!ci) continue; if (!ci->getCalledFunction()) { //ci->dump(); continue; } std::vector<Function*>::iterator fit = std::find(otherCalledFuncs->begin(), otherCalledFuncs->end(), ci->getCalledFunction()); if (fit == otherCalledFuncs->end()) otherCalledFuncs->push_back(ci->getCalledFunction()); } } llvm::dbgs() << "((((((((( Found " << otherCalledFuncs->size() << " functions.\n"; //This should be just for statistic. int tmp_funcNum_in_filter_notIn_other = 0; for (func_bbs_type::iterator fbs_it = filter_paths->begin(); fbs_it != filter_paths->end(); fbs_it++) { if (!fbs_it->first) { llvm::dbgs() << "[Warning]: Found a null Function pointer in filter_paths.\n"; continue; } std::vector<Function*>::iterator fit = std::find(otherCalledFuncs->begin(), otherCalledFuncs->end(), fbs_it->first); if (fit == otherCalledFuncs->end()) //otherCalledFuncs->push_back(fbs_it->first); tmp_funcNum_in_filter_notIn_other ++; } llvm::dbgs() << "<><><><> After searching filter_paths, found " << otherCalledFuncs->size() + tmp_funcNum_in_filter_notIn_other << " functions.\n"; /* for (entire_path::iterator ep_it = evo_paths->begin(); ep_it != evo_paths->end(); ep_it++) { dbgs() << "Path length is: " << ep_it->size() << '\n'; for (std::vector<std::pair< Function*, BasicBlock*> >::iterator pair_it = ep_it->begin(); pair_it != ep_it->end(); pair_it++) { dbgs() << "^^^^^^ " << pair_it->first->getName() << ": " << pair_it->second->getName() << '\n'; explore_basicblock_paths(pair_it->first, pair_it->second, &(*BB_paths_map)[*pair_it]); dbgs() << "^^^^^^ found " << (*BB_paths_map)[*pair_it].size() << " basicblocks.\n"; } } */ llvm::errs() << "on-end\n"; llvm::errs() << "=================================\n"; // output all of the paths /* errs()<<"Find "<<paths_found->size()<<" paths in all.\n"; for(paths::iterator ips = paths_found->begin();ips != paths_found->end();ips++) { // std::vector<BasicBlock*> *tmpP = dyn_cast<std::vector<BasicBlock*>*>(&*ips); dbgs() << "=========A Path Start============\n"; for(std::vector<BasicBlock*>::iterator ps = ips->begin(), pe = ips->end(); ps != pe; ps++) { BasicBlock *tmpStr = *ps; errs()<<"\t"<<tmpStr->getParent()->getName()<<": "<<tmpStr->getName()<<" -> \n"; } errs()<<"=================================\n"; } */ return false; }