Static Value-Flow Analysis
Loading...
Searching...
No Matches
AbstractStateManager.cpp
Go to the documentation of this file.
1//===- AbstractStateManager.cpp -- AE state-access implementations ---//
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// State-access bodies factored out of AbstractInterpretation.cpp /
24// SparseAbstractInterpretation.cpp. Class declarations stay in their
25// respective headers; this file just hosts the implementations of the
26// methods that used to live on the (now-folded) AbstractStateManager —
27// trace lookup, value get/has/update, GEP / load / store helpers, and
28// def/use queries — for dense and semi-sparse. Full-sparse stubs and
29// SVFG-backed overrides live in SparseAbstractInterpretation.cpp.
30//
31
34#include "SVFIR/SVFIR.h"
35#include "Util/Options.h"
36
37using namespace SVF;
38
39// =====================================================================
40// Dense (AbstractInterpretation) — direct trace lookup; sparse
41// subclasses override the virtuals below.
42// =====================================================================
43
45{
46 if (abstractTrace.count(node) == 0)
47 {
48 assert(false && "No preAbsTrace for this node");
49 abort();
50 }
51 return abstractTrace[node];
52}
53
58
60{
61 dst.joinWith(src);
62}
63
65{
66 return abstractTrace.count(node) != 0;
67}
68
80{
81 u32_t id = var->getId();
83 if (!as.getVarToVal().count(id))
84 {
85 if (var->getType()->isPointerTy())
87 else
88 as[id] = IntervalValue::top();
89 }
90 return as[id];
91}
92
99
101{
102 if (const ObjVar* objVar = SVFUtil::dyn_cast<ObjVar>(var))
103 return getAbsValue(objVar, node);
104 if (const ValVar* valVar = SVFUtil::dyn_cast<ValVar>(var))
105 return getAbsValue(valVar, node);
106 assert(false && "Unknown SVFVar kind");
107 abort();
108}
109
115{
116 auto it = abstractTrace.find(node);
117 if (it == abstractTrace.end())
118 return false;
119 return it->second.getVarToVal().count(var->getId()) != 0;
120}
121
123{
124 auto it = abstractTrace.find(node);
125 if (it == abstractTrace.end())
126 return false;
127 return it->second.getLocToVal().count(var->getId()) != 0;
128}
129
131{
132 if (const ObjVar* objVar = SVFUtil::dyn_cast<ObjVar>(var))
133 return hasAbsValue(objVar, node);
134 if (const ValVar* valVar = SVFUtil::dyn_cast<ValVar>(var))
135 return hasAbsValue(valVar, node);
136 return false;
137}
138
140{
141 abstractTrace[node][var->getId()] = val;
145{
148 as.store(addr, val);
150
152{
153 if (const ObjVar* objVar = SVFUtil::dyn_cast<ObjVar>(var))
155 else if (const ValVar* valVar = SVFUtil::dyn_cast<ValVar>(var))
156 updateAbsValue(valVar, val, node);
157 else
158 assert(false && "Unknown SVFVar kind");
159}
160
162{
164 for (const ValVar* var : vars)
165 {
166 u32_t id = var->getId();
167 result[id] = as[id];
168 }
169}
170
172{
174 for (const ObjVar* var : vars)
175 {
177 result.store(addr, as.load(addr));
178 }
179}
180
182{
184 for (const SVFVar* var : vars)
185 {
186 if (const ValVar* valVar = SVFUtil::dyn_cast<ValVar>(var))
187 {
188 u32_t id = valVar->getId();
189 result[id] = as[id];
190 }
191 else if (const ObjVar* objVar = SVFUtil::dyn_cast<ObjVar>(var))
192 {
194 result.store(addr, as.load(addr));
195 }
196 }
197}
198
200{
201 const ICFGNode* node = gep->getICFGNode();
202 if (gep->isConstantOffset())
203 return IntervalValue((s64_t)gep->accumulateConstantOffset());
204
205 IntervalValue res(0);
206 for (int i = gep->getOffsetVarAndGepTypePairVec().size() - 1; i >= 0; i--)
207 {
208 const ValVar* var = gep->getOffsetVarAndGepTypePairVec()[i].first;
209 const SVFType* type = gep->getOffsetVarAndGepTypePairVec()[i].second;
210
212 if (const ConstIntValVar* constInt = SVFUtil::dyn_cast<ConstIntValVar>(var))
213 idxLb = idxUb = constInt->getSExtValue();
214 else
215 {
217 if (idxItv.isBottom())
218 idxLb = idxUb = 0;
219 else
220 {
222 idxUb = idxItv.ub().getIntNumeral();
223 }
224 }
225
226 if (SVFUtil::isa<SVFPointerType>(type))
227 {
228 u32_t elemNum = gep->getAccessPath().getElementNum(gep->getAccessPath().gepSrcPointeeType());
229 idxLb = (double)Options::MaxFieldLimit() / elemNum < idxLb ? Options::MaxFieldLimit() : idxLb * elemNum;
230 idxUb = (double)Options::MaxFieldLimit() / elemNum < idxUb ? Options::MaxFieldLimit() : idxUb * elemNum;
231 }
232 else
233 {
235 {
236 const std::vector<u32_t>& so = PAG::getPAG()->getTypeInfo(type)->getFlattenedElemIdxVec();
237 if (so.empty() || idxUb >= (APOffset)so.size() || idxLb < 0)
238 idxLb = idxUb = 0;
239 else
240 {
243 }
244 }
245 else
246 idxLb = idxUb = 0;
247 }
248 res = res + IntervalValue(idxLb, idxUb);
249 }
251 if (res.isBottom())
252 res = IntervalValue(0);
253 return res;
254}
255
257{
258 const ICFGNode* node = gep->getICFGNode();
259 if (gep->isConstantOffset())
260 return IntervalValue((s64_t)gep->accumulateConstantByteOffset());
261
262 IntervalValue res(0);
263 for (int i = gep->getOffsetVarAndGepTypePairVec().size() - 1; i >= 0; i--)
264 {
265 const ValVar* idxOperandVar = gep->getOffsetVarAndGepTypePairVec()[i].first;
266 const SVFType* idxOperandType = gep->getOffsetVarAndGepTypePairVec()[i].second;
267
268 if (SVFUtil::isa<SVFArrayType>(idxOperandType) || SVFUtil::isa<SVFPointerType>(idxOperandType))
269 {
271 if (const SVFArrayType* arrOperandType = SVFUtil::dyn_cast<SVFArrayType>(idxOperandType))
272 elemByteSize = arrOperandType->getTypeOfElement()->getByteSize();
273 else if (SVFUtil::isa<SVFPointerType>(idxOperandType))
274 elemByteSize = gep->getAccessPath().gepSrcPointeeType()->getByteSize();
275 else
276 assert(false && "idxOperandType must be ArrType or PtrType");
277
278 if (const ConstIntValVar* op = SVFUtil::dyn_cast<ConstIntValVar>(idxOperandVar))
279 {
280 s64_t lb = (double)Options::MaxFieldLimit() / elemByteSize >= op->getSExtValue()
281 ? op->getSExtValue() * elemByteSize
283 res = res + IntervalValue(lb, lb);
284 }
285 else
286 {
288 if (idxVal.isBottom())
289 res = res + IntervalValue(0, 0);
290 else
291 {
292 s64_t ub = (idxVal.ub().getIntNumeral() < 0) ? 0
293 : (double)Options::MaxFieldLimit() / elemByteSize >= idxVal.ub().getIntNumeral()
294 ? elemByteSize * idxVal.ub().getIntNumeral()
296 s64_t lb = (idxVal.lb().getIntNumeral() < 0) ? 0
297 : (double)Options::MaxFieldLimit() / elemByteSize >= idxVal.lb().getIntNumeral()
298 ? elemByteSize * idxVal.lb().getIntNumeral()
300 res = res + IntervalValue(lb, ub);
301 }
302 }
303 }
304 else if (const SVFStructType* structOperandType = SVFUtil::dyn_cast<SVFStructType>(idxOperandType))
305 {
306 res = res + IntervalValue(gep->getAccessPath().getStructFieldOffset(idxOperandVar, structOperandType));
307 }
308 else
309 {
310 assert(false && "gep type pair only support arr/ptr/struct");
311 }
312 }
313 return res;
314}
315
317{
318 const ICFGNode* node = pointer->getICFGNode();
321 APOffset lb = offset.lb().getIntNumeral() < Options::MaxFieldLimit() ? offset.lb().getIntNumeral()
323 APOffset ub = offset.ub().getIntNumeral() < Options::MaxFieldLimit() ? offset.ub().getIntNumeral()
325 for (APOffset i = lb; i <= ub; i++)
326 {
327 const AbstractValue& addrs = getAbsValue(pointer, node);
328 for (const auto& addr : addrs.getAddrs())
329 {
330 // Null and black-hole addresses have no backing object.
332 continue;
333 s64_t baseObj = as.getIDFromAddr(addr);
334 assert(SVFUtil::isa<ObjVar>(svfir->getSVFVar(baseObj)) && "Fail to get the base object address!");
338 }
339 }
340 return gepAddrs;
341}
342
344{
345 const AbstractValue& ptrVal = getAbsValue(pointer, node);
347 AbstractValue res;
348 for (auto addr : ptrVal.getAddrs())
349 {
350 // Null and black-hole addresses have no backing object.
352 continue;
353 res.join_with(
354 getAbsValue(svfir->getSVFVar(as.getIDFromAddr(addr)), node));
355 }
356 return res;
357}
358
359void AbstractInterpretation::storeValue(const ValVar* pointer, const AbstractValue& val, const ICFGNode* node)
360{
361 const AbstractValue& ptrVal = getAbsValue(pointer, node);
363 for (auto addr : ptrVal.getAddrs())
364 {
365 // Null and black-hole addresses have no backing object.
367 continue;
368 updateAbsValue(svfir->getSVFVar(as.getIDFromAddr(addr)), val, node);
369 }
370}
371
373{
374 const AbstractValue& ptrVal = getAbsValue(var, node);
375 if (!ptrVal.isAddr())
376 return nullptr;
377 for (auto addr : ptrVal.getAddrs())
378 {
380 if (objId == 0)
381 continue;
382 return svfir->getBaseObject(objId)->getType();
383 }
384 return nullptr;
385}
386
388{
389 const ICFGNode* node = addr->getICFGNode();
390 if (const ObjVar* objvar = SVFUtil::dyn_cast<ObjVar>(addr->getRHSVar()))
391 {
393 {
394 return svfir->getBaseObject(objvar->getId())->getByteSizeOfObj();
395 }
396 else
397 {
398 const std::vector<SVFVar*>& sizes = addr->getArrSize();
399 u32_t elementSize = 1;
400 u64_t res = elementSize;
401 for (const SVFVar* value : sizes)
402 {
403 const AbstractValue& sizeVal = getAbsValue(value, node);
404 IntervalValue itv = sizeVal.getInterval();
405 if (itv.isBottom())
407 res = res * itv.ub().getIntNumeral() > Options::MaxFieldLimit()
408 ? Options::MaxFieldLimit() : res * itv.ub().getIntNumeral();
409 }
410 return (u32_t)res;
411 }
412 }
413 assert(false && "Addr rhs value is not ObjVar");
414 abort();
415}
#define BlackHoleObjAddr
newitem type
Definition cJSON.cpp:2739
buffer offset
Definition cJSON.cpp:1113
AbstractState & getAbsState(const ICFGNode *node)
u32_t getAllocaInstByteSize(const AddrStmt *addr)
virtual bool hasAbsValue(const ValVar *var, const ICFGNode *node) const
Side-effect-free existence check.
IntervalValue getGepByteOffset(const GepStmt *gep)
virtual AbstractValue loadValue(const ValVar *pointer, const ICFGNode *node)
Virtual so full-sparse can layer the GepObj overlay on top.
AddressValue getGepObjAddrs(const ValVar *pointer, IntervalValue offset)
IntervalValue getGepElementIndex(const GepStmt *gep)
virtual void joinStates(AbstractState &dst, const AbstractState &src)
SVFIR * svfir
Data and helpers reachable from SparseAbstractInterpretation.
virtual const AbstractValue & getAbsValue(const ValVar *var, const ICFGNode *node)
bool hasAbsState(const ICFGNode *node)
const SVFType * getPointeeElement(const ObjVar *var, const ICFGNode *node)
Map< const ICFGNode *, AbstractState > abstractTrace
per-node trace; owned here
virtual void updateAbsValue(const ValVar *var, const AbstractValue &val, const ICFGNode *node)
virtual void storeValue(const ValVar *pointer, const AbstractValue &val, const ICFGNode *node)
virtual void updateAbsState(const ICFGNode *node, const AbstractState &state)
u32_t getIDFromAddr(u32_t addr) const
Return the internal index if addr is an address otherwise return the value of idx.
void joinWith(const AbstractState &other)
domain join with other, important! other widen this.
static bool isNullOrBlackHoleAddr(u32_t addr)
Whether addr has no concrete backing memory object.
static u32_t getVirtualMemAddress(u32_t idx)
The physical address starts with 0x7f...... + idx.
void join_with(const AbstractValue &other)
IntervalValue & getInterval()
AddressValue & getAddrs()
bool isConstantByteSize() const
Check if byte size is a const value.
u32_t getByteSizeOfObj() const
Get the byte size of this object.
const SVFType * getType() const
Get obj type.
s64_t getIntNumeral() const
u32_t getFlattenedElemIdx(const SVFType *T, u32_t origId)
Flattened element idx of an array or struct by considering stride.
Definition IRGraph.cpp:148
const StInfo * getTypeInfo(const SVFType *T) const
Get struct info.
Definition IRGraph.cpp:259
void meet_with(const IntervalValue &other)
Return a intersected IntervalValue.
bool isBottom() const
static IntervalValue top()
Create the IntervalValue [-inf, +inf].
const BoundedInt & lb() const
Return the lower bound.
static Option< bool > ModelArrays
Definition Options.h:178
static const Option< u32_t > MaxFieldLimit
Maximum number of field derivations for an object.
Definition Options.h:34
const BaseObjVar * getBaseObject(NodeID id) const
Definition SVFIR.h:498
const SVFVar * getSVFVar(NodeID id) const
ObjVar/GepObjVar/BaseObjVar.
Definition SVFIR.h:135
static SVFIR * getPAG(bool buildFromFile=false)
Singleton design here to make sure we only have one instance during any analysis.
Definition SVFIR.h:120
const GepObjVar * getGepObjVar(NodeID id) const
Definition SVFIR.h:169
u32_t getByteSize() const
Definition SVFType.h:287
std::vector< u32_t > & getFlattenedElemIdxVec()
Definition SVFType.h:123
const ICFGNode * getICFGNode() const
for isBitcode
Definition BasicTypes.h:70
unsigned long long u64_t
Definition GeneralType.h:69
u32_t NodeID
Definition GeneralType.h:76
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