bool CverPruneStack::IsAnyCallesInvokeCast( Function *F, CallGraph &CG, SmallSet<Function *, 32> &Visited, int depth) { CVER_DEBUG("\t Analyzing " << F->getName() << "\n"); // static int maxDepth = 500; // if (depth >= maxDepth) { // return true; // } assert(!Visited.count(F)); Visited.insert(F); CallGraphNode *CGNode = CG[F]; bool mayCast = false; for (CallGraphNode::iterator I = CGNode->begin(); I != CGNode->end(); ++I) { Function *calleeFunction = I->second->getFunction(); if (!calleeFunction) continue; if (calleeFunction->getName() == sCast) return true; if (!Visited.count(calleeFunction)) mayCast |= IsAnyCallesInvokeCast(calleeFunction, CG, Visited, depth+1); // If the callee may cast, then simply return true. if (mayCast) return true; } return mayCast; }
/// UpdateCallGraphAfterInlining - Once we have cloned code over from a callee /// into the caller, update the specified callgraph to reflect the changes we /// made. Note that it's possible that not all code was copied over, so only /// some edges of the callgraph will be remain. static void UpdateCallGraphAfterInlining(const Function *Caller, const Function *Callee, Function::iterator FirstNewBlock, DenseMap<const Value*, Value*> &ValueMap, CallGraph &CG) { // Update the call graph by deleting the edge from Callee to Caller CallGraphNode *CalleeNode = CG[Callee]; CallGraphNode *CallerNode = CG[Caller]; CallerNode->removeCallEdgeTo(CalleeNode); // Since we inlined some uninlined call sites in the callee into the caller, // add edges from the caller to all of the callees of the callee. for (CallGraphNode::iterator I = CalleeNode->begin(), E = CalleeNode->end(); I != E; ++I) { const Instruction *OrigCall = I->first.getInstruction(); DenseMap<const Value*, Value*>::iterator VMI = ValueMap.find(OrigCall); // Only copy the edge if the call was inlined! if (VMI != ValueMap.end() && VMI->second) { // If the call was inlined, but then constant folded, there is no edge to // add. Check for this case. if (Instruction *NewCall = dyn_cast<Instruction>(VMI->second)) CallerNode->addCalledFunction(CallSite::get(NewCall), I->second); } } }
/// UpdateCallGraphAfterInlining - Once we have cloned code over from a callee /// into the caller, update the specified callgraph to reflect the changes we /// made. Note that it's possible that not all code was copied over, so only /// some edges of the callgraph may remain. static void UpdateCallGraphAfterInlining(CallSite CS, Function::iterator FirstNewBlock, ValueToValueMapTy &VMap, InlineFunctionInfo &IFI) { CallGraph &CG = *IFI.CG; const Function *Caller = CS.getInstruction()->getParent()->getParent(); const Function *Callee = CS.getCalledFunction(); CallGraphNode *CalleeNode = CG[Callee]; CallGraphNode *CallerNode = CG[Caller]; // Since we inlined some uninlined call sites in the callee into the caller, // add edges from the caller to all of the callees of the callee. CallGraphNode::iterator I = CalleeNode->begin(), E = CalleeNode->end(); // Consider the case where CalleeNode == CallerNode. CallGraphNode::CalledFunctionsVector CallCache; if (CalleeNode == CallerNode) { CallCache.assign(I, E); I = CallCache.begin(); E = CallCache.end(); } for (; I != E; ++I) { const Value *OrigCall = I->first; ValueToValueMapTy::iterator VMI = VMap.find(OrigCall); // Only copy the edge if the call was inlined! if (VMI == VMap.end() || VMI->second == 0) continue; // If the call was inlined, but then constant folded, there is no edge to // add. Check for this case. Instruction *NewCall = dyn_cast<Instruction>(VMI->second); if (NewCall == 0) continue; // Remember that this call site got inlined for the client of // InlineFunction. IFI.InlinedCalls.push_back(NewCall); // It's possible that inlining the callsite will cause it to go from an // indirect to a direct call by resolving a function pointer. If this // happens, set the callee of the new call site to a more precise // destination. This can also happen if the call graph node of the caller // was just unnecessarily imprecise. if (I->second->getFunction() == 0) if (Function *F = CallSite(NewCall).getCalledFunction()) { // Indirect call site resolved to direct call. CallerNode->addCalledFunction(CallSite(NewCall), CG[F]); continue; } CallerNode->addCalledFunction(CallSite(NewCall), I->second); } // Update the call graph by deleting the edge from Callee to Caller. We must // do this after the loop above in case Caller and Callee are the same. CallerNode->removeCallEdgeFor(CS); }
bool CverPruneStack::IsInvokeStack(Function *F, CallGraph &CG) { CallGraphNode *CGNode = CG[F]; for (CallGraphNode::iterator I = CGNode->begin(); I != CGNode->end(); ++I) { Function *calleeFunction = I->second->getFunction(); if (calleeFunction && calleeFunction->getName() == sStackEnter) return true; } return false; }
bool Fitness::callsUnknownFunction(const CallGraphNode &CGN) const { DEBUG(dbgs() << "Fitness::callsUnknownFunction()\n"); DEBUG(CGN.print(dbgs())); return std::any_of(CGN.begin(), CGN.end(), [this](const CallGraphNode::CallRecord &CR) { DEBUG(dbgs() << "Checking another CallRecord\n"); assert(CR.second); auto fun = CR.second->getFunction(); // if fun is nullptr, it is external return (!fun || getFunType(*fun) == FunType::Unknown); }); }
bool CallGraphChecker::existsInCallGraph(Instruction *Call, Function *Callee) { CallGraph &CG = getAnalysis<CallGraph>(); assert(Call && Callee); CallGraphNode *CallerNode = CG[Call->getParent()->getParent()]; CallGraphNode *CalleeNode = CG[Callee]; assert(CallerNode && CalleeNode); if (find(CallerNode->begin(), CallerNode->end(), CallGraphNode::CallRecord(Call, CalleeNode)) != CallerNode->end()) { return true; } // An instruction conservatively calls all functions by calling // CallsExternalNode. if (find(CallerNode->begin(), CallerNode->end(), CallGraphNode::CallRecord(Call, CG.getCallsExternalNode())) != CallerNode->end()) { return true; } return false; }
bool StructuredModuleEditor::getCallSite(Function *Func, uint64_t Index, CallSite &CS) { CallGraphNode *FuncNode = CG->getOrInsertFunction(Func); uint64_t Count = 0; for (CallGraphNode::const_iterator I = FuncNode->begin(), E = FuncNode->end(); I != E; ++I) { if (Count == Index) { CS = CallSite((*I).first); return true; } Count++; } return false; }
bool StructuredModuleEditor::removeFunc(Function *FunctionToRemove) { // Checks to make sure the function we are trying to remove // actually exists in the CFG if (FunctionToRemove == NULL) { OS << "Function does not exist in the call graph!\n"; return false; } CallGraphNode *NodeToRemove = (*CG)[FunctionToRemove]; // We cannot remove a node if it has any inteprocedural in-edges for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) { CallGraphNode *CallingNode = (*CG)[I]; for (CallGraphNode::iterator CGNI = CallingNode->begin(), CGNE = CallingNode->end(); CGNI != CGNE; ++CGNI) { Function *Caller = I; Function *Callee = CGNI->second->getFunction(); if (Callee == FunctionToRemove && Caller != Callee) { OS << "Cannot remove " << FunctionToRemove->getName() << " because it has at least one interprocedural edge!\n"; OS << "It is called by " << Caller->getName() << "\n"; return false; } } } // Removes all call graph edges from the node we are removing to its callees. NodeToRemove->removeAllCalledFunctions(); CG->getExternalCallingNode()->removeAnyCallEdgeTo(NodeToRemove); // Removes all call graph edges from callees to the node we are removing for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) { CallGraphNode *CallingNode = (*CG)[I]; CallingNode->removeAnyCallEdgeTo(NodeToRemove); } NodeToRemove->removeAnyCallEdgeTo(CG->getCallsExternalNode()); // Removes the function from the module and the CFG FunctionToRemove->dropAllReferences(); // Remove the function from the module CG->removeFunctionFromModule(NodeToRemove); return true; }
/// UpdateCallGraphAfterInlining - Once we have cloned code over from a callee /// into the caller, update the specified callgraph to reflect the changes we /// made. Note that it's possible that not all code was copied over, so only /// some edges of the callgraph may remain. static void UpdateCallGraphAfterInlining(CallSite CS, Function::iterator FirstNewBlock, DenseMap<const Value*, Value*> &ValueMap, CallGraph &CG) { const Function *Caller = CS.getInstruction()->getParent()->getParent(); const Function *Callee = CS.getCalledFunction(); CallGraphNode *CalleeNode = CG[Callee]; CallGraphNode *CallerNode = CG[Caller]; // Since we inlined some uninlined call sites in the callee into the caller, // add edges from the caller to all of the callees of the callee. CallGraphNode::iterator I = CalleeNode->begin(), E = CalleeNode->end(); // Consider the case where CalleeNode == CallerNode. CallGraphNode::CalledFunctionsVector CallCache; if (CalleeNode == CallerNode) { CallCache.assign(I, E); I = CallCache.begin(); E = CallCache.end(); } for (; I != E; ++I) { const Instruction *OrigCall = I->first.getInstruction(); DenseMap<const Value*, Value*>::iterator VMI = ValueMap.find(OrigCall); // Only copy the edge if the call was inlined! if (VMI != ValueMap.end() && VMI->second) { // If the call was inlined, but then constant folded, there is no edge to // add. Check for this case. if (Instruction *NewCall = dyn_cast<Instruction>(VMI->second)) CallerNode->addCalledFunction(CallSite::get(NewCall), I->second); } } // Update the call graph by deleting the edge from Callee to Caller. We must // do this after the loop above in case Caller and Callee are the same. CallerNode->removeCallEdgeFor(CS); }
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; }
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; }