Skip to content

Commit

Permalink
Callgraph (#1570)
Browse files Browse the repository at this point in the history
* creat IR call graph in SVFIR

* use IR call graph to build PTA call graph

* creat IR call graph in SVFIR

* use IR call graph to build PTA call graph

* add buildSVFIRCallGraph

* small fix

* small fix

* add copy constructor for CallGraph

* build a whole callgraph in llvmmodule

* create callgraphnode in calgraphBuilder

* clean code

* change ThreadCallGraphBuilder

* merge ThreadCallGraphBuilder and CallgraphBuilder

remove callgraph field

* small change

* small change

* small change

* remove all fields in CallGraphBuilder

* small change

* small change

---------

Co-authored-by: hwg <[email protected]>
  • Loading branch information
Geoffrey1014 and hwg authored Oct 11, 2024
1 parent e815bb5 commit 5db169c
Show file tree
Hide file tree
Showing 24 changed files with 158 additions and 126 deletions.
1 change: 1 addition & 0 deletions svf-llvm/include/SVF-LLVM/LLVMModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +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
CallGraph* callgraph;

/// Constructor
LLVMModuleSet();
Expand Down
5 changes: 5 additions & 0 deletions svf-llvm/lib/LLVMModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
#include "SVF-LLVM/ObjTypeInference.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "SVF-LLVM/ICFGBuilder.h"
#include "Graphs/CallGraph.h"
#include "Util/CallGraphBuilder.h"

using namespace std;
using namespace SVF;
Expand Down Expand Up @@ -169,6 +171,9 @@ void LLVMModuleSet::build()
initSVFFunction();
ICFGBuilder icfgbuilder;
icfg = icfgbuilder.build();

CallGraphBuilder callGraphBuilder;
callgraph = callGraphBuilder.buildSVFIRCallGraph(svfModule);
}

void LLVMModuleSet::createSVFDataStructure()
Expand Down
4 changes: 4 additions & 0 deletions svf-llvm/lib/SVFIRBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "SVFIR/SVFFileSystem.h"
#include "SVFIR/SVFModule.h"
#include "SVFIR/SVFValue.h"
#include "Util/CallGraphBuilder.h"
#include "Util/Options.h"
#include "Util/SVFUtil.h"

Expand All @@ -62,6 +63,9 @@ SVFIR* SVFIRBuilder::build()
// Build ICFG
pag->setICFG(llvmModuleSet()->getICFG());

// Set callgraph
pag->setCallGraph(llvmModuleSet()->callgraph);

// Set icfgnode in memobj
for (auto& it : SymbolTableInfo::SymbolInfo()->idToObjMap())
{
Expand Down
12 changes: 9 additions & 3 deletions svf/include/Graphs/CallGraph.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,11 @@ class CallGraphNode : public GenericCallGraphNodeTy

}

inline const std::string &getName() const
{
return fun->getName();
}

/// Get function of this call node
inline const SVFFunction* getFunction() const
{
Expand Down Expand Up @@ -254,8 +259,6 @@ class CallGraph : public GenericCallGraphTy
};

private:
CGEK kind;

/// Indirect call map
CallEdgeMap indirectCallMap;

Expand All @@ -270,6 +273,7 @@ class CallGraph : public GenericCallGraphTy

NodeID callGraphNodeNum;
u32_t numOfResolvedIndCallEdge;
CGEK kind;

/// Clean up memory
void destroy();
Expand All @@ -278,7 +282,9 @@ class CallGraph : public GenericCallGraphTy
/// Constructor
CallGraph(CGEK k = NormCallGraph);

/// Add callgraph Node
/// Copy constructor
CallGraph(const CallGraph& other);

void addCallGraphNode(const SVFFunction* fun);

/// Destructor
Expand Down
5 changes: 4 additions & 1 deletion svf/include/Graphs/ThreadCallGraph.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,10 @@ class ThreadCallGraph: public CallGraph
typedef Map<const CallICFGNode*, ParForEdgeSet> CallInstToParForEdgesMap;

/// Constructor
ThreadCallGraph();
ThreadCallGraph(const CallGraph& cg);

ThreadCallGraph(ThreadCallGraph& cg) = delete;

/// Destructor
virtual ~ThreadCallGraph()
{
Expand Down
13 changes: 13 additions & 0 deletions svf/include/SVFIR/SVFIR.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ class SVFIR : public IRGraph
ICFG* icfg; // ICFG
CommonCHGraph* chgraph; // class hierarchy graph
CallSiteSet callSiteSet; /// all the callsites of a program
CallGraph* callGraph; /// call graph

static std::unique_ptr<SVFIR> pag; ///< Singleton pattern here to enable instance of SVFIR can only be created once.

Expand Down Expand Up @@ -182,6 +183,18 @@ class SVFIR : public IRGraph
assert(chgraph && "empty ICFG! Build SVF IR first!");
return chgraph;
}

/// Set/Get CG
inline void setCallGraph(CallGraph* c)
{
callGraph = c;
}
inline CallGraph* getCallGraph()
{
assert(callGraph && "empty CallGraph! Build SVF IR first!");
return callGraph;
}

/// Get/set methods to get SVFStmts based on their kinds and ICFGNodes
//@{
/// Get edges set according to its kind
Expand Down
17 changes: 0 additions & 17 deletions svf/include/SVFIR/SVFModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,23 +130,6 @@ class SVFModule

/// Iterators
///@{
iterator begin()
{
return FunctionSet.begin();
}
const_iterator begin() const
{
return FunctionSet.begin();
}
iterator end()
{
return FunctionSet.end();
}
const_iterator end() const
{
return FunctionSet.end();
}

global_iterator global_begin()
{
return GlobalSet.begin();
Expand Down
26 changes: 5 additions & 21 deletions svf/include/Util/CallGraphBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,34 +38,18 @@ namespace SVF
{

class ICFG;
class SVFModule;

class CallGraphBuilder
{

protected:
CallGraph* callgraph;
ICFG* icfg;
public:
CallGraphBuilder(CallGraph* cg, ICFG* i): callgraph(cg),icfg(i)
{
}

/// Build normal callgraph
CallGraph* buildCallGraph(SVFModule* svfModule);

};
CallGraphBuilder()=default;

class ThreadCallGraphBuilder : public CallGraphBuilder
{

public:
ThreadCallGraphBuilder(ThreadCallGraph* cg, ICFG* i): CallGraphBuilder(cg,i)
{
}
/// Buidl SVFIR callgraoh
CallGraph* buildSVFIRCallGraph(SVFModule* svfModule);

/// Build thread-aware callgraph
CallGraph* buildThreadCallGraph(SVFModule* svfModule);

ThreadCallGraph* buildThreadCallGraph();
};

} // End namespace SVF
Expand Down
26 changes: 4 additions & 22 deletions svf/include/Util/SVFUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -327,29 +327,11 @@ inline bool isProgEntryFunction(const SVFFunction* fun)
return fun && fun->getName() == "main";
}

/// Get program entry function from module.
inline const SVFFunction* getProgFunction(SVFModule* svfModule, const std::string& funName)
{
for (SVFModule::const_iterator it = svfModule->begin(), eit = svfModule->end(); it != eit; ++it)
{
const SVFFunction *fun = *it;
if (fun->getName()==funName)
return fun;
}
return nullptr;
}
/// Get program entry function from function name.
const SVFFunction* getProgFunction(const std::string& funName);

/// Get program entry function from module.
inline const SVFFunction* getProgEntryFunction(SVFModule* svfModule)
{
for (SVFModule::const_iterator it = svfModule->begin(), eit = svfModule->end(); it != eit; ++it)
{
const SVFFunction *fun = *it;
if (isProgEntryFunction(fun))
return (fun);
}
return nullptr;
}
/// Get program entry function.
const SVFFunction* getProgEntryFunction();

/// Return true if this is a program exit function call
//@{
Expand Down
43 changes: 37 additions & 6 deletions svf/lib/Graphs/CallGraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,38 @@ CallGraph::CallGraph(CGEK k): kind(k)
numOfResolvedIndCallEdge = 0;
}

/// Copy constructor
CallGraph::CallGraph(const CallGraph& other) {
callGraphNodeNum = other.callGraphNodeNum;
numOfResolvedIndCallEdge = 0;
kind = other.kind;

/// copy call graph nodes
for (const auto& item : other)
{
const CallGraphNode* cgn = item.second;
CallGraphNode* callGraphNode = new CallGraphNode(cgn->getId(), cgn->getFunction());
addGNode(cgn->getId(),callGraphNode);
funToCallGraphNodeMap[cgn->getFunction()] = callGraphNode;
}

/// copy edges
for (const auto& item : other.callinstToCallGraphEdgesMap)
{
const CallICFGNode* cs = item.first;
for (const CallGraphEdge* edge : item.second)
{
CallGraphNode* src = getCallGraphNode(edge->getSrcID());
CallGraphNode* dst = getCallGraphNode(edge->getDstID());
CallGraphEdge* newEdge = new CallGraphEdge(src,dst,CallGraphEdge::CallRetEdge,edge->getCallSiteID());
newEdge->addDirectCallSite(cs);
addEdge(newEdge);
callinstToCallGraphEdgesMap[cs].insert(newEdge);
}
}

}

/*!
* Memory has been cleaned up at GenericGraph
*/
Expand All @@ -122,12 +154,11 @@ 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[fun] = callGraphNode;
void CallGraph::addCallGraphNode(const SVFFunction* fun) {
NodeID id = callGraphNodeNum;
CallGraphNode *callGraphNode = new CallGraphNode(id, fun);
addGNode(id, callGraphNode);
funToCallGraphNodeMap[callGraphNode->getFunction()] = callGraphNode;
callGraphNodeNum++;
}

Expand Down
4 changes: 1 addition & 3 deletions svf/lib/Graphs/SVFG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -427,9 +427,7 @@ void SVFG::connectIndirectSVFGEdges()
*/
void SVFG::connectFromGlobalToProgEntry()
{
SVFModule* svfModule = mssa->getPTA()->getModule();
const SVFFunction* mainFunc =
SVFUtil::getProgEntryFunction(svfModule);
const SVFFunction* mainFunc = SVFUtil::getProgEntryFunction();
FormalINSVFGNodeSet& formalIns = getFormalINSVFGNodes(mainFunc);
if (formalIns.empty())
return;
Expand Down
5 changes: 3 additions & 2 deletions svf/lib/Graphs/ThreadCallGraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,10 @@ using namespace SVFUtil;
/*!
* Constructor
*/
ThreadCallGraph::ThreadCallGraph() :
CallGraph(ThdCallGraph), tdAPI(ThreadAPI::getThreadAPI())
ThreadCallGraph::ThreadCallGraph(const CallGraph& cg) :
CallGraph(cg), tdAPI(ThreadAPI::getThreadAPI())
{
kind = ThdCallGraph;
DBOUT(DGENERAL, outs() << SVFUtil::pasMsg("Building ThreadCallGraph\n"));
}

Expand Down
7 changes: 3 additions & 4 deletions svf/lib/MSSA/MemRegion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,11 +173,10 @@ SVFIR::SVFStmtList& MRGenerator::getPAGEdgesFromInst(const ICFGNode* node)
void MRGenerator::collectModRefForLoadStore()
{

SVFModule* svfModule = pta->getModule();
for (SVFModule::const_iterator fi = svfModule->begin(), efi = svfModule->end(); fi != efi;
++fi)
CallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph();
for (const auto& item: *svfirCallGraph)
{
const SVFFunction& fun = **fi;
const SVFFunction& fun = *item.second->getFunction();

/// if this function does not have any caller, then we do not care its MSSA
if (Options::IgnoreDeadFun() && fun.isUncalledFunction())
Expand Down
6 changes: 3 additions & 3 deletions svf/lib/MSSA/MemSSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -575,10 +575,10 @@ u32_t MemSSA::getBBPhiNum() const
void MemSSA::dumpMSSA(OutStream& Out)
{

for (SVFModule::iterator fit = pta->getModule()->begin(), efit = pta->getModule()->end();
fit != efit; ++fit)
CallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph();
for (const auto& item: *svfirCallGraph)
{
const SVFFunction* fun = *fit;
const SVFFunction* fun = item.second->getFunction();
if(Options::MSSAFun()!="" && Options::MSSAFun()!=fun->getName())
continue;

Expand Down
7 changes: 3 additions & 4 deletions svf/lib/MSSA/SVFGBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,11 @@ std::unique_ptr<MemSSA> SVFGBuilder::buildMSSA(BVDataPTAImpl* pta, bool ptrOnlyM

auto mssa = std::make_unique<MemSSA>(pta, ptrOnlyMSSA);

SVFModule* svfModule = mssa->getPTA()->getModule();
for (SVFModule::const_iterator iter = svfModule->begin(), eiter = svfModule->end();
iter != eiter; ++iter)
CallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph();
for (const auto& item: *svfirCallGraph)
{

const SVFFunction *fun = *iter;
const SVFFunction *fun = item.second->getFunction();
if (isExtCall(fun))
continue;

Expand Down
5 changes: 3 additions & 2 deletions svf/lib/MTA/TCT.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,10 @@ void TCT::markRelProcs(const SVFFunction* svffun)
*/
void TCT::collectEntryFunInCallGraph()
{
for(SVFModule::const_iterator it = getSVFModule()->begin(), eit = getSVFModule()->end(); it!=eit; ++it)
CallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph();
for (const auto& item: *svfirCallGraph)
{
const SVFFunction* fun = (*it);
const SVFFunction* fun = item.second->getFunction();
if (SVFUtil::isExtCall(fun))
continue;
CallGraphNode* node = tcg->getCallGraphNode(fun);
Expand Down
10 changes: 4 additions & 6 deletions svf/lib/MemoryModel/PointerAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,15 +111,13 @@ void PointerAnalysis::initialize()
/// initialise pta call graph for every pointer analysis instance
if(Options::EnableThreadCallGraph())
{
ThreadCallGraph* cg = new ThreadCallGraph();
ThreadCallGraphBuilder bd(cg, pag->getICFG());
callgraph = bd.buildThreadCallGraph(pag->getModule());
CallGraphBuilder bd;
callgraph = bd.buildThreadCallGraph();
}
else
{
CallGraph* cg = new CallGraph();
CallGraphBuilder bd(cg,pag->getICFG());
callgraph = bd.buildCallGraph(pag->getModule());
CallGraph* cg = pag->getCallGraph();
callgraph = new CallGraph(*cg);
}
callGraphSCCDetection();

Expand Down
4 changes: 3 additions & 1 deletion svf/lib/SABER/SaberCondAllocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,10 @@ void SaberCondAllocator::allocate(const SVFModule *M)
{
DBOUT(DGENERAL, outs() << pasMsg("path condition allocation starts\n"));

for (const auto &func: *M)
CallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph();
for (const auto& item: *svfirCallGraph)
{
const SVFFunction *func = (item.second)->getFunction();
if (!SVFUtil::isExtCall(func))
{
// Allocate conditions for a program.
Expand Down
Loading

0 comments on commit 5db169c

Please sign in to comment.