68 return n.raw !=
nullptr ?
n.raw->toString() :
"";
73 std::string
str =
"shape=record";
75 if (SVFUtil::isa<FunEntryICFGNode>(node))
76 str +=
",color=yellow";
77 else if (SVFUtil::isa<FunExitICFGNode>(node))
78 str +=
",color=green";
79 else if (SVFUtil::isa<CallICFGNode>(node))
81 else if (SVFUtil::isa<RetICFGNode>(node))
83 else if (SVFUtil::isa<GlobalICFGNode>(node))
84 str +=
",color=purple";
86 str +=
",color=black";
91 template <
class EdgeIter>
96 return "style=dashed,color=gray";
98 return "style=solid,color=red";
100 return "style=solid,color=blue";
101 return "style=solid";
117 return "SlicedThreadCallGraph";
127 return n.raw !=
nullptr ?
n.raw->getName() :
"";
132 return "shape=record,color=black";
135 template <
class EdgeIter>
140 return "color=green";
143 return "color=black";
169 return n.raw !=
nullptr ?
n.raw->toString() :
"";
174 return "shape=record,color=black";
177 template <
class EdgeIter>
180 const SVFStmt*
s =
EI.currentEdge().underlying;
181 if (SVFUtil::isa<LoadStmt>(
s))
183 if (SVFUtil::isa<StoreStmt>(
s))
185 if (SVFUtil::isa<GepStmt>(
s))
186 return "color=purple";
187 if (SVFUtil::isa<AddrStmt>(
s))
188 return "color=green";
189 if (SVFUtil::isa<CallPE>(
s))
190 return "color=orange";
191 if (SVFUtil::isa<RetPE>(
s))
193 return "color=black";
219 return n.raw !=
nullptr ?
n.raw->toString() :
"";
224 if (SVFUtil::isa<StoreSVFGNode>(
n.raw))
225 return "shape=record,color=red";
226 if (SVFUtil::isa<LoadSVFGNode>(
n.raw))
227 return "shape=record,color=blue";
228 return "shape=record,color=black";
231 template <
class EdgeIter>
234 const SVFGEdge* e =
EI.currentEdge().underlying;
235 if (e !=
nullptr && SVFUtil::isa<IndirectSVFGEdge>(e))
236 return "style=dashed";
237 return "style=solid";
259 assert(
svfg !=
nullptr &&
"SlicedSVFGView: bind the SVFG before dumping");
279 const ICFGNode* node, std::vector<const ICFGNode*>&
out)
const
288 for (
auto it = GT::child_begin(
n), e = GT::child_end(
n); it != e; ++it)
289 out.push_back((*it).raw);
293 const ICFGNode* node, std::vector<const ICFGNode*>&
out)
const
302 for (
auto it = GT::child_begin(
n), e = GT::child_end(
n); it != e; ++it)
303 out.push_back((*it).raw);
339 std::vector<const ICFGNode*>
removed;
359 const CallICFGNode* call = SVFUtil::dyn_cast<CallICFGNode>(it->second);
363 if (
edge !=
nullptr && SVFUtil::isa<CallCFGEdge>(
edge) &&
373 std::vector<std::vector<const ICFGNode*>>
375 std::vector<const ICFGNode*> successors;
405 std::vector<std::pair<int, size_t>>
work;
406 work.emplace_back(root, 0);
407 while (!
work.empty())
473 std::vector<OrderedSet<const ICFGNode*>>
511 <<
"[ERROR] Local ICFG successor is neither kept nor indexed\n";
528 <<
" source nodes\n";
534 std::vector<const ICFGNode*>& successors)
538 if (
edge !=
nullptr && SVFUtil::isa<IntraCFGEdge>(
edge) &&
539 edge->getDstNode() !=
nullptr)
540 successors.push_back(
edge->getDstNode());
552 : pag(pag), keptStmts(keptStmts)
570 SVFUtil::dyn_cast<MultiOpndStmt>(stmt))
613 if (node !=
nullptr && node->
getFunction() !=
nullptr &&
632 for (
auto it = GT::child_edge_begin(
n), e = GT::child_edge_end(
n); it != e; ++it)
633 out.push_back((*it).underlying);
646 for (
auto it = GT::child_edge_begin(
n), e = GT::child_edge_end(
n); it != e; ++it)
647 out.push_back((*it).underlying);
688 std::vector<const CallGraphEdge*>
outEdges;
701 std::vector<const CallGraphEdge*>&
out)
const
720 std::vector<const CallGraphEdge*>&
out)
const
771 !
edge->getDirectCalls().empty() || !
edge->getIndirectCalls().empty();
823 if (node !=
nullptr && node->getFun() !=
nullptr)
834 tcgView = std::make_unique<SlicedThreadCallGraphView>(
838 icfgView = std::make_unique<SlicedICFGView>(
855 pagView = std::make_unique<SlicedPAGView>(
svfir, keptStmts);
874 SVFUtil::outs() <<
" Indirect callsites that lost all targets: "
918 std::vector<const ICFGNode*>&
out)
const
Set< const CallICFGNode * > CallInstSet
const FunObjVar * getFunction() const
Get function of this call node.
bool hasIndCSCallees(const CallICFGNode *cs) const
const CallGraphNode * getCallGraphNode(const std::string &name) const
Get call graph node.
Set< const FunObjVar * > FunctionSet
const RetICFGNode * getRetICFGNode() const
Return callsite.
const SVFBasicBlock * getEntryBlock() const
GEdgeKind getEdgeKind() const
iterator begin()
Iterators.
IDToNodeMapTy::iterator iterator
Node Iterators.
const GEdgeSetTy & getOutEdges() const
static void WriteGraphToFile(SVF::OutStream &O, const std::string &GraphName, const GraphType >, bool simple=false)
std::list< const SVFStmt * > SVFStmtList
ICFGNodeIDToNodeMapTy::iterator iterator
FunExitICFGNode * getFunExitICFGNode(const FunObjVar *fun)
Add a function exit node.
FunEntryICFGNode * getFunEntryICFGNode(const FunObjVar *fun)
Add a function entry node.
const std::vector< const ICFGNode * > & getICFGNodeList() const
const ICFGNode * front() const
static void getLocalSuccessors(const ICFGNode *node, const Map< const ICFGNode *, const ICFGNode * > &callsiteReturnNodes, std::vector< const ICFGNode * > &successors)
const ICFGNode * getFunExit(const FunObjVar *fun) const
Kept synthetic exit node of fun, or null when fun is outside the view.
Set< const ICFGNode * > keptNodesSet
void getPredNodes(const ICFGNode *node, std::vector< const ICFGNode * > &out) const
Get predecessor nodes (including bridged edges)
Map< const ICFGNode *, OrderedSet< const ICFGNode * > > bridgedPreds
void dump(const std::string &filename) const
Dump sliced ICFG to dot file.
bool isKeptNode(const ICFGNode *node) const
Check if a node is in the sliced view.
SlicedICFGView(ICFG *icfg, const OrderedSet< const ICFGNode * > &keepNodes)
Build an ICFG view from its explicit node membership.
void getSuccNodes(const ICFGNode *node, std::vector< const ICFGNode * > &out) const
Get successor nodes (including bridged edges)
Map< const ICFGNode *, OrderedSet< const ICFGNode * > > bridgedEdges
const ICFGNode * getFunEntry(const FunObjVar *fun) const
First kept node of fun's entry, or null when fun is outside the view.
void buildICFGSets(const OrderedSet< const ICFGNode * > &keepNodes)
void getFunICFGNodes(const FunObjVar *fun, std::vector< const ICFGNode * > &out) const
Kept ICFG nodes of fun.
OrderedSet< const ICFGNode * > keptNodes
SlicedPAGView(SVFIR *pag, const OrderedSet< const SVFStmt * > &keptStmts)
Set< NodeID > keptNodeIds
void dump(const std::string &filename) const
Dump the sliced PAG to a dot file.
OrderedSet< const SVFStmt * > keptStmts
size_t getKeptNodeCount() const
bool isKeptNode(const SVFGNode *n) const
Whether the node is retained (see the class comment for the rule).
void dump(const std::string &filename) const
Dump the sliced SVFG (retained nodes/edges only) via GraphWriter.
const Set< const FunObjVar * > & getKeptFunctions() const
Get all kept functions.
std::unique_ptr< SlicedPAGView > pagView
std::unique_ptr< SlicedThreadCallGraphView > tcgView
void dumpAll(const std::string &prefix) const
Dump all views to files.
std::unique_ptr< SlicedICFGView > icfgView
const SlicedPAGView * getPAG() const
Get SlicedPAGView.
void dumpStats(const std::string &prefix="") const
Output statistics.
SlicedSVFIRView(SVFIR *svfir, ThreadCallGraph &callGraph, ICFG *icfg, const OrderedSet< const ICFGNode * > &keepNodes)
const OrderedSet< const SVFStmt * > & getKeptStatements() const
Get all kept statements.
void ensurePAGView() const
const Set< const CallICFGNode * > & getIndirectSitesWithEmptyTargets() const
Get indirect call sites that lost all targets after filtering.
void getCalleesOf(const CallICFGNode *callSite, CallGraph::FunctionSet &callees) const
Retained callees of a callsite.
void getDirectCallsOf(const CallGraphEdge *edge, std::vector< const CallICFGNode * > &out) const
Retained callsites carried by an aggregated call-graph edge.
void buildCallGraphSets()
bool isKeptNode(const CallGraphNode *node) const
Check if a node is in the sliced view.
void dump(const std::string &filename) const
Dump sliced ThreadCallGraph to dot file.
OrderedSet< const CallGraphNode * > keptNodes
Set< const CallGraphEdge * > keptEdges
bool containsCallSite(const CallGraphEdge *edge, const CallICFGNode *callSite) const
Whether this precise callsite-to-callee relation is retained.
void getIndirectCallsOf(const CallGraphEdge *edge, std::vector< const CallICFGNode * > &out) const
Set< const FunObjVar * > keptFunctionsSet
Map< const CallGraphEdge *, CallGraphEdge::CallInstSet > keptDirectCalls
void getForkEdgesOf(const CallICFGNode *callSite, std::vector< const CallGraphEdge * > &out) const
void getOutEdgesOf(const CallGraphNode *node, std::vector< const CallGraphEdge * > &out) const
Get out edges of a node (only returns kept edges and target nodes)
Set< const CallICFGNode * > indirectSitesWithEmptyTargets
void getInEdgesOf(const CallGraphNode *node, std::vector< const CallGraphEdge * > &out) const
Get in edges of a node (only returns kept edges and source nodes)
void getJoinEdgesOf(const CallICFGNode *callSite, std::vector< const CallGraphEdge * > &out) const
Map< const CallGraphEdge *, CallGraphEdge::CallInstSet > keptIndirectCalls
OrderedSet< const ICFGNode * > extendedKeptNodes
SlicedThreadCallGraphView(ThreadCallGraph *tcg, const OrderedSet< const FunObjVar * > &keptFunctions, const OrderedSet< const ICFGNode * > &extendedKeptNodes)
bool test(unsigned Idx) const
bool hasThreadJoinEdge(const CallICFGNode *cs) const
Get call graph edge via call instruction.
JoinEdgeSet::const_iterator getJoinEdgeEnd(const CallICFGNode *cs) const
ForkEdgeSet::const_iterator getForkEdgeEnd(const CallICFGNode *cs) const
ForkEdgeSet::const_iterator getForkEdgeBegin(const CallICFGNode *cs) const
bool hasThreadForkEdge(const CallICFGNode *cs) const
Get call graph edge via call instruction.
JoinEdgeSet::const_iterator getJoinEdgeBegin(const CallICFGNode *cs) const
std::ostream & errs()
Overwrite llvm::errs()
std::ostream & outs()
Overwrite llvm::outs()
llvm::IRBuilder IRBuilder
std::string getNodeLabel(SlicedICFGNodeRef n, const SlicedICFGView *)
static std::string getNodeAttributes(SlicedICFGNodeRef n, const SlicedICFGView *)
static std::string getEdgeAttributes(SlicedICFGNodeRef, EdgeIter EI, const SlicedICFGView *)
static std::string getGraphName(const SlicedICFGView *)
static const void * getNodeIdentifier(SlicedICFGNodeRef n)
DOTGraphTraits(bool isSimple=false)
std::string getNodeLabel(SlicedPAGNodeRef n, const SlicedPAGView *)
static std::string getEdgeAttributes(SlicedPAGNodeRef, EdgeIter EI, const SlicedPAGView *)
static std::string getNodeAttributes(SlicedPAGNodeRef, const SlicedPAGView *)
DOTGraphTraits(bool isSimple=false)
static const void * getNodeIdentifier(SlicedPAGNodeRef n)
static std::string getGraphName(const SlicedPAGView *)
static const void * getNodeIdentifier(SlicedSVFGNodeRef n)
static std::string getNodeAttributes(SlicedSVFGNodeRef n, const SlicedSVFGView *)
DOTGraphTraits(bool isSimple=false)
static std::string getEdgeAttributes(SlicedSVFGNodeRef, EdgeIter EI, const SlicedSVFGView *)
std::string getNodeLabel(SlicedSVFGNodeRef n, const SlicedSVFGView *)
static std::string getGraphName(const SlicedSVFGView *)
static std::string getNodeAttributes(SlicedCallGraphNodeRef, const SlicedThreadCallGraphView *)
std::string getNodeLabel(SlicedCallGraphNodeRef n, const SlicedThreadCallGraphView *)
static const void * getNodeIdentifier(SlicedCallGraphNodeRef n)
DOTGraphTraits(bool isSimple=false)
static std::string getGraphName(const SlicedThreadCallGraphView *)
static std::string getEdgeAttributes(SlicedCallGraphNodeRef, EdgeIter EI, const SlicedThreadCallGraphView *)
const ICFGEdge * underlying