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
33#include "SVFIR/SVFIR.h"
34#include "SVFIR/SVFVariables.h"
35#include "Util/Options.h"
36#include "Util/SVFUtil.h"
37
38using namespace SVF;
39using namespace SVFUtil;
40
45{
46 idxOperandPairs.emplace_back(var, gepIterType);
47 return true;
48}
49
52{
53 for(auto it : idxOperandPairs)
54 {
55 if(SVFUtil::isa<ConstIntValVar>(it.first) == false)
56 return false;
57 }
58 return true;
59}
60
66{
67 if (SVFUtil::isa<SVFArrayType, SVFStructType>(type))
68 {
70 }
71 else if (type->isPointerTy())
72 {
73 // if type is a pointer, should be like:
74 // %2 = getelementptr inbounds i32*, i32** %1, ...
75 // where gepSrcPointee is of pointer type (i32*).
76 // this can be transformed to:
77 // %2 = getelementptr inbounds [N x i32], [N x i32]* %1, ...
78 // However, we do not know N without context information. int** implies non-contiguous blocks of memory
79 // In this case, we conservatively return max field limit
81 }
82 else if (type->isSingleValueType() || SVFUtil::isa<SVFFunctionType>(type))
83 {
84 return 1;
85 }
86 else
87 {
88 SVFUtil::outs() << "GepIter Type" << *type << "\n";
89 assert(false && "What other types for this gep?");
90 abort();
91 }
92}
93
94
97// e.g. idxOperandVar: i32 2 idxOperandType: %struct.Student = type { i32, [i8 x 12], i32 }
98// we accumulate field 0 (i32) byte size (4 Bytes), and field 1 ([i8x12]) byte size (12 Bytes)
99// then the return byte offset is 16 Bytes.
101{
103 if (const ConstIntValVar*op = SVFUtil::dyn_cast<ConstIntValVar>(idxOperandVar))
104 {
105 for (u32_t structField = 0; structField < (u32_t) op->getSExtValue(); ++structField)
106 {
107 u32_t flattenIdx = idxOperandType->getTypeInfo()->getFlattenedFieldIdxVec()[structField];
108 structByteOffset += idxOperandType->getTypeInfo()->getOriginalElemType(flattenIdx)->getByteSize();
109 }
110 return structByteOffset;
111 }
112 else
113 {
114 assert(false && "struct type can only pair with constant idx");
115 abort();
116 }
117}
118
127{
128 assert(isConstantOffset() && "not a constant offset");
129
131 for(int i = idxOperandPairs.size() - 1; i >= 0; i--)
132 {
135 // (2) %arrayidx = getelementptr inbounds [10 x i8], [10 x i8]* %b, i64 0, i64 8
136 const ValVar* var = idxOperandPairs[i].first;
143 const SVFType* type = idxOperandPairs[i].second;
147 assert(type && "this GepStmt comes from ExternalAPI cannot call this api");
148 const SVFType* type2 = type;
149 if (const SVFArrayType* arrType = SVFUtil::dyn_cast<SVFArrayType>(type))
150 {
152 type2 = arrType->getTypeOfElement();
153 }
154 else if (SVFUtil::isa<SVFPointerType>(type))
155 {
159 }
160
161 const ConstIntValVar* op = SVFUtil::dyn_cast<ConstIntValVar>(var);
162 if (const SVFStructType* structType = SVFUtil::dyn_cast<SVFStructType>(type))
163 {
168 for (u32_t structField = 0; structField < (u32_t)op->getSExtValue(); ++structField)
169 {
170 u32_t flattenIdx = structType->getTypeInfo()->getFlattenedFieldIdxVec()[structField];
171 type2 = structType->getTypeInfo()->getOriginalElemType(flattenIdx);
172 totalConstOffset += type2->getByteSize();
173 }
174 }
175 else
176 {
179 totalConstOffset += op->getSExtValue() * type2->getByteSize();
180 }
181 }
183 return totalConstOffset;
184}
185
193
195// struct inner{ int rollNumber; float percentage;};
196// struct Student { struct inner rollNumber; char studentName[10][3];}
197// char x = studentRecord[1].studentName[3][2];
198
215{
216
217 assert(isConstantOffset() && "not a constant offset");
218
220 //After the model-const and model-array options are turned on,
221 // the gepstmt offset generated by the array on the global
222 // node will be saved in getConstantStructFldIdx
223 if (idxOperandPairs.size() == 0)
225 for(int i = idxOperandPairs.size() - 1; i >= 0; i--)
226 {
227 const ValVar* var = idxOperandPairs[i].first;
228 const SVFType* type = idxOperandPairs[i].second;
229 assert(SVFUtil::isa<ConstIntValVar>(var) && "not a constant offset?");
230 s64_t constOffset = SVFUtil::dyn_cast<ConstIntValVar>(var)->getSExtValue();
231
232 if(type==nullptr)
233 {
235 continue;
236 }
237
238 if(SVFUtil::isa<SVFPointerType>(type))
240 else
241 {
243 if (offset >= 0)
244 {
245 const std::vector<u32_t>& so = PAG::getPAG()->getTypeInfo(type)->getFlattenedElemIdxVec();
246 // if offset is larger than the size of getFlattenedElemIdxVec (overflow)
247 // set offset the last index of getFlattenedElemIdxVec to avoid assertion
248 if (offset >= (APOffset)so.size())
249 {
250 SVFUtil::errs() << "It is an overflow access, hence it is the last idx\n";
251 offset = so.size() - 1;
252 }
253 else
254 {
255
256 }
257
260 offset);
262 }
263 }
264 }
265 return totalConstOffset;
266}
276
278{
279 assert(gepPointeeType == rhs.gepSrcPointeeType() && "source element type not match");
280 AccessPath ap(rhs);
282 for (auto &p : ap.getIdxOperandPairVec())
283 ap.addOffsetVarAndGepTypePair(p.first, p.second);
284
285 return ap;
286}
287
289{
290 if (fldIdx != rhs.fldIdx)
291 return (fldIdx < rhs.fldIdx);
292 else
293 {
295 const IdxOperandPairs& rhsPairVec = rhs.getIdxOperandPairVec();
296 if (pairVec.size() != rhsPairVec.size())
297 return (pairVec.size() < rhsPairVec.size());
298 else
299 {
300 IdxOperandPairs::const_iterator it = pairVec.begin();
301 IdxOperandPairs::const_iterator rhsIt = rhsPairVec.begin();
302 for (; it != pairVec.end() && rhsIt != rhsPairVec.end(); ++it, ++rhsIt)
303 {
304 return (*it) < (*rhsIt);
305 }
306
307 return false;
308 }
309 }
310}
311
313{
314 NodeBS lhsLocations = LHS.computeAllLocations();
315 NodeBS rhsLocations = RHS.computeAllLocations();
316 if (lhsLocations.intersects(rhsLocations))
317 {
319 return Same;
320 else if (lhsLocations.contains(rhsLocations))
321 return Superset;
322 else if (rhsLocations.contains(lhsLocations))
323 return Subset;
324 else
325 return Overlap;
326 }
327 else
328 {
329 return NonOverlap;
330 }
331}
332
334std::string AccessPath::dump() const
335{
336 std::string str;
337 std::stringstream rawstr(str);
338
339 rawstr << "AccessPath\tField_Index: " << getConstantStructFldIdx();
340 rawstr << ",\tNum-Stride: {";
342 IdxOperandPairs::const_iterator it = vec.begin();
343 IdxOperandPairs::const_iterator eit = vec.end();
344 for (; it != eit; ++it)
345 {
346 const SVFType* ty = it->second;
347 rawstr << " (Svf var: " << it->first->toString() << ", Iter type: " << *ty << ")";
348 }
349 rawstr << " }\n";
350 return rawstr.str();
351}
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:67
const SVFType * gepPointeeType
Definition AccessPath.h:185
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:184
APOffset getConstantStructFldIdx() const
Get methods.
Definition AccessPath.h:102
AccessPath operator+(const AccessPath &rhs) const
Overload operators.
const SVFType * gepSrcPointeeType() const
Definition AccessPath.h:114
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:183
u32_t getStructFieldOffset(const ValVar *idxOperandVar, const SVFStructType *idxOperandType) const
Return byte offset from the beginning of the structure to the field where it is located for struct ty...
const IdxOperandPairs & getIdxOperandPairVec() const
Definition AccessPath.h:110
bool addOffsetVarAndGepTypePair(const ValVar *var, const SVFType *gepIterType)
bool operator<(const AccessPath &rhs) const
APOffset computeConstantOffset() const
For example,.
u32_t getFlattenedElemIdx(const SVFType *T, u32_t origId)
Flattened element idx of an array or struct by considering stride.
Definition IRGraph.cpp:148
u32_t getNumOfFlattenElements(const SVFType *T)
Definition IRGraph.cpp:173
const StInfo * getTypeInfo(const SVFType *T) const
Get struct info.
Definition IRGraph.cpp:246
static const Option< u32_t > MaxFieldLimit
Maximum number of field derivations for an object.
Definition Options.h:34
static SVFIR * getPAG(bool buildFromFile=false)
Singleton design here to make sure we only have one instance during any analysis.
Definition SVFIR.h:120
std::string toString() const
void set(unsigned Idx)
std::vector< u32_t > & getFlattenedElemIdxVec()
Definition SVFType.h:123
std::ostream & errs()
Overwrite llvm::errs()
Definition SVFUtil.h:58
std::ostream & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:52
for isBitcode
Definition BasicTypes.h:70
s64_t APOffset
Definition GeneralType.h:80
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:76
unsigned u32_t
Definition GeneralType.h:67
signed long long s64_t
Definition GeneralType.h:70