Static Value-Flow Analysis
Loading...
Searching...
No Matches
IRGraph.cpp
Go to the documentation of this file.
1//===- SVFIR.cpp -- Program assignment graph------------------------------------//
2//
3// SVF: Static Value-Flow Analysis
4//
5// Copyright (C) <2013-2017> <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 * SVFIR.cpp
25 *
26 * Created on: Nov 1, 2013
27 * Author: Yulei Sui
28 */
29
30#include "Graphs/GraphPrinter.h"
31#include "Graphs/ICFG.h"
32#include "Graphs/IRGraph.h"
33#include "Util/GeneralType.h"
34#include "Util/Options.h"
35#include "Util/SVFUtil.h"
36
37using namespace SVF;
38using namespace SVFUtil;
39
41{
42
43 for (auto &pair: objTypeInfoMap)
44 {
45 if (ObjTypeInfo* ti = pair.second)
46 delete ti;
47 }
48
49 for (const SVFType* type : svfTypes)
50 delete type;
51 svfTypes.clear();
52
53 for (const StInfo* st : stInfos)
54 delete st;
55 stInfos.clear();
56}
57
62
63
65{
66 FunObjVarToIDMapTy::const_iterator iter = returnFunObjSymMap.find(func);
67 assert(iter!=returnFunObjSymMap.end() && "ret sym not found");
68 return iter->second;
69}
70
72{
73 FunObjVarToIDMapTy::const_iterator iter = varargFunObjSymMap.find(func);
74 assert(iter!=varargFunObjSymMap.end() && "vararg sym not found");
75 return iter->second;
76}
78{
79 if (const SVFArrayType* at = SVFUtil::dyn_cast<SVFArrayType>(type))
80 {
81 outs() << " {Type: " << *at << "}\n"
82 << "\tarray type "
83 << "\t [element size = " << getNumOfFlattenElements(at) << "]\n"
84 << "\n";
85 }
86 else if (const SVFStructType *st = SVFUtil::dyn_cast<SVFStructType>(type))
87 {
88 outs() <<" {Type: " << *st << "}\n";
89 const std::vector<const SVFType*>& finfo = getTypeInfo(st)->getFlattenFieldTypes();
90 int field_idx = 0;
91 for(const SVFType* type : finfo)
92 {
93 outs() << " \tField_idx = " << ++field_idx
94 << ", field type: " << *type << "\n";
95 }
96 outs() << "\n";
97 }
98 else if (const SVFPointerType* pt= SVFUtil::dyn_cast<SVFPointerType>(type))
99 {
100 outs() << *pt << "\n";
101 }
102 else if (const SVFFunctionType* fu =
103 SVFUtil::dyn_cast<SVFFunctionType>(type))
104 {
105 outs() << " {Type: " << *fu << "}\n\n";
106 }
107 else if (const SVFOtherType* ot = SVFUtil::dyn_cast<SVFOtherType>(type))
108 {
109 outs() << " {Type: "<< *ot << "(SVFOtherType)}\n\n";
110 }
111 else
112 {
113 assert(type->isSingleValueType() && "not a single value type, then what else!!");
116 outs() << " {Type: " << *type << "}\n"
117 << "\t [object size = " << eSize << "]\n"
118 << "\n";
119 }
120}
121
122const std::vector<const SVFType *> &IRGraph::getFlattenFieldTypes(const SVFStructType *T)
123{
125}
126
128{
130 {
131 const std::vector<const SVFType*>& so = getTypeInfo(baseType)->getFlattenElementTypes();
132 assert (flatten_idx < so.size() && !so.empty() && "element index out of bounds or struct opaque type, can't get element type!");
133 return so[flatten_idx];
134 }
135 else
136 {
137 const std::vector<const SVFType*>& so = getTypeInfo(baseType)->getFlattenFieldTypes();
138 assert (flatten_idx < so.size() && !so.empty() && "element index out of bounds or struct opaque type, can't get element type!");
139 return so[flatten_idx];
140 }
141}
142
147
149{
151 {
152 const std::vector<u32_t>& so = getTypeInfo(T)->getFlattenedElemIdxVec();
153 assert ((unsigned)origId < so.size() && !so.empty() && "element index out of bounds, can't get flattened index!");
154 return so[origId];
155 }
156 else
157 {
158 if(SVFUtil::isa<SVFStructType>(T))
159 {
160 const std::vector<u32_t>& so = getTypeInfo(T)->getFlattenedFieldIdxVec();
161 assert ((unsigned)origId < so.size() && !so.empty() && "Struct index out of bounds, can't get flattened index!");
162 return so[origId];
163 }
164 else if(SVFUtil::isa<SVFArrayType>(T))
165 {
167 return 0;
168 }
169 else
170 {
171 // Under LLVM's opaque pointers, the SVFType resolved for a GEP base can fold to
172 // something other than a struct/array SVFType even though the corresponding LLVM
173 // aggregate genuinely is a StructType/ArrayType (seen integrating SVF against an
174 // LLVM 21 -O0 build). Report the concrete type so a future hit of this branch is
175 // diagnosable rather than guessed at, then fall back to element 0 instead of
176 // crashing (the printed type survives into release builds even when the assert
177 // below is compiled out).
178 SVFUtil::errs() << "getFlattenedElemIdx: type is neither struct nor array: "
179 << T->toString() << "\n";
180 assert(false && "getFlattenedElemIdx: type is neither struct nor array (see printed type above)");
181 return 0;
182 }
183 }
184}
185
193
204
206{
210
211 APOffset offset = apOffset;
212 if(offset < 0)
213 {
214 writeWrnMsg("try to create a gep node with negative offset.");
215 offset = std::abs(offset);
216 }
217 u32_t maxOffset = baseObj->getMaxFieldOffsetLimit();
218
224 if (maxOffset == 0)
225 offset = 0;
231 else if ((u32_t)offset > maxOffset - 1)
232 {
238 else
242 offset = maxOffset - 1;
243 }
244
245 return offset;
246}
247
249{
250
252 if(type && type->isPointerTy())
253 {
255 }
256 return typeInfo;
257}
258
260{
261 assert(T);
262 SVFTypeSet::const_iterator it = svfTypes.find(T);
263 assert(it != svfTypes.end() && "type info not found? collect them first during SVFIR Building");
264 return (*it)->getTypeInfo();
265}
266
271{
272
274 outs() << "add edge from " << src->getId() << " kind :"
275 << src->getNodeKind() << " to " << dst->getId()
276 << " kind :" << dst->getNodeKind() << "\n");
277 src->addOutEdge(edge);
278 dst->addInEdge(edge);
279 return true;
280}
281
286{
287 SVFStmt edge(src,dst,kind, false);
288 return hasEdge(&edge, kind);
289}
290
295{
297 SVFStmt::SVFStmtSetTy::iterator it = KindToSVFStmtSetMap[kind].find(&edge);
298 if (it != KindToSVFStmtSetMap[kind].end())
299 {
300 return *it;
301 }
302 return nullptr;
303}
304
309{
310 SVFStmt edge(src,dst,SVFStmt::makeEdgeFlagWithCallInst(kind,callInst), false);
311 SVFStmt::SVFStmtSetTy::iterator it = KindToSVFStmtSetMap[kind].find(&edge);
312 if (it != KindToSVFStmtSetMap[kind].end())
313 {
314 return *it;
315 }
316 return nullptr;
317}
318
320{
321 SVFStmt::SVFStmtSetTy::iterator it = KindToSVFStmtSetMap[kind].find(edge);
322 if (it != KindToSVFStmtSetMap[kind].end())
323 {
324 return *it;
325 }
326 return nullptr;
327}
328
329
333void IRGraph::dump(std::string name)
334{
336}
337
342{
343 SVF::ViewGraph(this, "ProgramAssignmentGraph");
344}
345
346
348{
349 if (valVarNum != 0) return valVarNum;
350 u32_t num = 0;
351 for (const auto& item: *this)
352 {
353 if (SVFUtil::isa<ValVar>(item.second))
354 num++;
355 }
356 return valVarNum = num;
357}
358
359
361{
362 if (objVarNum != 0) return objVarNum;
363 u32_t num = 0;
364 for (const auto& item: *this)
365 {
366 if (SVFUtil::isa<ObjVar>(item.second))
367 num++;
368 }
369 return objVarNum = num;
370}
371
372
373
374namespace SVF
375{
379template<>
381{
382
385 DOTGraphTraits(bool isSimple = false) :
386 DefaultDOTGraphTraits(isSimple)
387 {
388 }
389
391 static std::string getGraphName(IRGraph *graph)
392 {
393 return graph->getGraphName();
394 }
395
398 static bool isNodeHidden(SVFVar *node, IRGraph *)
399 {
400 if (Options::ShowHiddenNode()) return false;
401 else return node->isIsolatedNode();
402 }
403
406 static std::string getNodeLabel(SVFVar *node, IRGraph*)
407 {
408 std::string str;
409 std::stringstream rawstr(str);
410 // print function info
411 if (node->getFunction())
412 rawstr << "[" << node->getFunction()->getName() << "] ";
413
414 rawstr << node->toString();
415
416 return rawstr.str();
417
418 }
419
420 static std::string getNodeAttributes(SVFVar *node, IRGraph*)
421 {
422 if (SVFUtil::isa<ValVar>(node))
423 {
424 if(SVFUtil::isa<GepValVar>(node))
425 return "shape=hexagon";
426 else if (SVFUtil::isa<DummyValVar>(node))
427 return "shape=diamond";
428 else
429 return "shape=box";
430 }
431 else if (SVFUtil::isa<ObjVar>(node))
432 {
433 if(SVFUtil::isa<GepObjVar>(node))
434 return "shape=doubleoctagon";
435 else if(SVFUtil::isa<BaseObjVar>(node))
436 return "shape=box3d";
437 else if (SVFUtil::isa<DummyObjVar>(node))
438 return "shape=tab";
439 else
440 return "shape=component";
441 }
442 else if (SVFUtil::isa<RetValPN>(node))
443 {
444 return "shape=Mrecord";
445 }
446 else if (SVFUtil::isa<VarArgValPN>(node))
447 {
448 return "shape=octagon";
449 }
450 else
451 {
452 assert(0 && "no such kind!!");
453 }
454 return "";
455 }
456
457 template<class EdgeIter>
459 {
460 std::string str;
461 std::stringstream rawstr(str);
462
463 rawstr << "shape=record";
464
465 const SVFStmt* edge = *(EI.getCurrent());
466 assert(edge && "No edge found!!");
467 if (SVFUtil::isa<AddrStmt>(edge))
468 {
469 rawstr << ",color=green";
470 }
471 else if (SVFUtil::isa<CopyStmt>(edge))
472 {
473 rawstr << ",color=black";
474 }
475 else if (SVFUtil::isa<GepStmt>(edge))
476 {
477 rawstr << ",color=\"purple:purple\"";
478 }
479 else if (SVFUtil::isa<StoreStmt>(edge))
480 {
481 rawstr << ",color=blue";
482 }
483 else if (SVFUtil::isa<LoadStmt>(edge))
484 {
485 rawstr << ",color=red";
486 }
487 else if (SVFUtil::isa<PhiStmt>(edge))
488 {
489 rawstr << ",color=grey";
490 }
491 else if (SVFUtil::isa<SelectStmt>(edge))
492 {
493 rawstr << ",color=grey";
494 }
495 else if (SVFUtil::isa<CmpStmt>(edge))
496 {
497 rawstr << ",color=grey";
498 }
499 else if (SVFUtil::isa<BinaryOPStmt>(edge))
500 {
501 rawstr << ",color=grey";
502 }
503 else if (SVFUtil::isa<UnaryOPStmt>(edge))
504 {
505 rawstr << ",color=grey";
506 }
507 else if (SVFUtil::isa<BranchStmt>(edge))
508 {
509 rawstr << ",color=grey";
510 }
511 else if (SVFUtil::isa<TDForkPE>(edge))
512 {
513 rawstr << ",color=Turquoise";
514 }
515 else if (SVFUtil::isa<TDJoinPE>(edge))
516 {
517 rawstr << ",color=Turquoise";
518 }
519 else if (SVFUtil::isa<CallPE>(edge))
520 {
521 rawstr << ",color=black,style=dashed";
522 }
523 else if (SVFUtil::isa<RetPE>(edge))
524 {
525 rawstr << ",color=black,style=dotted";
526 }
527 else
528 {
529 assert(false && "No such kind edge!!");
530 }
531
532 return rawstr.str();
533 }
534
535 template<class EdgeIter>
536 static std::string getEdgeSourceLabel(SVFVar*, EdgeIter EI)
537 {
538 const SVFStmt* edge = *(EI.getCurrent());
539 assert(edge && "No edge found!!");
540 if(const CallPE* calledge = SVFUtil::dyn_cast<CallPE>(edge))
541 {
542 return calledge->getFunEntryICFGNode()->getSourceLoc();
543 }
544 else if(const RetPE* retedge = SVFUtil::dyn_cast<RetPE>(edge))
545 {
546 return retedge->getCallSite()->getSourceLoc();
547 }
548 return "";
549 }
550};
551} // End namespace llvm
#define DBOUT(TYPE, X)
LLVM debug macros, define type of your DBUG model of each pass.
Definition SVFType.h:576
#define DPAGBuild
Definition SVFType.h:584
newitem type
Definition cJSON.cpp:2739
buffer offset
Definition cJSON.cpp:1113
const char *const name
Definition cJSON.h:264
cJSON * item
Definition cJSON.h:222
GEdgeSetTy::iterator iterator
static void WriteGraphToFile(SVF::OutStream &O, const std::string &GraphName, const GraphType &GT, bool simple=false)
u32_t getFlattenedElemIdx(const SVFType *T, u32_t origId)
Flattened element idx of an array or struct by considering stride.
Definition IRGraph.cpp:148
u32_t getNumOfFlattenElements(const SVFType *T)
Definition IRGraph.cpp:186
const std::vector< const SVFType * > & getFlattenFieldTypes(const SVFStructType *T)
Return the flattened field type for struct type only.
Definition IRGraph.cpp:122
void destorySymTable()
Definition IRGraph.cpp:40
SVFStmt * hasLabeledEdge(SVFVar *src, SVFVar *dst, SVFStmt::PEDGEK kind, const ICFGNode *cs)
Definition IRGraph.cpp:308
SVFStmt * hasEdge(SVFStmt *edge, SVFStmt::PEDGEK kind)
Definition IRGraph.cpp:319
void printFlattenFields(const SVFType *type)
Debug method.
Definition IRGraph.cpp:77
void dump(std::string name)
Dump SVFIR.
Definition IRGraph.cpp:333
virtual ~IRGraph()
Definition IRGraph.cpp:58
Set< const StInfo * > stInfos
(owned) All StInfo
Definition IRGraph.h:96
u32_t getObjectNodeNum()
Definition IRGraph.cpp:360
void view()
View graph from the debugger.
Definition IRGraph.cpp:341
virtual APOffset getModulusOffset(const BaseObjVar *baseObj, const APOffset &apOffset)
Given an offset from a Gep Instruction, return it modulus offset by considering memory layout.
Definition IRGraph.cpp:205
SVFStmt::KindToSVFStmtMapTy KindToSVFStmtSetMap
SVFIR edge map containing all PAGEdges.
Definition IRGraph.h:107
const SVFType * getFlatternedElemType(const SVFType *baseType, u32_t flatten_idx)
Return the type of a flattened element given a flattened index.
Definition IRGraph.cpp:127
ObjTypeInfo * createObjTypeInfo(const SVFType *type)
Create an objectInfo based on LLVM type (value is null, and type could be null, representing a dummy ...
Definition IRGraph.cpp:248
std::string getGraphName() const
Return graph name.
Definition IRGraph.h:342
FunObjVarToIDMapTy varargFunObjSymMap
vararg map
Definition IRGraph.h:85
NodeID getReturnNode(const FunObjVar *func) const
GetReturnNode - Return the unique node representing the return value of a function.
Definition IRGraph.cpp:64
const SVFType * getOriginalElemType(const SVFType *baseType, u32_t origId) const
Definition IRGraph.cpp:143
u32_t valVarNum
Definition IRGraph.h:112
IDToTypeInfoMapTy objTypeInfoMap
map a memory sym id to its obj
Definition IRGraph.h:86
bool addEdge(SVFVar *src, SVFVar *dst, SVFStmt *edge)
Add an edge into the graph.
Definition IRGraph.cpp:270
u32_t objVarNum
Definition IRGraph.h:113
NodeID getVarargNode(const FunObjVar *func) const
getVarargNode - Return the unique node representing the variadic argument of a variadic function.
Definition IRGraph.cpp:71
SVFStmt * hasNonlabeledEdge(SVFVar *src, SVFVar *dst, SVFStmt::PEDGEK kind)
Definition IRGraph.cpp:285
u32_t getValueNodeNum()
Definition IRGraph.cpp:347
SVFTypeSet svfTypes
Definition IRGraph.h:93
const StInfo * getTypeInfo(const SVFType *T) const
Get struct info.
Definition IRGraph.cpp:259
FunObjVarToIDMapTy returnFunObjSymMap
return map
Definition IRGraph.h:84
const ObjTypeInfo * createDummyObjTypeInfo(NodeID symId, const SVFType *type)
Definition IRGraph.cpp:194
void setFlag(MEMTYPE mask)
Flag for this object type.
static Option< bool > ModelArrays
Definition Options.h:178
static const Option< bool > CyclicFldIdx
Definition Options.h:179
static const Option< u32_t > MaxFieldLimit
Maximum number of field derivations for an object.
Definition Options.h:34
static const Option< bool > ShowHiddenNode
Definition Options.h:218
static GEdgeFlag makeEdgeFlagWithAddionalOpnd(GEdgeKind k, const SVFVar *var)
static GEdgeFlag makeEdgeFlagWithCallInst(GEdgeKind k, const ICFGNode *cs)
NodeID getId() const
Get ID.
Definition SVFValue.h:158
GNodeK getNodeKind() const
Get node kind.
Definition SVFValue.h:164
virtual const std::string & getName() const
Definition SVFValue.h:184
void addOutEdge(SVFStmt *outEdge)
void addInEdge(SVFStmt *inEdge)
Edge management methods.
virtual const FunObjVar * getFunction() const
Get containing function, or null for globals/constants.
virtual bool isIsolatedNode() const
Check if this node is isolated (no edges) in the SVFIR graph.
virtual const std::string toString() const
Get string representation.
const SVFType * getOriginalElemType(u32_t fldIdx) const
Definition SVFValue.cpp:69
std::vector< const SVFType * > & getFlattenElementTypes()
Definition SVFType.h:127
std::vector< u32_t > & getFlattenedElemIdxVec()
Definition SVFType.h:123
u32_t getNumOfFlattenElements() const
Return number of elements after flattening (including array elements)
Definition SVFType.h:164
std::vector< const SVFType * > & getFlattenFieldTypes()
Definition SVFType.h:131
std::vector< u32_t > & getFlattenedFieldIdxVec()
Definition SVFType.h:119
u32_t getNumOfFlattenFields() const
Return the number of fields after flattening (ignoring array elements)
Definition SVFType.h:170
std::ostream & errs()
Overwrite llvm::errs()
Definition SVFUtil.h:64
void writeWrnMsg(const std::string &msg)
Writes a message run through wrnMsg.
Definition SVFUtil.cpp:88
std::ostream & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:58
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)
s64_t APOffset
Definition GeneralType.h:80
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:76
unsigned u32_t
Definition GeneralType.h:67
static std::string getEdgeAttributes(SVFVar *, EdgeIter EI, IRGraph *)
Definition IRGraph.cpp:458
DOTGraphTraits(bool isSimple=false)
Definition IRGraph.cpp:385
static std::string getGraphName(IRGraph *graph)
Return name of the graph.
Definition IRGraph.cpp:391
static std::string getNodeLabel(SVFVar *node, IRGraph *)
Definition IRGraph.cpp:406
static std::string getNodeAttributes(SVFVar *node, IRGraph *)
Definition IRGraph.cpp:420
static bool isNodeHidden(SVFVar *node, IRGraph *)
Definition IRGraph.cpp:398
NodeType::iterator ChildIteratorType
Definition IRGraph.cpp:384
static std::string getEdgeSourceLabel(SVFVar *, EdgeIter EI)
Definition IRGraph.cpp:536