diff --git a/svf/include/Graphs/CFBasicBlockG.h b/svf/include/Graphs/CFBasicBlockG.h index 3d30da8ff..969477135 100644 --- a/svf/include/Graphs/CFBasicBlockG.h +++ b/svf/include/Graphs/CFBasicBlockG.h @@ -30,7 +30,7 @@ #ifndef SVF_CFBASICBLOCKG_H #define SVF_CFBASICBLOCKG_H #include "Util/SVFUtil.h" -#include "Graphs/ICFGNode.h" +#include "Graphs/ICFG.h" #include "Graphs/GenericGraph.h" namespace SVF @@ -43,8 +43,33 @@ typedef GenericEdge GenericCFBasicBlockEdgeTy; class CFBasicBlockEdge : public GenericCFBasicBlockEdgeTy { public: - CFBasicBlockEdge(CFBasicBlockNode *src, CFBasicBlockNode *dst) : GenericCFBasicBlockEdgeTy(src, dst, 0) {} + typedef struct equalCFBBEdge + { + bool + operator()(const CFBasicBlockEdge *lhs, const CFBasicBlockEdge *rhs) const + { + if (lhs->getSrcID() != rhs->getSrcID()) + return lhs->getSrcID() < rhs->getSrcID(); + else if (lhs->getDstID() != rhs->getDstID()) + return lhs->getDstID() < rhs->getDstID(); + else + return lhs->getICFGEdge() < rhs->getICFGEdge(); + } + } equalICFGEdgeWrapper; + + typedef OrderedSet CFBBEdgeSetTy; + typedef CFBBEdgeSetTy::iterator iterator; + typedef CFBBEdgeSetTy::const_iterator const_iterator; + +private: + const ICFGEdge *_icfgEdge; +public: + CFBasicBlockEdge(CFBasicBlockNode* src, CFBasicBlockNode* dst, + const ICFGEdge* edge) + : GenericCFBasicBlockEdgeTy(src, dst, 0), _icfgEdge(edge) + { + } friend std::ostream &operator<<(std::ostream &o, const CFBasicBlockEdge &edge) { @@ -54,20 +79,50 @@ class CFBasicBlockEdge : public GenericCFBasicBlockEdgeTy virtual const std::string toString() const { - return std::to_string(getSrcID()) + " --> " + std::to_string(getDstID()); + return _icfgEdge->toString(); + } + + inline const ICFGEdge *getICFGEdge() const + { + return _icfgEdge; + } + + using SVF::GenericEdge::operator==; + /// Add the hash function for std::set (we also can overload operator< to implement this) + // and duplicated elements in the set are not inserted (binary tree comparison) + //@{ + + virtual inline bool operator==(const CFBasicBlockEdge *rhs) const + { + return (rhs->getSrcID() == this->getSrcID() && rhs->getDstID() == this->getDstID() && + rhs->getICFGEdge() == this->getICFGEdge()); } + //@} + }; typedef GenericNode GenericCFBasicBlockNodeTy; class CFBasicBlockNode : public GenericCFBasicBlockNodeTy { +public: + typedef CFBasicBlockEdge::CFBBEdgeSetTy CFBBEdgeSetTy; + typedef CFBasicBlockEdge::CFBBEdgeSetTy ::iterator iterator; + typedef CFBasicBlockEdge::CFBBEdgeSetTy::const_iterator const_iterator; + private: - const SVFBasicBlock *_svfBasicBlock; /// Every CFBasicBlockNode holds a SVFBasicBlock std::vector _icfgNodes; /// Every CBFGNode holds a vector of ICFGNodes + CFBBEdgeSetTy InEdges; ///< all incoming edge of this node + CFBBEdgeSetTy OutEdges; ///< all outgoing edge of this node public: - CFBasicBlockNode(u32_t id, const SVFBasicBlock *svfBasicBlock); + CFBasicBlockNode(std::vector icfgNodes) + : GenericCFBasicBlockNodeTy((*icfgNodes.begin())->getId(), 0), + _icfgNodes(SVFUtil::move(icfgNodes)) + { + } + + CFBasicBlockNode(const SVFBasicBlock* bb); friend std::ostream &operator<<(std::ostream &o, const CFBasicBlockNode &node) { @@ -79,17 +134,20 @@ class CFBasicBlockNode : public GenericCFBasicBlockNodeTy inline std::string getName() const { - return _svfBasicBlock->getName(); + assert(!_icfgNodes.empty() && "no ICFG nodes in CFBB"); + return (*_icfgNodes.begin())->getBB()->getName(); } inline const SVFBasicBlock *getSVFBasicBlock() const { - return _svfBasicBlock; + assert(!_icfgNodes.empty() && "no ICFG nodes in CFBB"); + return (*_icfgNodes.begin())->getBB(); } inline const SVFFunction *getFunction() const { - return _svfBasicBlock->getFunction(); + assert(!_icfgNodes.empty() && "no ICFG nodes in CFBB"); + return (*_icfgNodes.begin())->getFun(); } inline std::vector::const_iterator begin() const @@ -101,6 +159,186 @@ class CFBasicBlockNode : public GenericCFBasicBlockNodeTy { return _icfgNodes.cend(); } + + inline void removeNode(const ICFGNode* node) + { + const auto it = std::find(_icfgNodes.begin(), _icfgNodes.end(), node); + assert(it != _icfgNodes.end() && "icfg node not in BB?"); + _icfgNodes.erase(it); + } + + inline void addNode(const ICFGNode* node) + { + _icfgNodes.push_back(node); + } + + inline u32_t getICFGNodeNum() const { + return _icfgNodes.size(); + } + +public: + /// Get incoming/outgoing edge set + ///@{ + inline const CFBBEdgeSetTy &getOutEdges() const + { + return OutEdges; + } + + inline const CFBBEdgeSetTy &getInEdges() const + { + return InEdges; + } + ///@} + + /// Has incoming/outgoing edge set + //@{ + inline bool hasIncomingEdge() const + { + return (InEdges.empty() == false); + } + + inline bool hasOutgoingEdge() const + { + return (OutEdges.empty() == false); + } + //@} + + /// iterators + //@{ + inline iterator OutEdgeBegin() + { + return OutEdges.begin(); + } + + inline iterator OutEdgeEnd() + { + return OutEdges.end(); + } + + inline iterator InEdgeBegin() + { + return InEdges.begin(); + } + + inline iterator InEdgeEnd() + { + return InEdges.end(); + } + + inline const_iterator OutEdgeBegin() const + { + return OutEdges.begin(); + } + + inline const_iterator OutEdgeEnd() const + { + return OutEdges.end(); + } + + inline const_iterator InEdgeBegin() const + { + return InEdges.begin(); + } + + inline const_iterator InEdgeEnd() const + { + return InEdges.end(); + } + //@} + + /// Iterators used for SCC detection, overwrite it in child class if necessory + //@{ + virtual inline iterator directOutEdgeBegin() + { + return OutEdges.begin(); + } + + virtual inline iterator directOutEdgeEnd() + { + return OutEdges.end(); + } + + virtual inline iterator directInEdgeBegin() + { + return InEdges.begin(); + } + + virtual inline iterator directInEdgeEnd() + { + return InEdges.end(); + } + + virtual inline const_iterator directOutEdgeBegin() const + { + return OutEdges.begin(); + } + + virtual inline const_iterator directOutEdgeEnd() const + { + return OutEdges.end(); + } + + virtual inline const_iterator directInEdgeBegin() const + { + return InEdges.begin(); + } + + virtual inline const_iterator directInEdgeEnd() const + { + return InEdges.end(); + } + //@} + + /// Add incoming and outgoing edges + //@{ + inline bool addIncomingEdge(CFBasicBlockEdge *inEdge) + { + return InEdges.insert(inEdge).second; + } + + inline bool addOutgoingEdge(CFBasicBlockEdge *outEdge) + { + return OutEdges.insert(outEdge).second; + } + //@} + + /// Remove incoming and outgoing edges + ///@{ + inline u32_t removeIncomingEdge(CFBasicBlockEdge *edge) + { + iterator it = InEdges.find(edge); + assert(it != InEdges.end() && "can not find in edge in SVFG node"); + return InEdges.erase(edge); + } + + inline u32_t removeOutgoingEdge(CFBasicBlockEdge *edge) + { + iterator it = OutEdges.find(edge); + assert(it != OutEdges.end() && "can not find out edge in SVFG node"); + return OutEdges.erase(edge); + } + ///@} + + /// Find incoming and outgoing edges + //@{ + inline CFBasicBlockEdge *hasIncomingEdge(CFBasicBlockEdge *edge) const + { + const_iterator it = InEdges.find(edge); + if (it != InEdges.end()) + return *it; + else + return nullptr; + } + + inline CFBasicBlockEdge *hasOutgoingEdge(CFBasicBlockEdge *edge) const + { + const_iterator it = OutEdges.find(edge); + if (it != OutEdges.end()) + return *it; + else + return nullptr; + } + //@} }; typedef GenericGraph GenericCFBasicBlockGTy; @@ -108,22 +346,14 @@ typedef GenericGraph GenericCFBasicBlockGTy; class CFBasicBlockGraph : public GenericCFBasicBlockGTy { friend class CFBasicBlockGBuilder; - -public: - typedef Map SVFBasicBlockToCFBasicBlockNodeMap; - private: - SVFBasicBlockToCFBasicBlockNodeMap _bbToNode; - const SVFFunction *_svfFunction; u32_t _totalCFBasicBlockNode{0}; u32_t _totalCFBasicBlockEdge{0}; + Map _bbToNode; public: - CFBasicBlockGraph(const SVFFunction *svfFunction) : _svfFunction(svfFunction) - { - - } + CFBasicBlockGraph() = default; ~CFBasicBlockGraph() override = default; @@ -139,16 +369,27 @@ class CFBasicBlockGraph : public GenericCFBasicBlockGTy return getGNode(id); } - inline CFBasicBlockNode *getCFBasicBlockNode(const SVFBasicBlock *bb) const + inline bool hasCFBasicBlockNode(NodeID id) const { - auto it = _bbToNode.find(bb); - if (it == _bbToNode.end()) return nullptr; - return it->second; + return hasGNode(id); } - inline bool hasCFBasicBlockEdge(CFBasicBlockNode *src, CFBasicBlockNode *dst) const + inline CFBasicBlockNode* getCFBasicBlockNode(const SVFBasicBlock* bb) const { + if (bb && _bbToNode.find(bb) != _bbToNode.end()) { + return _bbToNode.at(bb); + } else { + return nullptr; + } + } + + inline bool hasCFBasicBlockNode(const SVFBasicBlock* bb) const { - CFBasicBlockEdge edge(src, dst); + return bb && _bbToNode.find(bb) != _bbToNode.end(); + } + + bool hasCFBasicBlockEdge(CFBasicBlockNode *src, CFBasicBlockNode *dst, ICFGEdge *icfgEdge) + { + CFBasicBlockEdge edge(src, dst, icfgEdge); CFBasicBlockEdge *outEdge = src->hasOutgoingEdge(&edge); CFBasicBlockEdge *inEdge = dst->hasIncomingEdge(&edge); if (outEdge && inEdge) @@ -160,17 +401,79 @@ class CFBasicBlockGraph : public GenericCFBasicBlockGTy return false; } - CFBasicBlockEdge* getCFBasicBlockEdge(const CFBasicBlockNode *src, const CFBasicBlockNode *dst); + inline bool hasCFBasicBlockEdge(CFBasicBlockNode *src, CFBasicBlockNode *dst) const + { + for (const auto &e: src->getOutEdges()) + { + if (e->getDstNode() == dst) + return true; + } + return false; + } - CFBasicBlockEdge* getCFBasicBlockEdge(const SVFBasicBlock *src, const SVFBasicBlock *dst); + CFBasicBlockEdge* getCFBasicBlockEdge(const CFBasicBlockNode *src, const CFBasicBlockNode *dst, const ICFGEdge *icfgEdge); -private: + std::vector getCFBasicBlockEdge(const CFBasicBlockNode *src, const CFBasicBlockNode *dst); + + /// Remove a ICFGEdgeWrapper + inline void removeCFBBEdge(CFBasicBlockEdge *edge) + { + if (edge->getDstNode()->hasIncomingEdge(edge)) + { + edge->getDstNode()->removeIncomingEdge(edge); + } + if (edge->getSrcNode()->hasOutgoingEdge(edge)) + { + edge->getSrcNode()->removeOutgoingEdge(edge); + } + delete edge; + _totalCFBasicBlockEdge--; + } - /// Add a CFBasicBlockNode - inline const CFBasicBlockNode* getOrAddCFBasicBlockNode(const SVFBasicBlock *bb); + /// Remove a ICFGNodeWrapper + inline void removeCFBBNode(CFBasicBlockNode *node) + { + std::set temp; + for (CFBasicBlockEdge *e: node->getInEdges()) + temp.insert(e); + for (CFBasicBlockEdge *e: node->getOutEdges()) + temp.insert(e); + for (CFBasicBlockEdge *e: temp) + { + removeCFBBEdge(e); + } + removeGNode(node); + _totalCFBasicBlockNode--; + } - inline const CFBasicBlockEdge *getOrAddCFBasicBlockEdge(CFBasicBlockNode *src, CFBasicBlockNode *dst); + /// Remove node from nodeID + inline bool removeCFBBNode(NodeID id) + { + if (hasGNode(id)) + { + removeCFBBNode(getGNode(id)); + return true; + } + return false; + } + + /// Add ICFGEdgeWrapper + inline bool addCFBBEdge(CFBasicBlockEdge *edge) + { + bool added1 = edge->getDstNode()->addIncomingEdge(edge); + bool added2 = edge->getSrcNode()->addOutgoingEdge(edge); + assert(added1 && added2 && "edge not added??"); + _totalCFBasicBlockEdge++; + return true; + } + + /// Add a ICFGNodeWrapper + virtual inline void addCFBBNode(CFBasicBlockNode *node) + { + addGNode(node->getId(), node); + _totalCFBasicBlockNode++; + } }; class CFBasicBlockGBuilder @@ -180,9 +483,11 @@ class CFBasicBlockGBuilder CFBasicBlockGraph* _CFBasicBlockG; public: - CFBasicBlockGBuilder(const SVFFunction *func) : _CFBasicBlockG(new CFBasicBlockGraph(func)) {} + CFBasicBlockGBuilder() : _CFBasicBlockG() {} + + virtual void build(SVFModule* module); - void build(); + virtual void build(ICFG* icfg); inline CFBasicBlockGraph* getCFBasicBlockGraph() { diff --git a/svf/include/Graphs/ICFGWrapper.h b/svf/include/Graphs/ICFGWrapper.h deleted file mode 100644 index 62aba478e..000000000 --- a/svf/include/Graphs/ICFGWrapper.h +++ /dev/null @@ -1,728 +0,0 @@ -//===- ICFGWrapper.h -- ICFG Wrapper-----------------------------------------// -// -// SVF: Static Value-Flow Analysis -// -// Copyright (C) <2013-2017> -// - -// 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 . -// -//===----------------------------------------------------------------------===// - -/* - * ICFGWrapper.h - * - * Created on: Sep 26, 2023 - * Author: Xiao Cheng - */ - -#ifndef SVF_ICFGWRAPPER_H -#define SVF_ICFGWRAPPER_H - -#include "Graphs/ICFG.h" -#include "SVFIR/SVFIR.h" - -namespace SVF -{ -class ICFGNodeWrapper; - -typedef GenericEdge GenericICFGWrapperEdgeTy; - - -class ICFGEdgeWrapper : public GenericICFGWrapperEdgeTy -{ -public: - typedef struct equalICFGEdgeWrapper - { - bool - operator()(const ICFGEdgeWrapper *lhs, const ICFGEdgeWrapper *rhs) const - { - if (lhs->getSrcID() != rhs->getSrcID()) - return lhs->getSrcID() < rhs->getSrcID(); - else if (lhs->getDstID() != rhs->getDstID()) - return lhs->getDstID() < rhs->getDstID(); - else - return lhs->getICFGEdge() < rhs->getICFGEdge(); - } - } equalICFGEdgeWrapper; - - typedef OrderedSet ICFGEdgeWrapperSetTy; - typedef ICFGEdgeWrapperSetTy::iterator iterator; - typedef ICFGEdgeWrapperSetTy::const_iterator const_iterator; - -private: - ICFGEdge *_icfgEdge; - -public: - ICFGEdgeWrapper(ICFGNodeWrapper *src, ICFGNodeWrapper *dst, ICFGEdge *edge) : - GenericICFGWrapperEdgeTy(src, dst, 0), _icfgEdge(edge) - { - - } - - ~ICFGEdgeWrapper() {} - - virtual const std::string toString() const - { - return _icfgEdge->toString(); - } - - inline ICFGEdge *getICFGEdge() const - { - return _icfgEdge; - } - - inline void setICFGEdge(ICFGEdge *edge) - { - _icfgEdge = edge; - } - - using SVF::GenericEdge::operator==; - /// Add the hash function for std::set (we also can overload operator< to implement this) - // and duplicated elements in the set are not inserted (binary tree comparison) - //@{ - - virtual inline bool operator==(const ICFGEdgeWrapper *rhs) const - { - return (rhs->getSrcID() == this->getSrcID() && rhs->getDstID() == this->getDstID() && - rhs->getICFGEdge() == this->getICFGEdge()); - } - //@} - -}; - -typedef GenericNode GenericICFGNodeWrapperTy; - -class ICFGNodeWrapper : public GenericICFGNodeWrapperTy -{ -public: - typedef ICFGEdgeWrapper::ICFGEdgeWrapperSetTy ICFGEdgeWrapperSetTy; - typedef ICFGEdgeWrapper::ICFGEdgeWrapperSetTy::iterator iterator; - typedef ICFGEdgeWrapper::ICFGEdgeWrapperSetTy::const_iterator const_iterator; -private: - const ICFGNode *_icfgNode; - ICFGNodeWrapper *_callICFGNodeWrapper{nullptr}; - ICFGNodeWrapper *_retICFGNodeWrapper{nullptr}; - ICFGEdgeWrapperSetTy InEdges; ///< all incoming edge of this node - ICFGEdgeWrapperSetTy OutEdges; ///< all outgoing edge of this node -public: - ICFGNodeWrapper(const ICFGNode *node) : GenericICFGNodeWrapperTy(node->getId(), 0), _icfgNode(node) {} - - virtual ~ICFGNodeWrapper() - { - for (auto *edge: OutEdges) - delete edge; - } - - virtual const std::string toString() const - { - return _icfgNode->toString(); - } - - const ICFGNode *getICFGNode() const - { - return _icfgNode; - } - - ICFGNodeWrapper *getCallICFGNodeWrapper() const - { - return _callICFGNodeWrapper; - } - - void setCallICFGNodeWrapper(ICFGNodeWrapper *node) - { - _callICFGNodeWrapper = node; - } - - ICFGNodeWrapper *getRetICFGNodeWrapper() const - { - return _retICFGNodeWrapper; - } - - void setRetICFGNodeWrapper(ICFGNodeWrapper *node) - { - _retICFGNodeWrapper = node; - } - - - /// Get incoming/outgoing edge set - ///@{ - inline const ICFGEdgeWrapperSetTy &getOutEdges() const - { - return OutEdges; - } - - inline const ICFGEdgeWrapperSetTy &getInEdges() const - { - return InEdges; - } - ///@} - - /// Has incoming/outgoing edge set - //@{ - inline bool hasIncomingEdge() const - { - return (InEdges.empty() == false); - } - - inline bool hasOutgoingEdge() const - { - return (OutEdges.empty() == false); - } - //@} - - /// iterators - //@{ - inline iterator OutEdgeBegin() - { - return OutEdges.begin(); - } - - inline iterator OutEdgeEnd() - { - return OutEdges.end(); - } - - inline iterator InEdgeBegin() - { - return InEdges.begin(); - } - - inline iterator InEdgeEnd() - { - return InEdges.end(); - } - - inline const_iterator OutEdgeBegin() const - { - return OutEdges.begin(); - } - - inline const_iterator OutEdgeEnd() const - { - return OutEdges.end(); - } - - inline const_iterator InEdgeBegin() const - { - return InEdges.begin(); - } - - inline const_iterator InEdgeEnd() const - { - return InEdges.end(); - } - //@} - - /// Iterators used for SCC detection, overwrite it in child class if necessory - //@{ - virtual inline iterator directOutEdgeBegin() - { - return OutEdges.begin(); - } - - virtual inline iterator directOutEdgeEnd() - { - return OutEdges.end(); - } - - virtual inline iterator directInEdgeBegin() - { - return InEdges.begin(); - } - - virtual inline iterator directInEdgeEnd() - { - return InEdges.end(); - } - - virtual inline const_iterator directOutEdgeBegin() const - { - return OutEdges.begin(); - } - - virtual inline const_iterator directOutEdgeEnd() const - { - return OutEdges.end(); - } - - virtual inline const_iterator directInEdgeBegin() const - { - return InEdges.begin(); - } - - virtual inline const_iterator directInEdgeEnd() const - { - return InEdges.end(); - } - //@} - - /// Add incoming and outgoing edges - //@{ - inline bool addIncomingEdge(ICFGEdgeWrapper *inEdge) - { - return InEdges.insert(inEdge).second; - } - - inline bool addOutgoingEdge(ICFGEdgeWrapper *outEdge) - { - return OutEdges.insert(outEdge).second; - } - //@} - - /// Remove incoming and outgoing edges - ///@{ - inline u32_t removeIncomingEdge(ICFGEdgeWrapper *edge) - { - iterator it = InEdges.find(edge); - assert(it != InEdges.end() && "can not find in edge in SVFG node"); - return InEdges.erase(edge); - } - - inline u32_t removeOutgoingEdge(ICFGEdgeWrapper *edge) - { - iterator it = OutEdges.find(edge); - assert(it != OutEdges.end() && "can not find out edge in SVFG node"); - return OutEdges.erase(edge); - } - ///@} - - /// Find incoming and outgoing edges - //@{ - inline ICFGEdgeWrapper *hasIncomingEdge(ICFGEdgeWrapper *edge) const - { - const_iterator it = InEdges.find(edge); - if (it != InEdges.end()) - return *it; - else - return nullptr; - } - - inline ICFGEdgeWrapper *hasOutgoingEdge(ICFGEdgeWrapper *edge) const - { - const_iterator it = OutEdges.find(edge); - if (it != OutEdges.end()) - return *it; - else - return nullptr; - } - //@} -}; - -typedef std::vector> NodePairVector; -typedef GenericGraph GenericICFGWrapperTy; - -class ICFGWrapper : public GenericICFGWrapperTy -{ -public: - - typedef Map ICFGWrapperNodeIDToNodeMapTy; - typedef ICFGEdgeWrapper::ICFGEdgeWrapperSetTy ICFGEdgeWrapperSetTy; - typedef ICFGWrapperNodeIDToNodeMapTy::iterator iterator; - typedef ICFGWrapperNodeIDToNodeMapTy::const_iterator const_iterator; - typedef std::vector ICFGNodeWrapperVector; - typedef std::vector> ICFGNodeWrapperPairVector; - typedef Map SVFFuncToICFGNodeWrapperMap; -private: - static std::unique_ptr _icfgWrapper; ///< Singleton pattern here - SVFFuncToICFGNodeWrapperMap _funcToFunEntry; - SVFFuncToICFGNodeWrapperMap _funcToFunExit; - u32_t _edgeWrapperNum; ///< total num of node - u32_t _nodeWrapperNum; ///< total num of edge - ICFG *_icfg; - - /// Constructor - ICFGWrapper(ICFG *icfg) : _edgeWrapperNum(0), _nodeWrapperNum(0), _icfg(icfg) - { - assert(_icfg && "ICFGWrapper constructor cannot accept nullptr of icfg"); - } - -public: - /// Singleton design here to make sure we only have one instance during any analysis - //@{ - static inline const std::unique_ptr &getICFGWrapper(ICFG *_icfg) - { - if (_icfgWrapper == nullptr) - { - _icfgWrapper = std::make_unique(ICFGWrapper(_icfg)); - } - return _icfgWrapper; - } - - static inline const std::unique_ptr &getICFGWrapper() - { - assert(_icfgWrapper && "icfg wrapper not init?"); - return _icfgWrapper; - } - - static void releaseICFGWrapper() - { - ICFGWrapper *w = _icfgWrapper.release(); - delete w; - _icfgWrapper = nullptr; - } - //@} - - /// Destructor - virtual ~ICFGWrapper() = default; - - /// Get a ICFG node wrapper - inline ICFGNodeWrapper *getICFGNodeWrapper(NodeID id) const - { - if (!hasICFGNodeWrapper(id)) - return nullptr; - return getGNode(id); - } - - /// Whether has the ICFGNodeWrapper - inline bool hasICFGNodeWrapper(NodeID id) const - { - return hasGNode(id); - } - - /// Whether we has a ICFG Edge Wrapper - bool hasICFGEdgeWrapper(ICFGNodeWrapper *src, ICFGNodeWrapper *dst, ICFGEdge *icfgEdge) - { - ICFGEdgeWrapper edge(src, dst, icfgEdge); - ICFGEdgeWrapper *outEdge = src->hasOutgoingEdge(&edge); - ICFGEdgeWrapper *inEdge = dst->hasIncomingEdge(&edge); - if (outEdge && inEdge) - { - assert(outEdge == inEdge && "edges not match"); - return true; - } - else - return false; - } - - ICFGEdgeWrapper *hasICFGEdgeWrapper(ICFGNodeWrapper *src, ICFGNodeWrapper *dst) - { - for (const auto &e: src->getOutEdges()) - { - if (e->getDstNode() == dst) - return e; - } - return nullptr; - } - - /// Get a ICFG edge wrapper according to src, dst and icfgEdge - ICFGEdgeWrapper * - getICFGEdgeWrapper(const ICFGNodeWrapper *src, const ICFGNodeWrapper *dst, ICFGEdge *icfgEdge) - { - ICFGEdgeWrapper *edge = nullptr; - size_t counter = 0; - for (ICFGEdgeWrapper::ICFGEdgeWrapperSetTy::iterator iter = src->OutEdgeBegin(); - iter != src->OutEdgeEnd(); ++iter) - { - if ((*iter)->getDstID() == dst->getId()) - { - counter++; - edge = (*iter); - } - } - assert(counter <= 1 && "there's more than one edge between two ICFGNodeWrappers"); - return edge; - } - - /// View graph from the debugger - void view(); - - /// Dump graph into dot file - void dump(const std::string &filename); - - /// Remove a ICFGEdgeWrapper - inline void removeICFGEdgeWrapper(ICFGEdgeWrapper *edge) - { - if (edge->getDstNode()->hasIncomingEdge(edge)) - { - edge->getDstNode()->removeIncomingEdge(edge); - } - if (edge->getSrcNode()->hasOutgoingEdge(edge)) - { - edge->getSrcNode()->removeOutgoingEdge(edge); - } - delete edge; - _edgeWrapperNum--; - } - - /// Remove a ICFGNodeWrapper - inline void removeICFGNodeWrapper(ICFGNodeWrapper *node) - { - std::set temp; - for (ICFGEdgeWrapper *e: node->getInEdges()) - temp.insert(e); - for (ICFGEdgeWrapper *e: node->getOutEdges()) - temp.insert(e); - for (ICFGEdgeWrapper *e: temp) - { - removeICFGEdgeWrapper(e); - } - removeGNode(node); - _nodeWrapperNum--; - } - - /// Remove node from nodeID - inline bool removeICFGNodeWrapper(NodeID id) - { - if (hasICFGNodeWrapper(id)) - { - removeICFGNodeWrapper(getICFGNodeWrapper(id)); - return true; - } - return false; - } - - /// Add ICFGEdgeWrapper - inline bool addICFGEdgeWrapper(ICFGEdgeWrapper *edge) - { - bool added1 = edge->getDstNode()->addIncomingEdge(edge); - bool added2 = edge->getSrcNode()->addOutgoingEdge(edge); - assert(added1 && added2 && "edge not added??"); - _edgeWrapperNum++; - return true; - } - - /// Add a ICFGNodeWrapper - virtual inline void addICFGNodeWrapper(ICFGNodeWrapper *node) - { - addGNode(node->getId(), node); - _nodeWrapperNum++; - } - - const ICFGNodeWrapper *getFunEntry(const SVFFunction *func) const - { - auto it = _funcToFunEntry.find(func); - assert(it != _funcToFunEntry.end() && "no entry?"); - return it->second; - } - - const ICFGNodeWrapper *getFunExit(const SVFFunction *func) const - { - auto it = _funcToFunExit.find(func); - assert(it != _funcToFunExit.end() && "no exit?"); - return it->second; - } - - /// Add ICFGEdgeWrappers from nodeid pair - void addICFGNodeWrapperFromICFGNode(const ICFGNode *src); - - inline u32_t getNodeWrapperNum() const - { - return _nodeWrapperNum; - } - - inline u32_t getEdgeWrapperNum() const - { - return _edgeWrapperNum; - } - -}; - -class ICFGWrapperBuilder -{ -public: - ICFGWrapperBuilder() {} - - ~ICFGWrapperBuilder() {} - - void build(ICFG *icfg); -}; -} - -namespace SVF -{ -/* ! - * GenericGraphTraits specializations for generic graph algorithms. - * Provide graph traits for traversing from a constraint node using standard graph ICFGTraversals. - */ -template<> -struct GenericGraphTraits - : public GenericGraphTraits *> -{ -}; - -/// Inverse GenericGraphTraits specializations for call graph node, it is used for inverse ICFGTraversal. -template<> -struct GenericGraphTraits > : public GenericGraphTraits< - Inverse *> > -{ -}; - -template<> -struct GenericGraphTraits - : public GenericGraphTraits *> -{ - typedef SVF::ICFGNodeWrapper *NodeRef; -}; - -template<> -struct DOTGraphTraits : public DOTGraphTraits -{ - - typedef SVF::ICFGNodeWrapper NodeType; - - DOTGraphTraits(bool isSimple = false) : - DOTGraphTraits(isSimple) - { - } - - /// Return name of the graph - static std::string getGraphName(SVF::ICFGWrapper *) - { - return "ICFGWrapper"; - } - - static bool isNodeHidden(NodeType *node, SVF::ICFGWrapper *graph) - { - return false; - } - - std::string getNodeLabel(NodeType *node, SVF::ICFGWrapper *graph) - { - return getSimpleNodeLabel(node, graph); - } - - /// Return the label of an ICFG node - static std::string getSimpleNodeLabel(NodeType *node, SVF::ICFGWrapper *) - { - std::string str; - std::stringstream rawstr(str); - rawstr << "NodeID: " << node->getId() << "\n"; - if (const SVF::IntraICFGNode *bNode = SVF::SVFUtil::dyn_cast(node->getICFGNode())) - { - rawstr << "IntraICFGNode ID: " << bNode->getId() << " \t"; - SVF::SVFIR::SVFStmtList &edges = SVF::SVFIR::getPAG()->getSVFStmtList(bNode); - if (edges.empty()) - { - rawstr << bNode->getInst()->toString() << " \t"; - } - else - { - for (SVF::SVFIR::SVFStmtList::iterator it = edges.begin(), eit = edges.end(); it != eit; ++it) - { - const SVF::PAGEdge *edge = *it; - rawstr << edge->toString(); - } - } - rawstr << " {fun: " << bNode->getFun()->getName() << "}"; - } - else if (const SVF::FunEntryICFGNode *entry = SVF::SVFUtil::dyn_cast( - node->getICFGNode())) - { - rawstr << entry->toString(); - } - else if (const SVF::FunExitICFGNode *exit = SVF::SVFUtil::dyn_cast( - node->getICFGNode())) - { - rawstr << exit->toString(); - } - else if (const SVF::CallICFGNode *call = SVF::SVFUtil::dyn_cast(node->getICFGNode())) - { - rawstr << call->toString(); - } - else if (const SVF::RetICFGNode *ret = SVF::SVFUtil::dyn_cast(node->getICFGNode())) - { - rawstr << ret->toString(); - } - else if (const SVF::GlobalICFGNode *glob = SVF::SVFUtil::dyn_cast( - node->getICFGNode())) - { - SVF::SVFIR::SVFStmtList &edges = SVF::SVFIR::getPAG()->getSVFStmtList(glob); - for (SVF::SVFIR::SVFStmtList::iterator it = edges.begin(), eit = edges.end(); it != eit; ++it) - { - const SVF::PAGEdge *edge = *it; - rawstr << edge->toString(); - } - } - else - assert(false && "what else kinds of nodes do we have??"); - - return rawstr.str(); - } - - static std::string getNodeAttributes(NodeType *node, SVF::ICFGWrapper *) - { - std::string str; - std::stringstream rawstr(str); - - if (SVF::SVFUtil::isa(node->getICFGNode())) - { - rawstr << "color=black"; - } - else if (SVF::SVFUtil::isa(node->getICFGNode())) - { - rawstr << "color=yellow"; - } - else if (SVF::SVFUtil::isa(node->getICFGNode())) - { - rawstr << "color=green"; - } - else if (SVF::SVFUtil::isa(node->getICFGNode())) - { - rawstr << "color=red"; - } - else if (SVF::SVFUtil::isa(node->getICFGNode())) - { - rawstr << "color=blue"; - } - else if (SVF::SVFUtil::isa(node->getICFGNode())) - { - rawstr << "color=purple"; - } - else - assert(false && "no such kind of node!!"); - - rawstr << ""; - - return rawstr.str(); - } - - template - static std::string getEdgeAttributes(NodeType *, EdgeIter EI, SVF::ICFGWrapper *) - { - SVF::ICFGEdgeWrapper *edge = *(EI.getCurrent()); - assert(edge && "No edge found!!"); - if (!edge->getICFGEdge()) - return "style=solid"; - if (SVF::SVFUtil::isa(edge->getICFGEdge())) - return "style=solid,color=red"; - else if (SVF::SVFUtil::isa(edge->getICFGEdge())) - return "style=solid,color=blue"; - else - return "style=solid"; - return ""; - } - - template - static std::string getEdgeSourceLabel(NodeType *, EdgeIter EI) - { - SVF::ICFGEdgeWrapper *edge = *(EI.getCurrent()); - assert(edge && "No edge found!!"); - - std::string str; - std::stringstream rawstr(str); - if (!edge->getICFGEdge()) - return rawstr.str(); - if (SVF::CallCFGEdge *dirCall = SVF::SVFUtil::dyn_cast(edge->getICFGEdge())) - rawstr << dirCall->getCallSite(); - else if (SVF::RetCFGEdge *dirRet = SVF::SVFUtil::dyn_cast(edge->getICFGEdge())) - rawstr << dirRet->getCallSite(); - - return rawstr.str(); - } -}; - -} // End namespace SVF - -#endif //SVF_ICFGWRAPPER_H diff --git a/svf/lib/Graphs/CFBasicBlockG.cpp b/svf/lib/Graphs/CFBasicBlockG.cpp index f2643117d..0a6e1f2b9 100644 --- a/svf/lib/Graphs/CFBasicBlockG.cpp +++ b/svf/lib/Graphs/CFBasicBlockG.cpp @@ -32,13 +32,18 @@ namespace SVF { -CFBasicBlockNode::CFBasicBlockNode(u32_t id, const SVFBasicBlock *svfBasicBlock) : GenericCFBasicBlockNodeTy(id, 0), - _svfBasicBlock(svfBasicBlock) +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); + const SVFInstruction* ins = *it; + ICFGNode* icfgNode = PAG::getPAG()->getICFG()->getICFGNode(ins); _icfgNodes.push_back(icfgNode); } } @@ -47,7 +52,7 @@ const std::string CFBasicBlockNode::toString() const { std::string rawStr; std::stringstream stringstream(rawStr); - stringstream << "Block Name: " << _svfBasicBlock->getName() << "\n"; + stringstream << "Block Name: " << getName() << "\n"; for (const auto &icfgNode: _icfgNodes) { stringstream << icfgNode->toString() << "\n"; @@ -55,19 +60,14 @@ const std::string CFBasicBlockNode::toString() const return stringstream.str(); } -CFBasicBlockEdge* CFBasicBlockGraph::getCFBasicBlockEdge(const SVFBasicBlock *src, const SVFBasicBlock *dst) -{ - return getCFBasicBlockEdge(getCFBasicBlockNode(src), getCFBasicBlockNode(dst)); -} - -CFBasicBlockEdge* CFBasicBlockGraph::getCFBasicBlockEdge(const CFBasicBlockNode *src, const CFBasicBlockNode *dst) +CFBasicBlockEdge* CFBasicBlockGraph::getCFBasicBlockEdge(const CFBasicBlockNode *src, const CFBasicBlockNode *dst, const ICFGEdge* icfgEdge) { CFBasicBlockEdge *edge = nullptr; size_t counter = 0; for (auto iter = src->OutEdgeBegin(); iter != src->OutEdgeEnd(); ++iter) { - if ((*iter)->getDstID() == dst->getId()) + if ((*iter)->getDstID() == dst->getId() && (*iter)->getICFGEdge() == icfgEdge) { counter++; edge = (*iter); @@ -77,42 +77,101 @@ CFBasicBlockEdge* CFBasicBlockGraph::getCFBasicBlockEdge(const CFBasicBlockNode return edge; } -const CFBasicBlockNode* CFBasicBlockGraph::getOrAddCFBasicBlockNode(const SVFBasicBlock *bb) +std::vector CFBasicBlockGraph::getCFBasicBlockEdge(const CFBasicBlockNode *src, const CFBasicBlockNode *dst) { - auto it = _bbToNode.find(bb); - if (it != _bbToNode.end()) return it->second; - CFBasicBlockNode *node = new CFBasicBlockNode(_totalCFBasicBlockNode++, bb); - _bbToNode[bb] = node; - addGNode(node->getId(), node); - return node; + std::vector edges; + for (auto iter = src->OutEdgeBegin(); + iter != src->OutEdgeEnd(); ++iter) + { + if ((*iter)->getDstID() == dst->getId()) + { + edges.push_back(*iter); + } + } + return SVFUtil::move(edges); } -const CFBasicBlockEdge* CFBasicBlockGraph::getOrAddCFBasicBlockEdge(CFBasicBlockNode *src, CFBasicBlockNode *dst) +void CFBasicBlockGBuilder::build(SVFModule* module) { - if (const CFBasicBlockEdge *edge = getCFBasicBlockEdge(src, dst)) return edge; - CFBasicBlockEdge *edge = new CFBasicBlockEdge(src, dst); - bool added1 = edge->getDstNode()->addIncomingEdge(edge); - bool added2 = edge->getSrcNode()->addOutgoingEdge(edge); - (void) added1; - (void) added2; - assert(added1 && added2 && "edge not added??"); - _totalCFBasicBlockEdge++; - return edge; + _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); + } + } + } + } + _CFBasicBlockG->_bbToNode = bbToNode; } -void CFBasicBlockGBuilder::build() +void CFBasicBlockGBuilder::build(ICFG* icfg) { - for (const auto &bb: *_CFBasicBlockG->_svfFunction) + _CFBasicBlockG = new CFBasicBlockGraph(); + Map bbToNode; + for (const auto& node : *icfg) { - _CFBasicBlockG->getOrAddCFBasicBlockNode(bb); + 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); + } + } } - for (const auto &bb: *_CFBasicBlockG->_svfFunction) + + for (const auto& node : *icfg) { - for (const auto &succ: bb->getSuccessors()) + for (const auto &succ: node.second->getOutEdges()) { - _CFBasicBlockG->getOrAddCFBasicBlockEdge(_CFBasicBlockG->getCFBasicBlockNode(bb), - _CFBasicBlockG->getCFBasicBlockNode(succ)); + 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); + } + } } } + _CFBasicBlockG->_bbToNode = bbToNode; } } \ No newline at end of file diff --git a/svf/lib/Graphs/ICFGWrapper.cpp b/svf/lib/Graphs/ICFGWrapper.cpp deleted file mode 100644 index f5385d5ec..000000000 --- a/svf/lib/Graphs/ICFGWrapper.cpp +++ /dev/null @@ -1,97 +0,0 @@ -//===- ICFGWrapper.cpp -- ICFG Wrapper-----------------------------------------// -// -// SVF: Static Value-Flow Analysis -// -// Copyright (C) <2013-2017> -// - -// 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 . -// -//===----------------------------------------------------------------------===// - -/* - * ICFGWrapper.cpp - * - * Created on: Sep 26, 2023 - * Author: Xiao Cheng - */ - -#include "Graphs/ICFGWrapper.h" - -using namespace SVF; -using namespace SVFUtil; - -std::unique_ptr ICFGWrapper::_icfgWrapper = nullptr; - -void ICFGWrapper::view() -{ - SVF::ViewGraph(this, "ICFG Wrapper"); -} - -void ICFGWrapper::dump(const std::string& filename) -{ - GraphPrinter::WriteGraphToFile(SVFUtil::outs(), filename, this); -} - -void ICFGWrapper::addICFGNodeWrapperFromICFGNode(const ICFGNode *src) -{ - - if (!hasICFGNodeWrapper(src->getId())) - addICFGNodeWrapper(new ICFGNodeWrapper(src)); - ICFGNodeWrapper *curICFGNodeWrapper = getGNode(src->getId()); - if (isa(src)) - { - _funcToFunEntry.emplace(src->getFun(), curICFGNodeWrapper); - } - else if (isa(src)) - { - _funcToFunExit.emplace(src->getFun(), curICFGNodeWrapper); - } - else if (const CallICFGNode *callICFGNode = dyn_cast(src)) - { - if (!hasICFGNodeWrapper(callICFGNode->getRetICFGNode()->getId())) - addICFGNodeWrapper(new ICFGNodeWrapper(callICFGNode->getRetICFGNode())); - if (!curICFGNodeWrapper->getRetICFGNodeWrapper()) - curICFGNodeWrapper->setRetICFGNodeWrapper(getGNode(callICFGNode->getRetICFGNode()->getId())); - } - else if (const RetICFGNode *retICFGNode = dyn_cast(src)) - { - if (!hasICFGNodeWrapper(retICFGNode->getCallICFGNode()->getId())) - addICFGNodeWrapper(new ICFGNodeWrapper(retICFGNode->getCallICFGNode())); - if (!curICFGNodeWrapper->getCallICFGNodeWrapper()) - curICFGNodeWrapper->setCallICFGNodeWrapper(getGNode(retICFGNode->getCallICFGNode()->getId())); - } - for (const auto &e: src->getOutEdges()) - { - if (!hasICFGNodeWrapper(e->getDstID())) - addICFGNodeWrapper(new ICFGNodeWrapper(e->getDstNode())); - ICFGNodeWrapper *dstNodeWrapper = getGNode(e->getDstID()); - if (!hasICFGEdgeWrapper(curICFGNodeWrapper, dstNodeWrapper, e)) - { - ICFGEdgeWrapper *pEdge = new ICFGEdgeWrapper(curICFGNodeWrapper, dstNodeWrapper, e); - addICFGEdgeWrapper(pEdge); - } - } -} - - -void ICFGWrapperBuilder::build(ICFG *icfg) -{ - ICFGWrapper::releaseICFGWrapper(); - const std::unique_ptr &icfgWrapper = ICFGWrapper::getICFGWrapper(icfg); - for (const auto &i: *icfg) - { - icfgWrapper->addICFGNodeWrapperFromICFGNode(i.second); - } -} \ No newline at end of file