svf-tools 1.0.677 → 1.0.679

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.
@@ -47,6 +47,7 @@ class StInfo;
47
47
  class SymbolTableInfo
48
48
  {
49
49
  friend class SymbolTableBuilder;
50
+ friend class SVFIRWriter;
50
51
 
51
52
  public:
52
53
 
@@ -69,7 +70,7 @@ public:
69
70
  /// local (%) and global (@) identifiers are pointer types which have a value node id.
70
71
  typedef OrderedMap<const SVFValue*, SymID> ValueToIDMapTy;
71
72
  /// sym id to memory object map
72
- typedef OrderedMap<SymID,MemObj*> IDToMemMapTy;
73
+ typedef OrderedMap<SymID, MemObj*> IDToMemMapTy;
73
74
  /// function to sym id map
74
75
  typedef OrderedMap<const SVFFunction*, SymID> FunToIDMapTy;
75
76
  /// struct type to struct info map
@@ -77,11 +78,11 @@ public:
77
78
  //@}
78
79
 
79
80
  private:
80
- ValueToIDMapTy valSymMap; ///< map a value to its sym id
81
- ValueToIDMapTy objSymMap; ///< map a obj reference to its sym id
82
- FunToIDMapTy returnSymMap; ///< return map
83
- FunToIDMapTy varargSymMap; ///< vararg map
84
- IDToMemMapTy objMap; ///< map a memory sym id to its obj
81
+ ValueToIDMapTy valSymMap; ///< map a value to its sym id
82
+ ValueToIDMapTy objSymMap; ///< map a obj reference to its sym id
83
+ FunToIDMapTy returnSymMap; ///< return map
84
+ FunToIDMapTy varargSymMap; ///< vararg map
85
+ IDToMemMapTy objMap; ///< map a memory sym id to its obj
85
86
 
86
87
  // Singleton pattern here to enable instance of SymbolTableInfo can only be created once.
87
88
  static SymbolTableInfo* symInfo;
@@ -100,8 +101,9 @@ private:
100
101
 
101
102
  protected:
102
103
  /// Constructor
103
- SymbolTableInfo(void) :
104
- mod(nullptr), modelConstants(false), totalSymNum(0), maxStruct(nullptr), maxStSize(0)
104
+ SymbolTableInfo(void)
105
+ : mod(nullptr), modelConstants(false), totalSymNum(0),
106
+ maxStruct(nullptr), maxStSize(0)
105
107
  {
106
108
  }
107
109
 
@@ -269,6 +271,11 @@ public:
269
271
  return objMap;
270
272
  }
271
273
 
274
+ inline const IDToMemMapTy& idToObjMap() const
275
+ {
276
+ return objMap;
277
+ }
278
+
272
279
  inline FunToIDMapTy& retSyms()
273
280
  {
274
281
  return returnSymMap;
@@ -347,6 +354,7 @@ protected:
347
354
  */
348
355
  class MemObj
349
356
  {
357
+ friend class SVFIRWriter;
350
358
 
351
359
  private:
352
360
  /// Type information of this object
@@ -424,7 +432,7 @@ public:
424
432
  //@}
425
433
 
426
434
  /// Operator overloading
427
- inline bool operator==(const MemObj &mem) const
435
+ inline bool operator==(const MemObj& mem) const
428
436
  {
429
437
  return getValue() == mem.getValue();
430
438
  }
@@ -433,14 +441,14 @@ public:
433
441
  void destroy();
434
442
  };
435
443
 
436
-
437
-
438
444
  /*!
439
445
  * Type Info of an abstract memory object
440
446
  */
441
447
  class ObjTypeInfo
442
448
  {
449
+ friend class SVFIRWriter;
443
450
  friend class SymbolTableBuilder;
451
+
444
452
  public:
445
453
  typedef enum
446
454
  {
@@ -325,7 +325,7 @@ template <typename T>
325
325
  class Option : public OptionBase
326
326
  {
327
327
  public:
328
- Option(std::string name, std::string description, T init)
328
+ Option(const std::string& name, const std::string& description, T init)
329
329
  : OptionBase(name, description), isExplicitlySet(false), value(init)
330
330
  {
331
331
  assert(!name.empty() && "Option: empty option name given");
@@ -134,6 +134,7 @@ public:
134
134
  static const Option<bool> PAGDotGraph;
135
135
  static const Option<bool> ShowSVFIRValue;
136
136
  static const Option<bool> DumpICFG;
137
+ static const Option<std::string> DumpJson;
137
138
  static const Option<bool> CallGraphDotGraph;
138
139
  static const Option<bool> PAGPrint;
139
140
  static const Option<u32_t> IndirectCallLimit;
@@ -216,12 +216,16 @@ inline unsigned countPopulation(T Value)
216
216
  /// kept up to date. They are also significantly more memory intensive.
217
217
  template <unsigned ElementSize = 128> struct SparseBitVectorElement
218
218
  {
219
+ friend class SVFIRWriter;
220
+
219
221
  public:
220
222
  using BitWord = unsigned long;
221
223
  using size_type = unsigned;
222
224
  enum
223
225
  {
224
226
  BITWORD_SIZE = sizeof(BitWord) * CHAR_BIT,
227
+ // N.B. (+ BITWORD_SIZE - 1) is to round up, to ensure we can have
228
+ // sufficient bits to represent *at least* ElementSize bits.
225
229
  BITWORDS_PER_ELEMENT = (ElementSize + BITWORD_SIZE - 1) / BITWORD_SIZE,
226
230
  BITS_PER_ELEMENT = ElementSize
227
231
  };
@@ -453,6 +457,8 @@ public:
453
457
  template <unsigned ElementSize = 128>
454
458
  class SparseBitVector
455
459
  {
460
+ friend class SVFIRWriter;
461
+
456
462
  using ElementList = std::list<SparseBitVectorElement<ElementSize>>;
457
463
  using ElementListIter = typename ElementList::iterator;
458
464
  using ElementListConstIter = typename ElementList::const_iterator;
@@ -46,24 +46,24 @@ class ThreadAPI
46
46
  public:
47
47
  enum TD_TYPE
48
48
  {
49
- TD_DUMMY = 0, /// dummy type
50
- TD_FORK, /// create a new thread
51
- TD_JOIN, /// wait for a thread to join
52
- TD_DETACH, /// detach a thread directly instead wait for it to join
53
- TD_ACQUIRE, /// acquire a lock
54
- TD_TRY_ACQUIRE, /// try to acquire a lock
55
- TD_RELEASE, /// release a lock
56
- TD_EXIT, /// exit/kill a thread
57
- TD_CANCEL, /// cancel a thread by another
58
- TD_COND_WAIT, /// wait a condition
59
- TD_COND_SIGNAL, /// signal a condition
60
- TD_COND_BROADCAST, /// broadcast a condition
61
- TD_MUTEX_INI, /// initial a mutex variable
49
+ TD_DUMMY = 0, /// dummy type
50
+ TD_FORK, /// create a new thread
51
+ TD_JOIN, /// wait for a thread to join
52
+ TD_DETACH, /// detach a thread directly instead wait for it to join
53
+ TD_ACQUIRE, /// acquire a lock
54
+ TD_TRY_ACQUIRE, /// try to acquire a lock
55
+ TD_RELEASE, /// release a lock
56
+ TD_EXIT, /// exit/kill a thread
57
+ TD_CANCEL, /// cancel a thread by another
58
+ TD_COND_WAIT, /// wait a condition
59
+ TD_COND_SIGNAL, /// signal a condition
60
+ TD_COND_BROADCAST, /// broadcast a condition
61
+ TD_MUTEX_INI, /// initial a mutex variable
62
62
  TD_MUTEX_DESTROY, /// initial a mutex variable
63
- TD_CONDVAR_INI, /// initial a mutex variable
63
+ TD_CONDVAR_INI, /// initial a mutex variable
64
64
  TD_CONDVAR_DESTROY, /// initial a mutex variable
65
65
  TD_BAR_INIT, /// Barrier init
66
- TD_BAR_WAIT, /// Barrier wait
66
+ TD_BAR_WAIT, /// Barrier wait
67
67
  HARE_PAR_FOR
68
68
  };
69
69
 
@@ -101,14 +101,17 @@ SVFIR2ItvExeState::VAddrs SVFIR2ItvExeState::getGepObjAddress(u32_t pointer, u32
101
101
  return ret;
102
102
  }
103
103
 
104
-
105
104
  std::pair<s32_t, s32_t> SVFIR2ItvExeState::getGepOffset(const GepStmt *gep)
106
105
  {
106
+ /// for instant constant index, e.g. gep arr, 1
107
107
  if (gep->getOffsetVarAndGepTypePairVec().empty())
108
108
  return std::make_pair(gep->getConstantFieldIdx(), gep->getConstantFieldIdx());
109
109
 
110
110
  s32_t totalOffsetLb = 0;
111
111
  s32_t totalOffsetUb = 0;
112
+ /// default value of MaxFieldLimit is 512
113
+ u32_t maxFieldLimit = Options::MaxFieldLimit() - 1;
114
+ /// for variable index and nested indexes, e.g. 1) gep arr, idx 2) gep arr idx0, idx1
112
115
  for (int i = gep->getOffsetVarAndGepTypePairVec().size() - 1; i >= 0; i--)
113
116
  {
114
117
  const SVFValue *value = gep->getOffsetVarAndGepTypePairVec()[i].first->getValue();
@@ -116,50 +119,88 @@ std::pair<s32_t, s32_t> SVFIR2ItvExeState::getGepOffset(const GepStmt *gep)
116
119
  const SVFConstantInt *op = SVFUtil::dyn_cast<SVFConstantInt>(value);
117
120
  s32_t offsetLb = 0;
118
121
  s32_t offsetUb = 0;
119
- /// constant as the offset
122
+ /// offset is constant but stored in variable
120
123
  if (op)
121
124
  {
122
125
  offsetLb = offsetUb = op->getSExtValue();
123
126
  }
124
- /// variable as the offset
127
+ /// offset is variable, the concrete value isn't sure util runtime, and maybe not a concrete value.
128
+ /// e.g.
125
129
  else
126
130
  {
127
131
  u32_t idx = _svfir->getValueNode(value);
128
132
  if (!inVarToIValTable(idx)) return std::make_pair(-1, -1);
129
133
  IntervalValue &idxVal = _es[idx];
130
- if(idxVal.isBottom() || idxVal.isTop()) return std::make_pair(0, (s32_t)Options::MaxFieldLimit());
134
+ if (idxVal.isBottom() || idxVal.isTop()) return std::make_pair(0, (s32_t)Options::MaxFieldLimit());
135
+ // if idxVal is a concrete value
131
136
  if (idxVal.is_numeral())
132
137
  {
133
138
  offsetLb = offsetUb = idxVal.lb().getNumeral();
134
139
  }
135
140
  else
136
141
  {
142
+ // if inxVal is an interval. we should make sure that idxVal.lb>0 && idxVal.ub<MaxFieldLimit
137
143
  offsetLb = idxVal.lb().getNumeral() < 0 ? 0 : idxVal.lb().getNumeral();
144
+ offsetLb = idxVal.lb().getNumeral() > maxFieldLimit ? maxFieldLimit : offsetLb;
138
145
  offsetUb = idxVal.ub().getNumeral() < 0 ? 0 : idxVal.ub().getNumeral();
146
+ offsetUb = idxVal.ub().getNumeral() > maxFieldLimit ? maxFieldLimit : offsetUb;
139
147
  }
140
148
  }
141
149
  if (type == nullptr)
142
150
  {
143
- totalOffsetLb += offsetLb;
144
- totalOffsetUb += offsetUb;
151
+ if ((long long) (totalOffsetLb + offsetLb) > maxFieldLimit)
152
+ {
153
+ totalOffsetLb = maxFieldLimit;
154
+ }
155
+ else
156
+ {
157
+ totalOffsetLb += offsetLb;
158
+ }
159
+
160
+ if ((long long) (totalOffsetUb + offsetUb) > maxFieldLimit)
161
+ {
162
+ totalOffsetUb = maxFieldLimit;
163
+ }
164
+ else
165
+ {
166
+ totalOffsetUb += offsetUb;
167
+ }
145
168
  continue;
146
169
  }
147
- /// Caculate the offset
170
+
148
171
  if (const SVFPointerType *pty = SVFUtil::dyn_cast<SVFPointerType>(type))
149
172
  {
150
- totalOffsetLb += offsetLb * gep->getLocationSet().getElementNum(pty->getPtrElementType());
151
- totalOffsetUb += offsetUb * gep->getLocationSet().getElementNum(pty->getPtrElementType());
173
+ offsetLb = offsetLb * gep->getLocationSet().getElementNum(pty->getPtrElementType());
174
+ offsetUb = offsetUb * gep->getLocationSet().getElementNum(pty->getPtrElementType());
175
+
152
176
  }
153
177
  else
154
178
  {
155
179
  const std::vector<u32_t> &so = SymbolTableInfo::SymbolInfo()->getTypeInfo(type)->getFlattenedElemIdxVec();
156
- if(so.empty() || (u32_t)offsetUb >= so.size() || (u32_t)offsetLb >= so.size()) return std::make_pair(-1, -1);
157
- totalOffsetLb += SymbolTableInfo::SymbolInfo()->getFlattenedElemIdx(type, offsetLb);
158
- totalOffsetUb += SymbolTableInfo::SymbolInfo()->getFlattenedElemIdx(type, offsetUb);
180
+ if (so.empty() || (u32_t) offsetUb >= so.size() || (u32_t) offsetLb >= so.size())
181
+ return std::make_pair(-1, -1);
182
+ offsetLb = SymbolTableInfo::SymbolInfo()->getFlattenedElemIdx(type, offsetLb);
183
+ offsetUb = SymbolTableInfo::SymbolInfo()->getFlattenedElemIdx(type, offsetUb);
184
+ }
185
+ if ((long long) (totalOffsetLb + offsetLb) > maxFieldLimit)
186
+ {
187
+ totalOffsetLb = maxFieldLimit;
188
+ }
189
+ else
190
+ {
191
+ totalOffsetLb += offsetLb;
192
+ }
193
+ if ((long long) (totalOffsetUb + offsetUb) > maxFieldLimit)
194
+ {
195
+ totalOffsetUb = maxFieldLimit;
196
+ }
197
+ else
198
+ {
199
+ totalOffsetUb += offsetUb;
159
200
  }
160
201
  }
161
202
  std::pair<s32_t, s32_t> offSetPair;
162
- offSetPair.first = totalOffsetLb;
203
+ offSetPair.first = totalOffsetLb;
163
204
  offSetPair.second = totalOffsetUb;
164
205
  return offSetPair;
165
206
  }
@@ -646,10 +687,12 @@ void SVFIR2ItvExeState::translateGep(const GepStmt *gep)
646
687
  {
647
688
  u32_t rhs = gep->getRHSVarID();
648
689
  u32_t lhs = gep->getLHSVarID();
690
+ if (!inVarToAddrsTable(rhs)) return;
691
+ assert(!getVAddrs(rhs).empty());
649
692
  VAddrs &rhsVal = getVAddrs(rhs);
650
693
  if (rhsVal.empty()) return;
651
694
  std::pair<s32_t, s32_t> offsetPair = getGepOffset(gep);
652
- if(offsetPair.first == -1 && offsetPair.second == -1) return;
695
+ if (offsetPair.first == -1 && offsetPair.second == -1) return;
653
696
  if (!isVirtualMemAddress(*rhsVal.begin()))
654
697
  {
655
698
  return;
@@ -658,15 +701,16 @@ void SVFIR2ItvExeState::translateGep(const GepStmt *gep)
658
701
  {
659
702
  VAddrs gepAddrs;
660
703
  s32_t ub = offsetPair.second;
661
- if (offsetPair.second - offsetPair.first > (s32_t)Options::MaxFieldLimit() - 1)
704
+ if (offsetPair.second > (s32_t) Options::MaxFieldLimit() - 1)
662
705
  {
663
- ub = offsetPair.first + (s32_t)Options::MaxFieldLimit() - 1;
706
+ ub = Options::MaxFieldLimit() - 1;
664
707
  }
665
708
  for (s32_t i = offsetPair.first; i <= ub; i++)
666
709
  {
667
710
  gepAddrs.join_with(getGepObjAddress(rhs, i));
668
711
  }
669
- getEs().getVAddrs(lhs) = gepAddrs;
712
+ if(gepAddrs.empty()) return;
713
+ _es.getVAddrs(lhs) = gepAddrs;
670
714
  return;
671
715
  }
672
716
  }
@@ -47,7 +47,8 @@ FunEntryICFGNode::FunEntryICFGNode(NodeID id, const SVFFunction* f) : InterICFGN
47
47
  }
48
48
  }
49
49
 
50
- FunExitICFGNode::FunExitICFGNode(NodeID id, const SVFFunction* f) : InterICFGNode(id, FunExitBlock), formalRet(nullptr)
50
+ FunExitICFGNode::FunExitICFGNode(NodeID id, const SVFFunction* f)
51
+ : InterICFGNode(id, FunExitBlock), formalRet(nullptr)
51
52
  {
52
53
  fun = f;
53
54
  // if function is implemented
@@ -55,10 +56,8 @@ FunExitICFGNode::FunExitICFGNode(NodeID id, const SVFFunction* f) : InterICFGNod
55
56
  {
56
57
  bb = f->getExitBB();
57
58
  }
58
-
59
59
  }
60
60
 
61
-
62
61
  const std::string ICFGNode::toString() const
63
62
  {
64
63
  std::string str;