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/CallGraph.h"
31#include "Graphs/GraphPrinter.h"
32#include "Graphs/ICFG.h"
33#include "Util/Options.h"
34
35using namespace SVF;
36using namespace SVFUtil;
37
38class SVFIR;
39
41{
42 fun = f;
43 // if function is implemented
44 if (f->begin() != f->end())
45 {
46 bb = f->getEntryBlock();
47 }
48}
49
50const std::string ICFGNode::toString() const
51{
52 std::string str;
53 std::stringstream rawstr(str);
54 rawstr << "ICFGNode" << getId();
55 return rawstr.str();
56}
57
58void ICFGNode::dump() const
59{
60 outs() << this->toString() << "\n";
61}
62
63const std::string GlobalICFGNode::toString() const
64{
65 std::string str;
66 std::stringstream rawstr(str);
67 rawstr << "GlobalICFGNode" << getId();
68 for (const SVFStmt *stmt : getSVFStmts())
69 rawstr << "\n" << stmt->toString();
70 return rawstr.str();
71}
72
73
74const std::string IntraICFGNode::toString() const
75{
76 std::string str;
77 std::stringstream rawstr(str);
78 rawstr << "IntraICFGNode" << getId();
79 rawstr << " {fun: " << getFun()->getName() << getSourceLoc() << "}";
80 for (const SVFStmt *stmt : getSVFStmts())
81 rawstr << "\n" << stmt->toString();
82 if(getSVFStmts().empty())
83 rawstr << "\n" << valueOnlyToString();
84 return rawstr.str();
85}
86
87
88const std::string FunEntryICFGNode::toString() const
89{
90 std::string str;
91 std::stringstream rawstr(str);
92 rawstr << "FunEntryICFGNode" << getId();
93 rawstr << " {fun: " << getFun()->getName();
94 if (isExtCall(getFun())==false)
96 rawstr << "}";
97 for (const SVFStmt *stmt : getSVFStmts())
98 rawstr << "\n" << stmt->toString();
99 return rawstr.str();
100}
101
102const std::string FunEntryICFGNode::getSourceLoc() const
103{
104 return "function entry: " + fun->getSourceLoc();
105}
106
107const std::string FunExitICFGNode::toString() const
108{
109 const FunObjVar *fun = getFun();
110 std::string str;
111 std::stringstream rawstr(str);
112 rawstr << "FunExitICFGNode" << getId();
113 rawstr << " {fun: " << fun->getName();
114 // ensure the enclosing function has exit basic block
115 if (!isExtCall(fun) && fun->hasReturn())
117 rawstr << intraICFGNode->getSourceLoc();
118 rawstr << "}";
119 for (const SVFStmt *stmt : getSVFStmts())
120 rawstr << "\n" << stmt->toString();
121 return rawstr.str();
122}
123
124const std::string FunExitICFGNode::getSourceLoc() const
125{
126 return "function ret: " + fun->getSourceLoc();
127}
128
129const std::string CallICFGNode::toString() const
130{
131 std::string str;
132 std::stringstream rawstr(str);
133 rawstr << "CallICFGNode" << getId();
134 rawstr << " {fun: " << getFun()->getName() << ICFGNode::getSourceLoc() << "}";
135 for (const SVFStmt *stmt : getSVFStmts())
136 rawstr << "\n" << stmt->toString();
137 if(getSVFStmts().empty())
138 rawstr << "\n" << valueOnlyToString();
139 return rawstr.str();
140}
141
142const std::string RetICFGNode::toString() const
143{
144 std::string str;
145 std::stringstream rawstr(str);
146 rawstr << "RetICFGNode" << getId();
147 rawstr << " {fun: " << getFun()->getName() << ICFGNode::getSourceLoc() << "}";
148 for (const SVFStmt *stmt : getSVFStmts())
149 rawstr << "\n" << stmt->toString();
150 if(getSVFStmts().empty())
151 rawstr << "\n" << valueOnlyToString();
152 return rawstr.str();
153}
154
155const std::string ICFGEdge::toString() const
156{
157 std::string str;
158 std::stringstream rawstr(str);
159 rawstr << "ICFGEdge: [ICFGNode" << getDstID() << " <-- ICFGNode" << getSrcID() << "]\t";
160 return rawstr.str();
161}
162
163const std::string IntraCFGEdge::toString() const
164{
165 std::string str;
166 std::stringstream rawstr(str);
167 if(getCondition() == nullptr)
168 rawstr << "IntraCFGEdge: [ICFGNode" << getDstID() << " <-- ICFGNode" << getSrcID() << "]\t";
169 else
170 rawstr << "IntraCFGEdge: [ICFGNode" << getDstID() << " <-- ICFGNode" << getSrcID() << "] (branchCondition:" << getCondition()->toString() << ") (succCondValue: " << getSuccessorCondValue() << ") \t";
171
172 return rawstr.str();
173}
174
175const std::string CallCFGEdge::toString() const
176{
177 std::string str;
178 std::stringstream rawstr(str);
179 rawstr << "CallCFGEdge " << " [ICFGNode";
180 rawstr << getDstID() << " <-- ICFGNode" << getSrcID() << "]\t CallSite: " << getSrcNode()->toString() << "\t";
181 return rawstr.str();
182}
183
184const std::string RetCFGEdge::toString() const
185{
186 std::string str;
187 std::stringstream rawstr(str);
188 rawstr << "RetCFGEdge " << " [ICFGNode";
189 rawstr << getDstID() << " <-- ICFGNode" << getSrcID() << "]\t CallSite: " << getDstNode()->toString() << "\t";
190 return rawstr.str();
191}
192
195{
196 assert(SVFUtil::isa<RetICFGNode>(getDstNode()) && "not a RetICFGNode?");
197 return SVFUtil::cast<RetICFGNode>(getDstNode())->getCallICFGNode();
198}
199
208ICFG::ICFG(): totalICFGNode(0), globalBlockNode(nullptr)
209{
210}
211
213{
215 for (const auto &it: icfgNodeToSVFLoopVec)
216 {
217 for (const auto &loop: it.second)
218 {
219 loops.insert(loop);
220 }
221 }
222
223 for (const auto &it: loops)
224 {
225 delete it;
226 }
227 icfgNodeToSVFLoopVec.clear();
228}
229
231{
232 addGNode(node->getId(),node);
233}
234
240
241
244{
246 assert (entry && "fun entry not created in ICFGBuilder?");
247 return entry;
248}
251{
252 FunExitICFGNode* exit = getFunExitBlock(fun);
253 assert (exit && "fun exit not created in ICFGBuilder?");
254 return exit;
255}
256
261{
262 ICFGEdge edge(src,dst,kind);
265 if (outEdge && inEdge)
266 {
267 assert(outEdge == inEdge && "edges not match");
268 return outEdge;
269 }
270 else
271 return nullptr;
272}
273
278{
279 ICFGEdge edge(src,dst, kind);
282 if (outEdge && inEdge)
283 {
284 assert(outEdge == inEdge && "edges not match");
285 return outEdge;
286 }
287 else
288 return nullptr;
289}
290
295{
296 ICFGEdge edge(src,dst,kind);
299 if (outEdge && inEdge)
300 {
301 assert(outEdge == inEdge && "edges not match");
302 return outEdge;
303 }
304 else
305 return nullptr;
306}
307
308
313{
314
315 ICFGEdge * edge = nullptr;
316 u32_t counter = 0;
317 for (ICFGEdge::ICFGEdgeSetTy::iterator iter = src->OutEdgeBegin();
318 iter != src->OutEdgeEnd(); ++iter)
319 {
320 if ((*iter)->getDstID() == dst->getId() && (*iter)->getEdgeKind() == kind)
321 {
322 counter++;
323 edge = (*iter);
324 }
325 }
326 assert(counter <= 1 && "there's more than one edge between two ICFG nodes");
327 return edge;
328
329}
330
335{
338 if (edge != nullptr)
339 {
340 assert(edge->isIntraCFGEdge() && "this should be an intra CFG edge!");
341 return nullptr;
342 }
343 else
344 {
346 return (addICFGEdge(intraEdge) ? intraEdge : nullptr);
347 }
348}
349
354{
355
358 if (edge != nullptr)
359 {
360 assert(edge->isIntraCFGEdge() && "this should be an intra CFG edge!");
361 return nullptr;
362 }
363 else
364 {
366 intraEdge->setBranchCondVal(branchCondVal);
367 return (addICFGEdge(intraEdge) ? intraEdge : nullptr);
368 }
369}
370
371
376{
378 if (edge != nullptr)
379 {
380 assert(edge->isCallCFGEdge() && "this should be a call CFG edge!");
381 return nullptr;
382 }
383 else
384 {
386 return (addICFGEdge(callEdge) ? callEdge : nullptr);
387 }
388}
389
394{
396 if (edge != nullptr)
397 {
398 assert(edge->isRetCFGEdge() && "this should be a return CFG edge!");
399 return nullptr;
400 }
401 else
402 {
404 return (addICFGEdge(retEdge) ? retEdge : nullptr);
405 }
406}
407
408
412void ICFG::dump(const std::string& file, bool simple)
413{
415}
416
421{
422 SVF::ViewGraph(this, "Interprocedural Control-Flow Graph");
423}
424
429{
430 CallGraph::CallEdgeMap::const_iterator iter = callgraph->getIndCallMap().begin();
431 CallGraph::CallEdgeMap::const_iterator eiter = callgraph->getIndCallMap().end();
432 for (; iter != eiter; iter++)
433 {
434 CallICFGNode* callBlockNode = const_cast<CallICFGNode*>(iter->first);
435 assert(callBlockNode->isIndirectCall() && "this is not an indirect call?");
436 const CallGraph::FunctionSet & functions = iter->second;
437 for (CallGraph::FunctionSet::const_iterator func_iter = functions.begin(); func_iter != functions.end(); func_iter++)
438 {
439 const FunObjVar* callee = *func_iter;
440 RetICFGNode* retBlockNode = const_cast<RetICFGNode*>(callBlockNode->getRetICFGNode());
442 if (isExtCall(callee))
443 addIntraEdge(callBlockNode, retBlockNode);
444 else
445 {
448 addCallEdge(callBlockNode, calleeEntryNode);
450 {
451 for (const SVFStmt *stmt : retBlockNode->getSVFStmts())
452 {
453 if(const RetPE *retPE = SVFUtil::dyn_cast<RetPE>(stmt))
454 {
455 if(retPE->getFunExitICFGNode() == calleeExitNode)
456 SVFUtil::cast<RetCFGEdge>(retEdge)->addRetPE(retPE);
457 }
458 }
459 }
460
464 }
465
466 }
467 }
468 // dump ICFG
469 if (Options::DumpICFG())
470 {
471 dump("icfg_final");
472 }
473}
474
478namespace SVF
479{
480template<>
482{
483
485 DOTGraphTraits(bool isSimple = false) :
486 DOTGraphTraits<SVFIR*>(isSimple)
487 {
488 }
489
491 static std::string getGraphName(ICFG*)
492 {
493 return "ICFG";
494 }
495
496 std::string getNodeLabel(NodeType *node, ICFG *graph)
497 {
498 return getSimpleNodeLabel(node, graph);
499 }
500
502 static std::string getSimpleNodeLabel(NodeType *node, ICFG*)
503 {
504 return node->toString();
505 }
506
507 static bool isNodeHidden(ICFGNode *node, ICFG *)
508 {
510 return false;
511 else
512 return node->getInEdges().empty() && node->getOutEdges().empty();
513 }
514
515 static std::string getNodeAttributes(NodeType *node, ICFG*)
516 {
517 std::string str;
518 std::stringstream rawstr(str);
519
520 rawstr << "shape=record";
521
522 if(SVFUtil::isa<IntraICFGNode>(node))
523 {
524 rawstr << ",color=black";
525 }
526 else if(SVFUtil::isa<FunEntryICFGNode>(node))
527 {
528 rawstr << ",color=yellow";
529 }
530 else if(SVFUtil::isa<FunExitICFGNode>(node))
531 {
532 rawstr << ",color=green";
533 }
534 else if(SVFUtil::isa<CallICFGNode>(node))
535 {
536 rawstr << ",color=red";
537 }
538 else if(SVFUtil::isa<RetICFGNode>(node))
539 {
540 rawstr << ",color=blue";
541 }
542 else if(SVFUtil::isa<GlobalICFGNode>(node))
543 {
544 rawstr << ",color=purple";
545 }
546 else
547 assert(false && "no such kind of node!!");
548
549 return rawstr.str();
550 }
551
552 template<class EdgeIter>
553 static std::string getEdgeAttributes(NodeType*, EdgeIter EI, ICFG*)
554 {
555 ICFGEdge* edge = *(EI.getCurrent());
556 assert(edge && "No edge found!!");
557 if (SVFUtil::isa<CallCFGEdge>(edge))
558 return "style=solid,color=red";
559 else if (SVFUtil::isa<RetCFGEdge>(edge))
560 return "style=solid,color=blue";
561 else
562 return "style=solid";
563 return "";
564 }
565
566 template<class EdgeIter>
568 {
569 ICFGEdge* edge = *(EI.getCurrent());
570 assert(edge && "No edge found!!");
571
572 std::string str;
573 std::stringstream rawstr(str);
574 if (CallCFGEdge* dirCall = SVFUtil::dyn_cast<CallCFGEdge>(edge))
575 rawstr << dirCall->getSrcNode();
576 else if (RetCFGEdge* dirRet = SVFUtil::dyn_cast<RetCFGEdge>(edge))
577 {
578 if(RetICFGNode* ret = SVFUtil::dyn_cast<RetICFGNode>(dirRet->getDstNode()))
579 rawstr << ret->getCallICFGNode();
580 }
581
582 return rawstr.str();
583 }
584};
585} // End namespace llvm
virtual const std::string toString() const
Definition ICFG.cpp:175
CallEdgeMap & getIndCallMap()
Get callees from an indirect callsite.
Definition CallGraph.h:331
Set< const FunObjVar * > FunctionSet
Definition CallGraph.h:247
const std::string toString() const override
Definition ICFG.cpp:129
const RetICFGNode * getRetICFGNode() const
Return callsite.
Definition ICFGNode.h:440
bool isIndirectCall() const
Return true if this is an indirect call.
Definition ICFGNode.h:465
FunEntryICFGNode(NodeID id, const FunObjVar *f)
Definition ICFG.cpp:40
const FunObjVar * getFun() const override
Return function.
Definition ICFGNode.h:285
const std::string toString() const override
Definition ICFG.cpp:88
const std::string getSourceLoc() const override
Definition ICFG.cpp:102
const std::string toString() const override
Definition ICFG.cpp:107
const FunObjVar * getFun() const override
Return function.
Definition ICFGNode.h:354
const std::string getSourceLoc() const override
Definition ICFG.cpp:124
const SVFBasicBlock * getExitBB() const
bool hasReturn() const
NodeType * getSrcNode() const
NodeType * getDstNode() const
NodeID getDstID() const
NodeID getSrcID() const
get methods of the components
void addGNode(NodeID id, NodeType *node)
Add a Node.
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:63
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:155
const SVFBasicBlock * bb
Definition ICFGNode.h:146
void dump() const
Definition ICFG.cpp:58
virtual const FunObjVar * getFun() const
Return the function of this ICFGNode.
Definition ICFGNode.h:75
const FunObjVar * fun
Definition ICFGNode.h:145
virtual const std::string toString() const
Definition ICFG.cpp:50
const SVFStmtList & getSVFStmts() const
Definition ICFGNode.h:116
void view()
View graph from the debugger.
Definition ICFG.cpp:420
ICFGEdge * hasThreadICFGEdge(ICFGNode *src, ICFGNode *dst, ICFGEdge::ICFGEdgeK kind)
Definition ICFG.cpp:294
bool addICFGEdge(ICFGEdge *edge)
Add ICFG edge, only used by addIntraEdge, addCallEdge, addRetEdge etc.
Definition ICFG.h:252
void removeICFGEdge(ICFGEdge *edge)
Remove a ICFG edge.
Definition ICFG.h:147
ICFGEdge * getICFGEdge(const ICFGNode *src, const ICFGNode *dst, ICFGEdge::ICFGEdgeK kind)
Get a SVFG edge according to src and dst.
Definition ICFG.cpp:312
ICFG()
Constructor.
Definition ICFG.cpp:208
void checkIntraEdgeParents(const ICFGNode *srcNode, const ICFGNode *dstNode)
sanitize Intra edges, verify that both nodes belong to the same function.
Definition ICFG.h:161
ICFGEdge * addCallEdge(ICFGNode *srcNode, ICFGNode *dstNode)
Definition ICFG.cpp:375
ICFGNodeToSVFLoopVec icfgNodeToSVFLoopVec
map ICFG node to the SVF loops where it resides
Definition ICFG.h:72
FunExitICFGNode * getFunExitICFGNode(const FunObjVar *fun)
Add a function exit node.
Definition ICFG.cpp:250
ICFGEdge * hasInterICFGEdge(ICFGNode *src, ICFGNode *dst, ICFGEdge::ICFGEdgeK kind)
Definition ICFG.cpp:277
GlobalICFGNode * globalBlockNode
unique basic block for all globals
Definition ICFG.h:71
virtual void addGlobalICFGNode(GlobalICFGNode *globalICFGNode)
Definition ICFG.cpp:235
void dump(const std::string &file, bool simple=false)
Dump graph into dot file.
Definition ICFG.cpp:412
ICFGEdge * addRetEdge(ICFGNode *srcNode, ICFGNode *dstNode)
Definition ICFG.cpp:393
void updateCallGraph(CallGraph *callgraph)
update ICFG for indirect calls
Definition ICFG.cpp:428
ICFGEdge * hasIntraICFGEdge(ICFGNode *src, ICFGNode *dst, ICFGEdge::ICFGEdgeK kind)
Whether we has a SVFG edge.
Definition ICFG.cpp:260
ICFGEdge * addConditionalIntraEdge(ICFGNode *srcNode, ICFGNode *dstNode, s64_t branchCondVal)
Definition ICFG.cpp:353
FunExitICFGNode * getFunExitBlock(const FunObjVar *fun)
Get/Add a function exit node.
Definition ICFG.h:271
ICFGEdge * addIntraEdge(ICFGNode *srcNode, ICFGNode *dstNode)
Add intraprocedural and interprocedural control-flow edges.
Definition ICFG.cpp:334
FunEntryICFGNode * getFunEntryICFGNode(const FunObjVar *fun)
Add a function entry node.
Definition ICFG.cpp:243
~ICFG() override
Destructor.
Definition ICFG.cpp:212
virtual void addICFGNode(ICFGNode *node)
Add a ICFG node.
Definition ICFG.cpp:230
FunEntryICFGNode * getFunEntryBlock(const FunObjVar *fun)
Get/Add a function entry node.
Definition ICFG.h:262
s64_t getSuccessorCondValue() const
Definition ICFGEdge.h:144
virtual const std::string toString() const
Definition ICFG.cpp:163
const SVFVar * getCondition() const
Definition ICFGEdge.h:139
const std::string toString() const override
Definition ICFG.cpp:74
static const Option< bool > ShowHiddenNode
Definition Options.h:221
static const Option< bool > DumpICFG
Definition Options.h:119
const CallICFGNode * getCallSite() const
Return call ICFGNode at the callsite.
Definition ICFG.cpp:194
virtual const std::string toString() const
Definition ICFG.cpp:184
const std::string toString() const override
Definition ICFG.cpp:142
const ICFGNode * front() const
NodeID getId() const
Get ID.
Definition SVFValue.h:160
virtual const std::string getSourceLoc() const
Definition SVFValue.h:196
virtual const std::string & getName() const
Definition SVFValue.h:186
const std::string valueOnlyToString() const
Definition LLVMUtil.cpp:741
virtual const std::string toString() const
Get string representation.
bool isExtCall(const FunObjVar *fun)
Definition SVFUtil.cpp:441
std::ostream & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:52
for isBitcode
Definition BasicTypes.h:70
u32_t NodeID
Definition GeneralType.h:76
void ViewGraph(const GraphType &G, const std::string &name, bool ShortNames=false, GraphProgram::Name Program=GraphProgram::DOT)
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:76
unsigned u32_t
Definition GeneralType.h:67
signed long long s64_t
Definition GeneralType.h:70
std::string getNodeLabel(NodeType *node, ICFG *graph)
Definition ICFG.cpp:496
static std::string getGraphName(ICFG *)
Return name of the graph.
Definition ICFG.cpp:491
static bool isNodeHidden(ICFGNode *node, ICFG *)
Definition ICFG.cpp:507
static std::string getSimpleNodeLabel(NodeType *node, ICFG *)
Return the label of an ICFG node.
Definition ICFG.cpp:502
static std::string getEdgeSourceLabel(NodeType *, EdgeIter EI)
Definition ICFG.cpp:567
static std::string getEdgeAttributes(NodeType *, EdgeIter EI, ICFG *)
Definition ICFG.cpp:553
static std::string getNodeAttributes(NodeType *node, ICFG *)
Definition ICFG.cpp:515
DOTGraphTraits(bool isSimple=false)
Definition ICFG.cpp:485