svf-tools 1.0.973 → 1.0.975

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.
@@ -29,6 +29,7 @@
29
29
 
30
30
  #include "AE/Core/AbstractState.h"
31
31
  #include "Util/SVFUtil.h"
32
+ #include "Util/Options.h"
32
33
 
33
34
  using namespace SVF;
34
35
  using namespace SVFUtil;
@@ -97,25 +98,6 @@ AbstractState AbstractState::narrowing(const AbstractState& other)
97
98
 
98
99
  }
99
100
 
100
- /// domain widen with other, important! other widen this.
101
- void AbstractState::widenWith(const AbstractState& other)
102
- {
103
- for (auto it = _varToAbsVal.begin(); it != _varToAbsVal.end(); ++it)
104
- {
105
- auto key = it->first;
106
- if (other.getVarToVal().find(key) != other.getVarToVal().end())
107
- if (it->second.isInterval() && other._varToAbsVal.at(key).isInterval())
108
- it->second.getInterval().widen_with(other._varToAbsVal.at(key).getInterval());
109
- }
110
- for (auto it = _addrToAbsVal.begin(); it != _addrToAbsVal.end(); ++it)
111
- {
112
- auto key = it->first;
113
- if (other._addrToAbsVal.find(key) != other._addrToAbsVal.end())
114
- if (it->second.isInterval() && other._varToAbsVal.at(key).isInterval())
115
- it->second.getInterval().widen_with(other._addrToAbsVal.at(key).getInterval());
116
- }
117
- }
118
-
119
101
  /// domain join with other, important! other widen this.
120
102
  void AbstractState::joinWith(const AbstractState& other)
121
103
  {
@@ -147,27 +129,6 @@ void AbstractState::joinWith(const AbstractState& other)
147
129
  }
148
130
  }
149
131
 
150
- /// domain narrow with other, important! other widen this.
151
- void AbstractState::narrowWith(const AbstractState& other)
152
- {
153
- for (auto it = _varToAbsVal.begin(); it != _varToAbsVal.end(); ++it)
154
- {
155
- auto key = it->first;
156
- auto oit = other.getVarToVal().find(key);
157
- if (oit != other.getVarToVal().end())
158
- if (it->second.isInterval() && oit->second.isInterval())
159
- it->second.getInterval().narrow_with(oit->second.getInterval());
160
- }
161
- for (auto it = _addrToAbsVal.begin(); it != _addrToAbsVal.end(); ++it)
162
- {
163
- auto key = it->first;
164
- auto oit = other._addrToAbsVal.find(key);
165
- if (oit != other._addrToAbsVal.end())
166
- if (it->second.isInterval() && oit->second.isInterval())
167
- it->second.getInterval().narrow_with(oit->second.getInterval());
168
- }
169
- }
170
-
171
132
  /// domain meet with other, important! other widen this.
172
133
  void AbstractState::meetWith(const AbstractState& other)
173
134
  {
@@ -191,26 +152,320 @@ void AbstractState::meetWith(const AbstractState& other)
191
152
  }
192
153
  }
193
154
 
194
- /// Print values of all expressions
195
- void AbstractState::printExprValues(std::ostream &oss) const
155
+ // getGepObjAddrs
156
+ AddressValue AbstractState::getGepObjAddrs(u32_t pointer, IntervalValue offset)
157
+ {
158
+ AddressValue gepAddrs;
159
+ APOffset lb = offset.lb().getIntNumeral() < Options::MaxFieldLimit() ? offset.lb().getIntNumeral()
160
+ : Options::MaxFieldLimit();
161
+ APOffset ub = offset.ub().getIntNumeral() < Options::MaxFieldLimit() ? offset.ub().getIntNumeral()
162
+ : Options::MaxFieldLimit();
163
+ for (APOffset i = lb; i <= ub; i++)
164
+ {
165
+ AbstractValue addrs = (*this)[pointer];
166
+ for (const auto& addr : addrs.getAddrs())
167
+ {
168
+ s64_t baseObj = AbstractState::getInternalID(addr);
169
+ assert(SVFUtil::isa<ObjVar>(PAG::getPAG()->getGNode(baseObj)) && "Fail to get the base object address!");
170
+ NodeID gepObj = PAG::getPAG()->getGepObjVar(baseObj, i);
171
+ (*this)[gepObj] = AddressValue(AbstractState::getVirtualMemAddress(gepObj));
172
+ gepAddrs.insert(AbstractState::getVirtualMemAddress(gepObj));
173
+ }
174
+ }
175
+
176
+ return gepAddrs;
177
+ }
178
+ // initObjVar
179
+ void AbstractState::initObjVar(ObjVar* objVar)
180
+ {
181
+ NodeID varId = objVar->getId();
182
+
183
+ // Check if the object variable has an associated value
184
+ if (objVar->hasValue())
185
+ {
186
+ const MemObj* obj = objVar->getMemObj();
187
+
188
+ // Handle constant data, arrays, and structures
189
+ if (obj->isConstDataOrConstGlobal() || obj->isConstantArray() || obj->isConstantStruct())
190
+ {
191
+ if (const SVFConstantInt* consInt = SVFUtil::dyn_cast<SVFConstantInt>(obj->getValue()))
192
+ {
193
+ s64_t numeral = consInt->getSExtValue();
194
+ (*this)[varId] = IntervalValue(numeral, numeral);
195
+ }
196
+ else if (const SVFConstantFP* consFP = SVFUtil::dyn_cast<SVFConstantFP>(obj->getValue()))
197
+ {
198
+ (*this)[varId] = IntervalValue(consFP->getFPValue(), consFP->getFPValue());
199
+ }
200
+ else if (SVFUtil::isa<SVFConstantNullPtr>(obj->getValue()))
201
+ {
202
+ (*this)[varId] = IntervalValue(0, 0);
203
+ }
204
+ else if (SVFUtil::isa<SVFGlobalValue>(obj->getValue()))
205
+ {
206
+ (*this)[varId] = AddressValue(AbstractState::getVirtualMemAddress(varId));
207
+ }
208
+ else if (obj->isConstantArray() || obj->isConstantStruct())
209
+ {
210
+ (*this)[varId] = IntervalValue::top();
211
+ }
212
+ else
213
+ {
214
+ (*this)[varId] = IntervalValue::top();
215
+ }
216
+ }
217
+ // Handle non-constant memory objects
218
+ else
219
+ {
220
+ (*this)[varId] = AddressValue(AbstractState::getVirtualMemAddress(varId));
221
+ }
222
+ }
223
+ // If the object variable does not have an associated value, set it to a virtual memory address
224
+ else
225
+ {
226
+ (*this)[varId] = AddressValue(AbstractState::getVirtualMemAddress(varId));
227
+ }
228
+ return;
229
+ }
230
+
231
+ // getElementIndex
232
+ IntervalValue AbstractState::getElementIndex(const GepStmt* gep)
233
+ {
234
+ // If the GEP statement has a constant offset, return it directly as the interval value
235
+ if (gep->isConstantOffset())
236
+ return IntervalValue((s64_t)gep->accumulateConstantOffset());
237
+
238
+ IntervalValue res(0);
239
+ // Iterate over the list of offset variable and type pairs in reverse order
240
+ for (int i = gep->getOffsetVarAndGepTypePairVec().size() - 1; i >= 0; i--)
241
+ {
242
+ AccessPath::IdxOperandPair IdxVarAndType = gep->getOffsetVarAndGepTypePairVec()[i];
243
+ const SVFValue* value = gep->getOffsetVarAndGepTypePairVec()[i].first->getValue();
244
+ const SVFType* type = IdxVarAndType.second;
245
+
246
+ // Variables to store the lower and upper bounds of the index value
247
+ s64_t idxLb;
248
+ s64_t idxUb;
249
+
250
+ // Determine the lower and upper bounds based on whether the value is a constant
251
+ if (const SVFConstantInt* constInt = SVFUtil::dyn_cast<SVFConstantInt>(value))
252
+ idxLb = idxUb = constInt->getSExtValue();
253
+ else
254
+ {
255
+ IntervalValue idxItv = (*this)[PAG::getPAG()->getValueNode(value)].getInterval();
256
+ if (idxItv.isBottom())
257
+ idxLb = idxUb = 0;
258
+ else
259
+ {
260
+ idxLb = idxItv.lb().getIntNumeral();
261
+ idxUb = idxItv.ub().getIntNumeral();
262
+ }
263
+ }
264
+
265
+ // Adjust the bounds if the type is a pointer
266
+ if (SVFUtil::isa<SVFPointerType>(type))
267
+ {
268
+ u32_t elemNum = gep->getAccessPath().getElementNum(gep->getAccessPath().gepSrcPointeeType());
269
+ idxLb = (double)Options::MaxFieldLimit() / elemNum < idxLb ? Options::MaxFieldLimit() : idxLb * elemNum;
270
+ idxUb = (double)Options::MaxFieldLimit() / elemNum < idxUb ? Options::MaxFieldLimit() : idxUb * elemNum;
271
+ }
272
+ // Adjust the bounds for array or struct types using the symbol table info
273
+ else
274
+ {
275
+ if (Options::ModelArrays())
276
+ {
277
+ const std::vector<u32_t>& so = SymbolTableInfo::SymbolInfo()->getTypeInfo(type)->getFlattenedElemIdxVec();
278
+ if (so.empty() || idxUb >= (APOffset)so.size() || idxLb < 0)
279
+ {
280
+ idxLb = idxUb = 0;
281
+ }
282
+ else
283
+ {
284
+ idxLb = SymbolTableInfo::SymbolInfo()->getFlattenedElemIdx(type, idxLb);
285
+ idxUb = SymbolTableInfo::SymbolInfo()->getFlattenedElemIdx(type, idxUb);
286
+ }
287
+ }
288
+ else
289
+ idxLb = idxUb = 0;
290
+ }
291
+
292
+ // Add the calculated interval to the result
293
+ res = res + IntervalValue(idxLb, idxUb);
294
+ }
295
+
296
+ // Ensure the result is within the bounds of [0, MaxFieldLimit]
297
+ res.meet_with(IntervalValue((s64_t)0, (s64_t)Options::MaxFieldLimit()));
298
+ if (res.isBottom())
299
+ {
300
+ res = IntervalValue(0);
301
+ }
302
+ return res;
303
+ }
304
+ // getByteOffset
305
+ IntervalValue AbstractState::getByteOffset(const GepStmt* gep)
196
306
  {
197
- oss << "-----------Var and Value-----------\n";
198
- printTable(_varToAbsVal, oss);
199
- printTable(_addrToAbsVal, oss);
200
- oss << "-----------------------------------------\n";
307
+ // If the GEP statement has a constant byte offset, return it directly as the interval value
308
+ if (gep->isConstantOffset())
309
+ return IntervalValue((s64_t)gep->accumulateConstantByteOffset());
310
+
311
+ IntervalValue res(0); // Initialize the result interval 'res' to 0.
312
+
313
+ // Loop through the offsetVarAndGepTypePairVec in reverse order.
314
+ for (int i = gep->getOffsetVarAndGepTypePairVec().size() - 1; i >= 0; i--)
315
+ {
316
+ const SVFVar* idxOperandVar = gep->getOffsetVarAndGepTypePairVec()[i].first;
317
+ const SVFType* idxOperandType = gep->getOffsetVarAndGepTypePairVec()[i].second;
318
+
319
+ // Calculate the byte offset for array or pointer types
320
+ if (SVFUtil::isa<SVFArrayType>(idxOperandType) || SVFUtil::isa<SVFPointerType>(idxOperandType))
321
+ {
322
+ u32_t elemByteSize = 1;
323
+ if (const SVFArrayType* arrOperandType = SVFUtil::dyn_cast<SVFArrayType>(idxOperandType))
324
+ elemByteSize = arrOperandType->getTypeOfElement()->getByteSize();
325
+ else if (SVFUtil::isa<SVFPointerType>(idxOperandType))
326
+ elemByteSize = gep->getAccessPath().gepSrcPointeeType()->getByteSize();
327
+ else
328
+ assert(false && "idxOperandType must be ArrType or PtrType");
329
+
330
+ if (const SVFConstantInt* op = SVFUtil::dyn_cast<SVFConstantInt>(idxOperandVar->getValue()))
331
+ {
332
+ // Calculate the lower bound (lb) of the interval value
333
+ s64_t lb = (double)Options::MaxFieldLimit() / elemByteSize >= op->getSExtValue()
334
+ ? op->getSExtValue() * elemByteSize
335
+ : Options::MaxFieldLimit();
336
+ res = res + IntervalValue(lb, lb);
337
+ }
338
+ else
339
+ {
340
+ u32_t idx = PAG::getPAG()->getValueNode(idxOperandVar->getValue());
341
+ IntervalValue idxVal = (*this)[idx].getInterval();
342
+
343
+ if (idxVal.isBottom())
344
+ res = res + IntervalValue(0, 0);
345
+ else
346
+ {
347
+ // Ensure the bounds are non-negative and within the field limit
348
+ s64_t ub = (idxVal.ub().getIntNumeral() < 0) ? 0
349
+ : (double)Options::MaxFieldLimit() / elemByteSize >= idxVal.ub().getIntNumeral()
350
+ ? elemByteSize * idxVal.ub().getIntNumeral()
351
+ : Options::MaxFieldLimit();
352
+ s64_t lb = (idxVal.lb().getIntNumeral() < 0) ? 0
353
+ : (double)Options::MaxFieldLimit() / elemByteSize >= idxVal.lb().getIntNumeral()
354
+ ? elemByteSize * idxVal.lb().getIntNumeral()
355
+ : Options::MaxFieldLimit();
356
+ res = res + IntervalValue(lb, ub);
357
+ }
358
+ }
359
+ }
360
+ // Process struct subtypes by calculating the byte offset from the beginning to the field of the struct
361
+ else if (const SVFStructType* structOperandType = SVFUtil::dyn_cast<SVFStructType>(idxOperandType))
362
+ {
363
+ res = res + IntervalValue(gep->getAccessPath().getStructFieldOffset(idxOperandVar, structOperandType));
364
+ }
365
+ else
366
+ {
367
+ assert(false && "gep type pair only support arr/ptr/struct");
368
+ }
369
+ }
370
+ return res; // Return the resulting byte offset as an IntervalValue.
201
371
  }
202
372
 
203
- void AbstractState::printTable(const VarToAbsValMap&table, std::ostream &oss) const
373
+ AbstractValue AbstractState::loadValue(NodeID varId)
204
374
  {
205
- oss.flags(std::ios::left);
206
- std::set<NodeID> ordered;
207
- for (const auto &item: table)
375
+ AbstractValue res;
376
+ for (auto addr : (*this)[varId].getAddrs())
208
377
  {
209
- ordered.insert(item.first);
378
+ res.join_with(load(addr)); // q = *p
210
379
  }
211
- for (const auto &item: ordered)
380
+ return res;
381
+ }
382
+ // storeValue
383
+ void AbstractState::storeValue(NodeID varId, AbstractValue val)
384
+ {
385
+ for (auto addr : (*this)[varId].getAddrs())
212
386
  {
213
- oss << "Var" << std::to_string(item);
214
- oss << "\t Value: " << table.at(item).toString() << "\n";
387
+ store(addr, val); // *p = q
215
388
  }
216
389
  }
390
+
391
+ void AbstractState::printAbstractState() const
392
+ {
393
+ SVFUtil::outs() << "-----------Var and Value-----------\n";
394
+ u32_t fieldWidth = 20;
395
+ SVFUtil::outs().flags(std::ios::left);
396
+ std::vector<std::pair<u32_t, AbstractValue>> varToAbsValVec(_varToAbsVal.begin(), _varToAbsVal.end());
397
+ std::sort(varToAbsValVec.begin(), varToAbsValVec.end(), [](const auto &a, const auto &b)
398
+ {
399
+ return a.first < b.first;
400
+ });
401
+ for (const auto &item: varToAbsValVec)
402
+ {
403
+ SVFUtil::outs() << std::left << std::setw(fieldWidth) << ("Var" + std::to_string(item.first));
404
+ if (item.second.isInterval())
405
+ {
406
+ SVFUtil::outs() << " Value: " << item.second.getInterval().toString() << "\n";
407
+ }
408
+ else if (item.second.isAddr())
409
+ {
410
+ SVFUtil::outs() << " Value: {";
411
+ u32_t i = 0;
412
+ for (const auto& addr: item.second.getAddrs())
413
+ {
414
+ ++i;
415
+ if (i < item.second.getAddrs().size())
416
+ {
417
+ SVFUtil::outs() << "0x" << std::hex << addr << ", ";
418
+ }
419
+ else
420
+ {
421
+ SVFUtil::outs() << "0x" << std::hex << addr;
422
+ }
423
+ }
424
+ SVFUtil::outs() << "}\n";
425
+ }
426
+ else
427
+ {
428
+ SVFUtil::outs() << " Value: ⊥\n";
429
+ }
430
+ }
431
+
432
+ std::vector<std::pair<u32_t, AbstractValue>> addrToAbsValVec(_addrToAbsVal.begin(), _addrToAbsVal.end());
433
+ std::sort(addrToAbsValVec.begin(), addrToAbsValVec.end(), [](const auto &a, const auto &b)
434
+ {
435
+ return a.first < b.first;
436
+ });
437
+
438
+ for (const auto& item: addrToAbsValVec)
439
+ {
440
+ std::ostringstream oss;
441
+ oss << "0x" << std::hex << AbstractState::getVirtualMemAddress(item.first);
442
+ SVFUtil::outs() << std::left << std::setw(fieldWidth) << oss.str();
443
+ if (item.second.isInterval())
444
+ {
445
+ SVFUtil::outs() << " Value: " << item.second.getInterval().toString() << "\n";
446
+ }
447
+ else if (item.second.isAddr())
448
+ {
449
+ SVFUtil::outs() << " Value: {";
450
+ u32_t i = 0;
451
+ for (const auto& addr: item.second.getAddrs())
452
+ {
453
+ ++i;
454
+ if (i < item.second.getAddrs().size())
455
+ {
456
+ SVFUtil::outs() << "0x" << std::hex << addr << ", ";
457
+ }
458
+ else
459
+ {
460
+ SVFUtil::outs() << "0x" << std::hex << addr;
461
+ }
462
+ }
463
+ SVFUtil::outs() << "}\n";
464
+ }
465
+ else
466
+ {
467
+ SVFUtil::outs() << " Value: ⊥\n";
468
+ }
469
+ }
470
+ SVFUtil::outs() << "-----------------------------------------\n";
471
+ }