// advances this CFGIterator in the given direction. Forwards if fwDir=true and backwards if fwDir=false. // if pushAllChildren=true, all of the current node's unvisited children (predecessors or successors, // depending on fwDir) are pushed onto remainingNodes // It is assumed that for a given CFGIterator pushAllChildren either always = true or always = false. void CFGIterator::advance(bool fwDir, bool pushAllChildren) { assert(initialized); /*scope s(txt()<<"CFGIterator::advance(fwDir="<<fwDir<<", pushAllChildren="<<pushAllChildren<<") #remainingNodes="<<remainingNodes.size()); dbg<<" visited=\n"; for(set<CFGNode>::iterator it=visited.begin(); it!=visited.end(); it++) dbg << " "<<CFGNode2Str(*it)<<"\n";*/ if(remainingNodes.size()>0) { // pop the next CFG node from the front of the list CFGNode cur = remainingNodes.front(); remainingNodes.pop_front(); //dbg << "cur="<<CFGNode2Str(cur)<<endl; if(pushAllChildren) { // find its followers (either successors or predecessors, depending on value of fwDir), push back // those that have not yet been visited vector<CFGEdge> nextE; if(fwDir) { /* // Do not proceed forward if we've reached the end of a function if(!(isSgFunctionDefinition(cur.getNode()) && cur.getIndex()==3))*/ nextE = cur.outEdges(); } else { /* // Do not proceed backward if we've reached the end of a function if(!(isSgFunctionParameterList(cur.getNode()) && cur.getIndex()==0)) */ nextE = cur.inEdges(); } //dbg << " #nextE="<<nextE.size()<<endl; for(vector<CFGEdge>::iterator it=nextE.begin(); it!=nextE.end(); it++) { CFGNode nextN = (fwDir ? it->target() : nextN = it->source()); /*dbg << " nextN="<<CFGNode2Str(nextN)<<endl; dbg << " CFGIterator::advance "<<(fwDir?"descendant":"predecessor")<<": "<< "visited="<<(visited.find(nextN) != visited.end())<< " remaining="<<isRemaining(nextN)<<"\n";*/ // if we haven't yet visited this node and don't yet have it on the remainingNodes list if(visited.find(nextN) == visited.end() && !isRemaining(nextN)) { //printf(" pushing back node <%s: 0x%x: %s> visited=%d\n", nextN.getNode()->class_name().c_str(), nextN.getNode(), nextN.getNode()->unparseToString().c_str(), visited.find(nextN)!=visited.end()); remainingNodes.push_back(nextN); } } // if we still have any nodes left remaining if(remainingNodes.size()>0) { // take the next node from the front of the list and mark it as visited visited.insert(remainingNodes.front()); //cout << " remainingNodes.front()=["<<remainingNodes.front().getNode()->unparseToString()<<" | "<<remainingNodes.front().getNode()->class_name()<<"]"<<endl; } // Since pushAllChildren always = true or = false, we only need to worry about managing visited in the true case } } }
void visitorTraversal::analyzePath(std::vector<VertexID>& pathR) { std::vector<string> path; for (unsigned int j = 0; j < pathR.size(); j++) { SgGraphNode* R = getGraphNode[pathR[j]]; CFGNode cf = cfg->toCFGNode(R); string str = cf.toString();str.erase(std::remove(str.begin(), str.end(), '\n'), str.end()); path.push_back(str); } paths.push_back(path); // ROSE_ASSERT(sssv.find(path) != sssv.end()); }
// the default interesting filter bool defaultFilter (CFGNode cfgn) { SgNode * node = cfgn.getNode(); assert (node != NULL) ; //Keep the last index for initialized names. This way the definition of the variable doesn't //propagate to its assign initializer. if (isSgInitializedName(node)) { return (cfgn == node->cfgForEnd()); } else return (cfgn.isInteresting()); }
bool isDataflowInteresting(CFGNode cn) { ROSE_ASSERT (cn.getNode()); return (cn.getNode()->cfgIsIndexInteresting(cn.getIndex()) && //!isSgFunctionRefExp(cn.getNode()) && !isSgExprListExp(cn.getNode()) && !isSgForInitStatement(cn.getNode()) && //!isSgVarRefExp(cn.getNode()) && //!isSgValueExp(cn.getNode()) && //!isSgExprStatement(cn.getNode()) && !(isSgInitializedName(cn.getNode()) && cn.getIndex()==0)) || (isSgIfStmt(cn.getNode()) && cn.getIndex()==1 || cn.getIndex()==2); }
//! start from a CFG node 'n', collect all other CFG nodes which can be reached from 'n' void getReachableNodes(CFGNode n, set<CFGNode>& s) { if (s.find(n) != s.end()) return; // n is already in s s.insert(n); vector<CFGEdge> oe = n.outEdges(); for (vector<CFGEdge>::const_iterator i = oe.begin(); i != oe.end(); ++i) { getReachableNodes(i->target(), s); } }
void CFG::__printDotGraphForGraphviz() { FILE* f = fopen("../current-cfg.dot","w"); fprintf(f,"digraph graphname {\n"); for(vector<CFGNode*>::iterator it = _CFGBlocks.begin(); it != _CFGBlocks.end();++it) { CFGNode* c = *it; vector<CFGNode*> edges = c->getNextEdges(); string label = ""; //Print the label if(c->getCFGType() != CFG_DUMMY) { for(int i = c->getStartStatement(); i<= c->getEndStatement(); i++) { label += to_string((long long)i); if(i<c->getEndStatement()) label += ","; } fprintf(f,"%d [label=\"%s\"]\n",__indexOf(_CFGBlocks,*it), label.c_str()); } else { fprintf(f,"%d [label=\"Dummy %d\"]\n",__indexOf(_CFGBlocks,*it), c->getProcIndex()); } //Connect edges for(vector<CFGNode*>::iterator n = edges.begin(); n!= edges.end(); ++n) { fprintf(f,"%d -> %d\n", __indexOf(_CFGBlocks,*it), __indexOf(_CFGBlocks,*n)); } } fprintf(f,"}"); fclose(f); }
void visitorTraversal::analyzePath(std::vector<VertexID>& pathR) { std::vector<SgGraphNode*> exprPath; std::vector<string> path; //ss << "vector<string> sss;\n"; for (unsigned int j = 0; j < pathR.size(); j++) { SgGraphNode* R = getGraphNode[pathR[j]]; CFGNode cf = cfg->toCFGNode(R); // path.push_back(R->get_name()); string str = cf.toString(); str.erase(std::remove(str.begin(), str.end(), '\n'), str.end()); //ss << "string str = \"" << str << "\";\n"; ss << "sss.push_back(\"" << str << "\");\n"; } ss << "sssv.insert(sss);\n"; ss << "sss.clear();\n"; // paths.insert(path); }
bool gfilter (CFGNode cfgn) { SgNode *node = cfgn.getNode(); switch (node->variantT()) { //Keep the last index for initialized names. This way the def of the variable doesn't propagate to its assign //initializer. case V_SgInitializedName: return (cfgn == node->cfgForEnd()); #if 0 //For function calls, we only keep the last node. The function is actually called after all its parameters //are evaluated. // case V_SgFunctionCallExp: // return (cfgn == node->cfgForEnd()); // //For basic blocks and other "container" nodes, keep the node that appears before the contents are executed case V_SgBasicBlock: case V_SgExprStatement: case V_SgCommaOpExp: return (cfgn == node->cfgForBeginning()); // // case V_SgTryStmt: // return (cfgn == node->cfgForBeginning()); // // //We only want the middle appearance of the teritatry operator - after its conditional expression // //and before the true and false bodies. This makes it behave as an if statement for data flow // //purposes // case V_SgConditionalExp: // return (cfgn.getIndex() == 1); // // //Make these binary operators appear after their operands, because they are evaluated after their operands // case V_SgAndOp: // case V_SgOrOp: // return (cfgn == node->cfgForEnd()); #endif default: return cfgn.isInteresting(); } }
std::map<SgNode*,std::string> PathCollector::getAssociationsForPath(std::vector<SgGraphNode*> path) { std::map<SgNode*,std::string> conditionValueForPath; for (int i = 0; i < path.size(); i++) { //std::vector<SgGraphNode*> successors; //pathCollector->getGraph()->getSuccessors(path[i],successors); CFGNode node = cfg->toCFGNode(path[i]); std::vector<CFGEdge> edges = node.outEdges(); if (edges.size() > 1) { //std::cout << "associated node: " << path[i]->get_SgNode()->class_name() << std::endl; CFGNode eck_result = cfg->toCFGNode(path[i+1]); CFGEdge conditionEdge; int k = 0; int found = -1; while (k < edges.size()) { if (edges[k].target() == eck_result) { conditionEdge = edges[k]; found = k; break; } k++; } EdgeConditionKind edgeKind = conditionEdge.condition(); if (edgeKind == eckTrue) { conditionValueForPath[path[i]->get_SgNode()] = "true"; } else if (edgeKind == eckFalse) { conditionValueForPath[path[i]->get_SgNode()] = "false"; } else { std::cout << "edge kind not handled! exiting..." << std::endl; ROSE_ASSERT(false); } // std::cout << "edge value: " << conditionValueForPath[path[i]->get_SgNode()] << std::endl; } } return conditionValueForPath; }
void CFG::buildCFG(CFGNode n) { ROSE_ASSERT(n.getNode()); if (explored_.count(n) > 0) return; explored_.insert(n); SgGraphNode* from = NULL; if (all_nodes_.count(n) > 0) { from = all_nodes_[n]; } else { from = new SgGraphNode; from->set_SgNode(n.getNode()); from->addNewAttribute("info", new CFGNodeAttribute(n.getIndex(), graph_)); all_nodes_[n] = from; graph_->addNode(from); } std::vector<VirtualCFG::CFGEdge> outEdges = n.outEdges(); foreach (const VirtualCFG::CFGEdge& edge, outEdges) { CFGNode tar = edge.target(); SgGraphNode* to = NULL; if (all_nodes_.count(tar) > 0) to = all_nodes_[tar]; else { to = new SgGraphNode; to->set_SgNode(tar.getNode()); to->addNewAttribute("info", new CFGNodeAttribute(tar.getIndex(), graph_)); all_nodes_[tar] = to; graph_->addNode(to); } graph_->addDirectedEdge(new SgDirectedGraphEdge(from, to)); }
// the default interesting filter bool defaultFilter (CFGNode cfgn) { SgNode * node = cfgn.getNode(); assert (node != NULL) ; //Keep the last index for initialized names. This way the definition of the variable doesn't //propagate to its assign initializer. // if (isSgInitializedName(node)) // { // return (cfgn == node->cfgForEnd()); // } // else // return (cfgn.isInteresting()); switch(node->variantT()) { //Keep the last index for initialized names. This way the definition of the variable doesn't //propagate to its assign initializer. case V_SgInitializedName: return (cfgn == node->cfgForEnd()); // filter out this node type // abstract memory object cannot be created for these nodes case V_SgExprListExp: case V_SgNullStatement: case V_SgExprStatement: case V_SgFunctionRefExp: return false; case V_SgFunctionCallExp: return cfgn.getIndex()==2 || cfgn.getIndex()==3; case V_SgFunctionParameterList: return true; //return cfgn.getIndex()==1;*/ case V_SgFunctionDefinition: return cfgn.getIndex()==3; case V_SgReturnStmt: return cfgn.getIndex()==1; // Filter out intermediate dot expressions. We only care about the complete ones. case V_SgDotExp: //cout << "defaultFilter() node="<<cfgUtils::SgNode2Str(node)<<" node->get_parent()="<<cfgUtils::SgNode2Str(node->get_parent())<<" interesting="<<(!isSgDotExp(node->get_parent()))<<endl; return !isSgDotExp(node->get_parent()); /*case V_SgCastExp: return false;*/ default: return cfgn.isInteresting(); } }
void ProgramCFG::createSucc(BasicBlock *v){ (*colors)[v] = GRAY; std::vector<CFGNode*> currentNodes ; //currentNodes is a node list in which nodes are waiting for find succ. currentNodes.push_back(&((*nodes)[v]));//first currentNodes is v //errs()<<dfscount++<<" dfs: "<<(*nodes)[v].name<<"\n"; for(BasicBlock::iterator inst = v->begin(); inst != v->end(); inst ++){ //errs() << *inst<<"\n"; if(CallInst* call = dyn_cast<CallInst>(inst)){ if(isa<UnreachableInst>(++inst)){//exit ,abort ,xalloc_die, program exit. // errs()<< *(--inst)<<"\n"; goto finish; } --inst; Function *f = call->getCalledFunction(); //If there is a call asm instruction or function pointer call, // the return value of getCalledFunction will be null. //So we just ignore it. if(!f){ // errs() << "Find a CallInst: "<< *inst <<"\n" << "But can't find which function it calls.\n"; continue; } if(f->isDeclaration()) { // errs()<<"isDeclaration " << f->getName() << "\n"; continue; }else{ // errs() << "hasDefinition " << f->getName() << "\n"; } //only concerns the function in the targetFunctionList // if(targetFunctionList->find(f) == targetFunctionList->end()) continue; // errs() << "find a call : "<< f->getName() << "\n "; BasicBlock *entry = &f->getEntryBlock(); CFGNode *entryNode = &((*nodes)[entry]);//f's EntryBlock while(!currentNodes.empty()){ //link succ and prev to each other currentNodes.back()->addSucc(entryNode); entryNode->addPrev(currentNodes.back()); currentNodes.pop_back(); } if((*colors)[entry] == WHITE){//dfs createSucc(entry); } for(std::vector<BasicBlock*>::iterator ret= (*retBlocks)[f].begin(); ret != (*retBlocks)[f].end(); ret++){ currentNodes.push_back(&((*nodes)[*ret])); } } } //assert(currentNodes.size()==1); while(!currentNodes.empty()){ CFGNode* current = currentNodes.back(); currentNodes.pop_back(); for(succ_iterator succ = succ_begin(v),end = succ_end(v); succ != end; succ++){ CFGNode *succNode = &((*nodes)[*succ]); current->addSucc(succNode); succNode->addPrev(current); if((*colors)[*succ] == WHITE){ createSucc(*succ); } } } finish: //errs()<<"dfs back\n"; (*colors)[v] = BLACK; }
//! Constructor CFGEdge(CFGNode src, CFGNode tgt): src(src), tgt(tgt) { assert(src.getNode() != NULL && tgt.getNode() != NULL); }