svf-tools 1.0.1017 → 1.0.1018

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svf-tools",
3
- "version": "1.0.1017",
3
+ "version": "1.0.1018",
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(obj->isStack())
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 MemObj* mem = _pag->getObject(getPtrNodeID(var));
641
- assert(mem && "memory object is null??");
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
- // ┌── ICFGNodeKinds: Combines inter-procedural and intra-procedural control flow graph nodes
145
- // ├── Represents a node within a single procedure
146
- IntraBlock,
147
- // │ └── Represents a global-level block
148
- GlobalBlock,
149
- // │ └─ InterICFGNodeKinds: Types of inter-procedural control flow graph nodes
150
- // ├── Entry point of a function
151
- FunEntryBlock,
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
- // ┌── SVFVarKinds: Combines ValVarKinds and ObjVarKinds for variable nodes
161
- // │ ┌── ValVarKinds: Types of value variable nodes
162
- // │ │ ├── Represents a standard value variable
163
- ValNode,
164
- // │ │ ├── Represents a Function value variable
165
- FunValNode,
166
- // │ │ ├── Represents a GEP value variable
167
- GepValNode,
168
- // │ │ ├── Represents a return value node
169
- RetNode,
170
- // │ │ ├── Represents a variadic argument node
171
- VarargNode,
172
- // │ │ └── Dummy node for uninitialized values
173
- DummyValNode,
174
- // │ └── ObjVarKinds: Types of object variable nodes
175
- // ├── Represents an object variable
176
- ObjNode,
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
- // ┌── VFGNodeKinds: Various Value Flow Graph (VFG) node kinds with operations
188
- // ├── Represents a comparison operation
189
- Cmp,
190
- // ├── Represents a binary operation
191
- BinaryOp,
192
- // ├── Represents a unary operation
193
- UnaryOp,
194
- // │ ├── Represents a branch operation
195
- Branch,
196
- // ├── Dummy node for value propagation
197
- DummyVProp,
198
- // │ └── Represents a null pointer operation
199
- NPtr,
200
- // │ └── ArgumentVFGNodeKinds: Types of argument nodes in VFG
201
- // ├── Represents a function return value
202
- FRet,
203
- // ├── Represents an argument return value
204
- ARet,
205
- // │ ├── Represents an argument parameter
206
- AParm,
207
- // │ └── FParm: Represents a function parameter
208
- FParm,
209
- // │ └── StmtVFGNodeKinds: Types of statement nodes in VFG
210
- // ├── Represents an address operation
211
- Addr,
212
- // ├── Represents a copy operation
213
- Copy,
214
- // │ ├── Represents a GEP operation
215
- Gep,
216
- // ├── Represents a store operation
217
- Store,
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 == 10,
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 == 4,
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 isFIObjVarKinds(GNodeK n)
304
+ static inline bool isBaseObjVarKinds(GNodeK n)
344
305
  {
345
- static_assert(FunObjNode - FIObjNode == 1,
346
- "The number of FIObjVarKinds has changed, make sure the "
306
+ static_assert(DummyObjNode - BaseObjNode == 4,
307
+ "The number of BaseObjVarKinds has changed, make sure the "
347
308
  "range is correct");
348
- return n <= FunObjNode && n >= FIObjNode;
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
- const MemObj* mem = pag->getObject(id);
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<FIObjVar>(pag->getGNode(id)));
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 FIObjVar;
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 FIObjVar* var);
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, FIObjVar* var);
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
- /// FIObjNode: for field insensitive analysis
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 that this SVFVar resides in. Return nullptr if it is a global or constantexpr node
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 FIObjVar: public ObjVar
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
- FIObjVar(NodeID i, PNODEK ty = FIObjNode) : ObjVar(i, ty) {}
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 FIObjVar*)
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 isFIObjVarKinds(node->getNodeKind());
567
+ return isBaseObjVarKinds(node->getNodeKind());
554
568
  }
555
569
  static inline bool classof(const SVFVar* node)
556
570
  {
557
- return isFIObjVarKinds(node->getNodeKind());
571
+ return isBaseObjVarKinds(node->getNodeKind());
558
572
  }
559
573
  static inline bool classof(const GenericPAGNodeTy* node)
560
574
  {
561
- return isFIObjVarKinds(node->getNodeKind());
575
+ return isBaseObjVarKinds(node->getNodeKind());
562
576
  }
563
577
  static inline bool classof(const SVFBaseNode* node)
564
578
  {
565
- return isFIObjVarKinds(node->getNodeKind());
579
+ return isBaseObjVarKinds(node->getNodeKind());
566
580
  }
567
581
  //@}
568
582
 
569
583
  /// Constructor
570
- FIObjVar(const SVFValue* val, NodeID i, const MemObj* mem,
571
- PNODEK ty = FIObjNode)
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 FIObjVar
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) : FIObjVar(i, ty) {}
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 FIObjVar* node)
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 ObjVar
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) : ObjVar(i, DummyObjNode) {}
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
- : ObjVar(nullptr, i, m, ty)
1010
+ : BaseObjVar(nullptr, i, m, ty)
880
1011
  {
881
1012
  }
882
1013
 
@@ -374,8 +374,6 @@ bool isHeapAllocExtCallViaRet(const CallICFGNode* cs);
374
374
 
375
375
  bool isHeapAllocExtCall(const ICFGNode* cs);
376
376
 
377
-
378
-
379
377
  //@}
380
378
 
381
379
  u32_t getHeapAllocHoldingArgPosition(const CallICFGNode* cs);
@@ -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 FIObjVar, return the byte offset directly
320
- if (SVFUtil::isa<FIObjVar>(obj))
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 FIObjVar, add the offset directly
355
- if (SVFUtil::isa<FIObjVar>(obj))
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 FIObjVar, get the offset directly
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
- if (mem->isHeap())
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
  {
@@ -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 MemObj* mem = _pag->getObject(getPtrNodeID(var));
180
- assert(mem && "memory object is null??");
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();
@@ -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<FIObjVar>(node))
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<FIObjVar>(node))
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
- if(obj->isGlobalObj() || obj->isHeap())
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(obj->isStack())
586
+ else if(SVFUtil::isa<StackObjVar>(pVar))
585
587
  {
586
- if(const SVFFunction* svffun = pta->getPAG()->getGNode(id)->getFunction())
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 MemObj* obj = pag->getObject(id);
137
- assert(obj && "object not found!!");
138
- if(obj->isStack())
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 (FIObjVar* baseNode = SVFUtil::dyn_cast<FIObjVar>(node))
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(FIObjNode, FIObjVar);
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 FIObjVar* var)
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(FIObjNode, FIObjVar);
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(FIObjNode, FIObjVar);
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, FIObjVar* var)
1949
+ void SVFIRReader::fill(const cJSON*& fieldJson, BaseObjVar* var)
1948
1950
  {
1949
1951
  fill(fieldJson, static_cast<ObjVar*>(var));
1950
1952
  }
@@ -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 (FIObjVar* baseNode = SVFUtil::dyn_cast<FIObjVar>(node))
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
- FIObjVar *node = new FIObjVar(obj->getValue(), obj->getId(), obj);
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>(node) || SVFUtil::isa<VarArgPN>(node) || SVFUtil::isa<FunValVar>(node))
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 FIObjNode:
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 FIObjVar::toString() const
177
+ const std::string BaseObjVar::toString() const
176
178
  {
177
179
  std::string str;
178
180
  std::stringstream rawstr(str);
179
- rawstr << "FIObjVar ID: " << getId() << " (base object)";
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(nullptr, 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(nullptr, 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(nullptr, 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
- : FIObjVar(nullptr, i, mem, ty), callGraphNode(cgNode)
256
+ : BaseObjVar(nullptr, i, mem, ty), callGraphNode(cgNode)
204
257
  {
205
258
  isPtr = callGraphNode->getFunction()->getType()->isPointerTy();
206
259
  }
@@ -142,10 +142,16 @@ void SVFStat::performStat()
142
142
  numOfFunction++;
143
143
  if(mem->isGlobalObj())
144
144
  numOfGlobal++;
145
- if(mem->isStack())
145
+ if (pag->getBaseObject(obj->getId()) &&
146
+ SVFUtil::isa<StackObjVar>(
147
+ pag->getBaseObject(obj->getId())))
146
148
  numOfStack++;
147
- if(mem->isHeap())
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<FIObjVar, DummyObjVar>(initPN))
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
- if (const Function* func = SVFUtil::dyn_cast<Function>(
255
- llvmModuleSet()->getLLVMValue(iter->first)))
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
  }