svf-lib 1.0.729 → 1.0.733
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SVF-linux/Release-build/lib/libSvf.a +0 -0
- package/SVF-linux/include/DDA/DDAVFSolver.h +1 -1
- package/SVF-linux/include/Graphs/PAG.h +4 -4
- package/SVF-linux/include/Graphs/PAGNode.h +3 -3
- package/SVF-linux/include/MemoryModel/SVFIR.h +1 -1
- package/SVF-linux/include/MemoryModel/SVFSymbols.h +648 -0
- package/SVF-linux/include/MemoryModel/SymbolTableInfo.h +26 -14
- package/SVF-linux/include/SVF-FE/SymbolTableBuilder.h +1 -1
- package/SVF-osx/Release-build/lib/CUDD/libCudd.a +0 -0
- package/SVF-osx/Release-build/lib/libSvf.a +0 -0
- package/SVF-osx/include/DDA/ContextDDA.h +1 -1
- package/SVF-osx/include/DDA/DDAClient.h +8 -8
- package/SVF-osx/include/DDA/DDAVFSolver.h +6 -6
- package/SVF-osx/include/DDA/FlowDDA.h +1 -1
- package/SVF-osx/include/Graphs/ConsG.h +6 -6
- package/SVF-osx/include/Graphs/ConsGEdge.h +2 -2
- package/SVF-osx/include/Graphs/ConsGNode.h +1 -1
- package/SVF-osx/include/Graphs/ExternalPAG.h +14 -14
- package/SVF-osx/include/Graphs/ICFGNode.h +14 -14
- package/SVF-osx/include/Graphs/IRGraph.h +245 -0
- package/SVF-osx/include/Graphs/OfflineConsG.h +1 -1
- package/SVF-osx/include/Graphs/PAG.h +4 -4
- package/SVF-osx/include/Graphs/PAGNode.h +4 -4
- package/SVF-osx/include/Graphs/SVFG.h +1 -1
- package/SVF-osx/include/Graphs/SVFGOPT.h +3 -3
- package/SVF-osx/include/Graphs/VFG.h +19 -19
- package/SVF-osx/include/Graphs/VFGNode.h +2 -3
- package/SVF-osx/include/MSSA/MemRegion.h +11 -11
- package/SVF-osx/include/MSSA/MemSSA.h +4 -4
- package/SVF-osx/include/MTA/FSMPTA.h +1 -1
- package/SVF-osx/include/MemoryModel/LocationSet.h +0 -1
- package/SVF-osx/include/MemoryModel/PAGBuilderFromFile.h +8 -8
- package/SVF-osx/include/MemoryModel/PTAStat.h +31 -31
- package/SVF-osx/include/MemoryModel/PointerAnalysis.h +9 -9
- package/SVF-osx/include/MemoryModel/PointerAnalysisImpl.h +3 -3
- package/SVF-osx/include/MemoryModel/SVFIR.h +738 -0
- package/SVF-osx/include/MemoryModel/SVFStatements.h +738 -0
- package/SVF-osx/include/MemoryModel/SVFSymbols.h +648 -0
- package/SVF-osx/include/MemoryModel/SVFVariables.h +842 -0
- package/SVF-osx/include/MemoryModel/SymbolTableInfo.h +731 -0
- package/SVF-osx/include/SABER/SaberSVFGBuilder.h +0 -2
- package/SVF-osx/include/SABER/SrcSnkDDA.h +3 -3
- package/SVF-osx/include/SVF-FE/Graph2Json.h +1 -3
- package/SVF-osx/include/SVF-FE/SVFIRBuilder.h +392 -0
- package/SVF-osx/include/SVF-FE/SymbolTableBuilder.h +89 -0
- package/SVF-osx/include/Util/BasicTypes.h +0 -10
- package/SVF-osx/include/Util/CFLSolver.h +1 -1
- package/SVF-osx/include/Util/ExtAPI.h +1 -1
- package/SVF-osx/include/Util/IRAnnotator.h +6 -6
- package/SVF-osx/include/Util/Options.h +1 -1
- package/SVF-osx/include/Util/SVFUtil.h +11 -0
- package/SVF-osx/include/Util/TypeBasedHeapCloning.h +11 -11
- package/SVF-osx/include/WPA/Andersen.h +11 -100
- package/SVF-osx/include/WPA/AndersenSFR.h +4 -4
- package/SVF-osx/include/WPA/FlowSensitive.h +2 -2
- package/SVF-osx/include/WPA/FlowSensitiveTBHC.h +1 -1
- package/SVF-osx/include/WPA/Steensgaard.h +2 -2
- package/SVF-osx/include/WPA/TypeAnalysis.h +1 -1
- package/SVF-osx/include/WPA/VersionedFlowSensitive.h +2 -2
- package/SVF-osx/include/WPA/WPAStat.h +1 -2
- package/package.json +1 -1
|
@@ -0,0 +1,738 @@
|
|
|
1
|
+
//===- SVFIR.h -- IR of SVF ---------------------------------------------//
|
|
2
|
+
//
|
|
3
|
+
// SVF: Static Value-Flow Analysis
|
|
4
|
+
//
|
|
5
|
+
// Copyright (C) <2013-> <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 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 General Public License for more details.
|
|
17
|
+
|
|
18
|
+
// You should have received a copy of the GNU General Public License
|
|
19
|
+
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
20
|
+
//
|
|
21
|
+
//===----------------------------------------------------------------------===//
|
|
22
|
+
|
|
23
|
+
/*
|
|
24
|
+
* SVFIR.h
|
|
25
|
+
*
|
|
26
|
+
* Created on: 31, 12, 2021
|
|
27
|
+
* Author: Yulei Sui
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
#ifndef SVFIR_H_
|
|
31
|
+
#define SVFIR_H_
|
|
32
|
+
|
|
33
|
+
#include "Graphs/IRGraph.h"
|
|
34
|
+
|
|
35
|
+
namespace SVF
|
|
36
|
+
{
|
|
37
|
+
|
|
38
|
+
/*!
|
|
39
|
+
* SVF Intermediate representation, representing variables and statements as a Program Assignment Graph (PAG)
|
|
40
|
+
* Variables as nodes and statements as edges.
|
|
41
|
+
* SymID and NodeID are equal here (same numbering).
|
|
42
|
+
*/
|
|
43
|
+
class SVFIR : public IRGraph
|
|
44
|
+
{
|
|
45
|
+
|
|
46
|
+
friend class SVFIRBuilder;
|
|
47
|
+
friend class ExternalPAG;
|
|
48
|
+
friend class PAGBuilderFromFile;
|
|
49
|
+
friend class TypeBasedHeapCloning;
|
|
50
|
+
|
|
51
|
+
public:
|
|
52
|
+
typedef Set<const CallBlockNode*> CallSiteSet;
|
|
53
|
+
typedef OrderedMap<const CallBlockNode*,NodeID> CallSiteToFunPtrMap;
|
|
54
|
+
typedef Map<NodeID,CallSiteSet> FunPtrToCallSitesMap;
|
|
55
|
+
typedef Map<NodeID,NodeBS> MemObjToFieldsMap;
|
|
56
|
+
typedef std::vector<const SVFStmt*> PAGEdgeList;
|
|
57
|
+
typedef std::vector<const SVFVar*> PAGNodeList;
|
|
58
|
+
typedef std::vector<const CopyPE*> CopyPEList;
|
|
59
|
+
typedef std::vector<const BinaryOPPE*> BinaryOPList;
|
|
60
|
+
typedef std::vector<const UnaryOPPE*> UnaryOPList;
|
|
61
|
+
typedef std::vector<const CmpPE*> CmpPEList;
|
|
62
|
+
typedef Map<const SVFVar*,CopyPEList> PHINodeMap;
|
|
63
|
+
typedef Map<const SVFVar*,BinaryOPList> BinaryNodeMap;
|
|
64
|
+
typedef Map<const SVFVar*,UnaryOPList> UnaryNodeMap;
|
|
65
|
+
typedef Map<const SVFVar*,CmpPEList> CmpNodeMap;
|
|
66
|
+
typedef Map<const SVFFunction*,PAGNodeList> FunToArgsListMap;
|
|
67
|
+
typedef Map<const CallBlockNode*,PAGNodeList> CSToArgsListMap;
|
|
68
|
+
typedef Map<const RetBlockNode*,const SVFVar*> CSToRetMap;
|
|
69
|
+
typedef Map<const SVFFunction*,const SVFVar*> FunToRetMap;
|
|
70
|
+
typedef Map<const SVFFunction*,PAGEdgeSet> FunToPAGEdgeSetMap;
|
|
71
|
+
typedef Map<const ICFGNode*,PAGEdgeList> Inst2PAGEdgesMap;
|
|
72
|
+
typedef Map<NodeID, NodeID> NodeToNodeMap;
|
|
73
|
+
typedef std::pair<NodeID, Size_t> NodeOffset;
|
|
74
|
+
typedef std::pair<NodeID, LocationSet> NodeLocationSet;
|
|
75
|
+
typedef Map<NodeOffset,NodeID> NodeOffsetMap;
|
|
76
|
+
typedef Map<NodeLocationSet,NodeID> NodeLocationSetMap;
|
|
77
|
+
typedef Map<const Value*, NodeLocationSetMap> GepValPNMap;
|
|
78
|
+
typedef Map<NodePair,NodeID> NodePairSetMap;
|
|
79
|
+
|
|
80
|
+
private:
|
|
81
|
+
/// ValueNodes - This map indicates the Node that a particular Value* is
|
|
82
|
+
/// represented by. This contains entries for all pointers.
|
|
83
|
+
Inst2PAGEdgesMap inst2PAGEdgesMap; ///< Map a instruction to its PAGEdges
|
|
84
|
+
Inst2PAGEdgesMap inst2PTAPAGEdgesMap; ///< Map a instruction to its PointerAnalysis related PAGEdges
|
|
85
|
+
GepValPNMap GepValNodeMap; ///< Map a pair<base,off> to a gep value node id
|
|
86
|
+
NodeLocationSetMap GepObjNodeMap; ///< Map a pair<base,off> to a gep obj node id
|
|
87
|
+
MemObjToFieldsMap memToFieldsMap; ///< Map a mem object id to all its fields
|
|
88
|
+
PAGEdgeSet globPAGEdgesSet; ///< Global PAGEdges without control flow information
|
|
89
|
+
PHINodeMap phiNodeMap; ///< A set of phi copy edges
|
|
90
|
+
BinaryNodeMap binaryNodeMap; ///< A set of binary edges
|
|
91
|
+
UnaryNodeMap unaryNodeMap; ///< A set of unary edges
|
|
92
|
+
CmpNodeMap cmpNodeMap; ///< A set of comparision edges
|
|
93
|
+
FunToArgsListMap funArgsListMap; ///< Map a function to a list of all its formal parameters
|
|
94
|
+
CSToArgsListMap callSiteArgsListMap; ///< Map a callsite to a list of all its actual parameters
|
|
95
|
+
CSToRetMap callSiteRetMap; ///< Map a callsite to its callsite returns PAGNodes
|
|
96
|
+
FunToRetMap funRetMap; ///< Map a function to its unique function return PAGNodes
|
|
97
|
+
static SVFIR* pag; ///< Singleton pattern here to enable instance of SVFIR can only be created once.
|
|
98
|
+
CallSiteToFunPtrMap indCallSiteToFunPtrMap; ///< Map an indirect callsite to its function pointer
|
|
99
|
+
FunPtrToCallSitesMap funPtrToCallSitesMap; ///< Map a function pointer to the callsites where it is used
|
|
100
|
+
/// Valid pointers for pointer analysis resolution connected by SVFIR edges (constraints)
|
|
101
|
+
/// this set of candidate pointers can change during pointer resolution (e.g. adding new object nodes)
|
|
102
|
+
OrderedNodeSet candidatePointers;
|
|
103
|
+
ICFG* icfg; // ICFG
|
|
104
|
+
CallSiteSet callSiteSet; /// all the callsites of a program
|
|
105
|
+
|
|
106
|
+
/// Constructor
|
|
107
|
+
SVFIR(bool buildFromFile);
|
|
108
|
+
|
|
109
|
+
/// Clean up memory
|
|
110
|
+
void destroy();
|
|
111
|
+
|
|
112
|
+
public:
|
|
113
|
+
|
|
114
|
+
/// Singleton design here to make sure we only have one instance during any analysis
|
|
115
|
+
//@{
|
|
116
|
+
static inline SVFIR* getPAG(bool buildFromFile = false)
|
|
117
|
+
{
|
|
118
|
+
if (pag == nullptr)
|
|
119
|
+
{
|
|
120
|
+
pag = new SVFIR(buildFromFile);
|
|
121
|
+
}
|
|
122
|
+
return pag;
|
|
123
|
+
}
|
|
124
|
+
static void releasePAG()
|
|
125
|
+
{
|
|
126
|
+
if (pag)
|
|
127
|
+
delete pag;
|
|
128
|
+
pag = nullptr;
|
|
129
|
+
}
|
|
130
|
+
//@}
|
|
131
|
+
/// Return memToFieldsMap
|
|
132
|
+
inline MemObjToFieldsMap& getMemToFieldsMap()
|
|
133
|
+
{
|
|
134
|
+
return memToFieldsMap;
|
|
135
|
+
}
|
|
136
|
+
/// Return GepObjNodeMap
|
|
137
|
+
inline NodeLocationSetMap& getGepObjNodeMap()
|
|
138
|
+
{
|
|
139
|
+
return GepObjNodeMap;
|
|
140
|
+
}
|
|
141
|
+
/// Return ICFG
|
|
142
|
+
inline ICFG* getICFG()
|
|
143
|
+
{
|
|
144
|
+
return icfg;
|
|
145
|
+
}
|
|
146
|
+
/// Return valid pointers
|
|
147
|
+
inline OrderedNodeSet& getAllValidPtrs()
|
|
148
|
+
{
|
|
149
|
+
return candidatePointers;
|
|
150
|
+
}
|
|
151
|
+
/// Initialize candidate pointers
|
|
152
|
+
void initialiseCandidatePointers();
|
|
153
|
+
|
|
154
|
+
/// Destructor
|
|
155
|
+
virtual ~SVFIR()
|
|
156
|
+
{
|
|
157
|
+
destroy();
|
|
158
|
+
}
|
|
159
|
+
/// SVFIR build configurations
|
|
160
|
+
//@{
|
|
161
|
+
/// Whether to handle blackhole edge
|
|
162
|
+
static void handleBlackHole(bool b);
|
|
163
|
+
//@}
|
|
164
|
+
/// Get LLVM Module
|
|
165
|
+
inline SVFModule* getModule()
|
|
166
|
+
{
|
|
167
|
+
return SymbolTableInfo::SymbolInfo()->getModule();
|
|
168
|
+
}
|
|
169
|
+
inline void addCallSite(const CallBlockNode* call)
|
|
170
|
+
{
|
|
171
|
+
callSiteSet.insert(call);
|
|
172
|
+
}
|
|
173
|
+
inline const CallSiteSet& getCallSiteSet() const
|
|
174
|
+
{
|
|
175
|
+
return callSiteSet;
|
|
176
|
+
}
|
|
177
|
+
/// Get/set methods to get control flow information of a SVFStmt
|
|
178
|
+
//@{
|
|
179
|
+
/// Whether this instruction has SVFIR Edge
|
|
180
|
+
inline bool hasPAGEdgeList(const ICFGNode* inst) const
|
|
181
|
+
{
|
|
182
|
+
return inst2PAGEdgesMap.find(inst)!=inst2PAGEdgesMap.end();
|
|
183
|
+
}
|
|
184
|
+
inline bool hasPTAPAGEdgeList(const ICFGNode* inst) const
|
|
185
|
+
{
|
|
186
|
+
return inst2PTAPAGEdgesMap.find(inst)!=inst2PTAPAGEdgesMap.end();
|
|
187
|
+
}
|
|
188
|
+
/// Given an instruction, get all its PAGEdges
|
|
189
|
+
inline PAGEdgeList& getInstPAGEdgeList(const ICFGNode* inst)
|
|
190
|
+
{
|
|
191
|
+
return inst2PAGEdgesMap[inst];
|
|
192
|
+
}
|
|
193
|
+
/// Given an instruction, get all its PTA PAGEdges
|
|
194
|
+
inline PAGEdgeList& getInstPTAPAGEdgeList(const ICFGNode* inst)
|
|
195
|
+
{
|
|
196
|
+
return inst2PTAPAGEdgesMap[inst];
|
|
197
|
+
}
|
|
198
|
+
/// Add a SVFStmt into instruction map
|
|
199
|
+
inline void addToInstPAGEdgeList(ICFGNode* inst, SVFStmt* edge)
|
|
200
|
+
{
|
|
201
|
+
edge->setICFGNode(inst);
|
|
202
|
+
inst2PAGEdgesMap[inst].push_back(edge);
|
|
203
|
+
if (edge->isPTAEdge())
|
|
204
|
+
inst2PTAPAGEdgesMap[inst].push_back(edge);
|
|
205
|
+
}
|
|
206
|
+
/// Get global PAGEdges (not in a procedure)
|
|
207
|
+
inline void addGlobalPAGEdge(const SVFStmt* edge)
|
|
208
|
+
{
|
|
209
|
+
globPAGEdgesSet.insert(edge);
|
|
210
|
+
}
|
|
211
|
+
/// Get global PAGEdges (not in a procedure)
|
|
212
|
+
inline PAGEdgeSet& getGlobalPAGEdgeSet()
|
|
213
|
+
{
|
|
214
|
+
return globPAGEdgesSet;
|
|
215
|
+
}
|
|
216
|
+
/// Add phi node information
|
|
217
|
+
inline void addPhiNode(const SVFVar* res, const CopyPE* edge)
|
|
218
|
+
{
|
|
219
|
+
phiNodeMap[res].push_back(edge);
|
|
220
|
+
}
|
|
221
|
+
/// Whether this SVFVar is a result operand a of phi node
|
|
222
|
+
inline bool isPhiNode(const SVFVar* node) const
|
|
223
|
+
{
|
|
224
|
+
return phiNodeMap.find(node) != phiNodeMap.end();
|
|
225
|
+
}
|
|
226
|
+
/// Get all phi copy edges
|
|
227
|
+
inline PHINodeMap& getPhiNodeMap()
|
|
228
|
+
{
|
|
229
|
+
return phiNodeMap;
|
|
230
|
+
}
|
|
231
|
+
/// Get the corresponding PhiCopyPEs
|
|
232
|
+
inline const CopyPEList& getPhiCopyPEs(const SVFVar* node) const{
|
|
233
|
+
PHINodeMap::const_iterator it = phiNodeMap.find(node);
|
|
234
|
+
assert(it != phiNodeMap.end() && "PhiCopyPEs not found!");
|
|
235
|
+
return it->second;
|
|
236
|
+
}
|
|
237
|
+
/// Add phi node information
|
|
238
|
+
inline void addBinaryNode(const SVFVar* res, const BinaryOPPE* edge)
|
|
239
|
+
{
|
|
240
|
+
binaryNodeMap[res].push_back(edge);
|
|
241
|
+
}
|
|
242
|
+
/// Whether this SVFVar is a result operand a of phi node
|
|
243
|
+
inline bool isBinaryNode(const SVFVar* node) const
|
|
244
|
+
{
|
|
245
|
+
return binaryNodeMap.find(node) != binaryNodeMap.end();
|
|
246
|
+
}
|
|
247
|
+
/// Get all phi copy edges
|
|
248
|
+
inline BinaryNodeMap& getBinaryNodeMap()
|
|
249
|
+
{
|
|
250
|
+
return binaryNodeMap;
|
|
251
|
+
}
|
|
252
|
+
/// Get the corresponding BinaryPEs
|
|
253
|
+
inline const BinaryOPList& getBinaryPEs(const SVFVar* node) const{
|
|
254
|
+
BinaryNodeMap::const_iterator it = binaryNodeMap.find(node);
|
|
255
|
+
assert(it != binaryNodeMap.end() && "BinaryPEs not found!");
|
|
256
|
+
return it->second;
|
|
257
|
+
}
|
|
258
|
+
/// Add unary node information
|
|
259
|
+
inline void addUnaryNode(const SVFVar* res, const UnaryOPPE* edge)
|
|
260
|
+
{
|
|
261
|
+
unaryNodeMap[res].push_back(edge);
|
|
262
|
+
}
|
|
263
|
+
/// Whether this SVFVar is an unary node
|
|
264
|
+
inline bool isUnaryNode(const SVFVar* node) const
|
|
265
|
+
{
|
|
266
|
+
return unaryNodeMap.find(node) != unaryNodeMap.end();
|
|
267
|
+
}
|
|
268
|
+
/// Get all unary edges
|
|
269
|
+
inline UnaryNodeMap& getUnaryNodeMap()
|
|
270
|
+
{
|
|
271
|
+
return unaryNodeMap;
|
|
272
|
+
}
|
|
273
|
+
/// Get the corresponding UnaryPEs
|
|
274
|
+
inline const UnaryOPList& getUnaryPEs(const SVFVar* node) const{
|
|
275
|
+
UnaryNodeMap::const_iterator it = unaryNodeMap.find(node);
|
|
276
|
+
assert(it != unaryNodeMap.end() && "UnaryPEs not found!");
|
|
277
|
+
return it->second;
|
|
278
|
+
}
|
|
279
|
+
/// Add phi node information
|
|
280
|
+
inline void addCmpNode(const SVFVar* res, const CmpPE* edge)
|
|
281
|
+
{
|
|
282
|
+
cmpNodeMap[res].push_back(edge);
|
|
283
|
+
}
|
|
284
|
+
/// Whether this SVFVar is a result operand a of phi node
|
|
285
|
+
inline bool isCmpNode(const SVFVar* node) const
|
|
286
|
+
{
|
|
287
|
+
return cmpNodeMap.find(node) != cmpNodeMap.end();
|
|
288
|
+
}
|
|
289
|
+
/// Get all phi copy edges
|
|
290
|
+
inline CmpNodeMap& getCmpNodeMap()
|
|
291
|
+
{
|
|
292
|
+
return cmpNodeMap;
|
|
293
|
+
}
|
|
294
|
+
/// Get the corresponding CmpPEs
|
|
295
|
+
inline const CmpPEList& getCmpPEs(const SVFVar* node) const{
|
|
296
|
+
CmpNodeMap::const_iterator it = cmpNodeMap.find(node);
|
|
297
|
+
assert(it != cmpNodeMap.end() && "CmpPEs not found!");
|
|
298
|
+
return it->second;
|
|
299
|
+
}
|
|
300
|
+
//@}
|
|
301
|
+
|
|
302
|
+
private:
|
|
303
|
+
/// Get/set method for function/callsite arguments and returns
|
|
304
|
+
//@{
|
|
305
|
+
/// Add function arguments
|
|
306
|
+
inline void addFunArgs(const SVFFunction* fun, const SVFVar* arg)
|
|
307
|
+
{
|
|
308
|
+
FunEntryBlockNode* funEntryBlockNode = icfg->getFunEntryBlockNode(fun);
|
|
309
|
+
funEntryBlockNode->addFormalParms(arg);
|
|
310
|
+
funArgsListMap[fun].push_back(arg);
|
|
311
|
+
}
|
|
312
|
+
/// Add function returns
|
|
313
|
+
inline void addFunRet(const SVFFunction* fun, const SVFVar* ret)
|
|
314
|
+
{
|
|
315
|
+
FunExitBlockNode* funExitBlockNode = icfg->getFunExitBlockNode(fun);
|
|
316
|
+
funExitBlockNode->addFormalRet(ret);
|
|
317
|
+
funRetMap[fun] = ret;
|
|
318
|
+
}
|
|
319
|
+
/// Add callsite arguments
|
|
320
|
+
inline void addCallSiteArgs(CallBlockNode* callBlockNode,const SVFVar* arg)
|
|
321
|
+
{
|
|
322
|
+
callBlockNode->addActualParms(arg);
|
|
323
|
+
callSiteArgsListMap[callBlockNode].push_back(arg);
|
|
324
|
+
}
|
|
325
|
+
/// Add callsite returns
|
|
326
|
+
inline void addCallSiteRets(RetBlockNode* retBlockNode,const SVFVar* arg)
|
|
327
|
+
{
|
|
328
|
+
retBlockNode->addActualRet(arg);
|
|
329
|
+
callSiteRetMap[retBlockNode]= arg;
|
|
330
|
+
}
|
|
331
|
+
/// Add indirect callsites
|
|
332
|
+
inline void addIndirectCallsites(const CallBlockNode* cs,NodeID funPtr)
|
|
333
|
+
{
|
|
334
|
+
bool added = indCallSiteToFunPtrMap.insert(std::make_pair(cs,funPtr)).second;
|
|
335
|
+
funPtrToCallSitesMap[funPtr].insert(cs);
|
|
336
|
+
assert(added && "adding the same indirect callsite twice?");
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
public:
|
|
340
|
+
/// Function has arguments list
|
|
341
|
+
inline bool hasFunArgsList(const SVFFunction* func) const
|
|
342
|
+
{
|
|
343
|
+
return (funArgsListMap.find(func) != funArgsListMap.end());
|
|
344
|
+
}
|
|
345
|
+
/// Get function arguments list
|
|
346
|
+
inline FunToArgsListMap& getFunArgsMap()
|
|
347
|
+
{
|
|
348
|
+
return funArgsListMap;
|
|
349
|
+
}
|
|
350
|
+
/// Get function arguments list
|
|
351
|
+
inline const PAGNodeList& getFunArgsList(const SVFFunction* func) const
|
|
352
|
+
{
|
|
353
|
+
FunToArgsListMap::const_iterator it = funArgsListMap.find(func);
|
|
354
|
+
assert(it != funArgsListMap.end() && "this function doesn't have arguments");
|
|
355
|
+
return it->second;
|
|
356
|
+
}
|
|
357
|
+
/// Callsite has argument list
|
|
358
|
+
inline bool hasCallSiteArgsMap(const CallBlockNode* cs) const
|
|
359
|
+
{
|
|
360
|
+
return (callSiteArgsListMap.find(cs) != callSiteArgsListMap.end());
|
|
361
|
+
}
|
|
362
|
+
/// Get callsite argument list
|
|
363
|
+
inline CSToArgsListMap& getCallSiteArgsMap()
|
|
364
|
+
{
|
|
365
|
+
return callSiteArgsListMap;
|
|
366
|
+
}
|
|
367
|
+
/// Get callsite argument list
|
|
368
|
+
inline const PAGNodeList& getCallSiteArgsList(const CallBlockNode* cs) const
|
|
369
|
+
{
|
|
370
|
+
CSToArgsListMap::const_iterator it = callSiteArgsListMap.find(cs);
|
|
371
|
+
assert(it != callSiteArgsListMap.end() && "this call site doesn't have arguments");
|
|
372
|
+
return it->second;
|
|
373
|
+
}
|
|
374
|
+
/// Get callsite return
|
|
375
|
+
inline CSToRetMap& getCallSiteRets()
|
|
376
|
+
{
|
|
377
|
+
return callSiteRetMap;
|
|
378
|
+
}
|
|
379
|
+
/// Get callsite return
|
|
380
|
+
inline const SVFVar* getCallSiteRet(const RetBlockNode* cs) const
|
|
381
|
+
{
|
|
382
|
+
CSToRetMap::const_iterator it = callSiteRetMap.find(cs);
|
|
383
|
+
assert(it != callSiteRetMap.end() && "this call site doesn't have return");
|
|
384
|
+
return it->second;
|
|
385
|
+
}
|
|
386
|
+
inline bool callsiteHasRet(const RetBlockNode* cs) const
|
|
387
|
+
{
|
|
388
|
+
return callSiteRetMap.find(cs) != callSiteRetMap.end();
|
|
389
|
+
}
|
|
390
|
+
/// Get function return list
|
|
391
|
+
inline FunToRetMap& getFunRets()
|
|
392
|
+
{
|
|
393
|
+
return funRetMap;
|
|
394
|
+
}
|
|
395
|
+
/// Get function return list
|
|
396
|
+
inline const SVFVar* getFunRet(const SVFFunction* func) const
|
|
397
|
+
{
|
|
398
|
+
FunToRetMap::const_iterator it = funRetMap.find(func);
|
|
399
|
+
assert(it != funRetMap.end() && "this function doesn't have return");
|
|
400
|
+
return it->second;
|
|
401
|
+
}
|
|
402
|
+
inline bool funHasRet(const SVFFunction* func) const
|
|
403
|
+
{
|
|
404
|
+
return funRetMap.find(func) != funRetMap.end();
|
|
405
|
+
}
|
|
406
|
+
//@}
|
|
407
|
+
|
|
408
|
+
/// Node and edge statistics
|
|
409
|
+
//@{
|
|
410
|
+
inline Size_t getFieldValNodeNum() const
|
|
411
|
+
{
|
|
412
|
+
return GepValNodeMap.size();
|
|
413
|
+
}
|
|
414
|
+
inline Size_t getFieldObjNodeNum() const
|
|
415
|
+
{
|
|
416
|
+
return GepObjNodeMap.size();
|
|
417
|
+
}
|
|
418
|
+
//@}
|
|
419
|
+
|
|
420
|
+
/// Due to constaint expression, curInst is used to distinguish different instructions (e.g., memorycpy) when creating GepValPN.
|
|
421
|
+
inline NodeID getGepValNode(const Value* curInst, NodeID base, const LocationSet& ls) const
|
|
422
|
+
{
|
|
423
|
+
GepValPNMap::const_iterator iter = GepValNodeMap.find(curInst);
|
|
424
|
+
if(iter==GepValNodeMap.end()){
|
|
425
|
+
return UINT_MAX;
|
|
426
|
+
}
|
|
427
|
+
else{
|
|
428
|
+
NodeLocationSetMap::const_iterator lit = iter->second.find(std::make_pair(base, ls));
|
|
429
|
+
if(lit==iter->second.end())
|
|
430
|
+
return UINT_MAX;
|
|
431
|
+
else
|
|
432
|
+
return lit->second;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/// Add/get indirect callsites
|
|
437
|
+
//@{
|
|
438
|
+
inline const CallSiteToFunPtrMap& getIndirectCallsites() const
|
|
439
|
+
{
|
|
440
|
+
return indCallSiteToFunPtrMap;
|
|
441
|
+
}
|
|
442
|
+
inline NodeID getFunPtr(const CallBlockNode* cs) const
|
|
443
|
+
{
|
|
444
|
+
CallSiteToFunPtrMap::const_iterator it = indCallSiteToFunPtrMap.find(cs);
|
|
445
|
+
assert(it!=indCallSiteToFunPtrMap.end() && "indirect callsite not have a function pointer?");
|
|
446
|
+
return it->second;
|
|
447
|
+
}
|
|
448
|
+
inline const CallSiteSet& getIndCallSites(NodeID funPtr) const
|
|
449
|
+
{
|
|
450
|
+
FunPtrToCallSitesMap::const_iterator it = funPtrToCallSitesMap.find(funPtr);
|
|
451
|
+
assert(it!=funPtrToCallSitesMap.end() && "function pointer not used at any indirect callsite?");
|
|
452
|
+
return it->second;
|
|
453
|
+
}
|
|
454
|
+
inline bool isIndirectCallSites(const CallBlockNode* cs) const
|
|
455
|
+
{
|
|
456
|
+
return (indCallSiteToFunPtrMap.find(cs) != indCallSiteToFunPtrMap.end());
|
|
457
|
+
}
|
|
458
|
+
inline bool isFunPtr(NodeID id) const
|
|
459
|
+
{
|
|
460
|
+
return (funPtrToCallSitesMap.find(id) != funPtrToCallSitesMap.end());
|
|
461
|
+
}
|
|
462
|
+
//@}
|
|
463
|
+
/// Get an edge according to src, dst and kind
|
|
464
|
+
//@{
|
|
465
|
+
inline SVFStmt* getIntraPAGEdge(NodeID src, NodeID dst, SVFStmt::PEDGEK kind)
|
|
466
|
+
{
|
|
467
|
+
return getIntraPAGEdge(getGNode(src), getGNode(dst), kind);
|
|
468
|
+
}
|
|
469
|
+
inline SVFStmt* getIntraPAGEdge(SVFVar* src, SVFVar* dst, SVFStmt::PEDGEK kind)
|
|
470
|
+
{
|
|
471
|
+
SVFStmt edge(src,dst,kind);
|
|
472
|
+
const SVFStmt::PAGEdgeSetTy& edgeSet = getEdgeSet(kind);
|
|
473
|
+
SVFStmt::PAGEdgeSetTy::const_iterator it = edgeSet.find(&edge);
|
|
474
|
+
assert(it != edgeSet.end() && "can not find pag edge");
|
|
475
|
+
return (*it);
|
|
476
|
+
}
|
|
477
|
+
//@}
|
|
478
|
+
|
|
479
|
+
/// Get memory object - Return memory object according to pag node id
|
|
480
|
+
/// return whole allocated memory object if this node is a gep obj node
|
|
481
|
+
/// return nullptr is this node is not a ObjPN type
|
|
482
|
+
//@{
|
|
483
|
+
inline const MemObj*getObject(NodeID id) const
|
|
484
|
+
{
|
|
485
|
+
const SVFVar* node = getGNode(id);
|
|
486
|
+
if(const ObjPN* objPN = SVFUtil::dyn_cast<ObjPN>(node))
|
|
487
|
+
return getObject(objPN);
|
|
488
|
+
else
|
|
489
|
+
return nullptr;
|
|
490
|
+
}
|
|
491
|
+
inline const MemObj*getObject(const ObjPN* node) const
|
|
492
|
+
{
|
|
493
|
+
return node->getMemObj();
|
|
494
|
+
}
|
|
495
|
+
//@}
|
|
496
|
+
|
|
497
|
+
/// Get a field SVFIR Object node according to base mem obj and offset
|
|
498
|
+
NodeID getGepObjNode(const MemObj* obj, const LocationSet& ls);
|
|
499
|
+
/// Get a field obj SVFIR node according to a mem obj and a given offset
|
|
500
|
+
NodeID getGepObjNode(NodeID id, const LocationSet& ls) ;
|
|
501
|
+
/// Get a field-insensitive obj SVFIR node according to a mem obj
|
|
502
|
+
//@{
|
|
503
|
+
inline NodeID getFIObjNode(const MemObj* obj) const
|
|
504
|
+
{
|
|
505
|
+
return obj->getId();
|
|
506
|
+
}
|
|
507
|
+
inline NodeID getFIObjNode(NodeID id) const
|
|
508
|
+
{
|
|
509
|
+
SVFVar* node = pag->getGNode(id);
|
|
510
|
+
assert(SVFUtil::isa<ObjPN>(node) && "need an object node");
|
|
511
|
+
ObjPN* obj = SVFUtil::cast<ObjPN>(node);
|
|
512
|
+
return getFIObjNode(obj->getMemObj());
|
|
513
|
+
}
|
|
514
|
+
//@}
|
|
515
|
+
|
|
516
|
+
/// Get black hole and constant id
|
|
517
|
+
//@{
|
|
518
|
+
inline bool isBlkPtr(NodeID id) const
|
|
519
|
+
{
|
|
520
|
+
return (SymbolTableInfo::isBlkPtr(id));
|
|
521
|
+
}
|
|
522
|
+
inline bool isNullPtr(NodeID id) const
|
|
523
|
+
{
|
|
524
|
+
return (SymbolTableInfo::isNullPtr(id));
|
|
525
|
+
}
|
|
526
|
+
inline bool isBlkObjOrConstantObj(NodeID id) const
|
|
527
|
+
{
|
|
528
|
+
return (isBlkObj(id) || isConstantObj(id));
|
|
529
|
+
}
|
|
530
|
+
inline bool isBlkObj(NodeID id) const
|
|
531
|
+
{
|
|
532
|
+
return SymbolTableInfo::isBlkObj(id);
|
|
533
|
+
}
|
|
534
|
+
inline bool isConstantObj(NodeID id) const
|
|
535
|
+
{
|
|
536
|
+
const MemObj* obj = getObject(id);
|
|
537
|
+
assert(obj && "not an object node?");
|
|
538
|
+
return SymbolTableInfo::isConstantObj(id) || obj->isConstant();
|
|
539
|
+
}
|
|
540
|
+
inline bool isNonPointerObj(NodeID id) const
|
|
541
|
+
{
|
|
542
|
+
SVFVar* node = getGNode(id);
|
|
543
|
+
if (FIObjPN* fiNode = SVFUtil::dyn_cast<FIObjPN>(node))
|
|
544
|
+
{
|
|
545
|
+
return (fiNode->getMemObj()->hasPtrObj() == false);
|
|
546
|
+
}
|
|
547
|
+
else if (GepObjPN* gepNode = SVFUtil::dyn_cast<GepObjPN>(node))
|
|
548
|
+
{
|
|
549
|
+
return (gepNode->getMemObj()->isNonPtrFieldObj(gepNode->getLocationSet()));
|
|
550
|
+
}
|
|
551
|
+
else if (SVFUtil::isa<DummyObjPN>(node))
|
|
552
|
+
{
|
|
553
|
+
return false;
|
|
554
|
+
}
|
|
555
|
+
else
|
|
556
|
+
{
|
|
557
|
+
assert(false && "expecting a object node");
|
|
558
|
+
return false;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
//@}
|
|
562
|
+
|
|
563
|
+
/// Base and Offset methods for Value and Object node
|
|
564
|
+
//@{
|
|
565
|
+
/// Get a base pointer node given a field pointer
|
|
566
|
+
NodeID getBaseValNode(NodeID nodeId);
|
|
567
|
+
LocationSet getLocationSetFromBaseNode(NodeID nodeId);
|
|
568
|
+
inline NodeID getBaseObjNode(NodeID id) const
|
|
569
|
+
{
|
|
570
|
+
return getBaseObj(id)->getId();
|
|
571
|
+
}
|
|
572
|
+
inline const MemObj* getBaseObj(NodeID id) const
|
|
573
|
+
{
|
|
574
|
+
const SVFVar* node = pag->getGNode(id);
|
|
575
|
+
assert(SVFUtil::isa<ObjPN>(node) && "need an object node");
|
|
576
|
+
const ObjPN* obj = SVFUtil::cast<ObjPN>(node);
|
|
577
|
+
return obj->getMemObj();
|
|
578
|
+
}
|
|
579
|
+
//@}
|
|
580
|
+
|
|
581
|
+
/// Get all fields of an object
|
|
582
|
+
//@{
|
|
583
|
+
NodeBS& getAllFieldsObjNode(const MemObj* obj);
|
|
584
|
+
NodeBS& getAllFieldsObjNode(NodeID id);
|
|
585
|
+
NodeBS getFieldsAfterCollapse(NodeID id);
|
|
586
|
+
//@}
|
|
587
|
+
|
|
588
|
+
private:
|
|
589
|
+
/// add node into SVFIR
|
|
590
|
+
//@{
|
|
591
|
+
/// Add a value (pointer) node
|
|
592
|
+
inline NodeID addValNode(const Value* val, NodeID i)
|
|
593
|
+
{
|
|
594
|
+
SVFVar *node = new ValPN(val,i);
|
|
595
|
+
return addValNode(val, node, i);
|
|
596
|
+
}
|
|
597
|
+
/// Add a memory obj node
|
|
598
|
+
inline NodeID addObjNode(const Value* val, NodeID i)
|
|
599
|
+
{
|
|
600
|
+
const MemObj* mem = getMemObj(val);
|
|
601
|
+
assert(((mem->getId() == i)) && "not same object id?");
|
|
602
|
+
return addFIObjNode(mem);
|
|
603
|
+
}
|
|
604
|
+
/// Add a unique return node for a procedure
|
|
605
|
+
inline NodeID addRetNode(const SVFFunction* val, NodeID i)
|
|
606
|
+
{
|
|
607
|
+
SVFVar *node = new RetPN(val,i);
|
|
608
|
+
return addRetNode(val, node, i);
|
|
609
|
+
}
|
|
610
|
+
/// Add a unique vararg node for a procedure
|
|
611
|
+
inline NodeID addVarargNode(const SVFFunction* val, NodeID i)
|
|
612
|
+
{
|
|
613
|
+
SVFVar *node = new VarArgPN(val,i);
|
|
614
|
+
return addNode(node,i);
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
/// Add a temp field value node, this method can only invoked by getGepValNode
|
|
618
|
+
NodeID addGepValNode(const Value* curInst,const Value* val, const LocationSet& ls, NodeID i, const Type *type, u32_t fieldidx);
|
|
619
|
+
/// Add a field obj node, this method can only invoked by getGepObjNode
|
|
620
|
+
NodeID addGepObjNode(const MemObj* obj, const LocationSet& ls);
|
|
621
|
+
/// Add a field-insensitive node, this method can only invoked by getFIGepObjNode
|
|
622
|
+
NodeID addFIObjNode(const MemObj* obj);
|
|
623
|
+
//@}
|
|
624
|
+
|
|
625
|
+
/// Add a dummy value/object node according to node ID (llvm value is null)
|
|
626
|
+
//@{
|
|
627
|
+
inline NodeID addDummyValNode(NodeID i)
|
|
628
|
+
{
|
|
629
|
+
return addValNode(nullptr, new DummyValPN(i), i);
|
|
630
|
+
}
|
|
631
|
+
inline NodeID addDummyObjNode(NodeID i, const Type* type)
|
|
632
|
+
{
|
|
633
|
+
const MemObj* mem = addDummyMemObj(i, type);
|
|
634
|
+
return addObjNode(nullptr, new DummyObjPN(i,mem), i);
|
|
635
|
+
}
|
|
636
|
+
inline const MemObj* addDummyMemObj(NodeID i, const Type* type)
|
|
637
|
+
{
|
|
638
|
+
return SymbolTableInfo::SymbolInfo()->createDummyObj(i,type);
|
|
639
|
+
}
|
|
640
|
+
inline NodeID addBlackholeObjNode()
|
|
641
|
+
{
|
|
642
|
+
return addObjNode(nullptr, new DummyObjPN(getBlackHoleNode(),getBlackHoleObj()), getBlackHoleNode());
|
|
643
|
+
}
|
|
644
|
+
inline NodeID addConstantObjNode()
|
|
645
|
+
{
|
|
646
|
+
return addObjNode(nullptr, new DummyObjPN(getConstantNode(),getConstantObj()), getConstantNode());
|
|
647
|
+
}
|
|
648
|
+
inline NodeID addBlackholePtrNode()
|
|
649
|
+
{
|
|
650
|
+
return addDummyValNode(getBlkPtr());
|
|
651
|
+
}
|
|
652
|
+
//@}
|
|
653
|
+
|
|
654
|
+
/// Add a value (pointer) node
|
|
655
|
+
inline NodeID addValNode(const Value*, SVFVar *node, NodeID i)
|
|
656
|
+
{
|
|
657
|
+
assert(hasGNode(i) == false && "This NodeID clashes here. Please check NodeIDAllocator. Switch Strategy::DEBUG to SEQ or DENSE");
|
|
658
|
+
return addNode(node,i);
|
|
659
|
+
}
|
|
660
|
+
/// Add a memory obj node
|
|
661
|
+
inline NodeID addObjNode(const Value*, SVFVar *node, NodeID i)
|
|
662
|
+
{
|
|
663
|
+
assert(hasGNode(i) == false && "This NodeID clashes here. Please check NodeIDAllocator. Switch Strategy::DEBUG to SEQ or DENSE");
|
|
664
|
+
return addNode(node,i);
|
|
665
|
+
}
|
|
666
|
+
/// Add a unique return node for a procedure
|
|
667
|
+
inline NodeID addRetNode(const SVFFunction*, SVFVar *node, NodeID i)
|
|
668
|
+
{
|
|
669
|
+
return addNode(node,i);
|
|
670
|
+
}
|
|
671
|
+
/// Add a unique vararg node for a procedure
|
|
672
|
+
inline NodeID addVarargNode(const SVFFunction*, SVFVar *node, NodeID i)
|
|
673
|
+
{
|
|
674
|
+
return addNode(node,i);
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
/// Add an edge into SVFIR
|
|
678
|
+
//@{
|
|
679
|
+
/// Add Address edge
|
|
680
|
+
AddrPE* addAddrPE(NodeID src, NodeID dst);
|
|
681
|
+
/// Add Copy edge
|
|
682
|
+
CopyPE* addCopyPE(NodeID src, NodeID dst);
|
|
683
|
+
/// Add Copy edge
|
|
684
|
+
CmpPE* addCmpPE(NodeID src, NodeID dst);
|
|
685
|
+
/// Add Copy edge
|
|
686
|
+
BinaryOPPE* addBinaryOPPE(NodeID src, NodeID dst);
|
|
687
|
+
/// Add Unary edge
|
|
688
|
+
UnaryOPPE* addUnaryOPPE(NodeID src, NodeID dst);
|
|
689
|
+
/// Add Load edge
|
|
690
|
+
LoadPE* addLoadPE(NodeID src, NodeID dst);
|
|
691
|
+
/// Add Store edge
|
|
692
|
+
StorePE* addStorePE(NodeID src, NodeID dst, const IntraBlockNode* val);
|
|
693
|
+
/// Add Call edge
|
|
694
|
+
CallPE* addCallPE(NodeID src, NodeID dst, const CallBlockNode* cs);
|
|
695
|
+
/// Add Return edge
|
|
696
|
+
RetPE* addRetPE(NodeID src, NodeID dst, const CallBlockNode* cs);
|
|
697
|
+
/// Add Gep edge
|
|
698
|
+
GepPE* addGepPE(NodeID src, NodeID dst, const LocationSet& ls, bool constGep);
|
|
699
|
+
/// Add Offset(Gep) edge
|
|
700
|
+
NormalGepPE* addNormalGepPE(NodeID src, NodeID dst, const LocationSet& ls);
|
|
701
|
+
/// Add Variant(Gep) edge
|
|
702
|
+
VariantGepPE* addVariantGepPE(NodeID src, NodeID dst);
|
|
703
|
+
/// Add Thread fork edge for parameter passing
|
|
704
|
+
TDForkPE* addThreadForkPE(NodeID src, NodeID dst, const CallBlockNode* cs);
|
|
705
|
+
/// Add Thread join edge for parameter passing
|
|
706
|
+
TDJoinPE* addThreadJoinPE(NodeID src, NodeID dst, const CallBlockNode* cs);
|
|
707
|
+
//@}
|
|
708
|
+
|
|
709
|
+
/// Set a pointer points-to black hole (e.g. int2ptr)
|
|
710
|
+
SVFStmt* addBlackHoleAddrPE(NodeID node);
|
|
711
|
+
|
|
712
|
+
public:
|
|
713
|
+
inline NodeID addDummyValNode()
|
|
714
|
+
{
|
|
715
|
+
return addDummyValNode(NodeIDAllocator::get()->allocateValueId());
|
|
716
|
+
}
|
|
717
|
+
inline NodeID addDummyObjNode(const Type* type = nullptr)
|
|
718
|
+
{
|
|
719
|
+
return addDummyObjNode(NodeIDAllocator::get()->allocateObjectId(), type);
|
|
720
|
+
}
|
|
721
|
+
/// Whether a node is a valid pointer
|
|
722
|
+
//@{
|
|
723
|
+
bool isValidPointer(NodeID nodeId) const;
|
|
724
|
+
|
|
725
|
+
bool isValidTopLevelPtr(const SVFVar* node);
|
|
726
|
+
//@}
|
|
727
|
+
|
|
728
|
+
/// Print SVFIR
|
|
729
|
+
void print();
|
|
730
|
+
};
|
|
731
|
+
|
|
732
|
+
typedef SVFIR PAG;
|
|
733
|
+
|
|
734
|
+
} // End namespace SVF
|
|
735
|
+
|
|
736
|
+
|
|
737
|
+
|
|
738
|
+
#endif /* SVFIR_H_ */
|