Static Value-Flow Analysis
Public Types | Public Member Functions | Private Member Functions | Private Attributes | Friends | List of all members
SVF::AccessPath Class Reference

#include <AccessPath.h>

Public Types

enum  LSRelation {
  NonOverlap , Overlap , Subset , Superset ,
  Same
}
 
typedef std::pair< const SVFVar *, const SVFType * > IdxOperandPair
 
typedef std::vector< IdxOperandPairIdxOperandPairs
 

Public Member Functions

 AccessPath (APOffset o=0, const SVFType *srcTy=nullptr)
 Constructor. More...
 
 AccessPath (const AccessPath &ap)
 Copy Constructor. More...
 
 ~AccessPath ()
 
AccessPath operator+ (const AccessPath &rhs) const
 Overload operators. More...
 
bool operator< (const AccessPath &rhs) const
 
const AccessPathoperator= (const AccessPath &rhs)
 
bool operator== (const AccessPath &rhs) const
 
APOffset getConstantStructFldIdx () const
 Get methods. More...
 
void setFldIdx (APOffset idx)
 
const IdxOperandPairsgetIdxOperandPairVec () const
 
const SVFTypegepSrcPointeeType () const
 
APOffset computeConstantByteOffset () const
 
APOffset computeConstantOffset () const
 For example,. More...
 
u32_t getElementNum (const SVFType *type) const
 Return element number of a type. More...
 
bool addOffsetVarAndGepTypePair (const SVFVar *var, const SVFType *gepIterType)
 
bool isConstantOffset () const
 Return TRUE if this is a constant location set. More...
 
bool intersects (const AccessPath &RHS) const
 Return TRUE if we share any location in common with RHS. More...
 
u32_t getStructFieldOffset (const SVFVar *idxOperandVar, const SVFStructType *idxOperandType) const
 Return byte offset from the beginning of the structure to the field where it is located for struct type. More...
 
std::string dump () const
 Dump location set. More...
 

Private Member Functions

LSRelation checkRelation (const AccessPath &LHS, const AccessPath &RHS)
 Check relations of two location sets. More...
 
NodeBS computeAllLocations () const
 Compute all possible locations according to offset and number-stride pairs. More...
 

Private Attributes

APOffset fldIdx
 Accumulated Constant Offsets. More...
 
IdxOperandPairs idxOperandPairs
 a vector of actual offset in the form of <SVF Var, iterator type> More...
 
const SVFTypegepPointeeType
 

Friends

class SymbolTableInfo
 
class SVFIRWriter
 
class SVFIRReader
 

Detailed Description

Definition at line 52 of file AccessPath.h.

Member Typedef Documentation

◆ IdxOperandPair

typedef std::pair<const SVFVar*, const SVFType*> SVF::AccessPath::IdxOperandPair

Definition at line 64 of file AccessPath.h.

◆ IdxOperandPairs

Definition at line 65 of file AccessPath.h.

Member Enumeration Documentation

◆ LSRelation

Enumerator
NonOverlap 
Overlap 
Subset 
Superset 
Same 

Definition at line 59 of file AccessPath.h.

Constructor & Destructor Documentation

◆ AccessPath() [1/2]

SVF::AccessPath::AccessPath ( APOffset  o = 0,
const SVFType srcTy = nullptr 
)
inline

Constructor.

Definition at line 68 of file AccessPath.h.

68 : fldIdx(o), gepPointeeType(srcTy) {}
const SVFType * gepPointeeType
Definition: AccessPath.h:177
APOffset fldIdx
Accumulated Constant Offsets.
Definition: AccessPath.h:175

◆ AccessPath() [2/2]

SVF::AccessPath::AccessPath ( const AccessPath ap)
inline

Copy Constructor.

Definition at line 71 of file AccessPath.h.

72  : fldIdx(ap.fldIdx),
73  idxOperandPairs(ap.getIdxOperandPairVec()),
74  gepPointeeType(ap.gepSrcPointeeType())
75  {
76  }
IdxOperandPairs idxOperandPairs
a vector of actual offset in the form of <SVF Var, iterator type>
Definition: AccessPath.h:176

◆ ~AccessPath()

SVF::AccessPath::~AccessPath ( )
inline

Definition at line 78 of file AccessPath.h.

78 {}

Member Function Documentation

◆ addOffsetVarAndGepTypePair()

bool AccessPath::addOffsetVarAndGepTypePair ( const SVFVar var,
const SVFType gepIterType 
)

Add offset value to vector offsetVarAndGepTypePairs

Definition at line 42 of file AccessPath.cpp.

43 {
44  idxOperandPairs.emplace_back(var, gepIterType);
45  return true;
46 }

◆ checkRelation()

SVF::AccessPath::LSRelation AccessPath::checkRelation ( const AccessPath LHS,
const AccessPath RHS 
)
private

Check relations of two location sets.

Definition at line 310 of file AccessPath.cpp.

311 {
312  NodeBS lhsLocations = LHS.computeAllLocations();
313  NodeBS rhsLocations = RHS.computeAllLocations();
314  if (lhsLocations.intersects(rhsLocations))
315  {
316  if (lhsLocations == rhsLocations)
317  return Same;
318  else if (lhsLocations.contains(rhsLocations))
319  return Superset;
320  else if (rhsLocations.contains(lhsLocations))
321  return Subset;
322  else
323  return Overlap;
324  }
325  else
326  {
327  return NonOverlap;
328  }
329 }
NodeBS computeAllLocations() const
Compute all possible locations according to offset and number-stride pairs.
Definition: AccessPath.cpp:268
bool intersects(const SparseBitVector< ElementSize > *RHS) const
bool contains(const SparseBitVector< ElementSize > &RHS) const

◆ computeAllLocations()

NodeBS AccessPath::computeAllLocations ( ) const
private

Compute all possible locations according to offset and number-stride pairs.

Compute all possible locations according to offset and number-stride pairs.

Definition at line 268 of file AccessPath.cpp.

269 {
270  NodeBS result;
271  result.set(getConstantStructFldIdx());
272  return result;
273 }
APOffset getConstantStructFldIdx() const
Get methods.
Definition: AccessPath.h:100
void set(unsigned Idx)

◆ computeConstantByteOffset()

APOffset AccessPath::computeConstantByteOffset ( ) const

Computes the total constant byte offset of an access path. This function iterates over the offset-variable-type pairs in reverse order, accumulating the total byte offset for constant offsets. For each pair, it retrieves the corresponding SVFValue and determines the type of offset (whether it's an array, pointer, or structure). If the offset corresponds to a structure, it further resolves the actual element type based on the offset value. It then multiplies the offset value by the size of the type to compute the byte offset. This is used to handle composite types where offsets are derived from the type's internal structure, such as arrays or structures with fields of various types and sizes. The function asserts that the access path must have a constant offset, and it is intended to be used when the offset is known to be constant at compile time.

Returns
APOffset representing the computed total constant byte offset. e.g. GepStmt* gep = [i32*4], 2 APOffset byteOffset = gep->accumulateConstantByteOffset(); byteOffset should be 8 since i32 is 4 bytes and index is 2.

Return accumulated constant offset

"value" is the offset variable (must be a constant) "type" is the location where we want to compute offset Given a vector and elem byte size: [(value1,type1), (value2,type2), (value3,type3)], bytesize totalConstByteOffset = ByteOffset(value1,type1) * ByteOffset(value2,type2) + ByteOffset(value3,type3) For a pointer type (e.g., t1 is PointerType), we will retrieve the pointee type and times the offset, i.e., getElementNum(t1) X off1

For example, there is struct DEST{int a, char b[10], int c[5]} (1) c = getelementptr inbounds struct.DEST, struct.DEST* arr, i32 0, i32 2

for (1) offsetVarAndGepTypePairs.size() = 2 i = 0, type: struct.DEST*, PtrType, op = 0 i = 1, type: struct.DEST, StructType, op = 2 for (2) offsetVarAndGepTypePairs.size() = 2 i = 0, type: [10 x i8]*, PtrType, op = 0 i = 1, type: [10 x i8], ArrType, op = 8

if offsetVarAndGepTypePairs[i].second is nullptr, it means GepStmt comes from external API, this GepStmt is assigned in SVFIRExtAPI.cpp at SVFIRBuilder::getBaseTypeAndFlattenedFields ls.addOffsetVarAndGepTypePair()

for (2) i = 1, arrType: [10 x i8], type2 = i8

for (1) i = 0, ptrType: struct.DEST*, type2: struct.DEST for (2) i = 0, ptrType: [10 x i8]*, type2 = [10 x i8]

for (1) structType: struct.DEST structField = 0, flattenIdx = 0, type2: int structField = 1, flattenIdx = 1, type2: char[10] structField = 2, flattenIdx = 11, type2: int[5]

for (2) i = 0, op: 0, type: [10 x i8]*(Ptr), type2: [10 x i8](Arr) i = 1, op: 8, type: [10 x i8](Arr), type2: i8

Definition at line 125 of file AccessPath.cpp.

126 {
127  assert(isConstantOffset() && "not a constant offset");
128 
129  APOffset totalConstOffset = 0;
130  for(int i = idxOperandPairs.size() - 1; i >= 0; i--)
131  {
134  // (2) %arrayidx = getelementptr inbounds [10 x i8], [10 x i8]* %b, i64 0, i64 8
135  const SVFValue* value = idxOperandPairs[i].first->getValue();
142  const SVFType* type = idxOperandPairs[i].second;
146  assert(type && "this GepStmt comes from ExternalAPI cannot call this api");
147  const SVFType* type2 = type;
148  if (const SVFArrayType* arrType = SVFUtil::dyn_cast<SVFArrayType>(type))
149  {
151  type2 = arrType->getTypeOfElement();
152  }
153  else if (SVFUtil::isa<SVFPointerType>(type))
154  {
157  type2 = gepSrcPointeeType();
158  }
159 
160  const SVFConstantInt* op = SVFUtil::dyn_cast<SVFConstantInt>(value);
161  if (const SVFStructType* structType = SVFUtil::dyn_cast<SVFStructType>(type))
162  {
167  for (u32_t structField = 0; structField < (u32_t)op->getSExtValue(); ++structField)
168  {
169  u32_t flattenIdx = structType->getTypeInfo()->getFlattenedFieldIdxVec()[structField];
170  type2 = structType->getTypeInfo()->getOriginalElemType(flattenIdx);
171  totalConstOffset += type2->getByteSize();
172  }
173  }
174  else
175  {
178  totalConstOffset += op->getSExtValue() * type2->getByteSize();
179  }
180  }
181  totalConstOffset = Options::MaxFieldLimit() > totalConstOffset? totalConstOffset: Options::MaxFieldLimit();
182  return totalConstOffset;
183 }
unsigned u32_t
Definition: CommandLine.h:18
newitem type
Definition: cJSON.cpp:2739
bool isConstantOffset() const
Return TRUE if this is a constant location set.
Definition: AccessPath.cpp:49
const SVFType * gepSrcPointeeType() const
Definition: AccessPath.h:112
static const Option< u32_t > MaxFieldLimit
Maximum number of field derivations for an object.
Definition: Options.h:38
s64_t getSExtValue() const
Definition: SVFValue.h:959
StInfo * getTypeInfo()
Definition: SVFType.h:230
u32_t getByteSize() const
Definition: SVFType.h:244
const SVFType * getOriginalElemType(u32_t fldIdx) const
Definition: SVFValue.cpp:20
s64_t APOffset
Definition: GeneralType.h:60
unsigned u32_t
Definition: GeneralType.h:46

◆ computeConstantOffset()

APOffset AccessPath::computeConstantOffset ( ) const

For example,.

Return accumulated constant offset given OffsetVarVec compard to computeConstantByteOffset, it is field offset rather than byte offset e.g. GepStmt* gep = [i32*4], 2 APOffset byteOffset = gep->computeConstantOffset(); byteOffset should be 2 since it is field offset.

Return accumulated constant offset

"value" is the offset variable (must be a constant) "type" is the location where we want to compute offset Given a vector: [(value1,type1), (value2,type2), (value3,type3)] totalConstOffset = flattenOffset(value1,type1) * flattenOffset(value2,type2) + flattenOffset(value3,type3) For a pointer type (e.g., t1 is PointerType), we will retrieve the pointee type and times the offset, i.e., getElementNum(t1) X off1 %5 = getelementptr inbounds struct.Student, struct.Student* %4, i64 1 value1: i64 1 type1: struct.Student* computeConstantOffset = 32 %6 = getelementptr inbounds struct.Student, struct.Student* %5, i32 0, i32 1 value1: i32 0 type1: struct.Student* value2: i32 1 type2: struct.Student = type { struct.inner, [10 x [3 x i8]] } computeConstantOffset = 2 %7 = getelementptr inbounds [10 x [3 x i8]], [10 x [3 x i8]]* %6, i64 0, i64 3 value1: i64 0 type1: [10 x [3 x i8]]* value2: i64 3 type2: [10 x [3 x i8]] computeConstantOffset = 9 %8 = getelementptr inbounds [3 x i8], [3 x i8]* %7, i64 0, i64 2 value1: i64 0 type1: [3 x i8]* value2: i64 2 type2: [3 x i8] computeConstantOffset = 2

Definition at line 213 of file AccessPath.cpp.

214 {
215 
216  assert(isConstantOffset() && "not a constant offset");
217 
218  APOffset totalConstOffset = 0;
219  //After the model-const and model-array options are turned on,
220  // the gepstmt offset generated by the array on the global
221  // node will be saved in getConstantStructFldIdx
222  if (idxOperandPairs.size() == 0)
223  return getConstantStructFldIdx();
224  for(int i = idxOperandPairs.size() - 1; i >= 0; i--)
225  {
226  const SVFValue* value = idxOperandPairs[i].first->getValue();
227  const SVFType* type = idxOperandPairs[i].second;
228  const SVFConstantInt* op = SVFUtil::dyn_cast<SVFConstantInt>(value);
229  assert(op && "not a constant offset?");
230  if(type==nullptr)
231  {
232  totalConstOffset += op->getSExtValue();
233  continue;
234  }
235 
236  if(SVFUtil::isa<SVFPointerType>(type))
237  totalConstOffset += op->getSExtValue() * getElementNum(gepPointeeType);
238  else
239  {
240  APOffset offset = op->getSExtValue();
241  if (offset >= 0)
242  {
243  const std::vector<u32_t>& so = SymbolTableInfo::SymbolInfo()->getTypeInfo(type)->getFlattenedElemIdxVec();
244  // if offset is larger than the size of getFlattenedElemIdxVec (overflow)
245  // set offset the last index of getFlattenedElemIdxVec to avoid assertion
246  if (offset >= (APOffset)so.size())
247  {
248  SVFUtil::errs() << "It is an overflow access, hence it is the last idx\n";
249  offset = so.size() - 1;
250  }
251  else
252  {
253 
254  }
255 
256  u32_t flattenOffset =
258  offset);
259  totalConstOffset += flattenOffset;
260  }
261  }
262  }
263  return totalConstOffset;
264 }
buffer offset
Definition: cJSON.cpp:1113
u32_t getElementNum(const SVFType *type) const
Return element number of a type.
Definition: AccessPath.cpp:63
std::vector< u32_t > & getFlattenedElemIdxVec()
Definition: SVFType.h:98
u32_t getFlattenedElemIdx(const SVFType *T, u32_t origId)
Flattened element idx of an array or struct by considering stride.
static SymbolTableInfo * SymbolInfo()
Singleton design here to make sure we only have one instance during any analysis.
const StInfo * getTypeInfo(const SVFType *T) const
Get struct info.
std::ostream & errs()
Overwrite llvm::errs()
Definition: SVFUtil.h:56

◆ dump()

std::string AccessPath::dump ( ) const

Dump location set.

Definition at line 332 of file AccessPath.cpp.

333 {
334  std::string str;
335  std::stringstream rawstr(str);
336 
337  rawstr << "AccessPath\tField_Index: " << getConstantStructFldIdx();
338  rawstr << ",\tNum-Stride: {";
339  const IdxOperandPairs& vec = getIdxOperandPairVec();
340  IdxOperandPairs::const_iterator it = vec.begin();
341  IdxOperandPairs::const_iterator eit = vec.end();
342  for (; it != eit; ++it)
343  {
344  const SVFType* ty = it->second;
345  rawstr << " (Svf var: " << it->first->toString() << ", Iter type: " << *ty << ")";
346  }
347  rawstr << " }\n";
348  return rawstr.str();
349 }
const char *const string
Definition: cJSON.h:172
std::vector< IdxOperandPair > IdxOperandPairs
Definition: AccessPath.h:65
const IdxOperandPairs & getIdxOperandPairVec() const
Definition: AccessPath.h:108
std::string toString() const

◆ gepSrcPointeeType()

const SVFType* SVF::AccessPath::gepSrcPointeeType ( ) const
inline

Definition at line 112 of file AccessPath.h.

113  {
114  return gepPointeeType;
115  }

◆ getConstantStructFldIdx()

APOffset SVF::AccessPath::getConstantStructFldIdx ( ) const
inline

Get methods.

Definition at line 100 of file AccessPath.h.

101  {
102  return fldIdx;
103  }

◆ getElementNum()

u32_t AccessPath::getElementNum ( const SVFType type) const

Return element number of a type.

Return element number of a type (1) StructType or Array, return flattened number elements. (2) Pointer type, return max field limit (3) Non-pointer SingleValueType or Function Type, return 1

Definition at line 63 of file AccessPath.cpp.

64 {
65  if (SVFUtil::isa<SVFArrayType, SVFStructType>(type))
66  {
68  }
69  else if (type->isPointerTy())
70  {
71  // if type is a pointer, should be like:
72  // %2 = getelementptr inbounds i32*, i32** %1, ...
73  // where gepSrcPointee is of pointer type (i32*).
74  // this can be transformed to:
75  // %2 = getelementptr inbounds [N x i32], [N x i32]* %1, ...
76  // However, we do not know N without context information. int** implies non-contiguous blocks of memory
77  // In this case, we conservatively return max field limit
78  return Options::MaxFieldLimit();
79  }
80  else if (type->isSingleValueType() || SVFUtil::isa<SVFFunctionType>(type))
81  {
82  return 1;
83  }
84  else
85  {
86  SVFUtil::outs() << "GepIter Type" << *type << "\n";
87  assert(false && "What other types for this gep?");
88  abort();
89  }
90 }
u32_t getNumOfFlattenElements(const SVFType *T)
Number of flattened elements of an array or struct.
std::ostream & outs()
Overwrite llvm::outs()
Definition: SVFUtil.h:50

◆ getIdxOperandPairVec()

const IdxOperandPairs& SVF::AccessPath::getIdxOperandPairVec ( ) const
inline

Definition at line 108 of file AccessPath.h.

109  {
110  return idxOperandPairs;
111  }

◆ getStructFieldOffset()

u32_t AccessPath::getStructFieldOffset ( const SVFVar idxOperandVar,
const SVFStructType idxOperandType 
) const

Return byte offset from the beginning of the structure to the field where it is located for struct type.

Return byte offset from the beginning of the structure to the field where it is located for struct type

Definition at line 98 of file AccessPath.cpp.

99 {
100  const SVFValue* idxValue = idxOperandVar->getValue();
101  u32_t structByteOffset = 0;
102  if (const SVFConstantInt *op = SVFUtil::dyn_cast<SVFConstantInt>(idxValue))
103  {
104  for (u32_t structField = 0; structField < (u32_t) op->getSExtValue(); ++structField)
105  {
106  u32_t flattenIdx = idxOperandType->getTypeInfo()->getFlattenedFieldIdxVec()[structField];
107  structByteOffset += idxOperandType->getTypeInfo()->getOriginalElemType(flattenIdx)->getByteSize();
108  }
109  return structByteOffset;
110  }
111  else
112  {
113  assert(false && "struct type can only pair with constant idx");
114  abort();
115  }
116 }
const SVFValue * getValue() const
Get/has methods of the components.
Definition: SVFVariables.h:83
std::vector< u32_t > & getFlattenedFieldIdxVec()
Definition: SVFType.h:94

◆ intersects()

bool SVF::AccessPath::intersects ( const AccessPath RHS) const
inline

Return TRUE if we share any location in common with RHS.

Definition at line 156 of file AccessPath.h.

157  {
158  return computeAllLocations().intersects(RHS.computeAllLocations());
159  }

◆ isConstantOffset()

bool AccessPath::isConstantOffset ( ) const

Return TRUE if this is a constant location set.

Return true if all offset values are constants.

Definition at line 49 of file AccessPath.cpp.

50 {
51  for(auto it : idxOperandPairs)
52  {
53  if(SVFUtil::isa<SVFConstantInt>(it.first->getValue()) == false)
54  return false;
55  }
56  return true;
57 }

◆ operator+()

AccessPath AccessPath::operator+ ( const AccessPath rhs) const

Overload operators.

Definition at line 275 of file AccessPath.cpp.

276 {
277  assert(gepPointeeType == rhs.gepSrcPointeeType() && "source element type not match");
278  AccessPath ap(rhs);
279  ap.fldIdx += getConstantStructFldIdx();
280  for (auto &p : ap.getIdxOperandPairVec())
281  ap.addOffsetVarAndGepTypePair(p.first, p.second);
282 
283  return ap;
284 }
cJSON * p
Definition: cJSON.cpp:2559

◆ operator<()

bool AccessPath::operator< ( const AccessPath rhs) const

Definition at line 286 of file AccessPath.cpp.

287 {
288  if (fldIdx != rhs.fldIdx)
289  return (fldIdx < rhs.fldIdx);
290  else
291  {
292  const IdxOperandPairs& pairVec = getIdxOperandPairVec();
293  const IdxOperandPairs& rhsPairVec = rhs.getIdxOperandPairVec();
294  if (pairVec.size() != rhsPairVec.size())
295  return (pairVec.size() < rhsPairVec.size());
296  else
297  {
298  IdxOperandPairs::const_iterator it = pairVec.begin();
299  IdxOperandPairs::const_iterator rhsIt = rhsPairVec.begin();
300  for (; it != pairVec.end() && rhsIt != rhsPairVec.end(); ++it, ++rhsIt)
301  {
302  return (*it) < (*rhsIt);
303  }
304 
305  return false;
306  }
307  }
308 }

◆ operator=()

const AccessPath& SVF::AccessPath::operator= ( const AccessPath rhs)
inline

Definition at line 84 of file AccessPath.h.

85  {
86  fldIdx = rhs.fldIdx;
87  idxOperandPairs = rhs.getIdxOperandPairVec();
88  gepPointeeType = rhs.gepPointeeType;
89  return *this;
90  }

◆ operator==()

bool SVF::AccessPath::operator== ( const AccessPath rhs) const
inline

Definition at line 91 of file AccessPath.h.

92  {
93  return this->fldIdx == rhs.fldIdx &&
94  this->idxOperandPairs == rhs.idxOperandPairs && this->gepPointeeType == rhs.gepPointeeType;
95  }

◆ setFldIdx()

void SVF::AccessPath::setFldIdx ( APOffset  idx)
inline

Definition at line 104 of file AccessPath.h.

105  {
106  fldIdx = idx;
107  }

Friends And Related Function Documentation

◆ SVFIRReader

friend class SVFIRReader
friend

Definition at line 56 of file AccessPath.h.

◆ SVFIRWriter

friend class SVFIRWriter
friend

Definition at line 55 of file AccessPath.h.

◆ SymbolTableInfo

friend class SymbolTableInfo
friend

Definition at line 54 of file AccessPath.h.

Member Data Documentation

◆ fldIdx

APOffset SVF::AccessPath::fldIdx
private

Accumulated Constant Offsets.

Definition at line 175 of file AccessPath.h.

◆ gepPointeeType

const SVFType* SVF::AccessPath::gepPointeeType
private

Definition at line 177 of file AccessPath.h.

◆ idxOperandPairs

IdxOperandPairs SVF::AccessPath::idxOperandPairs
private

a vector of actual offset in the form of <SVF Var, iterator type>

Definition at line 176 of file AccessPath.h.


The documentation for this class was generated from the following files: