Static Value-Flow Analysis
Loading...
Searching...
No Matches
ICFG.cpp
Go to the documentation of this file.
1//===- ICFG.cpp -- Sparse value-flow graph-----------------------------------//
2//
3// SVF: Static Value-Flow Analysis
4//
5// Copyright (C) <2013-2018> <Yulei Sui>
6//
7
8// This program is free software: you can redistribute it and/or modify
9// it under the terms of the GNU Affero General Public License as published by
10// the Free Software Foundation, either version 3 of the License, or
11// (at your option) any later version.
12
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU Affero General Public License for more details.
17
18// You should have received a copy of the GNU Affero General Public License
19// along with this program. If not, see <http://www.gnu.org/licenses/>.
20//
21//===----------------------------------------------------------------------===//
22
23/*
24 * ICFG.cpp
25 *
26 * Created on: Sep 11, 2018
27 * Author: Yulei Sui
28 */
29
30#include "Graphs/ICFG.h"
31#include "Graphs/PTACallGraph.h"
32#include "SVFIR/SVFIR.h"
33#include "SVFIR/SVFModule.h"
34#include <Util/Options.h>
35
36using namespace SVF;
37using namespace SVFUtil;
38
39
41{
42 fun = f;
43 // if function is implemented
44 if (f->begin() != f->end())
45 {
46 bb = f->getEntryBlock();
47 }
48}
49
51 : InterICFGNode(id, FunExitBlock), formalRet(nullptr)
52{
53 fun = f;
54 // if function is implemented
55 if (f->begin() != f->end())
56 {
57 bb = f->getExitBB();
58 }
59}
60
61const std::string ICFGNode::toString() const
62{
63 std::string str;
64 std::stringstream rawstr(str);
65 rawstr << "ICFGNode" << getId();
66 return rawstr.str();
67}
68
69void ICFGNode::dump() const
70{
71 outs() << this->toString() << "\n";
72}
73
74const std::string GlobalICFGNode::toString() const
75{
76 std::string str;
77 std::stringstream rawstr(str);
78 rawstr << "GlobalICFGNode" << getId();
79 for (const SVFStmt *stmt : getSVFStmts())
80 rawstr << "\n" << stmt->toString();
81 return rawstr.str();
82}
83
84
85const std::string IntraICFGNode::toString() const
86{
87 std::string str;
88 std::stringstream rawstr(str);
89 rawstr << "IntraICFGNode" << getId();
90 rawstr << " {fun: " << getFun()->getName() << getSourceLoc() << "}";
91 for (const SVFStmt *stmt : getSVFStmts())
92 rawstr << "\n" << stmt->toString();
93 if(getSVFStmts().empty())
94 rawstr << "\n" << valueOnlyToString();
95 return rawstr.str();
96}
97
98
99const std::string FunEntryICFGNode::toString() const
100{
101 std::string str;
102 std::stringstream rawstr(str);
103 rawstr << "FunEntryICFGNode" << getId();
104 rawstr << " {fun: " << getFun()->getName();
105 if (isExtCall(getFun())==false)
106 rawstr << getFun()->getSourceLoc();
107 rawstr << "}";
108 for (const SVFStmt *stmt : getSVFStmts())
109 rawstr << "\n" << stmt->toString();
110 return rawstr.str();
111}
112
113const std::string FunExitICFGNode::toString() const
114{
115 const SVFFunction *fun = getFun();
116 std::string str;
117 std::stringstream rawstr(str);
118 rawstr << "FunExitICFGNode" << getId();
119 rawstr << " {fun: " << fun->getName();
120 // ensure the enclosing function has exit basic block
121 if (!isExtCall(fun) && fun->hasReturn())
123 rawstr << intraICFGNode->getSourceLoc();
124 rawstr << "}";
125 for (const SVFStmt *stmt : getSVFStmts())
126 rawstr << "\n" << stmt->toString();
127 return rawstr.str();
128}
129
130
131const std::string CallICFGNode::toString() const
132{
133 std::string str;
134 std::stringstream rawstr(str);
135 rawstr << "CallICFGNode" << getId();
136 rawstr << " {fun: " << getFun()->getName() << ICFGNode::getSourceLoc() << "}";
137 for (const SVFStmt *stmt : getSVFStmts())
138 rawstr << "\n" << stmt->toString();
139 if(getSVFStmts().empty())
140 rawstr << "\n" << valueOnlyToString();
141 return rawstr.str();
142}
143
144const std::string RetICFGNode::toString() const
145{
146 std::string str;
147 std::stringstream rawstr(str);
148 rawstr << "RetICFGNode" << getId();
149 rawstr << " {fun: " << getFun()->getName() << ICFGNode::getSourceLoc() << "}";
150 for (const SVFStmt *stmt : getSVFStmts())
151 rawstr << "\n" << stmt->toString();
152 if(getSVFStmts().empty())
153 rawstr << "\n" << valueOnlyToString();
154 return rawstr.str();
155}
156
157const std::string ICFGEdge::toString() const
158{
159 std::string str;
160 std::stringstream rawstr(str);
161 rawstr << "ICFGEdge: [ICFGNode" << getDstID() << " <-- ICFGNode" << getSrcID() << "]\t";
162 return rawstr.str();
163}
164
165const std::string IntraCFGEdge::toString() const
166{
167 std::string str;
168 std::stringstream rawstr(str);
169 if(getCondition() == nullptr)
170 rawstr << "IntraCFGEdge: [ICFGNode" << getDstID() << " <-- ICFGNode" << getSrcID() << "]\t";
171 else
172 rawstr << "IntraCFGEdge: [ICFGNode" << getDstID() << " <-- ICFGNode" << getSrcID() << "] (branchCondition:" << getCondition()->toString() << ") (succCondValue: " << getSuccessorCondValue() << ") \t";
173
174 return rawstr.str();
175}
176
177const std::string CallCFGEdge::toString() const
178{
179 std::string str;
180 std::stringstream rawstr(str);
181 rawstr << "CallCFGEdge " << " [ICFGNode";
182 rawstr << getDstID() << " <-- ICFGNode" << getSrcID() << "]\t CallSite: " << getSrcNode()->toString() << "\t";
183 return rawstr.str();
184}
185
186const std::string RetCFGEdge::toString() const
187{
188 std::string str;
189 std::stringstream rawstr(str);
190 rawstr << "RetCFGEdge " << " [ICFGNode";
191 rawstr << getDstID() << " <-- ICFGNode" << getSrcID() << "]\t CallSite: " << getDstNode()->toString() << "\t";
192 return rawstr.str();
193}
194
197{
198 assert(SVFUtil::isa<RetICFGNode>(getDstNode()) && "not a RetICFGNode?");
199 return SVFUtil::cast<RetICFGNode>(getDstNode())->getCallICFGNode();
200}
201
210ICFG::ICFG(): totalICFGNode(0), globalBlockNode(nullptr)
211{
212}
213
215{
217 for (const auto &it: icfgNodeToSVFLoopVec)
218 {
219 for (const auto &loop: it.second)
220 {
221 loops.insert(loop);
222 }
223 }
224
225 for (const auto &it: loops)
226 {
227 delete it;
228 }
229 icfgNodeToSVFLoopVec.clear();
230}
231
232
235{
237 assert (entry && "fun entry not created in ICFGBuilder?");
238 return entry;
239}
242{
243 FunExitICFGNode* exit = getFunExitBlock(fun);
244 assert (exit && "fun exit not created in ICFGBuilder?");
245 return exit;
246}
247
252{
253 ICFGEdge edge(src,dst,kind);
256 if (outEdge && inEdge)
257 {
258 assert(outEdge == inEdge && "edges not match");
259 return outEdge;
260 }
261 else
262 return nullptr;
263}
264
269{
270 ICFGEdge edge(src,dst, kind);
273 if (outEdge && inEdge)
274 {
275 assert(outEdge == inEdge && "edges not match");
276 return outEdge;
277 }
278 else
279 return nullptr;
280}
281
286{
287 ICFGEdge edge(src,dst,kind);
290 if (outEdge && inEdge)
291 {
292 assert(outEdge == inEdge && "edges not match");
293 return outEdge;
294 }
295 else
296 return nullptr;
297}
298
299
304{
305
306 ICFGEdge * edge = nullptr;
307 u32_t counter = 0;
308 for (ICFGEdge::ICFGEdgeSetTy::iterator iter = src->OutEdgeBegin();
309 iter != src->OutEdgeEnd(); ++iter)
310 {
311 if ((*iter)->getDstID() == dst->getId() && (*iter)->getEdgeKind() == kind)
312 {
313 counter++;
314 edge = (*iter);
315 }
316 }
317 assert(counter <= 1 && "there's more than one edge between two ICFG nodes");
318 return edge;
319
320}
321
326{
329 if (edge != nullptr)
330 {
331 assert(edge->isIntraCFGEdge() && "this should be an intra CFG edge!");
332 return nullptr;
333 }
334 else
335 {
337 return (addICFGEdge(intraEdge) ? intraEdge : nullptr);
338 }
339}
340
345{
346
349 if (edge != nullptr)
350 {
351 assert(edge->isIntraCFGEdge() && "this should be an intra CFG edge!");
352 return nullptr;
353 }
354 else
355 {
357 intraEdge->setBranchCondVal(branchCondVal);
358 return (addICFGEdge(intraEdge) ? intraEdge : nullptr);
359 }
360}
361
362
367{
369 if (edge != nullptr)
370 {
371 assert(edge->isCallCFGEdge() && "this should be a call CFG edge!");
372 return nullptr;
373 }
374 else
375 {
377 return (addICFGEdge(callEdge) ? callEdge : nullptr);
378 }
379}
380
385{
387 if (edge != nullptr)
388 {
389 assert(edge->isRetCFGEdge() && "this should be a return CFG edge!");
390 return nullptr;
391 }
392 else
393 {
395 return (addICFGEdge(retEdge) ? retEdge : nullptr);
396 }
397}
398
399
403void ICFG::dump(const std::string& file, bool simple)
404{
406}
407
412{
413 SVF::ViewGraph(this, "Interprocedural Control-Flow Graph");
414}
415
420{
421 PTACallGraph::CallEdgeMap::const_iterator iter = callgraph->getIndCallMap().begin();
422 PTACallGraph::CallEdgeMap::const_iterator eiter = callgraph->getIndCallMap().end();
423 for (; iter != eiter; iter++)
424 {
425 CallICFGNode* callBlockNode = const_cast<CallICFGNode*>(iter->first);
426 assert(callBlockNode->isIndirectCall() && "this is not an indirect call?");
427 const PTACallGraph::FunctionSet & functions = iter->second;
428 for (PTACallGraph::FunctionSet::const_iterator func_iter = functions.begin(); func_iter != functions.end(); func_iter++)
429 {
430 const SVFFunction* callee = *func_iter;
431 RetICFGNode* retBlockNode = const_cast<RetICFGNode*>(callBlockNode->getRetICFGNode());
433 if (isExtCall(callee))
434 addIntraEdge(callBlockNode, retBlockNode);
435 else
436 {
439 if(ICFGEdge* callEdge = addCallEdge(callBlockNode, calleeEntryNode))
440 {
441 for (const SVFStmt *stmt : callBlockNode->getSVFStmts())
442 {
443 if(const CallPE *callPE = SVFUtil::dyn_cast<CallPE>(stmt))
444 {
445 if(callPE->getFunEntryICFGNode() == calleeEntryNode)
446 SVFUtil::cast<CallCFGEdge>(callEdge)->addCallPE(callPE);
447 }
448 }
449 }
451 {
452 for (const SVFStmt *stmt : retBlockNode->getSVFStmts())
453 {
454 if(const RetPE *retPE = SVFUtil::dyn_cast<RetPE>(stmt))
455 {
456 if(retPE->getFunExitICFGNode() == calleeExitNode)
457 SVFUtil::cast<RetCFGEdge>(retEdge)->addRetPE(retPE);
458 }
459 }
460 }
461
465 }
466
467 }
468 }
469 // dump ICFG
470 if (Options::DumpICFG())
471 {
472 dump("icfg_final");
473 }
474}
475
479namespace SVF
480{
481template<>
483{
484
486 DOTGraphTraits(bool isSimple = false) :
487 DOTGraphTraits<SVFIR*>(isSimple)
488 {
489 }
490
492 static std::string getGraphName(ICFG*)
493 {
494 return "ICFG";
495 }
496
497 std::string getNodeLabel(NodeType *node, ICFG *graph)
498 {
499 return getSimpleNodeLabel(node, graph);
500 }
501
503 static std::string getSimpleNodeLabel(NodeType *node, ICFG*)
504 {
505 return node->toString();
506 }
507
508 static bool isNodeHidden(ICFGNode *node, ICFG *)
509 {
511 return false;
512 else
513 return node->getInEdges().empty() && node->getOutEdges().empty();
514 }
515
516 static std::string getNodeAttributes(NodeType *node, ICFG*)
517 {
518 std::string str;
519 std::stringstream rawstr(str);
520
521 if(SVFUtil::isa<IntraICFGNode>(node))
522 {
523 rawstr << "color=black";
524 }
525 else if(SVFUtil::isa<FunEntryICFGNode>(node))
526 {
527 rawstr << "color=yellow";
528 }
529 else if(SVFUtil::isa<FunExitICFGNode>(node))
530 {
531 rawstr << "color=green";
532 }
533 else if(SVFUtil::isa<CallICFGNode>(node))
534 {
535 rawstr << "color=red";
536 }
537 else if(SVFUtil::isa<RetICFGNode>(node))
538 {
539 rawstr << "color=blue";
540 }
541 else if(SVFUtil::isa<GlobalICFGNode>(node))
542 {
543 rawstr << "color=purple";
544 }
545 else
546 assert(false && "no such kind of node!!");
547
548 rawstr << "";
549
550 return rawstr.str();
551 }
552
553 template<class EdgeIter>
554 static std::string getEdgeAttributes(NodeType*, EdgeIter EI, ICFG*)
555 {
556 ICFGEdge* edge = *(EI.getCurrent());
557 assert(edge && "No edge found!!");
558 if (SVFUtil::isa<CallCFGEdge>(edge))
559 return "style=solid,color=red";
560 else if (SVFUtil::isa<RetCFGEdge>(edge))
561 return "style=solid,color=blue";
562 else
563 return "style=solid";
564 return "";
565 }
566
567 template<class EdgeIter>
569 {
570 ICFGEdge* edge = *(EI.getCurrent());
571 assert(edge && "No edge found!!");
572
573 std::string str;
574 std::stringstream rawstr(str);
575 if (CallCFGEdge* dirCall = SVFUtil::dyn_cast<CallCFGEdge>(edge))
576 rawstr << dirCall->getSrcNode();
577 else if (RetCFGEdge* dirRet = SVFUtil::dyn_cast<RetCFGEdge>(edge))
578 {
579 if(RetICFGNode* ret = SVFUtil::dyn_cast<RetICFGNode>(dirRet->getDstNode()))
580 rawstr << ret->getCallICFGNode();
581 }
582
583 return rawstr.str();
584 }
585};
586} // End namespace llvm
virtual const std::string toString() const
Definition ICFG.cpp:177
const std::string toString() const override
Definition ICFG.cpp:131
const RetICFGNode * getRetICFGNode() const
Return callsite.
Definition ICFGNode.h:457
bool isIndirectCall() const
Return true if this is an indirect call.
Definition ICFGNode.h:482
FunEntryICFGNode(NodeID id)
Constructor to create empty FunEntryICFGNode (for SVFIRReader/deserialization)
Definition ICFGNode.h:289
const SVFFunction * getFun() const override
Return function.
Definition ICFGNode.h:295
const std::string toString() const override
Definition ICFG.cpp:99
const std::string toString() const override
Definition ICFG.cpp:113
FunExitICFGNode(NodeID id)
Constructor to create empty FunExitICFGNode (for SVFIRReader/deserialization)
Definition ICFGNode.h:360
const SVFFunction * getFun() const override
Return function.
Definition ICFGNode.h:366
NodeType * getSrcNode() const
NodeType * getDstNode() const
NodeID getDstID() const
NodeID getSrcID() const
get methods of the components
bool hasIncomingEdge() const
Has incoming/outgoing edge set.
bool hasOutgoingEdge() const
iterator OutEdgeEnd()
const GEdgeSetTy & getOutEdges() const
const GEdgeSetTy & getInEdges() const
iterator OutEdgeBegin()
iterators
const std::string toString() const override
Definition ICFG.cpp:74
static void WriteGraphToFile(SVF::OutStream &O, const std::string &GraphName, const GraphType &GT, bool simple=false)
virtual const std::string toString() const
Definition ICFG.cpp:157
const SVFFunction * fun
Definition ICFGNode.h:148
const SVFBasicBlock * bb
Definition ICFGNode.h:149
virtual const SVFFunction * getFun() const
Return the function of this ICFGNode.
Definition ICFGNode.h:76
void dump() const
Definition ICFG.cpp:69
virtual const std::string toString() const
Definition ICFG.cpp:61
const SVFStmtList & getSVFStmts() const
Definition ICFGNode.h:117
void view()
View graph from the debugger.
Definition ICFG.cpp:411
FunEntryICFGNode * getFunEntryICFGNode(const SVFFunction *fun)
Add a function entry node.
Definition ICFG.cpp:234
ICFGEdge * hasThreadICFGEdge(ICFGNode *src, ICFGNode *dst, ICFGEdge::ICFGEdgeK kind)
Definition ICFG.cpp:285
FunEntryICFGNode * getFunEntryBlock(const SVFFunction *fun)
Get/Add a function entry node.
Definition ICFG.h:287
FunExitICFGNode * getFunExitBlock(const SVFFunction *fun)
Get/Add a function exit node.
Definition ICFG.h:296
bool addICFGEdge(ICFGEdge *edge)
Add ICFG edge, only used by addIntraEdge, addCallEdge, addRetEdge etc.
Definition ICFG.h:277
void removeICFGEdge(ICFGEdge *edge)
Remove a ICFG edge.
Definition ICFG.h:151
void updateCallGraph(PTACallGraph *callgraph)
update ICFG for indirect calls
Definition ICFG.cpp:419
ICFGEdge * getICFGEdge(const ICFGNode *src, const ICFGNode *dst, ICFGEdge::ICFGEdgeK kind)
Get a SVFG edge according to src and dst.
Definition ICFG.cpp:303
ICFG()
Constructor.
Definition ICFG.cpp:210
void checkIntraEdgeParents(const ICFGNode *srcNode, const ICFGNode *dstNode)
sanitize Intra edges, verify that both nodes belong to the same function.
Definition ICFG.h:165
ICFGEdge * addCallEdge(ICFGNode *srcNode, ICFGNode *dstNode)
Definition ICFG.cpp:366
ICFGNodeToSVFLoopVec icfgNodeToSVFLoopVec
map ICFG node to the SVF loops where it resides
Definition ICFG.h:72
ICFGEdge * hasInterICFGEdge(ICFGNode *src, ICFGNode *dst, ICFGEdge::ICFGEdgeK kind)
Definition ICFG.cpp:268
void dump(const std::string &file, bool simple=false)
Dump graph into dot file.
Definition ICFG.cpp:403
ICFGEdge * addRetEdge(ICFGNode *srcNode, ICFGNode *dstNode)
Definition ICFG.cpp:384
ICFGEdge * hasIntraICFGEdge(ICFGNode *src, ICFGNode *dst, ICFGEdge::ICFGEdgeK kind)
Whether we has a SVFG edge.
Definition ICFG.cpp:251
ICFGEdge * addConditionalIntraEdge(ICFGNode *srcNode, ICFGNode *dstNode, s64_t branchCondVal)
Definition ICFG.cpp:344
ICFGEdge * addIntraEdge(ICFGNode *srcNode, ICFGNode *dstNode)
Add intraprocedural and interprocedural control-flow edges.
Definition ICFG.cpp:325
~ICFG() override
Destructor.
Definition ICFG.cpp:214
FunExitICFGNode * getFunExitICFGNode(const SVFFunction *fun)
Add a function exit node.
Definition ICFG.cpp:241
s64_t getSuccessorCondValue() const
Definition ICFGEdge.h:147
virtual const std::string toString() const
Definition ICFG.cpp:165
const SVFVar * getCondition() const
Definition ICFGEdge.h:142
const std::string toString() const override
Definition ICFG.cpp:85
static const Option< bool > ShowHiddenNode
Definition Options.h:228
static const Option< bool > DumpICFG
Definition Options.h:123
CallEdgeMap & getIndCallMap()
Get callees from an indirect callsite.
Set< const SVFFunction * > FunctionSet
const CallICFGNode * getCallSite() const
Return call ICFGNode at the callsite.
Definition ICFG.cpp:196
virtual const std::string toString() const
Definition ICFG.cpp:186
const std::string toString() const override
Definition ICFG.cpp:144
NodeID getId() const
Get ID.
const std::string valueOnlyToString() const
Definition LLVMUtil.cpp:746
virtual const std::string getSourceLoc() const
const ICFGNode * front() const
Definition SVFValue.h:605
bool hasReturn() const
Definition SVFValue.h:471
const SVFBasicBlock * getExitBB() const
Definition SVFValue.cpp:186
const std::string & getName() const
Definition SVFValue.h:243
virtual const std::string getSourceLoc() const
Definition SVFValue.h:280
virtual const std::string toString() const
bool isExtCall(const SVFFunction *fun)
Definition SVFUtil.h:278
std::ostream & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:50
for isBitcode
Definition BasicTypes.h:68
u32_t NodeID
Definition GeneralType.h:55
void ViewGraph(const GraphType &G, const std::string &name, bool ShortNames=false, GraphProgram::Name Program=GraphProgram::DOT)
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74
unsigned u32_t
Definition GeneralType.h:46
signed long long s64_t
Definition GeneralType.h:49
std::string getNodeLabel(NodeType *node, ICFG *graph)
Definition ICFG.cpp:497
static std::string getGraphName(ICFG *)
Return name of the graph.
Definition ICFG.cpp:492
static bool isNodeHidden(ICFGNode *node, ICFG *)
Definition ICFG.cpp:508
static std::string getSimpleNodeLabel(NodeType *node, ICFG *)
Return the label of an ICFG node.
Definition ICFG.cpp:503
static std::string getEdgeSourceLabel(NodeType *, EdgeIter EI)
Definition ICFG.cpp:568
static std::string getEdgeAttributes(NodeType *, EdgeIter EI, ICFG *)
Definition ICFG.cpp:554
static std::string getNodeAttributes(NodeType *node, ICFG *)
Definition ICFG.cpp:516
DOTGraphTraits(bool isSimple=false)
Definition ICFG.cpp:486