diff --git a/svf/include/AbstractExecution/WTO.h b/svf/include/AbstractExecution/WTO.h index 9f391425f..baf6e96ee 100644 --- a/svf/include/AbstractExecution/WTO.h +++ b/svf/include/AbstractExecution/WTO.h @@ -492,11 +492,12 @@ class CFBasicBlockGWTO NodeRefToCycleDepthNumber _nodeToCDN; CycleDepthNumber _num; CFBasicBlockNodes _stack; + CFBasicBlockGraph* _graph; public: explicit CFBasicBlockGWTO() : _num(0) {} - explicit CFBasicBlockGWTO(const CFBasicBlockNode *entry) : _num(0) + explicit CFBasicBlockGWTO(CFBasicBlockGraph* graph, const CFBasicBlockNode *entry) : _num(0), _graph(graph) { build(entry); } @@ -652,12 +653,13 @@ class CFBasicBlockGWTO const CFBasicBlockGWTOCycleDepth &_headWTOCycleDepth; const CFBasicBlockNode *_head; NodeRefToWTOCycleDepthPtr &_nodeToWTOCycleDepth; + CFBasicBlockGraph* _graph; public: - explicit TailBuilder(NodeRefToWTOCycleDepthPtr &nodeToWTOCycleDepth, NodeRefSet &tails, const CFBasicBlockNode *head, + explicit TailBuilder(CFBasicBlockGraph* graph, NodeRefToWTOCycleDepthPtr &nodeToWTOCycleDepth, NodeRefSet &tails, const CFBasicBlockNode *head, const CFBasicBlockGWTOCycleDepth &headWTOCycleDepth) : _tails(tails), _headWTOCycleDepth(headWTOCycleDepth), _head(head), _nodeToWTOCycleDepth( - nodeToWTOCycleDepth) + nodeToWTOCycleDepth), _graph(graph) { } @@ -671,14 +673,23 @@ class CFBasicBlockGWTO virtual void visit(const CFBasicBlockGWTONode &node) override { - for (const auto &edge: node.node()->getOutEdges()) - { - const CFBasicBlockNode *succ = edge->getDstNode(); + if(const CallICFGNode* callNode = SVFUtil::dyn_cast(node.node()->getICFGNodes().front())) { + const CFBasicBlockNode *succ = _graph->getCFBasicBlockNode(callNode->getRetICFGNode()->getId()); const CFBasicBlockGWTOCycleDepth &succNesting = getWTOCycleDepth(succ); if (succ != _head && succNesting <= _headWTOCycleDepth) { _tails.insert(node.node()); } + } else { + for (const auto &edge: node.node()->getOutEdges()) + { + const CFBasicBlockNode *succ = edge->getDstNode(); + const CFBasicBlockGWTOCycleDepth &succNesting = getWTOCycleDepth(succ); + if (succ != _head && succNesting <= _headWTOCycleDepth) + { + _tails.insert(node.node()); + } + } } } @@ -751,13 +762,21 @@ class CFBasicBlockGWTO const CFBasicBlockGWTOCycle *component(const CFBasicBlockNode *node) { WTOCompRefList partition; - for (auto it = node->getOutEdges().begin(), et = node->getOutEdges().end(); it != et; ++it) - { - const CFBasicBlockNode *succ = (*it)->getDstNode(); + if (const CallICFGNode* callNode = SVFUtil::dyn_cast(node->getICFGNodes().front())) { + const CFBasicBlockNode *succ = _graph->getCFBasicBlockNode(callNode->getRetICFGNode()->getId()); if (getCDN(succ) == 0) { visit(succ, partition); } + } else { + for (auto it = node->getOutEdges().begin(), et = node->getOutEdges().end(); it != et; ++it) + { + const CFBasicBlockNode *succ = (*it)->getDstNode(); + if (getCDN(succ) == 0) + { + visit(succ, partition); + } + } } const CFBasicBlockGWTOCycle *ptr = newCycle(node, partition); _headToCycle.emplace(node, ptr); @@ -776,9 +795,8 @@ class CFBasicBlockGWTO head = _num; setCDN(node, head); loop = false; - for (auto it = node->getOutEdges().begin(), et = node->getOutEdges().end(); it != et; ++it) - { - const CFBasicBlockNode *succ = (*it)->getDstNode(); + if (const CallICFGNode* callNode = SVFUtil::dyn_cast(node->getICFGNodes().front())) { + const CFBasicBlockNode *succ = _graph->getCFBasicBlockNode(callNode->getRetICFGNode()->getId()); CycleDepthNumber succ_dfn = getCDN(succ); if (succ_dfn == CycleDepthNumber(0)) { @@ -793,6 +811,25 @@ class CFBasicBlockGWTO head = min; loop = true; } + } else { + for (auto it = node->getOutEdges().begin(), et = node->getOutEdges().end(); it != et; ++it) + { + const CFBasicBlockNode *succ = (*it)->getDstNode(); + CycleDepthNumber succ_dfn = getCDN(succ); + if (succ_dfn == CycleDepthNumber(0)) + { + min = visit(succ, partition); + } + else + { + min = succ_dfn; + } + if (min <= head) + { + head = min; + loop = true; + } + } } if (head == getCDN(node)) { @@ -831,7 +868,7 @@ class CFBasicBlockGWTO for (const auto &head: _headToCycle) { NodeRefSet tails; - TailBuilder builder(_nodeToDepth, tails, head.first, getWTOCycleDepth(head.first)); + TailBuilder builder(_graph, _nodeToDepth, tails, head.first, getWTOCycleDepth(head.first)); for (auto it = head.second->begin(), eit = head.second->end(); it != eit; ++it) { (*it)->accept(&builder); diff --git a/svf/include/Graphs/CFBasicBlockG.h b/svf/include/Graphs/CFBasicBlockG.h index 5e92f2323..f198d7072 100644 --- a/svf/include/Graphs/CFBasicBlockG.h +++ b/svf/include/Graphs/CFBasicBlockG.h @@ -127,8 +127,6 @@ class CFBasicBlockNode : public GenericCFBasicBlockNodeTy { } - CFBasicBlockNode(const SVFBasicBlock* bb); - friend std::ostream &operator<<(std::ostream &o, const CFBasicBlockNode &node) { o << node.toString(); @@ -143,10 +141,9 @@ class CFBasicBlockNode : public GenericCFBasicBlockNodeTy return (*_icfgNodes.begin())->getBB()->getName(); } - inline const SVFBasicBlock *getSVFBasicBlock() const + inline const std::vector& getICFGNodes() const { - assert(!_icfgNodes.empty() && "no ICFG nodes in CFBB"); - return (*_icfgNodes.begin())->getBB(); + return _icfgNodes; } inline const SVFFunction *getFunction() const @@ -355,7 +352,6 @@ class CFBasicBlockGraph : public GenericCFBasicBlockGTy private: u32_t _totalCFBasicBlockNode{0}; u32_t _totalCFBasicBlockEdge{0}; - Map _funToFirstNode; public: CFBasicBlockGraph() = default; @@ -379,27 +375,6 @@ class CFBasicBlockGraph : public GenericCFBasicBlockGTy return hasGNode(id); } - inline CFBasicBlockNode* getFirstCFBasicBlockNode(const SVFFunction* fun) const - { - if (fun && _funToFirstNode.find(fun) != _funToFirstNode.end()) - { - return _funToFirstNode.at(fun); - } - else - { - return nullptr; - } - } - inline bool hasFirstCFBasicBlockNode(const SVFFunction* fun) const - { - return fun && _funToFirstNode.find(fun) != _funToFirstNode.end(); - } - - inline void setFirstCFBasicBlockNode(const Map& svfNodeMap) - { - _funToFirstNode = svfNodeMap; - } - bool hasCFBasicBlockEdge(CFBasicBlockNode *src, CFBasicBlockNode *dst, ICFGEdge *icfgEdge) { @@ -490,24 +465,6 @@ class CFBasicBlockGraph : public GenericCFBasicBlockGTy } }; -class CFBasicBlockGBuilder -{ - -private: - CFBasicBlockGraph* _CFBasicBlockG; - -public: - CFBasicBlockGBuilder() : _CFBasicBlockG() {} - - virtual void build(SVFModule* module); - - virtual void build(ICFG* icfg); - - inline CFBasicBlockGraph* getCFBasicBlockGraph() - { - return _CFBasicBlockG; - } -}; } @@ -537,6 +494,9 @@ struct GenericGraphTraits typedef SVF::CFBasicBlockNode *NodeRef; }; +} // End namespace SVF + +namespace SVF { template<> struct DOTGraphTraits : public DOTGraphTraits { @@ -544,7 +504,7 @@ struct DOTGraphTraits : public DOTGraphTraits(isSimple) + DOTGraphTraits(isSimple) { } @@ -574,22 +534,70 @@ struct DOTGraphTraits : public DOTGraphTraitsgetICFGNodes().size() == 1) { + const ICFGNode* n = node->getICFGNodes()[0]; + if(SVFUtil::isa(n)) + { + rawstr << "color=black"; + } + else if(SVFUtil::isa(n)) + { + rawstr << "color=yellow"; + } + else if(SVFUtil::isa(n)) + { + rawstr << "color=green"; + } + else if(SVFUtil::isa(n)) + { + rawstr << "color=red"; + } + else if(SVFUtil::isa(n)) + { + rawstr << "color=blue"; + } + else if(SVFUtil::isa(n)) + { + rawstr << "color=purple"; + } + else + assert(false && "no such kind of node!!"); + } else { + rawstr << "color=black"; + } + rawstr << ""; return rawstr.str(); } template static std::string getEdgeAttributes(NodeType *, EdgeIter EI, SVF::CFBasicBlockGraph *) { - return "style=solid"; + CFBasicBlockEdge* edge = *(EI.getCurrent()); + assert(edge && "No edge found!!"); + if (SVFUtil::isa(edge->getICFGEdge())) + return "style=solid,color=red"; + else if (SVFUtil::isa(edge->getICFGEdge())) + return "style=solid,color=blue"; + else + return "style=solid"; + return ""; } template static std::string getEdgeSourceLabel(NodeType *, EdgeIter EI) { - return ""; + CFBasicBlockEdge* edge = *(EI.getCurrent()); + assert(edge && "No edge found!!"); + + std::string str; + std::stringstream rawstr(str); + if (const CallCFGEdge* dirCall = SVFUtil::dyn_cast(edge->getICFGEdge())) + rawstr << dirCall->getCallSite(); + else if (const RetCFGEdge* dirRet = SVFUtil::dyn_cast(edge->getICFGEdge())) + rawstr << dirRet->getCallSite(); + + return rawstr.str(); } }; - -} // End namespace SVF +} #endif //SVF_CFBASICBLOCKG_H \ No newline at end of file diff --git a/svf/include/Util/CFBasicBlockGBuilder.h b/svf/include/Util/CFBasicBlockGBuilder.h new file mode 100644 index 000000000..c6235dffc --- /dev/null +++ b/svf/include/Util/CFBasicBlockGBuilder.h @@ -0,0 +1,58 @@ +//===- CFBasicBlockGBuilder.h ----------------------------------------------------------------// +// +// SVF: Static Value-Flow Analysis +// +// Copyright (C) <2013-> +// + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. + +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// +//===----------------------------------------------------------------------===// + +/* + * CFBasicBlockGBuilder.h + * + * Created on: 17 Oct. 2023 + * Author: Xiao, Jiawei + */ + +#include "Graphs/CFBasicBlockG.h" + +namespace SVF { + +class CFBasicBlockGBuilder +{ + +private: + CFBasicBlockGraph* _CFBasicBlockG; + +public: + CFBasicBlockGBuilder() : _CFBasicBlockG() {} + + virtual void build(ICFG* icfg); + + inline CFBasicBlockGraph* getCFBasicBlockGraph() + { + return _CFBasicBlockG; + } +private: + void initCFBasicBlockGNodes(ICFG *icfg, Map> &bbToNodes); + + void addInterBBEdge(ICFG *icfg, Map> &bbToNodes); + + void addIntraBBEdge(ICFG *icfg, Map> &bbToNodes); + + void addInterProceduralEdge(ICFG *icfg, Map> &bbToNodes); +}; +} \ No newline at end of file diff --git a/svf/lib/Graphs/CFBasicBlockG.cpp b/svf/lib/Graphs/CFBasicBlockG.cpp index 23fb39d9c..548e78d0a 100644 --- a/svf/lib/Graphs/CFBasicBlockG.cpp +++ b/svf/lib/Graphs/CFBasicBlockG.cpp @@ -32,21 +32,6 @@ namespace SVF { -CFBasicBlockNode::CFBasicBlockNode(const SVFBasicBlock* svfBasicBlock) - : GenericCFBasicBlockNodeTy( - PAG::getPAG() - ->getICFG() - ->getICFGNode(*svfBasicBlock->getInstructionList().begin()) - ->getId(), - 0) -{ - for (auto it = svfBasicBlock->begin(); it != svfBasicBlock->end(); ++it) - { - const SVFInstruction* ins = *it; - ICFGNode* icfgNode = PAG::getPAG()->getICFG()->getICFGNode(ins); - _icfgNodes.push_back(icfgNode); - } -} const std::string CFBasicBlockNode::toString() const { @@ -91,101 +76,5 @@ std::vector CFBasicBlockGraph::getCFBasicBlockEdge(const CFBa return SVFUtil::move(edges); } -void CFBasicBlockGBuilder::build(SVFModule* module) -{ - _CFBasicBlockG = new CFBasicBlockGraph(); - Map bbToNode; - for (const auto& func : *module) - { - for (const auto& bb : *func) - { - CFBasicBlockNode* pNode = new CFBasicBlockNode(bb); - bbToNode[bb] = pNode; - _CFBasicBlockG->addCFBBNode(pNode); - } - } - - for (const auto& func : *module) - { - for (const auto& bb : *func) - { - for (const auto &succ: bb->getSuccessors()) - { - ICFG *icfg = PAG::getPAG()->getICFG(); - const ICFGNode *pred = icfg->getICFGNode(bb->getTerminator()); - const ICFGEdge *edge = nullptr; - for (const auto &inst: succ->getInstructionList()) - { - if (const ICFGEdge *e = icfg->getICFGEdge(pred, icfg->getICFGNode(inst), ICFGEdge::ICFGEdgeK::IntraCF)) - { - edge = e; - break; - } - } - if (SVFUtil::isa(edge)) - { - CFBasicBlockEdge *pEdge = new CFBasicBlockEdge(bbToNode[bb], bbToNode[succ], edge); - _CFBasicBlockG->addCFBBEdge(pEdge); - } - } - } - } } -void CFBasicBlockGBuilder::build(ICFG* icfg) -{ - _CFBasicBlockG = new CFBasicBlockGraph(); - Map bbToNode; - Map funToFirstNode; - for (const auto& node : *icfg) - { - CFBasicBlockNode* pNode = nullptr; - if (const SVFBasicBlock* bb = node.second->getBB()) - { - if (bbToNode.find(bb) == bbToNode.end()) - { - pNode = new CFBasicBlockNode({node.second}); - bbToNode[node.second->getBB()] = pNode; - _CFBasicBlockG->addCFBBNode(pNode); - } - else - { - pNode = bbToNode[node.second->getBB()]; - pNode->addNode(node.second); - } - const SVFFunction* fun = node.second->getFun(); - if (funToFirstNode.find(fun) == funToFirstNode.end()) - { - funToFirstNode[fun] = nullptr; - } - } - } - - for (const auto& node : *icfg) - { - for (const auto &succ: node.second->getOutEdges()) - { - const SVFFunction* node_fun = node.second->getFun(); - const SVFFunction* succ_fun = succ->getDstNode()->getFun(); - const SVFBasicBlock* node_bb = node.second->getBB(); - const SVFBasicBlock* succ_bb = succ->getDstNode()->getBB(); - if (node_fun == succ_fun) - { - if (node_bb != succ_bb) - { - CFBasicBlockEdge *pEdge = new CFBasicBlockEdge(bbToNode[node_bb], bbToNode[succ_bb], succ); - _CFBasicBlockG->addCFBBEdge(pEdge); - } - } - } - } - - for (auto it = funToFirstNode.begin(); it != funToFirstNode.end(); ++it) - { - const SVFFunction* fun = it->first; - const SVFBasicBlock* bb = *fun->getBasicBlockList().begin(); - funToFirstNode[fun] = bbToNode[bb]; - } - _CFBasicBlockG->_funToFirstNode = funToFirstNode; -} -} \ No newline at end of file diff --git a/svf/lib/Util/CFBasicBlockGBuilder.cpp b/svf/lib/Util/CFBasicBlockGBuilder.cpp new file mode 100644 index 000000000..4c0c2ab2c --- /dev/null +++ b/svf/lib/Util/CFBasicBlockGBuilder.cpp @@ -0,0 +1,147 @@ +//===- CFBasicBlockGBuilder.cpp ----------------------------------------------------------------// +// +// SVF: Static Value-Flow Analysis +// +// Copyright (C) <2013-> +// + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. + +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// +//===----------------------------------------------------------------------===// + +/* + * CFBasicBlockGBuilder.cpp + * + * Created on: 17 Oct. 2023 + * Author: Xiao, Jiawei + */ +#include "Util/CFBasicBlockGBuilder.h" + +namespace SVF{ + +void CFBasicBlockGBuilder::initCFBasicBlockGNodes(ICFG *icfg, + Map> &bbToNodes) { + for (const auto &node: *icfg) { + CFBasicBlockNode *pNode; + if (const SVFBasicBlock *bb = node.second->getBB()) { + if (const CallICFGNode *callNode = SVFUtil::dyn_cast(node.second)) { + pNode = new CFBasicBlockNode({callNode}); + bbToNodes[bb].push_back(pNode); + _CFBasicBlockG->addCFBBNode(pNode); + + auto *retNode = new CFBasicBlockNode({callNode->getRetICFGNode()}); + bbToNodes[bb].push_back(retNode); + _CFBasicBlockG->addCFBBNode(retNode); + + } else if (!SVFUtil::isa(node.second)) { + if (bbToNodes.find(bb) == bbToNodes.end()) { + pNode = new CFBasicBlockNode({node.second}); + bbToNodes[node.second->getBB()] = {pNode}; + _CFBasicBlockG->addCFBBNode(pNode); + } else { + pNode = bbToNodes[node.second->getBB()].back(); + if (!SVFUtil::isa(pNode->getICFGNodes()[0])) { + pNode->addNode(node.second); + } else { + pNode = new CFBasicBlockNode({node.second}); + bbToNodes[node.second->getBB()].push_back(pNode); + _CFBasicBlockG->addCFBBNode(pNode); + } + } + } + } + } +} + +void CFBasicBlockGBuilder::addInterBBEdge(ICFG *icfg, + Map> &bbToNodes) { + // connect inter-BB BBNodes + for (const auto &node: *icfg) { + for (const auto &succ: node.second->getOutEdges()) { + const SVFFunction *node_fun = node.second->getFun(); + const SVFFunction *succ_fun = succ->getDstNode()->getFun(); + const SVFBasicBlock *node_bb = node.second->getBB(); + const SVFBasicBlock *succ_bb = succ->getDstNode()->getBB(); + if (node_fun == succ_fun) { + if (node_bb != succ_bb) { + CFBasicBlockEdge *pEdge = new CFBasicBlockEdge(bbToNodes[node_bb].back(), + bbToNodes[succ_bb].front(), succ); + _CFBasicBlockG->addCFBBEdge(pEdge); + } + } + } + } +} + +void CFBasicBlockGBuilder::addIntraBBEdge(ICFG *icfg, + Map> &bbToNodes) { + // connect intra-BB BBNodes + for (const auto &bbNodes: bbToNodes) { + for (u32_t i = 0; i < bbNodes.second.size() - 1; ++i) { + if (ICFGEdge *icfgEdge = icfg->getICFGEdge( + const_cast(bbNodes.second[i]->getICFGNodes().back()), + const_cast(bbNodes.second[i + 1]->getICFGNodes().front()), + ICFGEdge::IntraCF)) { + CFBasicBlockEdge *pEdge = new CFBasicBlockEdge(bbNodes.second[i], bbNodes.second[i + 1], icfgEdge); + _CFBasicBlockG->addCFBBEdge(pEdge); + } else { + // no intra-procedural edge, maybe ext api + } + } + } +} + +void CFBasicBlockGBuilder::addInterProceduralEdge(ICFG *icfg, + Map> &bbToNodes) { + // connect inter-procedural BBNodes + for (const auto &bbNodes: bbToNodes) { + for (u32_t i = 0; i < bbNodes.second.size(); ++i) { + if (const CallICFGNode *callICFGNode = SVFUtil::dyn_cast( + bbNodes.second[i]->getICFGNodes().front())) { + for (const auto &icfgEdge: callICFGNode->getOutEdges()) { + if (const CallCFGEdge *callEdge = SVFUtil::dyn_cast(icfgEdge)) { + CFBasicBlockEdge *pEdge = new CFBasicBlockEdge(bbNodes.second[i], + bbToNodes[callEdge->getDstNode()->getBB()].front(), + callEdge); + _CFBasicBlockG->addCFBBEdge(pEdge); + } + } + } else if (const RetICFGNode *retICFGNode = SVFUtil::dyn_cast( + bbNodes.second[i]->getICFGNodes().front())) { + for (const auto &icfgEdge: retICFGNode->getInEdges()) { + if (const RetCFGEdge *retEdge = SVFUtil::dyn_cast(icfgEdge)) { + CFBasicBlockEdge *pEdge = new CFBasicBlockEdge(bbToNodes[retEdge->getSrcNode()->getBB()].back(), + bbNodes.second[i], + retEdge); + _CFBasicBlockG->addCFBBEdge(pEdge); + } + } + } else { + // other nodes are intra-procedural + } + } + } +} + +void CFBasicBlockGBuilder::build(ICFG* icfg) +{ + _CFBasicBlockG = new CFBasicBlockGraph(); + Map> bbToNodes; + + initCFBasicBlockGNodes(icfg, bbToNodes); + addInterBBEdge(icfg, bbToNodes); + addIntraBBEdge(icfg, bbToNodes); + addInterProceduralEdge(icfg, bbToNodes); +} +} \ No newline at end of file