svf-tools 1.0.1017 → 1.0.1019
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/package.json +1 -1
- package/svf/include/DDA/DDAVFSolver.h +5 -4
- package/svf/include/Graphs/GenericGraph.h +62 -101
- package/svf/include/MemoryModel/PointerAnalysis.h +2 -4
- package/svf/include/SVFIR/SVFFileSystem.h +3 -3
- package/svf/include/SVFIR/SVFIR.h +35 -0
- package/svf/include/SVFIR/SVFVariables.h +153 -22
- package/svf/include/Util/SVFUtil.h +0 -2
- package/svf/lib/AE/Svfexe/AEDetector.cpp +5 -5
- package/svf/lib/DDA/ContextDDA.cpp +3 -1
- package/svf/lib/DDA/FlowDDA.cpp +2 -3
- package/svf/lib/Graphs/ConsG.cpp +1 -1
- package/svf/lib/Graphs/IRGraph.cpp +1 -1
- package/svf/lib/MSSA/MemRegion.cpp +5 -3
- package/svf/lib/MemoryModel/PointerAnalysis.cpp +3 -3
- package/svf/lib/MemoryModel/PointerAnalysisImpl.cpp +1 -1
- package/svf/lib/SVFIR/SVFFileSystem.cpp +7 -5
- package/svf/lib/SVFIR/SVFIR.cpp +3 -3
- package/svf/lib/SVFIR/SVFVariables.cpp +64 -11
- package/svf/lib/Util/SVFStat.cpp +8 -2
- package/svf/lib/WPA/AndersenSFR.cpp +1 -1
- package/svf-llvm/include/SVF-LLVM/LLVMUtil.h +3 -0
- package/svf-llvm/lib/LLVMUtil.cpp +24 -0
- package/svf-llvm/lib/SVFIRBuilder.cpp +38 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svf-tools",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1019",
|
|
4
4
|
"description": "* <b>[TypeClone](https://github.com/SVF-tools/SVF/wiki/TypeClone) published in our [ECOOP paper](https://yuleisui.github.io/publications/ecoop20.pdf) is now available in SVF </b> * <b>SVF now uses a single script for its build. Just type [`source ./build.sh`](https://github.com/SVF-tools/SVF/blob/master/build.sh) in your terminal, that's it!</b> * <b>SVF now supports LLVM-10.0.0! </b> * <b>We thank [bsauce](https://github.com/bsauce) for writing a user manual of SVF ([link1](https://www.jianshu.com/p/068a08ec749c) and [link2](https://www.jianshu.com/p/777c30d4240e)) in Chinese </b> * <b>SVF now supports LLVM-9.0.0 (Thank [Byoungyoung Lee](https://github.com/SVF-tools/SVF/issues/142) for his help!). </b> * <b>SVF now supports a set of [field-sensitive pointer analyses](https://yuleisui.github.io/publications/sas2019a.pdf). </b> * <b>[Use SVF as an external lib](https://github.com/SVF-tools/SVF/wiki/Using-SVF-as-a-lib-in-your-own-tool) for your own project (Contributed by [Hongxu Chen](https://github.com/HongxuChen)). </b> * <b>SVF now supports LLVM-7.0.0. </b> * <b>SVF now supports Docker. [Try SVF in Docker](https://github.com/SVF-tools/SVF/wiki/Try-SVF-in-Docker)! </b> * <b>SVF now supports [LLVM-6.0.0](https://github.com/svf-tools/SVF/pull/38) (Contributed by [Jack Anthony](https://github.com/jackanth)). </b> * <b>SVF now supports [LLVM-4.0.0](https://github.com/svf-tools/SVF/pull/23) (Contributed by Jared Carlson. Thank [Jared](https://github.com/jcarlson23) and [Will](https://github.com/dtzWill) for their in-depth [discussions](https://github.com/svf-tools/SVF/pull/18) about updating SVF!) </b> * <b>SVF now supports analysis for C++ programs.</b> <br />",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -471,9 +471,11 @@ protected:
|
|
|
471
471
|
virtual inline bool isLocalCVarInRecursion(const CVar& var) const
|
|
472
472
|
{
|
|
473
473
|
NodeID id = getPtrNodeID(var);
|
|
474
|
+
const BaseObjVar* baseObj = _pag->getBaseObject(id);
|
|
475
|
+
assert(baseObj && "base object is null??");
|
|
474
476
|
const MemObj* obj = _pag->getObject(id);
|
|
475
477
|
assert(obj && "object not found!!");
|
|
476
|
-
if(
|
|
478
|
+
if(SVFUtil::isa<StackObjVar>(baseObj))
|
|
477
479
|
{
|
|
478
480
|
if(const SVFFunction* svffun = _pag->getGNode(id)->getFunction())
|
|
479
481
|
{
|
|
@@ -637,9 +639,8 @@ protected:
|
|
|
637
639
|
//@{
|
|
638
640
|
virtual inline bool isHeapCondMemObj(const CVar& var, const StoreSVFGNode*)
|
|
639
641
|
{
|
|
640
|
-
const
|
|
641
|
-
|
|
642
|
-
return mem->isHeap();
|
|
642
|
+
const BaseObjVar* pVar = _pag->getBaseObject(getPtrNodeID(var));
|
|
643
|
+
return pVar && SVFUtil::isa<HeapObjVar, DummyObjVar>(pVar);
|
|
643
644
|
}
|
|
644
645
|
|
|
645
646
|
inline bool isArrayCondMemObj(const CVar& var) const
|
|
@@ -141,105 +141,66 @@ public:
|
|
|
141
141
|
|
|
142
142
|
enum GNodeK
|
|
143
143
|
{
|
|
144
|
-
// ┌──
|
|
145
|
-
//
|
|
146
|
-
|
|
147
|
-
// │
|
|
148
|
-
|
|
149
|
-
//
|
|
150
|
-
//
|
|
151
|
-
|
|
152
|
-
// │ ├── Exit point of a function
|
|
153
|
-
FunExitBlock,
|
|
154
|
-
// │ ├── Call site in the function
|
|
155
|
-
FunCallBlock,
|
|
156
|
-
// │ └── Return site in the function
|
|
157
|
-
FunRetBlock,
|
|
144
|
+
// ┌── ICFGNode: Classes of inter-procedural and intra-procedural control flow graph nodes
|
|
145
|
+
IntraBlock, // ├──Represents a node within a single procedure
|
|
146
|
+
GlobalBlock, // ├──Represents a global-level block
|
|
147
|
+
// │ └─ InterICFGNode: Classes of inter-procedural control flow graph nodes
|
|
148
|
+
FunEntryBlock, // ├──Entry point of a function
|
|
149
|
+
FunExitBlock, // ├──Exit point of a function
|
|
150
|
+
FunCallBlock, // ├──Call site in the function
|
|
151
|
+
FunRetBlock, // ├──Return site in the function
|
|
158
152
|
// └────────
|
|
159
153
|
|
|
160
|
-
// ┌──
|
|
161
|
-
// │
|
|
162
|
-
//
|
|
163
|
-
|
|
164
|
-
//
|
|
165
|
-
|
|
166
|
-
//
|
|
167
|
-
|
|
168
|
-
// │
|
|
169
|
-
|
|
170
|
-
//
|
|
171
|
-
|
|
172
|
-
//
|
|
173
|
-
|
|
174
|
-
//
|
|
175
|
-
//
|
|
176
|
-
|
|
177
|
-
// │ ├── GepObjNode: Represents a GEP object variable
|
|
178
|
-
GepObjNode,
|
|
179
|
-
// │ └── FIObjNode: Represents a flow-insensitive object node
|
|
180
|
-
FIObjNode,
|
|
181
|
-
// │ ├──FunObjNode: Types of function object
|
|
182
|
-
FunObjNode,
|
|
183
|
-
// │ └── DummyObjNode: Dummy node for uninitialized objects
|
|
184
|
-
DummyObjNode,
|
|
154
|
+
// ┌── SVFVar: Classes of top-level variables (ValVar) and address-taken variables (ObjVar)
|
|
155
|
+
// │ └── ValVar: Classes of top-level variable nodes
|
|
156
|
+
ValNode, // ├──Represents a standard value variable
|
|
157
|
+
FunValNode, // ├──Represents a Function value variable
|
|
158
|
+
GepValNode, // ├──Represents a GEP value variable
|
|
159
|
+
RetNode, // ├──Represents a return value node
|
|
160
|
+
VarargNode, // ├──Represents a variadic argument node
|
|
161
|
+
DummyValNode, // ├──Dummy node for uninitialized values
|
|
162
|
+
// │ └── ObjVar: Classes of object variable nodes
|
|
163
|
+
ObjNode, // ├──Represents an object variable
|
|
164
|
+
GepObjNode, // ├──Represents a GEP object variable
|
|
165
|
+
// │ └── BaseObjVar: Classes of base object nodes
|
|
166
|
+
BaseObjNode, // ├──Represents a base object node
|
|
167
|
+
FunObjNode, // ├──Types of function object
|
|
168
|
+
HeapObjNode, // ├──Types of heap object
|
|
169
|
+
StackObjNode, // ├──Types of stack object
|
|
170
|
+
DummyObjNode, // ├──Dummy node for uninitialized objects
|
|
185
171
|
// └────────
|
|
186
172
|
|
|
187
|
-
// ┌──
|
|
188
|
-
//
|
|
189
|
-
|
|
190
|
-
//
|
|
191
|
-
|
|
192
|
-
//
|
|
193
|
-
|
|
194
|
-
// │
|
|
195
|
-
|
|
196
|
-
//
|
|
197
|
-
|
|
198
|
-
//
|
|
199
|
-
|
|
200
|
-
//
|
|
201
|
-
//
|
|
202
|
-
|
|
203
|
-
//
|
|
204
|
-
|
|
205
|
-
// │
|
|
206
|
-
|
|
207
|
-
//
|
|
208
|
-
|
|
209
|
-
// │ └──
|
|
210
|
-
//
|
|
211
|
-
|
|
212
|
-
//
|
|
213
|
-
|
|
214
|
-
// │
|
|
215
|
-
|
|
216
|
-
//
|
|
217
|
-
|
|
218
|
-
// │ └── Represents a load operation
|
|
219
|
-
Load,
|
|
220
|
-
// │ └── PHIVFGNodeKinds: Types of PHI nodes in VFG
|
|
221
|
-
// │ ├── Represents a type-based PHI node
|
|
222
|
-
TPhi,
|
|
223
|
-
// │ ├── Represents an intra-procedural PHI node
|
|
224
|
-
TIntraPhi,
|
|
225
|
-
// │ └── Represents an inter-procedural PHI node
|
|
226
|
-
TInterPhi,
|
|
227
|
-
// │ └── MRSVFGNodeKinds: Memory-related SVFG nodes
|
|
228
|
-
// │ ├── Function parameter input
|
|
229
|
-
FPIN,
|
|
230
|
-
// │ ├── Function parameter output
|
|
231
|
-
FPOUT,
|
|
232
|
-
// │ ├── Argument parameter input
|
|
233
|
-
APIN,
|
|
234
|
-
// │ └── Argument parameter output
|
|
235
|
-
APOUT,
|
|
236
|
-
// │ └── MSSAPHISVFGNodeKinds: Mem SSA PHI nodes for SVFG
|
|
237
|
-
// │ ├── Memory PHI node
|
|
238
|
-
MPhi,
|
|
239
|
-
// │ ├── Intra-procedural memory PHI node
|
|
240
|
-
MIntraPhi,
|
|
241
|
-
// │ └── MInterPhi: Inter-procedural memory PHI node
|
|
242
|
-
MInterPhi,
|
|
173
|
+
// ┌── VFGNode: Classes of Value Flow Graph (VFG) node kinds with operations
|
|
174
|
+
Cmp, // ├──Represents a comparison operation
|
|
175
|
+
BinaryOp, // ├──Represents a binary operation
|
|
176
|
+
UnaryOp, // ├──Represents a unary operation
|
|
177
|
+
Branch, // ├──Represents a branch operation
|
|
178
|
+
DummyVProp, // ├──Dummy node for value propagation
|
|
179
|
+
NPtr, // ├──Represents a null pointer operation
|
|
180
|
+
// │ └── ArgumentVFGNode: Classes of argument nodes in VFG
|
|
181
|
+
FRet, // ├──Represents a function return value
|
|
182
|
+
ARet, // ├──Represents an argument return value
|
|
183
|
+
AParm, // ├──Represents an argument parameter
|
|
184
|
+
FParm, // ├──Represents a function parameter
|
|
185
|
+
// │ └── StmtVFGNode: Classes of statement nodes in VFG
|
|
186
|
+
Addr, // ├──Represents an address operation
|
|
187
|
+
Copy, // ├──Represents a copy operation
|
|
188
|
+
Gep, // ├──Represents a GEP operation
|
|
189
|
+
Store, // ├──Represents a store operation
|
|
190
|
+
Load, // ├──Represents a load operation
|
|
191
|
+
// │ └── PHIVFGNode: Classes of PHI nodes in VFG
|
|
192
|
+
TPhi, // ├──Represents a type-based PHI node
|
|
193
|
+
TIntraPhi, // ├──Represents an intra-procedural PHI node
|
|
194
|
+
TInterPhi, // ├──Represents an inter-procedural PHI node
|
|
195
|
+
// │ └── MRSVFGNode: Classes of Memory-related SVFG nodes
|
|
196
|
+
FPIN, // ├──Function parameter input
|
|
197
|
+
FPOUT, // ├──Function parameter output
|
|
198
|
+
APIN, // ├──Argument parameter input
|
|
199
|
+
APOUT, // ├──Argument parameter output
|
|
200
|
+
// │ └── MSSAPHISVFGNode: Classes of Mem SSA PHI nodes for SVFG
|
|
201
|
+
MPhi, // ├──Memory PHI node
|
|
202
|
+
MIntraPhi, // ├──Intra-procedural memory PHI node
|
|
203
|
+
MInterPhi, // ├──Inter-procedural memory PHI node
|
|
243
204
|
// └────────
|
|
244
205
|
|
|
245
206
|
// Additional specific graph node types
|
|
@@ -317,7 +278,7 @@ protected:
|
|
|
317
278
|
|
|
318
279
|
static inline bool isSVFVarKind(GNodeK n)
|
|
319
280
|
{
|
|
320
|
-
static_assert(DummyObjNode - ValNode ==
|
|
281
|
+
static_assert(DummyObjNode - ValNode == 12,
|
|
321
282
|
"The number of SVFVarKinds has changed, make sure the "
|
|
322
283
|
"range is correct");
|
|
323
284
|
|
|
@@ -334,18 +295,18 @@ protected:
|
|
|
334
295
|
|
|
335
296
|
static inline bool isObjVarKinds(GNodeK n)
|
|
336
297
|
{
|
|
337
|
-
static_assert(DummyObjNode - ObjNode ==
|
|
298
|
+
static_assert(DummyObjNode - ObjNode == 6,
|
|
338
299
|
"The number of ObjVarKinds has changed, make sure the "
|
|
339
300
|
"range is correct");
|
|
340
301
|
return n <= DummyObjNode && n >= ObjNode;
|
|
341
302
|
}
|
|
342
303
|
|
|
343
|
-
static inline bool
|
|
304
|
+
static inline bool isBaseObjVarKinds(GNodeK n)
|
|
344
305
|
{
|
|
345
|
-
static_assert(
|
|
346
|
-
"The number of
|
|
306
|
+
static_assert(DummyObjNode - BaseObjNode == 4,
|
|
307
|
+
"The number of BaseObjVarKinds has changed, make sure the "
|
|
347
308
|
"range is correct");
|
|
348
|
-
return n <=
|
|
309
|
+
return n <= DummyObjNode && n >= BaseObjNode;
|
|
349
310
|
}
|
|
350
311
|
|
|
351
312
|
static inline bool isVFGNodeKinds(GNodeK n)
|
|
@@ -304,9 +304,7 @@ public:
|
|
|
304
304
|
//@{
|
|
305
305
|
inline bool isHeapMemObj(NodeID id) const
|
|
306
306
|
{
|
|
307
|
-
|
|
308
|
-
assert(mem && "memory object is null??");
|
|
309
|
-
return mem->isHeap();
|
|
307
|
+
return pag->getBaseObject(id) && SVFUtil::isa<HeapObjVar, DummyObjVar>(pag->getBaseObject(id));
|
|
310
308
|
}
|
|
311
309
|
|
|
312
310
|
inline bool isArrayMemObj(NodeID id) const
|
|
@@ -321,7 +319,7 @@ public:
|
|
|
321
319
|
///@{
|
|
322
320
|
inline bool isFIObjNode(NodeID id) const
|
|
323
321
|
{
|
|
324
|
-
return (SVFUtil::isa<
|
|
322
|
+
return (SVFUtil::isa<BaseObjVar>(pag->getGNode(id)));
|
|
325
323
|
}
|
|
326
324
|
inline NodeID getBaseObjVar(NodeID id)
|
|
327
325
|
{
|
|
@@ -166,7 +166,7 @@ class ValVar;
|
|
|
166
166
|
class ObjVar;
|
|
167
167
|
class GepValVar;
|
|
168
168
|
class GepObjVar;
|
|
169
|
-
class
|
|
169
|
+
class BaseObjVar;
|
|
170
170
|
class RetPN;
|
|
171
171
|
class VarArgPN;
|
|
172
172
|
class DummyValVar;
|
|
@@ -456,7 +456,7 @@ private:
|
|
|
456
456
|
cJSON* contentToJson(const ObjVar* var);
|
|
457
457
|
cJSON* contentToJson(const GepValVar* var);
|
|
458
458
|
cJSON* contentToJson(const GepObjVar* var);
|
|
459
|
-
cJSON* contentToJson(const
|
|
459
|
+
cJSON* contentToJson(const BaseObjVar* var);
|
|
460
460
|
cJSON* contentToJson(const RetPN* var);
|
|
461
461
|
cJSON* contentToJson(const VarArgPN* var);
|
|
462
462
|
cJSON* contentToJson(const DummyValVar* var);
|
|
@@ -1231,7 +1231,7 @@ private:
|
|
|
1231
1231
|
void fill(const cJSON*& fieldJson, ObjVar* var);
|
|
1232
1232
|
void fill(const cJSON*& fieldJson, GepValVar* var);
|
|
1233
1233
|
void fill(const cJSON*& fieldJson, GepObjVar* var);
|
|
1234
|
-
void fill(const cJSON*& fieldJson,
|
|
1234
|
+
void fill(const cJSON*& fieldJson, BaseObjVar* var);
|
|
1235
1235
|
void fill(const cJSON*& fieldJson, RetPN* var);
|
|
1236
1236
|
void fill(const cJSON*& fieldJson, VarArgPN* var);
|
|
1237
1237
|
void fill(const cJSON*& fieldJson, DummyValVar* var);
|
|
@@ -401,6 +401,17 @@ public:
|
|
|
401
401
|
else
|
|
402
402
|
return nullptr;
|
|
403
403
|
}
|
|
404
|
+
|
|
405
|
+
inline const BaseObjVar* getBaseObject(NodeID id) const
|
|
406
|
+
{
|
|
407
|
+
const SVFVar* node = getGNode(id);
|
|
408
|
+
if(const GepObjVar* gepObjVar = SVFUtil::dyn_cast<GepObjVar>(node))
|
|
409
|
+
return SVFUtil::dyn_cast<BaseObjVar>(
|
|
410
|
+
getGNode(gepObjVar->getBaseNode()));
|
|
411
|
+
else
|
|
412
|
+
return SVFUtil::dyn_cast<BaseObjVar>(node);
|
|
413
|
+
}
|
|
414
|
+
|
|
404
415
|
inline const MemObj*getObject(const ObjVar* node) const
|
|
405
416
|
{
|
|
406
417
|
return node->getMemObj();
|
|
@@ -565,6 +576,30 @@ private:
|
|
|
565
576
|
return addFIObjNode(mem);
|
|
566
577
|
}
|
|
567
578
|
|
|
579
|
+
/**
|
|
580
|
+
* Creates and adds a heap object node to the SVFIR
|
|
581
|
+
*/
|
|
582
|
+
inline NodeID addHeapObjNode(const SVFValue* val, const SVFFunction* f, NodeID i)
|
|
583
|
+
{
|
|
584
|
+
const MemObj* mem = getMemObj(val);
|
|
585
|
+
assert(mem->getId() == i && "not same object id?");
|
|
586
|
+
memToFieldsMap[i].set(i);
|
|
587
|
+
HeapObjVar *node = new HeapObjVar(f, val->getType(), i, mem);
|
|
588
|
+
return addObjNode(val, node, i);
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
/**
|
|
592
|
+
* Creates and adds a stack object node to the SVFIR
|
|
593
|
+
*/
|
|
594
|
+
inline NodeID addStackObjNode(const SVFValue* val, const SVFFunction* f, NodeID i)
|
|
595
|
+
{
|
|
596
|
+
const MemObj* mem = getMemObj(val);
|
|
597
|
+
assert(mem->getId() == i && "not same object id?");
|
|
598
|
+
memToFieldsMap[i].set(i);
|
|
599
|
+
StackObjVar *node = new StackObjVar(f, val->getType(), i, mem);
|
|
600
|
+
return addObjNode(val, node, i);
|
|
601
|
+
}
|
|
602
|
+
|
|
568
603
|
NodeID addFunObjNode(const CallGraphNode* callGraphNode, NodeID id);
|
|
569
604
|
/// Add a unique return node for a procedure
|
|
570
605
|
inline NodeID addRetNode(const CallGraphNode* callGraphNode, NodeID i)
|
|
@@ -58,7 +58,7 @@ public:
|
|
|
58
58
|
/// Vararg: unique node for vararg parameter
|
|
59
59
|
/// GepValNode: temporary gep value node for field sensitivity
|
|
60
60
|
/// GepValNode: temporary gep obj node for field sensitivity
|
|
61
|
-
///
|
|
61
|
+
/// BaseObjNode: for field insensitive analysis
|
|
62
62
|
/// DummyValNode and DummyObjNode: for non-llvm-value node
|
|
63
63
|
typedef GNodeK PNODEK;
|
|
64
64
|
typedef s64_t GEdgeKind;
|
|
@@ -68,6 +68,7 @@ protected:
|
|
|
68
68
|
SVFStmt::KindToSVFStmtMapTy InEdgeKindToSetMap;
|
|
69
69
|
SVFStmt::KindToSVFStmtMapTy OutEdgeKindToSetMap;
|
|
70
70
|
bool isPtr; /// whether it is a pointer (top-level or address-taken)
|
|
71
|
+
const SVFFunction* func; /// function containing this variable
|
|
71
72
|
|
|
72
73
|
/// Constructor to create an empty object (for deserialization)
|
|
73
74
|
SVFVar(NodeID i, PNODEK k) : GenericPAGNodeTy(i, k), value{} {}
|
|
@@ -117,16 +118,29 @@ public:
|
|
|
117
118
|
// TODO: (Optimization) Should it return const reference instead of value?
|
|
118
119
|
virtual const std::string getValueName() const = 0;
|
|
119
120
|
|
|
120
|
-
/// Return the function
|
|
121
|
+
/// Return the function containing this SVFVar
|
|
122
|
+
/// @return The SVFFunction containing this variable, or nullptr if it's a global/constant expression
|
|
121
123
|
virtual inline const SVFFunction* getFunction() const
|
|
122
124
|
{
|
|
125
|
+
// Return cached function if available
|
|
126
|
+
if(func) return func;
|
|
127
|
+
|
|
128
|
+
// If we have an associated LLVM value, check its parent function
|
|
123
129
|
if (value)
|
|
124
130
|
{
|
|
131
|
+
// For instructions, return the function containing the parent basic block
|
|
125
132
|
if (auto inst = SVFUtil::dyn_cast<SVFInstruction>(value))
|
|
133
|
+
{
|
|
126
134
|
return inst->getParent()->getParent();
|
|
135
|
+
}
|
|
136
|
+
// For function arguments, return their parent function
|
|
127
137
|
else if (auto arg = SVFUtil::dyn_cast<SVFArgument>(value))
|
|
138
|
+
{
|
|
128
139
|
return arg->getParent();
|
|
140
|
+
}
|
|
129
141
|
}
|
|
142
|
+
|
|
143
|
+
// Return nullptr for globals/constants with no parent function
|
|
130
144
|
return nullptr;
|
|
131
145
|
}
|
|
132
146
|
|
|
@@ -532,43 +546,43 @@ public:
|
|
|
532
546
|
* Field-insensitive Gep Obj variable, this is dynamic generated for field sensitive analysis
|
|
533
547
|
* Each field-insensitive gep obj node represents all fields of a MemObj (base)
|
|
534
548
|
*/
|
|
535
|
-
class
|
|
549
|
+
class BaseObjVar : public ObjVar
|
|
536
550
|
{
|
|
537
551
|
friend class SVFIRWriter;
|
|
538
552
|
friend class SVFIRReader;
|
|
539
553
|
|
|
540
554
|
protected:
|
|
541
555
|
/// Constructor to create empty ObjVar (for SVFIRReader/deserialization)
|
|
542
|
-
|
|
556
|
+
BaseObjVar(NodeID i, PNODEK ty = BaseObjNode) : ObjVar(i, ty) {}
|
|
543
557
|
|
|
544
558
|
public:
|
|
545
559
|
/// Methods for support type inquiry through isa, cast, and dyn_cast:
|
|
546
560
|
//@{
|
|
547
|
-
static inline bool classof(const
|
|
561
|
+
static inline bool classof(const BaseObjVar*)
|
|
548
562
|
{
|
|
549
563
|
return true;
|
|
550
564
|
}
|
|
551
565
|
static inline bool classof(const ObjVar* node)
|
|
552
566
|
{
|
|
553
|
-
return
|
|
567
|
+
return isBaseObjVarKinds(node->getNodeKind());
|
|
554
568
|
}
|
|
555
569
|
static inline bool classof(const SVFVar* node)
|
|
556
570
|
{
|
|
557
|
-
return
|
|
571
|
+
return isBaseObjVarKinds(node->getNodeKind());
|
|
558
572
|
}
|
|
559
573
|
static inline bool classof(const GenericPAGNodeTy* node)
|
|
560
574
|
{
|
|
561
|
-
return
|
|
575
|
+
return isBaseObjVarKinds(node->getNodeKind());
|
|
562
576
|
}
|
|
563
577
|
static inline bool classof(const SVFBaseNode* node)
|
|
564
578
|
{
|
|
565
|
-
return
|
|
579
|
+
return isBaseObjVarKinds(node->getNodeKind());
|
|
566
580
|
}
|
|
567
581
|
//@}
|
|
568
582
|
|
|
569
583
|
/// Constructor
|
|
570
|
-
|
|
571
|
-
|
|
584
|
+
BaseObjVar(const SVFValue* val, NodeID i, const MemObj* mem,
|
|
585
|
+
PNODEK ty = BaseObjNode)
|
|
572
586
|
: ObjVar(val, i, mem, ty)
|
|
573
587
|
{
|
|
574
588
|
}
|
|
@@ -584,6 +598,127 @@ public:
|
|
|
584
598
|
virtual const std::string toString() const;
|
|
585
599
|
};
|
|
586
600
|
|
|
601
|
+
|
|
602
|
+
/**
|
|
603
|
+
* @brief Class representing a heap object variable in the SVFIR
|
|
604
|
+
*
|
|
605
|
+
* This class models heap-allocated objects in the program analysis. It extends BaseObjVar
|
|
606
|
+
* to specifically handle heap memory locations.
|
|
607
|
+
*/
|
|
608
|
+
class HeapObjVar: public BaseObjVar
|
|
609
|
+
{
|
|
610
|
+
|
|
611
|
+
friend class SVFIRWriter;
|
|
612
|
+
friend class SVFIRReader;
|
|
613
|
+
|
|
614
|
+
protected:
|
|
615
|
+
/// Constructor to create heap object var
|
|
616
|
+
HeapObjVar(NodeID i, PNODEK ty = HeapObjNode) : BaseObjVar(i, ty) {}
|
|
617
|
+
|
|
618
|
+
public:
|
|
619
|
+
/// Methods for support type inquiry through isa, cast, and dyn_cast:
|
|
620
|
+
//@{
|
|
621
|
+
static inline bool classof(const HeapObjVar*)
|
|
622
|
+
{
|
|
623
|
+
return true;
|
|
624
|
+
}
|
|
625
|
+
static inline bool classof(const BaseObjVar* node)
|
|
626
|
+
{
|
|
627
|
+
return node->getNodeKind() == HeapObjNode;
|
|
628
|
+
}
|
|
629
|
+
static inline bool classof(const ObjVar* node)
|
|
630
|
+
{
|
|
631
|
+
return node->getNodeKind() == HeapObjNode;
|
|
632
|
+
}
|
|
633
|
+
static inline bool classof(const SVFVar* node)
|
|
634
|
+
{
|
|
635
|
+
return node->getNodeKind() == HeapObjNode;
|
|
636
|
+
}
|
|
637
|
+
static inline bool classof(const GenericPAGNodeTy* node)
|
|
638
|
+
{
|
|
639
|
+
return node->getNodeKind() == HeapObjNode;
|
|
640
|
+
}
|
|
641
|
+
static inline bool classof(const SVFBaseNode* node)
|
|
642
|
+
{
|
|
643
|
+
return node->getNodeKind() == HeapObjNode;
|
|
644
|
+
}
|
|
645
|
+
//@}
|
|
646
|
+
|
|
647
|
+
/// Constructor
|
|
648
|
+
HeapObjVar(const SVFFunction* func, const SVFType* svfType, NodeID i,
|
|
649
|
+
const MemObj* mem, PNODEK ty = HeapObjNode);
|
|
650
|
+
|
|
651
|
+
/// Return name of a LLVM value
|
|
652
|
+
inline const std::string getValueName() const
|
|
653
|
+
{
|
|
654
|
+
return " (heap base object)";
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
virtual const std::string toString() const;
|
|
658
|
+
};
|
|
659
|
+
|
|
660
|
+
|
|
661
|
+
/**
|
|
662
|
+
* @brief Represents a stack-allocated object variable in the SVFIR (SVF Intermediate Representation)
|
|
663
|
+
* @inherits BaseObjVar
|
|
664
|
+
*
|
|
665
|
+
* This class models variables that are allocated on the stack in the program.
|
|
666
|
+
* It provides type checking functionality through LLVM-style RTTI (Runtime Type Information)
|
|
667
|
+
* methods like classof.
|
|
668
|
+
*/
|
|
669
|
+
class StackObjVar: public BaseObjVar
|
|
670
|
+
{
|
|
671
|
+
|
|
672
|
+
friend class SVFIRWriter;
|
|
673
|
+
friend class SVFIRReader;
|
|
674
|
+
|
|
675
|
+
protected:
|
|
676
|
+
/// Constructor to create stack object var
|
|
677
|
+
StackObjVar(NodeID i, PNODEK ty = StackObjNode) : BaseObjVar(i, ty) {}
|
|
678
|
+
|
|
679
|
+
public:
|
|
680
|
+
/// Methods for support type inquiry through isa, cast, and dyn_cast:
|
|
681
|
+
//@{
|
|
682
|
+
static inline bool classof(const StackObjVar*)
|
|
683
|
+
{
|
|
684
|
+
return true;
|
|
685
|
+
}
|
|
686
|
+
static inline bool classof(const BaseObjVar* node)
|
|
687
|
+
{
|
|
688
|
+
return node->getNodeKind() == StackObjNode;
|
|
689
|
+
}
|
|
690
|
+
static inline bool classof(const ObjVar* node)
|
|
691
|
+
{
|
|
692
|
+
return node->getNodeKind() == StackObjNode;
|
|
693
|
+
}
|
|
694
|
+
static inline bool classof(const SVFVar* node)
|
|
695
|
+
{
|
|
696
|
+
return node->getNodeKind() == StackObjNode;
|
|
697
|
+
}
|
|
698
|
+
static inline bool classof(const GenericPAGNodeTy* node)
|
|
699
|
+
{
|
|
700
|
+
return node->getNodeKind() == StackObjNode;
|
|
701
|
+
}
|
|
702
|
+
static inline bool classof(const SVFBaseNode* node)
|
|
703
|
+
{
|
|
704
|
+
return node->getNodeKind() == StackObjNode;
|
|
705
|
+
}
|
|
706
|
+
//@}
|
|
707
|
+
|
|
708
|
+
/// Constructor
|
|
709
|
+
StackObjVar(const SVFFunction* f, const SVFType* svfType, NodeID i,
|
|
710
|
+
const MemObj* mem, PNODEK ty = StackObjNode);
|
|
711
|
+
|
|
712
|
+
/// Return name of a LLVM value
|
|
713
|
+
inline const std::string getValueName() const
|
|
714
|
+
{
|
|
715
|
+
return " (stack base object)";
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
virtual const std::string toString() const;
|
|
719
|
+
};
|
|
720
|
+
|
|
721
|
+
|
|
587
722
|
class CallGraphNode;
|
|
588
723
|
|
|
589
724
|
class FunValVar : public ValVar
|
|
@@ -625,16 +760,12 @@ public:
|
|
|
625
760
|
|
|
626
761
|
/// Constructor
|
|
627
762
|
FunValVar(const CallGraphNode* cgn, NodeID i, const ICFGNode* icn,
|
|
628
|
-
PNODEK ty = FunValNode)
|
|
629
|
-
: ValVar(nullptr, i, ty, icn), callGraphNode(cgn)
|
|
630
|
-
{
|
|
631
|
-
|
|
632
|
-
}
|
|
763
|
+
PNODEK ty = FunValNode);
|
|
633
764
|
|
|
634
765
|
virtual const std::string toString() const;
|
|
635
766
|
};
|
|
636
767
|
|
|
637
|
-
class FunObjVar : public
|
|
768
|
+
class FunObjVar : public BaseObjVar
|
|
638
769
|
{
|
|
639
770
|
friend class SVFIRWriter;
|
|
640
771
|
friend class SVFIRReader;
|
|
@@ -644,7 +775,7 @@ private:
|
|
|
644
775
|
|
|
645
776
|
private:
|
|
646
777
|
/// Constructor to create empty ObjVar (for SVFIRReader/deserialization)
|
|
647
|
-
FunObjVar(NodeID i, PNODEK ty = FunObjNode) :
|
|
778
|
+
FunObjVar(NodeID i, PNODEK ty = FunObjNode) : BaseObjVar(i, ty) {}
|
|
648
779
|
|
|
649
780
|
public:
|
|
650
781
|
/// Methods for support type inquiry through isa, cast, and dyn_cast:
|
|
@@ -653,7 +784,7 @@ public:
|
|
|
653
784
|
{
|
|
654
785
|
return true;
|
|
655
786
|
}
|
|
656
|
-
static inline bool classof(const
|
|
787
|
+
static inline bool classof(const BaseObjVar* node)
|
|
657
788
|
{
|
|
658
789
|
return node->getNodeKind() == FunObjNode;
|
|
659
790
|
}
|
|
@@ -840,14 +971,14 @@ public:
|
|
|
840
971
|
/*
|
|
841
972
|
* Dummy object variable
|
|
842
973
|
*/
|
|
843
|
-
class DummyObjVar: public
|
|
974
|
+
class DummyObjVar: public BaseObjVar
|
|
844
975
|
{
|
|
845
976
|
friend class SVFIRWriter;
|
|
846
977
|
friend class SVFIRReader;
|
|
847
978
|
|
|
848
979
|
private:
|
|
849
980
|
/// Constructor to create empty DummyObjVar (for SVFIRReader/deserialization)
|
|
850
|
-
DummyObjVar(NodeID i) :
|
|
981
|
+
DummyObjVar(NodeID i) : BaseObjVar(i, DummyObjNode) {}
|
|
851
982
|
|
|
852
983
|
public:
|
|
853
984
|
//@{ Methods for support type inquiry through isa, cast, and dyn_cast:
|
|
@@ -876,7 +1007,7 @@ public:
|
|
|
876
1007
|
|
|
877
1008
|
/// Constructor
|
|
878
1009
|
DummyObjVar(NodeID i, const MemObj* m, PNODEK ty = DummyObjNode)
|
|
879
|
-
:
|
|
1010
|
+
: BaseObjVar(nullptr, i, m, ty)
|
|
880
1011
|
{
|
|
881
1012
|
}
|
|
882
1013
|
|
|
@@ -316,8 +316,8 @@ IntervalValue BufOverflowDetector::getAccessOffset(SVF::AbstractState& as, SVF::
|
|
|
316
316
|
SVFIR* svfir = PAG::getPAG();
|
|
317
317
|
auto obj = svfir->getGNode(objId);
|
|
318
318
|
|
|
319
|
-
// if the object is a
|
|
320
|
-
if (SVFUtil::isa<
|
|
319
|
+
// if the object is a BaseObjVar, return the byte offset directly
|
|
320
|
+
if (SVFUtil::isa<BaseObjVar>(obj))
|
|
321
321
|
{
|
|
322
322
|
return as.getByteOffset(gep);
|
|
323
323
|
}
|
|
@@ -351,8 +351,8 @@ void BufOverflowDetector::updateGepObjOffsetFromBase(SVF::AddressValue gepAddrs,
|
|
|
351
351
|
{
|
|
352
352
|
NodeID objId = AbstractState::getInternalID(objAddr);
|
|
353
353
|
auto obj = svfir->getGNode(objId);
|
|
354
|
-
// if the object is a
|
|
355
|
-
if (SVFUtil::isa<
|
|
354
|
+
// if the object is a BaseObjVar, add the offset directly
|
|
355
|
+
if (SVFUtil::isa<BaseObjVar>(obj))
|
|
356
356
|
{
|
|
357
357
|
for (const auto& gepAddr : gepAddrs)
|
|
358
358
|
{
|
|
@@ -491,7 +491,7 @@ bool BufOverflowDetector::canSafelyAccessMemory(AbstractState& as, const SVF::SV
|
|
|
491
491
|
}
|
|
492
492
|
else
|
|
493
493
|
{
|
|
494
|
-
// if the object is a
|
|
494
|
+
// if the object is a BaseObjVar, get the offset directly
|
|
495
495
|
offset = len;
|
|
496
496
|
}
|
|
497
497
|
// if the offset is greater than the size, return false
|
|
@@ -336,7 +336,9 @@ bool ContextDDA::isHeapCondMemObj(const CxtVar& var, const StoreSVFGNode*)
|
|
|
336
336
|
{
|
|
337
337
|
const MemObj* mem = _pag->getObject(getPtrNodeID(var));
|
|
338
338
|
assert(mem && "memory object is null??");
|
|
339
|
-
|
|
339
|
+
const BaseObjVar* baseVar = _pag->getBaseObject(getPtrNodeID(var));
|
|
340
|
+
assert(baseVar && "base object is null??");
|
|
341
|
+
if (SVFUtil::isa<HeapObjVar, DummyObjVar>(baseVar))
|
|
340
342
|
{
|
|
341
343
|
if (!mem->getValue())
|
|
342
344
|
{
|
package/svf/lib/DDA/FlowDDA.cpp
CHANGED
|
@@ -176,9 +176,8 @@ PointsTo FlowDDA::processGepPts(const GepSVFGNode* gep, const PointsTo& srcPts)
|
|
|
176
176
|
/// (4) not involved in recursion
|
|
177
177
|
bool FlowDDA::isHeapCondMemObj(const NodeID& var, const StoreSVFGNode*)
|
|
178
178
|
{
|
|
179
|
-
const
|
|
180
|
-
|
|
181
|
-
if(mem->isHeap())
|
|
179
|
+
const BaseObjVar* pVar = _pag->getBaseObject(getPtrNodeID(var));
|
|
180
|
+
if(pVar && SVFUtil::isa<HeapObjVar, DummyObjVar>(pVar))
|
|
182
181
|
{
|
|
183
182
|
// if(const Instruction* mallocSite = SVFUtil::dyn_cast<Instruction>(mem->getValue())) {
|
|
184
183
|
// const SVFFunction* fun = mallocSite->getParent()->getParent();
|
package/svf/lib/Graphs/ConsG.cpp
CHANGED
|
@@ -811,7 +811,7 @@ struct DOTGraphTraits<ConstraintGraph*> : public DOTGraphTraits<SVFIR*>
|
|
|
811
811
|
{
|
|
812
812
|
if(SVFUtil::isa<GepObjVar>(node))
|
|
813
813
|
return "shape=doubleoctagon";
|
|
814
|
-
else if(SVFUtil::isa<
|
|
814
|
+
else if(SVFUtil::isa<BaseObjVar>(node))
|
|
815
815
|
return "shape=box3d";
|
|
816
816
|
else if (SVFUtil::isa<DummyObjVar>(node))
|
|
817
817
|
return "shape=tab";
|
|
@@ -174,7 +174,7 @@ struct DOTGraphTraits<IRGraph*> : public DefaultDOTGraphTraits
|
|
|
174
174
|
{
|
|
175
175
|
if(SVFUtil::isa<GepObjVar>(node))
|
|
176
176
|
return "shape=doubleoctagon";
|
|
177
|
-
else if(SVFUtil::isa<
|
|
177
|
+
else if(SVFUtil::isa<BaseObjVar>(node))
|
|
178
178
|
return "shape=box3d";
|
|
179
179
|
else if (SVFUtil::isa<DummyObjVar>(node))
|
|
180
180
|
return "shape=tab";
|
|
@@ -577,13 +577,15 @@ bool MRGenerator::isNonLocalObject(NodeID id, const SVFFunction* curFun) const
|
|
|
577
577
|
const MemObj* obj = pta->getPAG()->getObject(id);
|
|
578
578
|
assert(obj && "object not found!!");
|
|
579
579
|
/// if the object is heap or global
|
|
580
|
-
|
|
580
|
+
const BaseObjVar* pVar = pta->getPAG()->getBaseObject(id);
|
|
581
|
+
assert(pVar && "object not found!");
|
|
582
|
+
if(obj->isGlobalObj() || SVFUtil::isa<HeapObjVar, DummyObjVar>(pVar))
|
|
581
583
|
return true;
|
|
582
584
|
/// or if the local variable of its callers
|
|
583
585
|
/// or a local variable is in function recursion cycles
|
|
584
|
-
else if(
|
|
586
|
+
else if(SVFUtil::isa<StackObjVar>(pVar))
|
|
585
587
|
{
|
|
586
|
-
if(const SVFFunction* svffun =
|
|
588
|
+
if(const SVFFunction* svffun = pVar->getFunction())
|
|
587
589
|
{
|
|
588
590
|
if(svffun!=curFun)
|
|
589
591
|
return true;
|
|
@@ -133,9 +133,9 @@ void PointerAnalysis::initialize()
|
|
|
133
133
|
*/
|
|
134
134
|
bool PointerAnalysis::isLocalVarInRecursiveFun(NodeID id) const
|
|
135
135
|
{
|
|
136
|
-
const
|
|
137
|
-
assert(
|
|
138
|
-
if(
|
|
136
|
+
const BaseObjVar* baseObjVar = pag->getBaseObject(id);
|
|
137
|
+
assert(baseObjVar && "base object not found!!");
|
|
138
|
+
if(SVFUtil::isa<StackObjVar>(baseObjVar))
|
|
139
139
|
{
|
|
140
140
|
if(const SVFFunction* svffun = pag->getGNode(id)->getFunction())
|
|
141
141
|
{
|
|
@@ -362,7 +362,7 @@ void BVDataPTAImpl::readGepObjVarMapFromFile(std::ifstream& F)
|
|
|
362
362
|
const MemObj* obj = nullptr;
|
|
363
363
|
if (GepObjVar* gepObjVar = SVFUtil::dyn_cast<GepObjVar>(node))
|
|
364
364
|
obj = gepObjVar->getMemObj();
|
|
365
|
-
else if (
|
|
365
|
+
else if (BaseObjVar* baseNode = SVFUtil::dyn_cast<BaseObjVar>(node))
|
|
366
366
|
obj = baseNode->getMemObj();
|
|
367
367
|
else if (DummyObjVar* baseNode = SVFUtil::dyn_cast<DummyObjVar>(node))
|
|
368
368
|
obj = baseNode->getMemObj();
|
|
@@ -218,11 +218,13 @@ cJSON* SVFIRWriter::virtToJson(const SVFVar* var)
|
|
|
218
218
|
CASE(VarargNode, VarArgPN);
|
|
219
219
|
CASE(GepValNode, GepValVar);
|
|
220
220
|
CASE(GepObjNode, GepObjVar);
|
|
221
|
-
CASE(
|
|
221
|
+
CASE(BaseObjNode, BaseObjVar);
|
|
222
222
|
CASE(DummyValNode, DummyValVar);
|
|
223
223
|
CASE(DummyObjNode, DummyObjVar);
|
|
224
224
|
CASE(FunObjNode, FunObjVar);
|
|
225
225
|
CASE(FunValNode, FunValVar);
|
|
226
|
+
CASE(HeapObjNode, HeapObjVar);
|
|
227
|
+
CASE(StackObjNode, StackObjVar);
|
|
226
228
|
#undef CASE
|
|
227
229
|
}
|
|
228
230
|
}
|
|
@@ -341,7 +343,7 @@ cJSON* SVFIRWriter::contentToJson(const GepObjVar* var)
|
|
|
341
343
|
return root;
|
|
342
344
|
}
|
|
343
345
|
|
|
344
|
-
cJSON* SVFIRWriter::contentToJson(const
|
|
346
|
+
cJSON* SVFIRWriter::contentToJson(const BaseObjVar* var)
|
|
345
347
|
{
|
|
346
348
|
return contentToJson(static_cast<const ObjVar*>(var));
|
|
347
349
|
}
|
|
@@ -1621,7 +1623,7 @@ SVFVar* SVFIRReader::createPAGNode(NodeID id, GNodeK kind)
|
|
|
1621
1623
|
CASE(VarargNode, VarArgPN);
|
|
1622
1624
|
CASE(GepValNode, GepValVar);
|
|
1623
1625
|
CASE(GepObjNode, GepObjVar);
|
|
1624
|
-
CASE(
|
|
1626
|
+
CASE(BaseObjNode, BaseObjVar);
|
|
1625
1627
|
CASE(DummyValNode, DummyValVar);
|
|
1626
1628
|
CASE(DummyObjNode, DummyObjVar);
|
|
1627
1629
|
#undef CASE
|
|
@@ -1903,7 +1905,7 @@ void SVFIRReader::virtFill(const cJSON*& fieldJson, SVFVar* var)
|
|
|
1903
1905
|
CASE(VarargNode, VarArgPN);
|
|
1904
1906
|
CASE(GepValNode, GepValVar);
|
|
1905
1907
|
CASE(GepObjNode, GepObjVar);
|
|
1906
|
-
CASE(
|
|
1908
|
+
CASE(BaseObjNode, BaseObjVar);
|
|
1907
1909
|
CASE(DummyValNode, DummyValVar);
|
|
1908
1910
|
CASE(DummyObjNode, DummyObjVar);
|
|
1909
1911
|
#undef CASE
|
|
@@ -1944,7 +1946,7 @@ void SVFIRReader::fill(const cJSON*& fieldJson, GepObjVar* var)
|
|
|
1944
1946
|
JSON_READ_FIELD_FWD(fieldJson, var, base);
|
|
1945
1947
|
}
|
|
1946
1948
|
|
|
1947
|
-
void SVFIRReader::fill(const cJSON*& fieldJson,
|
|
1949
|
+
void SVFIRReader::fill(const cJSON*& fieldJson, BaseObjVar* var)
|
|
1948
1950
|
{
|
|
1949
1951
|
fill(fieldJson, static_cast<ObjVar*>(var));
|
|
1950
1952
|
}
|
package/svf/lib/SVFIR/SVFIR.cpp
CHANGED
|
@@ -403,7 +403,7 @@ NodeID SVFIR::getGepObjVar(NodeID id, const APOffset& apOffset)
|
|
|
403
403
|
SVFVar* node = pag->getGNode(id);
|
|
404
404
|
if (GepObjVar* gepNode = SVFUtil::dyn_cast<GepObjVar>(node))
|
|
405
405
|
return getGepObjVar(gepNode->getMemObj(), gepNode->getConstantFieldIdx() + apOffset);
|
|
406
|
-
else if (
|
|
406
|
+
else if (BaseObjVar* baseNode = SVFUtil::dyn_cast<BaseObjVar>(node))
|
|
407
407
|
return getGepObjVar(baseNode->getMemObj(), apOffset);
|
|
408
408
|
else if (DummyObjVar* baseNode = SVFUtil::dyn_cast<DummyObjVar>(node))
|
|
409
409
|
return getGepObjVar(baseNode->getMemObj(), apOffset);
|
|
@@ -468,7 +468,7 @@ NodeID SVFIR::addFIObjNode(const MemObj* obj)
|
|
|
468
468
|
//assert(findPAGNode(i) == false && "this node should not be created before");
|
|
469
469
|
NodeID base = obj->getId();
|
|
470
470
|
memToFieldsMap[base].set(obj->getId());
|
|
471
|
-
|
|
471
|
+
BaseObjVar*node = new BaseObjVar(obj->getValue(), obj->getId(), obj);
|
|
472
472
|
return addObjNode(obj->getValue(), node, obj->getId());
|
|
473
473
|
}
|
|
474
474
|
|
|
@@ -689,7 +689,7 @@ bool SVFIR::isValidTopLevelPtr(const SVFVar* node)
|
|
|
689
689
|
if (isValidPointer(node->getId()))
|
|
690
690
|
{
|
|
691
691
|
// TODO: after svf value is removed, we use type to determine top level ptr
|
|
692
|
-
if (SVFUtil::isa<RetPN
|
|
692
|
+
if (SVFUtil::isa<RetPN, VarArgPN, FunValVar, HeapObjVar, StackObjVar>(node))
|
|
693
693
|
{
|
|
694
694
|
return true;
|
|
695
695
|
}
|
|
@@ -40,7 +40,7 @@ using namespace SVFUtil;
|
|
|
40
40
|
* SVFVar constructor
|
|
41
41
|
*/
|
|
42
42
|
SVFVar::SVFVar(const SVFValue* val, NodeID i, PNODEK k) :
|
|
43
|
-
GenericPAGNodeTy(i,k), value(val)
|
|
43
|
+
GenericPAGNodeTy(i,k), value(val), func(nullptr)
|
|
44
44
|
{
|
|
45
45
|
assert( ValNode <= k && k <= DummyObjNode && "new SVFIR node kind?");
|
|
46
46
|
switch (k)
|
|
@@ -52,12 +52,6 @@ SVFVar::SVFVar(const SVFValue* val, NodeID i, PNODEK k) :
|
|
|
52
52
|
isPtr = val->getType()->isPointerTy();
|
|
53
53
|
break;
|
|
54
54
|
}
|
|
55
|
-
case RetNode:
|
|
56
|
-
case FunObjNode:
|
|
57
|
-
{
|
|
58
|
-
// to be completed in derived class
|
|
59
|
-
break;
|
|
60
|
-
}
|
|
61
55
|
case FunValNode:
|
|
62
56
|
case VarargNode:
|
|
63
57
|
case DummyValNode:
|
|
@@ -67,7 +61,7 @@ SVFVar::SVFVar(const SVFValue* val, NodeID i, PNODEK k) :
|
|
|
67
61
|
}
|
|
68
62
|
case ObjNode:
|
|
69
63
|
case GepObjNode:
|
|
70
|
-
case
|
|
64
|
+
case BaseObjNode:
|
|
71
65
|
case DummyObjNode:
|
|
72
66
|
{
|
|
73
67
|
isPtr = true;
|
|
@@ -75,6 +69,14 @@ SVFVar::SVFVar(const SVFValue* val, NodeID i, PNODEK k) :
|
|
|
75
69
|
isPtr = val->getType()->isPointerTy();
|
|
76
70
|
break;
|
|
77
71
|
}
|
|
72
|
+
case RetNode:
|
|
73
|
+
case FunObjNode:
|
|
74
|
+
case HeapObjNode:
|
|
75
|
+
case StackObjNode:
|
|
76
|
+
{
|
|
77
|
+
// to be completed in derived class
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
78
80
|
default:
|
|
79
81
|
assert(false && "var not handled");
|
|
80
82
|
break;
|
|
@@ -172,11 +174,11 @@ const std::string GepObjVar::toString() const
|
|
|
172
174
|
return rawstr.str();
|
|
173
175
|
}
|
|
174
176
|
|
|
175
|
-
const std::string
|
|
177
|
+
const std::string BaseObjVar::toString() const
|
|
176
178
|
{
|
|
177
179
|
std::string str;
|
|
178
180
|
std::stringstream rawstr(str);
|
|
179
|
-
rawstr << "
|
|
181
|
+
rawstr << "BaseObjVar ID: " << getId() << " (base object)";
|
|
180
182
|
if (Options::ShowSVFIRValue())
|
|
181
183
|
{
|
|
182
184
|
rawstr << "\n";
|
|
@@ -185,6 +187,57 @@ const std::string FIObjVar::toString() const
|
|
|
185
187
|
return rawstr.str();
|
|
186
188
|
}
|
|
187
189
|
|
|
190
|
+
HeapObjVar::HeapObjVar(const SVFFunction* f, const SVFType* svfType, NodeID i,
|
|
191
|
+
const MemObj* mem, PNODEK ty)
|
|
192
|
+
: BaseObjVar(mem->getValue(), i, mem, ty)
|
|
193
|
+
{
|
|
194
|
+
isPtr = svfType->isPointerTy();
|
|
195
|
+
func = f;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const std::string HeapObjVar::toString() const
|
|
199
|
+
{
|
|
200
|
+
std::string str;
|
|
201
|
+
std::stringstream rawstr(str);
|
|
202
|
+
rawstr << "HeapObjVar ID: " << getId();
|
|
203
|
+
if (Options::ShowSVFIRValue())
|
|
204
|
+
{
|
|
205
|
+
rawstr << "\n";
|
|
206
|
+
rawstr << valueOnlyToString();
|
|
207
|
+
}
|
|
208
|
+
return rawstr.str();
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
StackObjVar::StackObjVar(const SVFFunction* f, const SVFType* svfType, NodeID i,
|
|
212
|
+
const MemObj* mem, PNODEK ty)
|
|
213
|
+
: BaseObjVar(mem->getValue(), i, mem, ty)
|
|
214
|
+
{
|
|
215
|
+
isPtr = svfType->isPointerTy();
|
|
216
|
+
func = f;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const std::string StackObjVar::toString() const
|
|
220
|
+
{
|
|
221
|
+
std::string str;
|
|
222
|
+
std::stringstream rawstr(str);
|
|
223
|
+
rawstr << "StackObjVar ID: " << getId();
|
|
224
|
+
if (Options::ShowSVFIRValue())
|
|
225
|
+
{
|
|
226
|
+
rawstr << "\n";
|
|
227
|
+
rawstr << valueOnlyToString();
|
|
228
|
+
}
|
|
229
|
+
return rawstr.str();
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
FunValVar::FunValVar(const CallGraphNode* cgn, NodeID i, const ICFGNode* icn,
|
|
235
|
+
PNODEK ty)
|
|
236
|
+
: ValVar(cgn->getFunction(), i, ty, icn), callGraphNode(cgn)
|
|
237
|
+
{
|
|
238
|
+
isPtr = cgn->getFunction()->getType()->isPointerTy();
|
|
239
|
+
}
|
|
240
|
+
|
|
188
241
|
const std::string FunValVar::toString() const
|
|
189
242
|
{
|
|
190
243
|
std::string str;
|
|
@@ -200,7 +253,7 @@ const std::string FunValVar::toString() const
|
|
|
200
253
|
|
|
201
254
|
FunObjVar::FunObjVar(const CallGraphNode* cgNode, NodeID i, const MemObj* mem,
|
|
202
255
|
PNODEK ty)
|
|
203
|
-
:
|
|
256
|
+
: BaseObjVar(mem->getValue(), i, mem, ty), callGraphNode(cgNode)
|
|
204
257
|
{
|
|
205
258
|
isPtr = callGraphNode->getFunction()->getType()->isPointerTy();
|
|
206
259
|
}
|
package/svf/lib/Util/SVFStat.cpp
CHANGED
|
@@ -142,10 +142,16 @@ void SVFStat::performStat()
|
|
|
142
142
|
numOfFunction++;
|
|
143
143
|
if(mem->isGlobalObj())
|
|
144
144
|
numOfGlobal++;
|
|
145
|
-
if(
|
|
145
|
+
if (pag->getBaseObject(obj->getId()) &&
|
|
146
|
+
SVFUtil::isa<StackObjVar>(
|
|
147
|
+
pag->getBaseObject(obj->getId())))
|
|
146
148
|
numOfStack++;
|
|
147
|
-
if(
|
|
149
|
+
if (pag->getBaseObject(obj->getId()) &&
|
|
150
|
+
SVFUtil::isa<HeapObjVar, DummyObjVar>(
|
|
151
|
+
pag->getBaseObject(obj->getId())))
|
|
152
|
+
{
|
|
148
153
|
numOfHeap++;
|
|
154
|
+
}
|
|
149
155
|
if(mem->isVarArray())
|
|
150
156
|
numOfHasVarArray++;
|
|
151
157
|
if(mem->isVarStruct())
|
|
@@ -136,7 +136,7 @@ void AndersenSFR::fieldExpand(NodeSet& initials, APOffset offset, NodeBS& stride
|
|
|
136
136
|
APOffset initOffset;
|
|
137
137
|
if (GepObjVar *gepNode = SVFUtil::dyn_cast<GepObjVar>(initPN))
|
|
138
138
|
initOffset = gepNode->getConstantFieldIdx();
|
|
139
|
-
else if (SVFUtil::isa<
|
|
139
|
+
else if (SVFUtil::isa<BaseObjVar, DummyObjVar>(initPN))
|
|
140
140
|
initOffset = 0;
|
|
141
141
|
else
|
|
142
142
|
{
|
|
@@ -360,6 +360,9 @@ inline bool isHeapAllocExtCall(const Instruction *inst)
|
|
|
360
360
|
return isHeapAllocExtCallViaRet(inst) || isHeapAllocExtCallViaArg(inst);
|
|
361
361
|
}
|
|
362
362
|
|
|
363
|
+
// Check if a given value represents a heap object.
|
|
364
|
+
bool isHeapObj(const Value* val);
|
|
365
|
+
|
|
363
366
|
/// Whether an instruction is a callsite in the application code, excluding llvm intrinsic calls
|
|
364
367
|
bool isNonInstricCallSite(const Instruction* inst);
|
|
365
368
|
|
|
@@ -646,6 +646,30 @@ bool LLVMUtil::isHeapAllocExtCallViaArg(const Instruction* inst)
|
|
|
646
646
|
}
|
|
647
647
|
}
|
|
648
648
|
|
|
649
|
+
/**
|
|
650
|
+
* Check if a given value represents a heap object.
|
|
651
|
+
*
|
|
652
|
+
* @param val The value to check.
|
|
653
|
+
* @return True if the value represents a heap object, false otherwise.
|
|
654
|
+
*/
|
|
655
|
+
bool LLVMUtil::isHeapObj(const Value* val)
|
|
656
|
+
{
|
|
657
|
+
// Check if the value is an argument in the program entry function
|
|
658
|
+
if (ArgInProgEntryFunction(val))
|
|
659
|
+
{
|
|
660
|
+
// Return true if the value does not have a first use via cast instruction
|
|
661
|
+
return !getFirstUseViaCastInst(val);
|
|
662
|
+
}
|
|
663
|
+
// Check if the value is an instruction and if it is a heap allocation external call
|
|
664
|
+
else if (SVFUtil::isa<Instruction>(val) &&
|
|
665
|
+
LLVMUtil::isHeapAllocExtCall(SVFUtil::cast<Instruction>(val)))
|
|
666
|
+
{
|
|
667
|
+
return true;
|
|
668
|
+
}
|
|
669
|
+
// Return false if none of the above conditions are met
|
|
670
|
+
return false;
|
|
671
|
+
}
|
|
672
|
+
|
|
649
673
|
bool LLVMUtil::isNonInstricCallSite(const Instruction* inst)
|
|
650
674
|
{
|
|
651
675
|
bool res = false;
|
|
@@ -214,15 +214,21 @@ void SVFIRBuilder::initialiseNodes()
|
|
|
214
214
|
pag->addBlackholePtrNode();
|
|
215
215
|
addNullPtrNode();
|
|
216
216
|
|
|
217
|
+
// Iterate over all value symbols in the symbol table
|
|
217
218
|
for (SymbolTableInfo::ValueToIDMapTy::iterator iter =
|
|
218
219
|
symTable->valSyms().begin(); iter != symTable->valSyms().end();
|
|
219
220
|
++iter)
|
|
220
221
|
{
|
|
222
|
+
// Debug output for adding value node
|
|
221
223
|
DBOUT(DPAGBuild, outs() << "add val node " << iter->second << "\n");
|
|
224
|
+
|
|
225
|
+
// Skip blackhole and null pointer symbols
|
|
222
226
|
if(iter->second == symTable->blkPtrSymID() || iter->second == symTable->nullPtrSymID())
|
|
223
227
|
continue;
|
|
224
228
|
|
|
225
229
|
const ICFGNode* icfgNode = nullptr;
|
|
230
|
+
|
|
231
|
+
// Check if the value is an instruction and get its ICFG node
|
|
226
232
|
if (const Instruction* inst =
|
|
227
233
|
SVFUtil::dyn_cast<Instruction>(llvmModuleSet()->getLLVMValue(iter->first)))
|
|
228
234
|
{
|
|
@@ -232,30 +238,59 @@ void SVFIRBuilder::initialiseNodes()
|
|
|
232
238
|
}
|
|
233
239
|
}
|
|
234
240
|
|
|
241
|
+
// Check if the value is a function and get its call graph node
|
|
235
242
|
if (const Function* func =
|
|
236
243
|
SVFUtil::dyn_cast<Function>(llvmModuleSet()->getLLVMValue(iter->first)))
|
|
237
244
|
{
|
|
238
245
|
const CallGraphNode* cgn = llvmModuleSet()->getCallGraphNode(func);
|
|
246
|
+
// add value node representing the function
|
|
239
247
|
pag->addFunValNode(cgn, iter->second, icfgNode);
|
|
240
248
|
}
|
|
241
249
|
else
|
|
242
250
|
{
|
|
251
|
+
// Add value node to PAG
|
|
243
252
|
pag->addValNode(iter->first, iter->second, icfgNode);
|
|
244
253
|
}
|
|
245
254
|
}
|
|
246
255
|
|
|
256
|
+
// Iterate over all object symbols in the symbol table
|
|
247
257
|
for (SymbolTableInfo::ValueToIDMapTy::iterator iter =
|
|
248
258
|
symTable->objSyms().begin(); iter != symTable->objSyms().end();
|
|
249
259
|
++iter)
|
|
250
260
|
{
|
|
261
|
+
// Debug output for adding object node
|
|
251
262
|
DBOUT(DPAGBuild, outs() << "add obj node " << iter->second << "\n");
|
|
263
|
+
|
|
264
|
+
// Skip blackhole and constant symbols
|
|
252
265
|
if(iter->second == symTable->blackholeSymID() || iter->second == symTable->constantSymID())
|
|
253
266
|
continue;
|
|
254
|
-
|
|
255
|
-
|
|
267
|
+
|
|
268
|
+
// Get the LLVM value corresponding to the symbol
|
|
269
|
+
const Value* llvmValue = llvmModuleSet()->getLLVMValue(iter->first);
|
|
270
|
+
|
|
271
|
+
// Check if the value is a function and add a function object node
|
|
272
|
+
if (const Function* func = SVFUtil::dyn_cast<Function>(llvmValue))
|
|
256
273
|
{
|
|
257
274
|
pag->addFunObjNode(llvmModuleSet()->getCallGraphNode(func), iter->second);
|
|
258
275
|
}
|
|
276
|
+
// Check if the value is a heap object and add a heap object node
|
|
277
|
+
else if (LLVMUtil::isHeapObj(llvmValue))
|
|
278
|
+
{
|
|
279
|
+
const SVFFunction* f =
|
|
280
|
+
SVFUtil::cast<SVFInstruction>(iter->first)->getFunction();
|
|
281
|
+
pag->addHeapObjNode(iter->first, f, iter->second);
|
|
282
|
+
llvmModuleSet()->setValueAttr(llvmValue,pag->getGNode(iter->second));
|
|
283
|
+
}
|
|
284
|
+
// Check if the value is an alloca instruction and add a stack object node
|
|
285
|
+
else if (SVFUtil::isa<AllocaInst>(llvmValue))
|
|
286
|
+
{
|
|
287
|
+
const SVFFunction* f =
|
|
288
|
+
SVFUtil::cast<SVFInstruction>(iter->first)->getFunction();
|
|
289
|
+
pag->addStackObjNode(iter->first, f, iter->second);
|
|
290
|
+
llvmModuleSet()->setValueAttr(llvmValue,
|
|
291
|
+
pag->getGNode(iter->second));
|
|
292
|
+
}
|
|
293
|
+
// Add a generic object node for other types of values
|
|
259
294
|
else
|
|
260
295
|
{
|
|
261
296
|
pag->addObjNode(iter->first, iter->second);
|
|
@@ -1347,7 +1382,7 @@ void SVFIRBuilder::setCurrentBBAndValueForPAGEdge(PAGEdge* edge)
|
|
|
1347
1382
|
{
|
|
1348
1383
|
const SVFFunction* srcFun = edge->getSrcNode()->getFunction();
|
|
1349
1384
|
const SVFFunction* dstFun = edge->getDstNode()->getFunction();
|
|
1350
|
-
if(srcFun!=nullptr && !SVFUtil::isa<RetPE>(edge) && !SVFUtil::isa<SVFFunction>(edge->getSrcNode()->getValue()))
|
|
1385
|
+
if(srcFun!=nullptr && !SVFUtil::isa<RetPE>(edge) && edge->getSrcNode()->hasValue() && !SVFUtil::isa<SVFFunction>(edge->getSrcNode()->getValue()))
|
|
1351
1386
|
{
|
|
1352
1387
|
assert(srcFun==curInst->getFunction() && "SrcNode of the PAGEdge not in the same function?");
|
|
1353
1388
|
}
|