diff --git a/svf-llvm/include/SVF-LLVM/LLVMModule.h b/svf-llvm/include/SVF-LLVM/LLVMModule.h index fa56bca99..7b5a81e38 100644 --- a/svf-llvm/include/SVF-LLVM/LLVMModule.h +++ b/svf-llvm/include/SVF-LLVM/LLVMModule.h @@ -105,7 +105,7 @@ class LLVMModuleSet InstToBlockNodeMapTy InstToBlockNodeMap; ///< map a basic block to its ICFGNode FunToFunEntryNodeMapTy FunToFunEntryNodeMap; ///< map a function to its FunExitICFGNode FunToFunExitNodeMapTy FunToFunExitNodeMap; ///< map a function to its FunEntryICFGNode - PTACallGraph* callgraph; + CallGraph* callgraph; /// Constructor LLVMModuleSet(); diff --git a/svf/include/Graphs/CallGraph.h b/svf/include/Graphs/CallGraph.h new file mode 100644 index 000000000..e92765899 --- /dev/null +++ b/svf/include/Graphs/CallGraph.h @@ -0,0 +1,264 @@ +//===- CallGraph.h -- Call graph representation----------------------------// +// +// 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 . +// +//===----------------------------------------------------------------------===// + +/* + * CallGraph.h + * + * Created on: Nov 7, 2013 + * Author: Yulei Sui + */ + +#ifndef CALLGRAPH_H_ +#define CALLGRAPH_H_ + +#include "Graphs/GenericGraph.h" +#include "SVFIR/SVFValue.h" +#include "Graphs/ICFG.h" +#include + +namespace SVF +{ + +class CallGraphNode; +class SVFModule; + + +/* + * Call Graph edge representing a calling relation between two functions + * Multiple calls from function A to B are merged into one call edge + * Each call edge has a set of direct callsites and a set of indirect callsites + */ +typedef GenericEdge GenericCallGraphEdgeTy; +class CallGraphEdge : public GenericCallGraphEdgeTy +{ + +public: + typedef Set CallInstSet; + +private: + CallInstSet directCalls; +public: + /// Constructor + CallGraphEdge(CallGraphNode* s, CallGraphNode* d, const CallICFGNode* icfgNode) : + GenericCallGraphEdgeTy(s, d, icfgNode->getId()) + { + } + /// Destructor + virtual ~CallGraphEdge() + { + } + + /// Add direct callsite + //@{ + void addDirectCallSite(const CallICFGNode* call); + //@} + + /// Iterators for direct and indirect callsites + //@{ + inline CallInstSet::const_iterator directCallsBegin() const + { + return directCalls.begin(); + } + inline CallInstSet::const_iterator directCallsEnd() const + { + return directCalls.end(); + } + //@} + + /// ClassOf + //@{ + static inline bool classof(const CallGraphEdge*) + { + return true; + } + //@} + + /// Overloading operator << for dumping ICFG node ID + //@{ + friend OutStream& operator<< (OutStream &o, const CallGraphEdge&edge) + { + o << edge.toString(); + return o; + } + //@} + + virtual const std::string toString() const; + + typedef GenericNode::GEdgeSetTy CallGraphEdgeSet; + +}; + +/* + * Call Graph node representing a function + */ +typedef GenericNode GenericCallGraphNodeTy; +class CallGraphNode : public GenericCallGraphNodeTy +{ +private: + const SVFFunction* fun; + +public: + /// Constructor + CallGraphNode(NodeID i, const SVFFunction* f) : GenericCallGraphNodeTy(i,CallNodeKd), fun(f) + { + } + + inline const std::string &getName() const + { + return fun->getName(); + } + + /// Get function of this call node + inline const SVFFunction* getFunction() const + { + return fun; + } + + + /// Overloading operator << for dumping ICFG node ID + //@{ + friend OutStream& operator<< (OutStream &o, const CallGraphNode&node) + { + o << node.toString(); + return o; + } + //@} + + virtual const std::string toString() const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + //@{ + static inline bool classof(const CallGraphNode*) + { + return true; + } + + static inline bool classof(const GenericICFGNodeTy* node) + { + return node->getNodeKind() == CallNodeKd; + } + + static inline bool classof(const SVFBaseNode* node) + { + return node->getNodeKind() == CallNodeKd; + } + //@} +}; + +/*! + * Pointer Analysis Call Graph used internally for various pointer analysis + */ +typedef GenericGraph GenericCallGraphTy; +class CallGraph : public GenericCallGraphTy +{ + friend class PTACallGraph; + +public: + typedef CallGraphEdge::CallGraphEdgeSet CallGraphEdgeSet; + typedef Map FunToCallGraphNodeMap; + typedef Map CallInstToCallGraphEdgesMap; + typedef Set FunctionSet; + typedef OrderedMap CallEdgeMap; + +protected: + FunToCallGraphNodeMap funToCallGraphNodeMap; ///< Call Graph node map + CallInstToCallGraphEdgesMap callinstToCallGraphEdgesMap; ///< Map a call instruction to its corresponding call edges + + NodeID callGraphNodeNum; + + /// Clean up memory + void destroy(); + + /// Add call graph edge + inline void addEdge(CallGraphEdge* edge) + { + edge->getDstNode()->addIncomingEdge(edge); + edge->getSrcNode()->addOutgoingEdge(edge); + } + + +public: + /// Constructor + CallGraph(); + + void addCallGraphNode(const SVFFunction* fun); + + /// Destructor + virtual ~CallGraph() + { + destroy(); + } + + /// Get call graph node + //@{ + inline CallGraphNode* getCallGraphNode(NodeID id) const + { + return getGNode(id); + } + inline CallGraphNode* getCallGraphNode(const SVFFunction* fun) const + { + FunToCallGraphNodeMap::const_iterator it = funToCallGraphNodeMap.find(fun); + assert(it!=funToCallGraphNodeMap.end() && "call graph node not found!!"); + return it->second; + } + + //@} + + /// Whether we have already created this call graph edge + CallGraphEdge* hasGraphEdge(CallGraphNode* src, CallGraphNode* dst, + const CallICFGNode* callIcfgNode) const; + + /// Add direct call edges + void addDirectCallGraphEdge(const CallICFGNode* call, const SVFFunction* callerFun, const SVFFunction* calleeFun); + /// Dump the graph + void dump(const std::string& filename); + + /// View the graph from the debugger + void view(); +}; + +} // End namespace SVF + +namespace SVF +{ +/* ! + * GenericGraphTraits specializations for generic graph algorithms. + * Provide graph traits for traversing from a constraint node using standard graph traversals. + */ +template<> struct GenericGraphTraits : public GenericGraphTraits* > +{ +}; + +/// Inverse GenericGraphTraits specializations for call graph node, it is used for inverse traversal. +template<> +struct GenericGraphTraits > : public GenericGraphTraits* > > +{ +}; + +template<> struct GenericGraphTraits : public GenericGraphTraits* > +{ + typedef SVF::CallGraphNode*NodeRef; +}; + +} // End namespace llvm + +#endif /* CALLGRAPH_H_ */ diff --git a/svf/include/Graphs/PTACallGraph.h b/svf/include/Graphs/PTACallGraph.h index f1fc2bc6e..1cbc93351 100644 --- a/svf/include/Graphs/PTACallGraph.h +++ b/svf/include/Graphs/PTACallGraph.h @@ -40,6 +40,7 @@ namespace SVF class PTACallGraphNode; class SVFModule; +class CallGraph; /* @@ -47,8 +48,8 @@ class SVFModule; * Multiple calls from function A to B are merged into one call edge * Each call edge has a set of direct callsites and a set of indirect callsites */ -typedef GenericEdge GenericCallGraphEdgeTy; -class PTACallGraphEdge : public GenericCallGraphEdgeTy +typedef GenericEdge GenericPTACallGraphEdgeTy; +class PTACallGraphEdge : public GenericPTACallGraphEdgeTy { public: @@ -66,7 +67,7 @@ class PTACallGraphEdge : public GenericCallGraphEdgeTy public: /// Constructor PTACallGraphEdge(PTACallGraphNode* s, PTACallGraphNode* d, CEDGEK kind, CallSiteID cs) : - GenericCallGraphEdgeTy(s, d, makeEdgeFlagWithInvokeID(kind, cs)), csId(cs) + GenericPTACallGraphEdgeTy(s, d, makeEdgeFlagWithInvokeID(kind, cs)), csId(cs) { } /// Destructor @@ -144,7 +145,7 @@ class PTACallGraphEdge : public GenericCallGraphEdgeTy { return true; } - static inline bool classof(const GenericCallGraphEdgeTy *edge) + static inline bool classof(const GenericPTACallGraphEdgeTy *edge) { return edge->getEdgeKind() == PTACallGraphEdge::CallRetEdge || edge->getEdgeKind() == PTACallGraphEdge::TDForkEdge || @@ -170,21 +171,15 @@ class PTACallGraphEdge : public GenericCallGraphEdgeTy /* * Call Graph node representing a function */ -typedef GenericNode GenericCallGraphNodeTy; -class PTACallGraphNode : public GenericCallGraphNodeTy +typedef GenericNode GenericPTACallGraphNodeTy; +class PTACallGraphNode : public GenericPTACallGraphNodeTy { - -public: - typedef PTACallGraphEdge::CallGraphEdgeSet CallGraphEdgeSet; - typedef PTACallGraphEdge::CallGraphEdgeSet::iterator iterator; - typedef PTACallGraphEdge::CallGraphEdgeSet::const_iterator const_iterator; - private: const SVFFunction* fun; public: /// Constructor - PTACallGraphNode(NodeID i, const SVFFunction* f) : GenericCallGraphNodeTy(i,CallNodeKd), fun(f) + PTACallGraphNode(NodeID i, const SVFFunction* f) : GenericPTACallGraphNodeTy(i,CallNodeKd), fun(f) { } @@ -237,8 +232,8 @@ class PTACallGraphNode : public GenericCallGraphNodeTy /*! * Pointer Analysis Call Graph used internally for various pointer analysis */ -typedef GenericGraph GenericCallGraphTy; -class PTACallGraph : public GenericCallGraphTy +typedef GenericGraph GenericPTACallGraphTy; +class PTACallGraph : public GenericPTACallGraphTy { public: @@ -278,14 +273,36 @@ class PTACallGraph : public GenericCallGraphTy /// Clean up memory void destroy(); +protected: + /// Add CallSiteID + inline CallSiteID addCallSite(const CallICFGNode* cs, const SVFFunction* callee) + { + std::pair newCS(std::make_pair(cs, callee)); + CallSiteToIdMap::const_iterator it = csToIdMap.find(newCS); + //assert(it == csToIdMap.end() && "cannot add a callsite twice"); + if(it == csToIdMap.end()) + { + CallSiteID id = totalCallSiteNum++; + csToIdMap.insert(std::make_pair(newCS, id)); + idToCSMap.insert(std::make_pair(id, newCS)); + return id; + } + return it->second; + } + + /// Add call graph edge + inline void addEdge(PTACallGraphEdge* edge) + { + edge->getDstNode()->addIncomingEdge(edge); + edge->getSrcNode()->addOutgoingEdge(edge); + } + public: /// Constructor PTACallGraph(CGEK k = NormCallGraph); /// Copy constructor - PTACallGraph(const PTACallGraph& other); - - void addCallGraphNode(const SVFFunction* fun); + PTACallGraph(const CallGraph& other); /// Destructor virtual ~PTACallGraph() @@ -349,22 +366,8 @@ class PTACallGraph : public GenericCallGraphTy //@} - /// Add/Get CallSiteID + /// Get CallSiteID //@{ - inline CallSiteID addCallSite(const CallICFGNode* cs, const SVFFunction* callee) - { - std::pair newCS(std::make_pair(cs, callee)); - CallSiteToIdMap::const_iterator it = csToIdMap.find(newCS); - //assert(it == csToIdMap.end() && "cannot add a callsite twice"); - if(it == csToIdMap.end()) - { - CallSiteID id = totalCallSiteNum++; - csToIdMap.insert(std::make_pair(newCS, id)); - idToCSMap.insert(std::make_pair(id, newCS)); - return id; - } - return it->second; - } inline CallSiteID getCallSiteID(const CallICFGNode* cs, const SVFFunction* callee) const { CallSitePair newCS(std::make_pair(cs, callee)); @@ -439,16 +442,10 @@ class PTACallGraph : public GenericCallGraphTy return it->second.end(); } //@} - /// Add call graph edge - inline void addEdge(PTACallGraphEdge* edge) - { - edge->getDstNode()->addIncomingEdge(edge); - edge->getSrcNode()->addOutgoingEdge(edge); - } - /// Add direct/indirect call edges + + /// Add indirect call edges //@{ - void addDirectCallGraphEdge(const CallICFGNode* call, const SVFFunction* callerFun, const SVFFunction* calleeFun); void addIndirectCallGraphEdge(const CallICFGNode* cs,const SVFFunction* callerFun, const SVFFunction* calleeFun); //@} @@ -494,4 +491,4 @@ template<> struct GenericGraphTraits : public GenericGraphTr } // End namespace llvm -#endif /* CALLGRAPH_H_ */ +#endif /* PTACALLGRAPH_H_ */ diff --git a/svf/include/Graphs/ThreadCallGraph.h b/svf/include/Graphs/ThreadCallGraph.h index 5bef82c2d..ba48e0e9c 100644 --- a/svf/include/Graphs/ThreadCallGraph.h +++ b/svf/include/Graphs/ThreadCallGraph.h @@ -172,7 +172,7 @@ class ThreadCallGraph: public PTACallGraph typedef Map CallInstToParForEdgesMap; /// Constructor - ThreadCallGraph(const PTACallGraph& cg); + ThreadCallGraph(const CallGraph& cg); ThreadCallGraph(ThreadCallGraph& cg) = delete; diff --git a/svf/include/SVFIR/SVFIR.h b/svf/include/SVFIR/SVFIR.h index 4076383aa..96c174712 100644 --- a/svf/include/SVFIR/SVFIR.h +++ b/svf/include/SVFIR/SVFIR.h @@ -35,6 +35,7 @@ namespace SVF { class CommonCHGraph; +class CallGraph; /*! * SVF Intermediate representation, representing variables and statements as a Program Assignment Graph (PAG) * Variables as nodes and statements as edges. @@ -98,7 +99,7 @@ class SVFIR : public IRGraph ICFG* icfg; // ICFG CommonCHGraph* chgraph; // class hierarchy graph CallSiteSet callSiteSet; /// all the callsites of a program - PTACallGraph* callGraph; /// call graph + CallGraph* callGraph; /// call graph static std::unique_ptr pag; ///< Singleton pattern here to enable instance of SVFIR can only be created once. @@ -185,13 +186,13 @@ class SVFIR : public IRGraph } /// Set/Get CG - inline void setCallGraph(PTACallGraph* c) + inline void setCallGraph(CallGraph* c) { callGraph = c; } - inline PTACallGraph* getCallGraph() + inline CallGraph* getCallGraph() { - assert(callGraph && "empty PTACallGraph! Build SVF IR first!"); + assert(callGraph && "empty CallGraph! Build SVF IR first!"); return callGraph; } diff --git a/svf/include/Util/CallGraphBuilder.h b/svf/include/Util/CallGraphBuilder.h index c8b65a85d..337d30e22 100644 --- a/svf/include/Util/CallGraphBuilder.h +++ b/svf/include/Util/CallGraphBuilder.h @@ -31,7 +31,6 @@ #ifndef INCLUDE_SVF_FE_CALLGRAPHBUILDER_H_ #define INCLUDE_SVF_FE_CALLGRAPHBUILDER_H_ -#include "Graphs/PTACallGraph.h" #include "Graphs/ThreadCallGraph.h" namespace SVF @@ -39,6 +38,8 @@ namespace SVF class ICFG; class SVFModule; +class CallGraph; +class ThreadCallGraph; class CallGraphBuilder { @@ -46,7 +47,10 @@ class CallGraphBuilder CallGraphBuilder()=default; /// Buidl SVFIR callgraoh - PTACallGraph* buildSVFIRCallGraph(SVFModule* svfModule); + CallGraph* buildSVFIRCallGraph(SVFModule* svfModule); + + /// Buidl PTA callgraoh + PTACallGraph* buildPTACallGraph(); /// Build thread-aware callgraph ThreadCallGraph* buildThreadCallGraph(); diff --git a/svf/lib/Graphs/CallGraph.cpp b/svf/lib/Graphs/CallGraph.cpp new file mode 100644 index 000000000..6b6fe35b4 --- /dev/null +++ b/svf/lib/Graphs/CallGraph.cpp @@ -0,0 +1,211 @@ +//===- CallGraph.cpp -- Call graph used internally in SVF------------------// +// +// 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 . +// +//===----------------------------------------------------------------------===// + + +/* + * CallGraph.cpp + * + * Created on: Nov 7, 2013 + * Author: Yulei Sui + */ + +#include "Graphs/CallGraph.h" +#include "SVFIR/SVFIR.h" +#include "SVFIR/SVFModule.h" +#include "Util/SVFUtil.h" +#include + +using namespace SVF; +using namespace SVFUtil; + + +/// Add direct callsite +//@{ +void CallGraphEdge::addDirectCallSite(const CallICFGNode* call) +{ + assert(call->getCalledFunction() && "not a direct callsite??"); + directCalls.insert(call); +} +//@} + +const std::string CallGraphEdge::toString() const +{ + std::string str; + std::stringstream rawstr(str); + rawstr << "CallICFGNode ID: " << getEdgeKindWithoutMask(); + rawstr << "direct call"; + rawstr << "[" << getDstID() << "<--" << getSrcID() << "]\t"; + return rawstr.str(); +} + +const std::string CallGraphNode::toString() const +{ + std::string str; + std::stringstream rawstr(str); + rawstr << "CallGraphNode ID: " << getId() << " {fun: " << fun->getName() << "}"; + return rawstr.str(); +} + + +/// Constructor +CallGraph::CallGraph() +{ + callGraphNodeNum = 0; +} + + +/*! + * Memory has been cleaned up at GenericGraph + */ +void CallGraph::destroy() +{ +} + +/*! + * Add call graph node + */ +void CallGraph::addCallGraphNode(const SVFFunction* fun) +{ + NodeID id = callGraphNodeNum; + CallGraphNode*callGraphNode = new CallGraphNode(id, fun); + addGNode(id, callGraphNode); + funToCallGraphNodeMap[callGraphNode->getFunction()] = callGraphNode; + callGraphNodeNum++; +} + +/*! + * Whether we have already created this call graph edge + */ +CallGraphEdge* CallGraph::hasGraphEdge(CallGraphNode* src, + CallGraphNode* dst, + const CallICFGNode* callIcfgNode) const +{ + CallGraphEdge edge(src,dst,callIcfgNode); + CallGraphEdge* outEdge = src->hasOutgoingEdge(&edge); + CallGraphEdge* inEdge = dst->hasIncomingEdge(&edge); + if (outEdge && inEdge) + { + assert(outEdge == inEdge && "edges not match"); + return outEdge; + } + else + return nullptr; +} + +/*! + * Add direct call edges + */ +void CallGraph::addDirectCallGraphEdge(const CallICFGNode* cs,const SVFFunction* callerFun, const SVFFunction* calleeFun) +{ + + CallGraphNode* caller = getCallGraphNode(callerFun); + CallGraphNode* callee = getCallGraphNode(calleeFun); + + + if(!hasGraphEdge(caller,callee, cs)) + { + CallGraphEdge* edge = new CallGraphEdge(caller,callee, cs); + edge->addDirectCallSite(cs); + addEdge(edge); + callinstToCallGraphEdgesMap[cs].insert(edge); + } +} + +/*! + * Dump call graph into dot file + */ +void CallGraph::dump(const std::string& filename) +{ + GraphPrinter::WriteGraphToFile(outs(), filename, this); +} + +void CallGraph::view() +{ + SVF::ViewGraph(this, "Call Graph"); +} + +namespace SVF +{ + +/*! + * Write value flow graph into dot file for debugging + */ +template<> +struct DOTGraphTraits : public DefaultDOTGraphTraits +{ + + typedef CallGraphNode NodeType; + typedef NodeType::iterator ChildIteratorType; + DOTGraphTraits(bool isSimple = false) : + DefaultDOTGraphTraits(isSimple) + { + } + + /// Return name of the graph + static std::string getGraphName(CallGraph*) + { + return "Call Graph"; + } + /// Return function name; + static std::string getNodeLabel(CallGraphNode*node, CallGraph*) + { + return node->toString(); + } + + static std::string getNodeAttributes(CallGraphNode*node, CallGraph*) + { + const SVFFunction* fun = node->getFunction(); + if (!SVFUtil::isExtCall(fun)) + { + return "shape=box"; + } + else + return "shape=Mrecord"; + } + + template + static std::string getEdgeAttributes(CallGraphNode*, EdgeIter EI, + CallGraph*) + { + + //TODO: mark indirect call of Fork with different color + CallGraphEdge* edge = *(EI.getCurrent()); + assert(edge && "No edge found!!"); + + std::string color = "color=black"; + return color; + } + + template + static std::string getEdgeSourceLabel(NodeType*, EdgeIter EI) + { + CallGraphEdge* edge = *(EI.getCurrent()); + assert(edge && "No edge found!!"); + + std::string str; + std::stringstream rawstr(str); + rawstr << edge->getEdgeKindWithoutMask(); + + return rawstr.str(); + } +}; +} // End namespace llvm diff --git a/svf/lib/Graphs/PTACallGraph.cpp b/svf/lib/Graphs/PTACallGraph.cpp index 8efffdd29..7c30f3828 100644 --- a/svf/lib/Graphs/PTACallGraph.cpp +++ b/svf/lib/Graphs/PTACallGraph.cpp @@ -29,6 +29,7 @@ */ #include "Graphs/PTACallGraph.h" +#include "Graphs/CallGraph.h" #include "SVFIR/SVFIR.h" #include "SVFIR/SVFModule.h" #include "Util/SVFUtil.h" @@ -39,8 +40,7 @@ using namespace SVFUtil; PTACallGraph::CallSiteToIdMap PTACallGraph::csToIdMap; PTACallGraph::IdToCallSiteMap PTACallGraph::idToCSMap; -CallSiteID PTACallGraph::totalCallSiteNum = 1; - +CallSiteID PTACallGraph::totalCallSiteNum=1; /// Add direct and indirect callsite //@{ @@ -113,16 +113,16 @@ PTACallGraph::PTACallGraph(CGEK k): kind(k) } /// Copy constructor -PTACallGraph::PTACallGraph(const PTACallGraph& other) +PTACallGraph::PTACallGraph(const CallGraph& other) { - callGraphNodeNum = other.callGraphNodeNum; + callGraphNodeNum = other.getTotalNodeNum(); numOfResolvedIndCallEdge = 0; - kind = other.kind; + kind = NormCallGraph; /// copy call graph nodes for (const auto& item : other) { - const PTACallGraphNode* cgn = item.second; + const CallGraphNode* cgn = item.second; PTACallGraphNode* callGraphNode = new PTACallGraphNode(cgn->getId(), cgn->getFunction()); addGNode(cgn->getId(),callGraphNode); funToCallGraphNodeMap[cgn->getFunction()] = callGraphNode; @@ -132,11 +132,13 @@ PTACallGraph::PTACallGraph(const PTACallGraph& other) for (const auto& item : other.callinstToCallGraphEdgesMap) { const CallICFGNode* cs = item.first; - for (const PTACallGraphEdge* edge : item.second) + for (const CallGraphEdge* edge : item.second) { PTACallGraphNode* src = getCallGraphNode(edge->getSrcID()); PTACallGraphNode* dst = getCallGraphNode(edge->getDstID()); - PTACallGraphEdge* newEdge = new PTACallGraphEdge(src,dst, PTACallGraphEdge::CallRetEdge,edge->getCallSiteID()); + CallSiteID csId = addCallSite(cs, dst->getFunction()); + + PTACallGraphEdge* newEdge = new PTACallGraphEdge(src,dst, PTACallGraphEdge::CallRetEdge,csId); newEdge->addDirectCallSite(cs); addEdge(newEdge); callinstToCallGraphEdgesMap[cs].insert(newEdge); @@ -152,18 +154,6 @@ void PTACallGraph::destroy() { } -/*! - * Add call graph node - */ -void PTACallGraph::addCallGraphNode(const SVFFunction* fun) -{ - NodeID id = callGraphNodeNum; - PTACallGraphNode*callGraphNode = new PTACallGraphNode(id, fun); - addGNode(id, callGraphNode); - funToCallGraphNodeMap[callGraphNode->getFunction()] = callGraphNode; - callGraphNodeNum++; -} - /*! * Whether we have already created this call graph edge */ @@ -200,25 +190,6 @@ PTACallGraphEdge* PTACallGraph::getGraphEdge(PTACallGraphNode* src, return nullptr; } -/*! - * Add direct call edges - */ -void PTACallGraph::addDirectCallGraphEdge(const CallICFGNode* cs,const SVFFunction* callerFun, const SVFFunction* calleeFun) -{ - - PTACallGraphNode* caller = getCallGraphNode(callerFun); - PTACallGraphNode* callee = getCallGraphNode(calleeFun); - - CallSiteID csId = addCallSite(cs, callee->getFunction()); - - if(!hasGraphEdge(caller,callee, PTACallGraphEdge::CallRetEdge,csId)) - { - PTACallGraphEdge* edge = new PTACallGraphEdge(caller,callee, PTACallGraphEdge::CallRetEdge,csId); - edge->addDirectCallSite(cs); - addEdge(edge); - callinstToCallGraphEdgesMap[cs].insert(edge); - } -} /*! * Add indirect call edge to update call graph diff --git a/svf/lib/Graphs/ThreadCallGraph.cpp b/svf/lib/Graphs/ThreadCallGraph.cpp index 3d232d931..4bf7272d7 100644 --- a/svf/lib/Graphs/ThreadCallGraph.cpp +++ b/svf/lib/Graphs/ThreadCallGraph.cpp @@ -39,8 +39,8 @@ using namespace SVFUtil; /*! * Constructor */ -ThreadCallGraph::ThreadCallGraph(const PTACallGraph& cg) : - PTACallGraph(cg), tdAPI(ThreadAPI::getThreadAPI()) +ThreadCallGraph::ThreadCallGraph(const CallGraph& cg) : + PTACallGraph(cg), tdAPI(ThreadAPI::getThreadAPI()) { kind = ThdCallGraph; DBOUT(DGENERAL, outs() << SVFUtil::pasMsg("Building ThreadCallGraph\n")); diff --git a/svf/lib/MSSA/MemRegion.cpp b/svf/lib/MSSA/MemRegion.cpp index 5d194507b..71f9d4c25 100644 --- a/svf/lib/MSSA/MemRegion.cpp +++ b/svf/lib/MSSA/MemRegion.cpp @@ -31,6 +31,7 @@ #include "SVFIR/SVFModule.h" #include "MSSA/MemRegion.h" #include "MSSA/MSSAMuChi.h" +#include "Graphs/CallGraph.h" using namespace SVF; using namespace SVFUtil; @@ -173,7 +174,7 @@ SVFIR::SVFStmtList& MRGenerator::getPAGEdgesFromInst(const ICFGNode* node) void MRGenerator::collectModRefForLoadStore() { - PTACallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph(); + CallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph(); for (const auto& item: *svfirCallGraph) { const SVFFunction& fun = *item.second->getFunction(); diff --git a/svf/lib/MSSA/MemSSA.cpp b/svf/lib/MSSA/MemSSA.cpp index 2aaac4260..b239c3e64 100644 --- a/svf/lib/MSSA/MemSSA.cpp +++ b/svf/lib/MSSA/MemSSA.cpp @@ -31,6 +31,7 @@ #include "MSSA/MemPartition.h" #include "MSSA/MemSSA.h" #include "Graphs/SVFGStat.h" +#include "Graphs/CallGraph.h" using namespace SVF; using namespace SVFUtil; @@ -575,7 +576,7 @@ u32_t MemSSA::getBBPhiNum() const void MemSSA::dumpMSSA(OutStream& Out) { - PTACallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph(); + CallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph(); for (const auto& item: *svfirCallGraph) { const SVFFunction* fun = item.second->getFunction(); diff --git a/svf/lib/MSSA/SVFGBuilder.cpp b/svf/lib/MSSA/SVFGBuilder.cpp index 4e5b2484b..95a181f3c 100644 --- a/svf/lib/MSSA/SVFGBuilder.cpp +++ b/svf/lib/MSSA/SVFGBuilder.cpp @@ -33,6 +33,8 @@ #include "Graphs/SVFG.h" #include "MSSA/SVFGBuilder.h" #include "WPA/Andersen.h" +#include "Graphs/CallGraph.h" + using namespace SVF; using namespace SVFUtil; @@ -101,7 +103,7 @@ std::unique_ptr SVFGBuilder::buildMSSA(BVDataPTAImpl* pta, bool ptrOnlyM auto mssa = std::make_unique(pta, ptrOnlyMSSA); - PTACallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph(); + CallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph(); for (const auto& item: *svfirCallGraph) { diff --git a/svf/lib/MTA/TCT.cpp b/svf/lib/MTA/TCT.cpp index 547aaba40..752654176 100644 --- a/svf/lib/MTA/TCT.cpp +++ b/svf/lib/MTA/TCT.cpp @@ -31,6 +31,7 @@ #include "Util/Options.h" #include "MTA/TCT.h" #include "MTA/MTA.h" +#include "Graphs/CallGraph.h" #include @@ -185,7 +186,7 @@ void TCT::markRelProcs(const SVFFunction* svffun) */ void TCT::collectEntryFunInCallGraph() { - PTACallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph(); + CallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph(); for (const auto& item: *svfirCallGraph) { const SVFFunction* fun = item.second->getFunction(); diff --git a/svf/lib/MemoryModel/PointerAnalysis.cpp b/svf/lib/MemoryModel/PointerAnalysis.cpp index 32520fe12..9f4a8122a 100644 --- a/svf/lib/MemoryModel/PointerAnalysis.cpp +++ b/svf/lib/MemoryModel/PointerAnalysis.cpp @@ -116,8 +116,8 @@ void PointerAnalysis::initialize() } else { - PTACallGraph* cg = pag->getCallGraph(); - callgraph = new PTACallGraph(*cg); + CallGraphBuilder bd; + callgraph = bd.buildPTACallGraph(); } callGraphSCCDetection(); diff --git a/svf/lib/SABER/SaberCondAllocator.cpp b/svf/lib/SABER/SaberCondAllocator.cpp index ba9dff0a4..518b812a1 100644 --- a/svf/lib/SABER/SaberCondAllocator.cpp +++ b/svf/lib/SABER/SaberCondAllocator.cpp @@ -35,6 +35,7 @@ #include #include #include "SVFIR/SVFStatements.h" +#include "Graphs/CallGraph.h" using namespace SVF; using namespace SVFUtil; @@ -59,7 +60,7 @@ void SaberCondAllocator::allocate(const SVFModule *M) { DBOUT(DGENERAL, outs() << pasMsg("path condition allocation starts\n")); - PTACallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph(); + CallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph(); for (const auto& item: *svfirCallGraph) { const SVFFunction *func = (item.second)->getFunction(); diff --git a/svf/lib/SVFIR/SVFIR.cpp b/svf/lib/SVFIR/SVFIR.cpp index 311dd8249..b79145c27 100644 --- a/svf/lib/SVFIR/SVFIR.cpp +++ b/svf/lib/SVFIR/SVFIR.cpp @@ -29,6 +29,7 @@ #include "Util/Options.h" #include "SVFIR/SVFIR.h" +#include "Graphs/CallGraph.h" using namespace SVF; using namespace SVFUtil; diff --git a/svf/lib/Util/CDGBuilder.cpp b/svf/lib/Util/CDGBuilder.cpp index dd3dbb0e7..12739ad65 100644 --- a/svf/lib/Util/CDGBuilder.cpp +++ b/svf/lib/Util/CDGBuilder.cpp @@ -27,7 +27,7 @@ * Author: Xiao Cheng */ #include "Util/CDGBuilder.h" -#include "Graphs/PTACallGraph.h" +#include "Graphs/CallGraph.h" using namespace SVF; using namespace SVFUtil; @@ -123,7 +123,7 @@ s64_t CDGBuilder::getBBSuccessorBranchID(const SVFBasicBlock *BB, const SVFBasic */ void CDGBuilder::buildControlDependence(const SVFModule *svfgModule) { - PTACallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph(); + CallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph(); for (const auto& item: *svfirCallGraph) { const SVFFunction *svfFun = (item.second)->getFunction(); diff --git a/svf/lib/Util/CallGraphBuilder.cpp b/svf/lib/Util/CallGraphBuilder.cpp index a0fa7a952..ba01d4d1f 100644 --- a/svf/lib/Util/CallGraphBuilder.cpp +++ b/svf/lib/Util/CallGraphBuilder.cpp @@ -32,13 +32,15 @@ #include "Util/CallGraphBuilder.h" #include "Graphs/ICFG.h" #include "SVFIR/SVFIR.h" +#include "Graphs/CallGraph.h" +#include "Graphs/ThreadCallGraph.h" using namespace SVF; using namespace SVFUtil; -PTACallGraph* CallGraphBuilder::buildSVFIRCallGraph(SVFModule* svfModule) +CallGraph* CallGraphBuilder::buildSVFIRCallGraph(SVFModule* svfModule) { - PTACallGraph* callgraph = new PTACallGraph(); + CallGraph* callgraph = new CallGraph(); for (const SVFFunction* svfFunc: svfModule->getFunctionSet()) { callgraph->addCallGraphNode(svfFunc); @@ -64,9 +66,15 @@ PTACallGraph* CallGraphBuilder::buildSVFIRCallGraph(SVFModule* svfModule) return callgraph; } +PTACallGraph* CallGraphBuilder::buildPTACallGraph() +{ + CallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph(); + return new PTACallGraph(*svfirCallGraph); +} + ThreadCallGraph* CallGraphBuilder::buildThreadCallGraph() { - PTACallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph(); + CallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph(); ThreadCallGraph* cg = new ThreadCallGraph(*svfirCallGraph); ThreadAPI* tdAPI = ThreadAPI::getThreadAPI(); diff --git a/svf/lib/Util/SVFStat.cpp b/svf/lib/Util/SVFStat.cpp index 2bd350e4a..717354a38 100644 --- a/svf/lib/Util/SVFStat.cpp +++ b/svf/lib/Util/SVFStat.cpp @@ -29,6 +29,7 @@ #include "Util/Options.h" #include "Util/SVFStat.h" +#include "Graphs/CallGraph.h" using namespace SVF; using namespace std; @@ -216,7 +217,7 @@ void SVFStat::branchStat() { u32_t numOfBB_2Succ = 0; u32_t numOfBB_3Succ = 0; - PTACallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph(); + CallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph(); for (const auto& item: *svfirCallGraph) { const SVFFunction* func = item.second->getFunction(); diff --git a/svf/lib/Util/SVFUtil.cpp b/svf/lib/Util/SVFUtil.cpp index 46d893af2..bf7282945 100644 --- a/svf/lib/Util/SVFUtil.cpp +++ b/svf/lib/Util/SVFUtil.cpp @@ -30,6 +30,7 @@ #include "Util/Options.h" #include "Util/SVFUtil.h" #include "MemoryModel/PointsTo.h" +#include "Graphs/CallGraph.h" #include /// increase stack size @@ -401,10 +402,10 @@ bool SVFUtil::isProgExitCall(const CallICFGNode* cs) /// Get program entry function from module. const SVFFunction* SVFUtil::getProgFunction(const std::string& funName) { - PTACallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph(); + CallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph(); for (const auto& item: *svfirCallGraph) { - const PTACallGraphNode*fun = item.second; + const CallGraphNode*fun = item.second; if (fun->getName()==funName) return fun->getFunction(); } @@ -414,10 +415,10 @@ const SVFFunction* SVFUtil::getProgFunction(const std::string& funName) /// Get program entry function from module. const SVFFunction* SVFUtil::getProgEntryFunction() { - PTACallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph(); + CallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph(); for (const auto& item: *svfirCallGraph) { - const PTACallGraphNode*fun = item.second; + const CallGraphNode*fun = item.second; if (isProgEntryFunction(fun->getFunction())) return (fun->getFunction()); } diff --git a/svf/lib/Util/ThreadAPI.cpp b/svf/lib/Util/ThreadAPI.cpp index 5739d8eac..6e5bbbf9c 100644 --- a/svf/lib/Util/ThreadAPI.cpp +++ b/svf/lib/Util/ThreadAPI.cpp @@ -32,7 +32,7 @@ #include "Util/ThreadAPI.h" #include "Util/SVFUtil.h" -#include "Graphs/PTACallGraph.h" +#include "Graphs/CallGraph.h" #include "SVFIR/SVFIR.h" #include /// std output @@ -270,7 +270,7 @@ void ThreadAPI::performAPIStat(SVFModule* module) statInit(tdAPIStatMap); - PTACallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph(); + CallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph(); for (const auto& item: *svfirCallGraph) { for (SVFFunction::const_iterator bit = (item.second)->getFunction()->begin(), ebit = (item.second)->getFunction()->end(); bit != ebit; ++bit)