Static Value-Flow Analysis
Loading...
Searching...
No Matches
AccessPath.cpp
Go to the documentation of this file.
1//===- AccessPath.cpp -- Location set for modeling abstract memory object----//
2//
3// SVF: Static Value-Flow Analysis
4//
5// Copyright (C) <2013-> <Yulei Sui>
6//
7
8// This program is free software: you can redistribute it and/or modify
9// it under the terms of the GNU Affero General Public License as published by
10// the Free Software Foundation, either version 3 of the License, or
11// (at your option) any later version.
12
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU Affero General Public License for more details.
17
18// You should have received a copy of the GNU Affero General Public License
19// along with this program. If not, see <http://www.gnu.org/licenses/>.
20//
21//===----------------------------------------------------------------------===//
22
23/*
24 * @file: AccessPath.cpp
25 * @author: yesen
26 * @date: 26 Sep 2014
27 *
28 * LICENSE
29 *
30 */
31
32#include "Util/Options.h"
34#include "Util/SVFUtil.h"
35
36using namespace SVF;
37using namespace SVFUtil;
38
43{
44 idxOperandPairs.emplace_back(var, gepIterType);
45 return true;
46}
47
50{
51 for(auto it : idxOperandPairs)
52 {
53 if(SVFUtil::isa<ConstantIntValVar>(it.first) == false)
54 return false;
55 }
56 return true;
57}
58
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
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}
91
92
95// e.g. idxOperandVar: i32 2 idxOperandType: %struct.Student = type { i32, [i8 x 12], i32 }
96// we accumulate field 0 (i32) byte size (4 Bytes), and field 1 ([i8x12]) byte size (12 Bytes)
97// then the return byte offset is 16 Bytes.
99{
101 if (const ConstantIntValVar *op = SVFUtil::dyn_cast<ConstantIntValVar>(idxOperandVar))
102 {
103 for (u32_t structField = 0; structField < (u32_t) op->getSExtValue(); ++structField)
104 {
105 u32_t flattenIdx = idxOperandType->getTypeInfo()->getFlattenedFieldIdxVec()[structField];
106 structByteOffset += idxOperandType->getTypeInfo()->getOriginalElemType(flattenIdx)->getByteSize();
107 }
108 return structByteOffset;
109 }
110 else
111 {
112 assert(false && "struct type can only pair with constant idx");
113 abort();
114 }
115}
116
125{
126 assert(isConstantOffset() && "not a constant offset");
127
129 for(int i = idxOperandPairs.size() - 1; i >= 0; i--)
130 {
133 // (2) %arrayidx = getelementptr inbounds [10 x i8], [10 x i8]* %b, i64 0, i64 8
134 const SVFVar* var = idxOperandPairs[i].first;
141 const SVFType* type = idxOperandPairs[i].second;
145 assert(type && "this GepStmt comes from ExternalAPI cannot call this api");
146 const SVFType* type2 = type;
147 if (const SVFArrayType* arrType = SVFUtil::dyn_cast<SVFArrayType>(type))
148 {
150 type2 = arrType->getTypeOfElement();
151 }
152 else if (SVFUtil::isa<SVFPointerType>(type))
153 {
157 }
158
159 const ConstantIntValVar* op = SVFUtil::dyn_cast<ConstantIntValVar>(var);
160 if (const SVFStructType* structType = SVFUtil::dyn_cast<SVFStructType>(type))
161 {
166 for (u32_t structField = 0; structField < (u32_t)op->getSExtValue(); ++structField)
167 {
168 u32_t flattenIdx = structType->getTypeInfo()->getFlattenedFieldIdxVec()[structField];
169 type2 = structType->getTypeInfo()->getOriginalElemType(flattenIdx);
170 totalConstOffset += type2->getByteSize();
171 }
172 }
173 else
174 {
177 totalConstOffset += op->getSExtValue() * type2->getByteSize();
178 }
179 }
181 return totalConstOffset;
182}
183
191
193// struct inner{ int rollNumber; float percentage;};
194// struct Student { struct inner rollNumber; char studentName[10][3];}
195// char x = studentRecord[1].studentName[3][2];
196
213{
214
215 assert(isConstantOffset() && "not a constant offset");
216
218 //After the model-const and model-array options are turned on,
219 // the gepstmt offset generated by the array on the global
220 // node will be saved in getConstantStructFldIdx
221 if (idxOperandPairs.size() == 0)
223 for(int i = idxOperandPairs.size() - 1; i >= 0; i--)
224 {
225 const SVFVar* var = idxOperandPairs[i].first;
226 const SVFType* type = idxOperandPairs[i].second;
227 assert(SVFUtil::isa<ConstantIntValVar>(var) && "not a constant offset?");
228 s64_t constOffset = SVFUtil::dyn_cast<ConstantIntValVar>(var)->getSExtValue();
229
230 if(type==nullptr)
231 {
233 continue;
234 }
235
236 if(SVFUtil::isa<SVFPointerType>(type))
238 else
239 {
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
258 offset);
260 }
261 }
262 }
263 return totalConstOffset;
264}
274
276{
277 assert(gepPointeeType == rhs.gepSrcPointeeType() && "source element type not match");
278 AccessPath ap(rhs);
280 for (auto &p : ap.getIdxOperandPairVec())
281 ap.addOffsetVarAndGepTypePair(p.first, p.second);
282
283 return ap;
284}
285
287{
288 if (fldIdx != rhs.fldIdx)
289 return (fldIdx < rhs.fldIdx);
290 else
291 {
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}
309
311{
312 NodeBS lhsLocations = LHS.computeAllLocations();
313 NodeBS rhsLocations = RHS.computeAllLocations();
314 if (lhsLocations.intersects(rhsLocations))
315 {
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}
330
332std::string AccessPath::dump() const
333{
334 std::string str;
335 std::stringstream rawstr(str);
336
337 rawstr << "AccessPath\tField_Index: " << getConstantStructFldIdx();
338 rawstr << ",\tNum-Stride: {";
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}
cJSON * p
Definition cJSON.cpp:2559
newitem type
Definition cJSON.cpp:2739
buffer offset
Definition cJSON.cpp:1113
std::vector< IdxOperandPair > IdxOperandPairs
Definition AccessPath.h:65
const SVFType * gepPointeeType
Definition AccessPath.h:177
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 ty...
bool addOffsetVarAndGepTypePair(const SVFVar *var, const SVFType *gepIterType)
u32_t getElementNum(const SVFType *type) const
Return element number of a type.
bool isConstantOffset() const
Return TRUE if this is a constant location set.
APOffset computeConstantByteOffset() const
std::string dump() const
Dump location set.
IdxOperandPairs idxOperandPairs
a vector of actual offset in the form of <SVF Var, iterator type>
Definition AccessPath.h:176
APOffset getConstantStructFldIdx() const
Get methods.
Definition AccessPath.h:100
AccessPath operator+(const AccessPath &rhs) const
Overload operators.
const SVFType * gepSrcPointeeType() const
Definition AccessPath.h:112
NodeBS computeAllLocations() const
Compute all possible locations according to offset and number-stride pairs.
LSRelation checkRelation(const AccessPath &LHS, const AccessPath &RHS)
Check relations of two location sets.
APOffset fldIdx
Accumulated Constant Offsets.
Definition AccessPath.h:175
const IdxOperandPairs & getIdxOperandPairVec() const
Definition AccessPath.h:108
bool operator<(const AccessPath &rhs) const
APOffset computeConstantOffset() const
For example,.
static const Option< u32_t > MaxFieldLimit
Maximum number of field derivations for an object.
Definition Options.h:38
std::string toString() const
void set(unsigned Idx)
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.
u32_t getNumOfFlattenElements(const SVFType *T)
Number of flattened elements of an array or struct.
std::ostream & errs()
Overwrite llvm::errs()
Definition SVFUtil.h:56
std::ostream & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:50
for isBitcode
Definition BasicTypes.h:68
s64_t APOffset
Definition GeneralType.h:60
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74
unsigned u32_t
Definition GeneralType.h:46
signed long long s64_t
Definition GeneralType.h:49