svf-lib 1.0.1925 → 1.0.1927
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.
- package/SVF-linux/Release-build/bin/ae +0 -0
- package/SVF-linux/Release-build/bin/svf-ex +0 -0
- package/SVF-linux/Release-build/include/AE/Core/AbstractState.h +750 -0
- package/SVF-linux/Release-build/include/AE/Core/AbstractValue.h +514 -39
- package/SVF-linux/Release-build/include/AE/Core/AddressValue.h +32 -25
- package/SVF-linux/Release-build/include/AE/Core/ExeState.h +2 -2
- package/SVF-linux/Release-build/include/AE/Core/IntervalValue.h +9 -24
- package/SVF-linux/Release-build/include/AE/Core/RelationSolver.h +9 -9
- package/SVF-linux/Release-build/include/AE/Svfexe/{AbstractExecution.h → AbstractInterpretation.h} +24 -22
- package/SVF-linux/Release-build/include/AE/Svfexe/BufOverflowChecker.h +5 -5
- package/SVF-linux/Release-build/include/AE/Svfexe/SVFIR2ItvExeState.h +23 -25
- package/SVF-linux/Release-build/lib/libSvfCore.a +0 -0
- package/SVF-osx/Release-build/bin/ae +0 -0
- package/SVF-osx/Release-build/bin/svf-ex +0 -0
- package/SVF-osx/Release-build/include/AE/Core/AbstractState.h +2 -3
- package/SVF-osx/Release-build/include/AE/Core/IntervalValue.h +1 -0
- package/SVF-osx/Release-build/include/AE/Core/RelExeState.h +1 -1
- package/SVF-osx/Release-build/include/AE/Svfexe/AbstractInterpretation.h +3 -4
- package/SVF-osx/Release-build/include/AE/Svfexe/ICFGSimplification.h +1 -2
- package/SVF-osx/Release-build/include/AE/Svfexe/{SVFIR2ItvExeState.h → SVFIR2AbsState.h} +8 -9
- package/SVF-osx/Release-build/lib/libSvfCore.a +0 -0
- package/SVF-osx/Release-build/lib/libSvfLLVM.a +0 -0
- package/package.json +1 -1
- package/SVF-linux/Release-build/include/AE/Core/IntervalExeState.h +0 -650
- package/SVF-osx/Release-build/include/AE/Core/ConsExeState.h +0 -453
- package/SVF-osx/Release-build/include/AE/Core/ExeState.h +0 -304
- package/SVF-osx/Release-build/include/AE/Core/SingleAbsValue.h +0 -477
- package/SVF-osx/Release-build/include/AE/Core/SymState.h +0 -221
- package/SVF-osx/Release-build/include/AE/Svfexe/SVFIR2ConsExeState.h +0 -148
|
@@ -0,0 +1,750 @@
|
|
|
1
|
+
//===- AbstractExeState.h ----Interval Domain-------------------------//
|
|
2
|
+
//
|
|
3
|
+
// SVF: Static Value-Flow Analysis
|
|
4
|
+
//
|
|
5
|
+
// Copyright (C) <2013-2022> <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
|
+
* IntervalExeState.h
|
|
24
|
+
*
|
|
25
|
+
* Created on: Jul 9, 2022
|
|
26
|
+
* Author: Xiao Cheng, Jiawei Wang
|
|
27
|
+
*
|
|
28
|
+
* [-oo,+oo]
|
|
29
|
+
* / / \ \
|
|
30
|
+
* [-oo,1] ... [-oo,10] ... [-1,+oo] ... [0,+oo]
|
|
31
|
+
* \ \ / /
|
|
32
|
+
* \ [-1,10] /
|
|
33
|
+
* \ / \ /
|
|
34
|
+
* ... [-1,1] ... [0,10] ...
|
|
35
|
+
* \ | \ / \ /
|
|
36
|
+
* ... [-1,0] [0,1] ... [1,9] ...
|
|
37
|
+
* \ | \ | \ /
|
|
38
|
+
* ... [-1,-1] [0,0] [1,1] ...
|
|
39
|
+
* \ \ \ / /
|
|
40
|
+
* ⊥
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
#ifndef Z3_EXAMPLE_INTERVAL_DOMAIN_H
|
|
44
|
+
#define Z3_EXAMPLE_INTERVAL_DOMAIN_H
|
|
45
|
+
|
|
46
|
+
#include "AE/Core/ExeState.h"
|
|
47
|
+
#include "AE/Core/IntervalValue.h"
|
|
48
|
+
#include "AE/Core/AbstractValue.h"
|
|
49
|
+
#include "Util/Z3Expr.h"
|
|
50
|
+
|
|
51
|
+
#include <iomanip>
|
|
52
|
+
|
|
53
|
+
namespace SVF
|
|
54
|
+
{
|
|
55
|
+
class AbstractState
|
|
56
|
+
{
|
|
57
|
+
friend class SVFIR2ItvExeState;
|
|
58
|
+
friend class RelationSolver;
|
|
59
|
+
public:
|
|
60
|
+
typedef Map<u32_t, AbstractValue> VarToAbsValMap;
|
|
61
|
+
|
|
62
|
+
typedef VarToAbsValMap LocToAbsValMap;
|
|
63
|
+
|
|
64
|
+
public:
|
|
65
|
+
/// default constructor
|
|
66
|
+
AbstractState() {}
|
|
67
|
+
|
|
68
|
+
AbstractState(VarToAbsValMap&_varToValMap, LocToAbsValMap&_locToValMap) : _varToAbsVal(_varToValMap),
|
|
69
|
+
_locToAbsVal(_locToValMap) {}
|
|
70
|
+
|
|
71
|
+
/// copy constructor
|
|
72
|
+
AbstractState(const AbstractState&rhs) : _varToAbsVal(rhs.getVarToVal()),
|
|
73
|
+
_locToAbsVal(rhs.getLocToVal())
|
|
74
|
+
{
|
|
75
|
+
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
virtual ~AbstractState() = default;
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
/// The physical address starts with 0x7f...... + idx
|
|
82
|
+
static inline u32_t getVirtualMemAddress(u32_t idx)
|
|
83
|
+
{
|
|
84
|
+
return AddressValue::getVirtualMemAddress(idx);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/// Check bit value of val start with 0x7F000000, filter by 0xFF000000
|
|
88
|
+
static inline bool isVirtualMemAddress(u32_t val)
|
|
89
|
+
{
|
|
90
|
+
return AddressValue::isVirtualMemAddress(val);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/// Return the internal index if idx is an address otherwise return the value of idx
|
|
94
|
+
static inline u32_t getInternalID(u32_t idx)
|
|
95
|
+
{
|
|
96
|
+
return AddressValue::getInternalID(idx);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
static inline bool isNullPtr(u32_t addr)
|
|
100
|
+
{
|
|
101
|
+
return getInternalID(addr) == 0;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
AbstractState&operator=(const AbstractState&rhs)
|
|
105
|
+
{
|
|
106
|
+
if (rhs != *this)
|
|
107
|
+
{
|
|
108
|
+
_varToAbsVal = rhs._varToAbsVal;
|
|
109
|
+
_locToAbsVal = rhs._locToAbsVal;
|
|
110
|
+
}
|
|
111
|
+
return *this;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/// move constructor
|
|
115
|
+
AbstractState(AbstractState&&rhs) : _varToAbsVal(std::move(rhs._varToAbsVal)),
|
|
116
|
+
_locToAbsVal(std::move(rhs._locToAbsVal))
|
|
117
|
+
{
|
|
118
|
+
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/// operator= move constructor
|
|
122
|
+
AbstractState&operator=(AbstractState&&rhs)
|
|
123
|
+
{
|
|
124
|
+
if (&rhs != this)
|
|
125
|
+
{
|
|
126
|
+
_varToAbsVal = std::move(rhs._varToAbsVal);
|
|
127
|
+
_locToAbsVal = std::move(rhs._locToAbsVal);
|
|
128
|
+
}
|
|
129
|
+
return *this;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/// Set all value bottom
|
|
133
|
+
AbstractState bottom() const
|
|
134
|
+
{
|
|
135
|
+
AbstractState inv = *this;
|
|
136
|
+
for (auto &item: inv._varToAbsVal)
|
|
137
|
+
{
|
|
138
|
+
if (item.second.isInterval())
|
|
139
|
+
item.second.getInterval().set_to_bottom();
|
|
140
|
+
}
|
|
141
|
+
return inv;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/// Set all value top
|
|
145
|
+
AbstractState top() const
|
|
146
|
+
{
|
|
147
|
+
AbstractState inv = *this;
|
|
148
|
+
for (auto &item: inv._varToAbsVal)
|
|
149
|
+
{
|
|
150
|
+
if (item.second.isInterval())
|
|
151
|
+
item.second.getInterval().set_to_top();
|
|
152
|
+
}
|
|
153
|
+
return inv;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/// Copy some values and return a new IntervalExeState
|
|
157
|
+
AbstractState sliceState(Set<u32_t> &sl)
|
|
158
|
+
{
|
|
159
|
+
AbstractState inv;
|
|
160
|
+
for (u32_t id: sl)
|
|
161
|
+
{
|
|
162
|
+
inv._varToAbsVal[id] = _varToAbsVal[id];
|
|
163
|
+
}
|
|
164
|
+
return inv;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
protected:
|
|
168
|
+
VarToAbsValMap _varToAbsVal; ///< Map a variable (symbol) to its abstract value
|
|
169
|
+
LocToAbsValMap _locToAbsVal; ///< Map a memory address to its stored abstract value
|
|
170
|
+
|
|
171
|
+
public:
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
/// get abstract value of variable
|
|
175
|
+
inline virtual AbstractValue &operator[](u32_t varId)
|
|
176
|
+
{
|
|
177
|
+
return _varToAbsVal[varId];
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/// get abstract value of variable
|
|
181
|
+
inline virtual const AbstractValue &operator[](u32_t varId) const
|
|
182
|
+
{
|
|
183
|
+
return _varToAbsVal.at(varId);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/// whether the variable is in varToAddrs table
|
|
187
|
+
inline bool inVarToAddrsTable(u32_t id) const
|
|
188
|
+
{
|
|
189
|
+
if (_varToAbsVal.find(id)!= _varToAbsVal.end())
|
|
190
|
+
{
|
|
191
|
+
if (_varToAbsVal.at(id).isAddr())
|
|
192
|
+
{
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/// whether the variable is in varToVal table
|
|
200
|
+
inline virtual bool inVarToValTable(u32_t id) const
|
|
201
|
+
{
|
|
202
|
+
if (_varToAbsVal.find(id) != _varToAbsVal.end())
|
|
203
|
+
{
|
|
204
|
+
if (_varToAbsVal.at(id).isInterval())
|
|
205
|
+
{
|
|
206
|
+
return true;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/// whether the memory address stores memory addresses
|
|
213
|
+
inline bool inLocToAddrsTable(u32_t id) const
|
|
214
|
+
{
|
|
215
|
+
if (_locToAbsVal.find(id)!= _locToAbsVal.end())
|
|
216
|
+
{
|
|
217
|
+
if (_locToAbsVal.at(id).isAddr())
|
|
218
|
+
{
|
|
219
|
+
return true;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return false;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/// whether the memory address stores abstract value
|
|
226
|
+
inline virtual bool inLocToValTable(u32_t id) const
|
|
227
|
+
{
|
|
228
|
+
if (_locToAbsVal.find(id) != _locToAbsVal.end())
|
|
229
|
+
{
|
|
230
|
+
if (_locToAbsVal.at(id).isInterval())
|
|
231
|
+
{
|
|
232
|
+
return true;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return false;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/// get var2val map
|
|
239
|
+
const VarToAbsValMap&getVarToVal() const
|
|
240
|
+
{
|
|
241
|
+
return _varToAbsVal;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/// get loc2val map
|
|
245
|
+
const LocToAbsValMap&getLocToVal() const
|
|
246
|
+
{
|
|
247
|
+
return _locToAbsVal;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
public:
|
|
251
|
+
|
|
252
|
+
/// domain widen with other, and return the widened domain
|
|
253
|
+
AbstractState widening(const AbstractState&other);
|
|
254
|
+
|
|
255
|
+
/// domain narrow with other, and return the narrowed domain
|
|
256
|
+
AbstractState narrowing(const AbstractState&other);
|
|
257
|
+
|
|
258
|
+
/// domain widen with other, important! other widen this.
|
|
259
|
+
void widenWith(const AbstractState&other);
|
|
260
|
+
|
|
261
|
+
/// domain join with other, important! other widen this.
|
|
262
|
+
void joinWith(const AbstractState&other);
|
|
263
|
+
|
|
264
|
+
/// domain narrow with other, important! other widen this.
|
|
265
|
+
void narrowWith(const AbstractState&other);
|
|
266
|
+
|
|
267
|
+
/// domain meet with other, important! other widen this.
|
|
268
|
+
void meetWith(const AbstractState&other);
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
/// Return int value from an expression if it is a numeral, otherwise return an approximate value
|
|
272
|
+
inline s32_t Interval2NumValue(const IntervalValue &e) const
|
|
273
|
+
{
|
|
274
|
+
//TODO: return concrete value;
|
|
275
|
+
return (s32_t) e.lb().getNumeral();
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/// Return true if map has bottom value
|
|
279
|
+
inline bool has_bottom()
|
|
280
|
+
{
|
|
281
|
+
for (auto it = _varToAbsVal.begin(); it != _varToAbsVal.end(); ++it)
|
|
282
|
+
{
|
|
283
|
+
if (it->second.isInterval())
|
|
284
|
+
{
|
|
285
|
+
if (it->second.getInterval().isBottom())
|
|
286
|
+
{
|
|
287
|
+
return true;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
for (auto it = _locToAbsVal.begin(); it != _locToAbsVal.end(); ++it)
|
|
292
|
+
{
|
|
293
|
+
if (it->second.isInterval())
|
|
294
|
+
{
|
|
295
|
+
if (it->second.getInterval().isBottom())
|
|
296
|
+
{
|
|
297
|
+
return true;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
return false;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
u32_t hash() const;
|
|
305
|
+
|
|
306
|
+
public:
|
|
307
|
+
inline void store(u32_t addr, const AbstractValue &val)
|
|
308
|
+
{
|
|
309
|
+
assert(isVirtualMemAddress(addr) && "not virtual address?");
|
|
310
|
+
if (isNullPtr(addr)) return;
|
|
311
|
+
u32_t objId = getInternalID(addr);
|
|
312
|
+
_locToAbsVal[objId] = val;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
inline virtual AbstractValue &load(u32_t addr)
|
|
316
|
+
{
|
|
317
|
+
assert(isVirtualMemAddress(addr) && "not virtual address?");
|
|
318
|
+
u32_t objId = getInternalID(addr);
|
|
319
|
+
auto it = _locToAbsVal.find(objId);
|
|
320
|
+
if(it != _locToAbsVal.end())
|
|
321
|
+
return it->second;
|
|
322
|
+
else
|
|
323
|
+
{
|
|
324
|
+
_locToAbsVal[objId] = IntervalValue::top();
|
|
325
|
+
return _locToAbsVal[objId];
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
/// Print values of all expressions
|
|
331
|
+
void printExprValues(std::ostream &oss) const;
|
|
332
|
+
|
|
333
|
+
std::string toString() const
|
|
334
|
+
{
|
|
335
|
+
return "";
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
bool equals(const AbstractState&other) const;
|
|
339
|
+
|
|
340
|
+
static bool eqVarToValMap(const VarToAbsValMap&lhs, const VarToAbsValMap&rhs)
|
|
341
|
+
{
|
|
342
|
+
if (lhs.size() != rhs.size()) return false;
|
|
343
|
+
for (const auto &item: lhs)
|
|
344
|
+
{
|
|
345
|
+
auto it = rhs.find(item.first);
|
|
346
|
+
if (it == rhs.end())
|
|
347
|
+
return false;
|
|
348
|
+
if (item.second.getType() == it->second.getType())
|
|
349
|
+
{
|
|
350
|
+
if (item.second.isInterval())
|
|
351
|
+
{
|
|
352
|
+
if (!item.second.getInterval().equals(it->second.getInterval()))
|
|
353
|
+
{
|
|
354
|
+
return false;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
else if (item.second.isAddr())
|
|
358
|
+
{
|
|
359
|
+
if (!item.second.getAddrs().equals(it->second.getAddrs()))
|
|
360
|
+
{
|
|
361
|
+
return false;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
else
|
|
366
|
+
{
|
|
367
|
+
return false;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
return true;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
static bool lessThanVarToValMap(const VarToAbsValMap&lhs, const VarToAbsValMap&rhs)
|
|
375
|
+
{
|
|
376
|
+
if (lhs.empty()) return !rhs.empty();
|
|
377
|
+
for (const auto &item: lhs)
|
|
378
|
+
{
|
|
379
|
+
auto it = rhs.find(item.first);
|
|
380
|
+
if (it == rhs.end()) return false;
|
|
381
|
+
// judge from expr id
|
|
382
|
+
if (item.second.getInterval().geq(it->second.getInterval())) return false;
|
|
383
|
+
}
|
|
384
|
+
return true;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// lhs >= rhs
|
|
388
|
+
static bool geqVarToValMap(const VarToAbsValMap&lhs, const VarToAbsValMap&rhs)
|
|
389
|
+
{
|
|
390
|
+
if (rhs.empty()) return true;
|
|
391
|
+
for (const auto &item: rhs)
|
|
392
|
+
{
|
|
393
|
+
auto it = lhs.find(item.first);
|
|
394
|
+
if (it == lhs.end()) return false;
|
|
395
|
+
// judge from expr id
|
|
396
|
+
if (it->second.isInterval() && item.second.isInterval())
|
|
397
|
+
{
|
|
398
|
+
if (!it->second.getInterval().geq(item.second.getInterval()))
|
|
399
|
+
return false;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
}
|
|
403
|
+
return true;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
bool operator==(const AbstractState&rhs) const
|
|
407
|
+
{
|
|
408
|
+
return eqVarToValMap(_varToAbsVal, rhs.getVarToVal()) &&
|
|
409
|
+
eqVarToValMap(_locToAbsVal, rhs.getLocToVal());
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
bool operator!=(const AbstractState&rhs) const
|
|
413
|
+
{
|
|
414
|
+
return !(*this == rhs);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
bool operator<(const AbstractState&rhs) const
|
|
418
|
+
{
|
|
419
|
+
return !(*this >= rhs);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
bool operator>=(const AbstractState&rhs) const
|
|
424
|
+
{
|
|
425
|
+
return geqVarToValMap(_varToAbsVal, rhs.getVarToVal()) && geqVarToValMap(_locToAbsVal, rhs.getLocToVal());
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
void clear()
|
|
429
|
+
{
|
|
430
|
+
_locToAbsVal.clear();
|
|
431
|
+
_varToAbsVal.clear();
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
protected:
|
|
436
|
+
void printTable(const VarToAbsValMap&table, std::ostream &oss) const;
|
|
437
|
+
|
|
438
|
+
};
|
|
439
|
+
|
|
440
|
+
class SparseAbstractState : public AbstractState
|
|
441
|
+
{
|
|
442
|
+
friend class SVFIR2ItvExeState;
|
|
443
|
+
friend class RelationSolver;
|
|
444
|
+
|
|
445
|
+
public:
|
|
446
|
+
static SparseAbstractState globalES;
|
|
447
|
+
|
|
448
|
+
public:
|
|
449
|
+
/// default constructor
|
|
450
|
+
SparseAbstractState() : AbstractState() {}
|
|
451
|
+
|
|
452
|
+
SparseAbstractState(VarToAbsValMap&_varToValMap, LocToAbsValMap&_locToValMap) : AbstractState(_varToValMap, _locToValMap) {}
|
|
453
|
+
|
|
454
|
+
/// copy constructor
|
|
455
|
+
SparseAbstractState(const SparseAbstractState&rhs) : AbstractState(rhs)
|
|
456
|
+
{
|
|
457
|
+
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
virtual ~SparseAbstractState() = default;
|
|
461
|
+
|
|
462
|
+
SparseAbstractState&operator=(const SparseAbstractState&rhs)
|
|
463
|
+
{
|
|
464
|
+
AbstractState::operator=(rhs);
|
|
465
|
+
return *this;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
virtual void printExprValues(std::ostream &oss) const;
|
|
469
|
+
|
|
470
|
+
/// move constructor
|
|
471
|
+
SparseAbstractState(SparseAbstractState&&rhs) : AbstractState(std::move(rhs))
|
|
472
|
+
{
|
|
473
|
+
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/// operator= move constructor
|
|
477
|
+
SparseAbstractState&operator=(SparseAbstractState&&rhs)
|
|
478
|
+
{
|
|
479
|
+
AbstractState::operator=(std::move(rhs));
|
|
480
|
+
return *this;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
public:
|
|
484
|
+
|
|
485
|
+
/// get memory addresses of variable
|
|
486
|
+
AbstractValue &getAddrs(u32_t id)
|
|
487
|
+
{
|
|
488
|
+
if (_varToAbsVal.find(id)!= _varToAbsVal.end())
|
|
489
|
+
{
|
|
490
|
+
return _varToAbsVal[id];
|
|
491
|
+
}
|
|
492
|
+
else if (globalES._varToAbsVal.find(id)!= globalES._varToAbsVal.end())
|
|
493
|
+
{
|
|
494
|
+
return globalES._varToAbsVal[id];
|
|
495
|
+
}
|
|
496
|
+
else
|
|
497
|
+
{
|
|
498
|
+
globalES._varToAbsVal[id] = AddressValue();
|
|
499
|
+
return globalES._varToAbsVal[id];
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/// get abstract value of variable
|
|
504
|
+
inline AbstractValue &operator[](u32_t varId)
|
|
505
|
+
{
|
|
506
|
+
auto localIt = _varToAbsVal.find(varId);
|
|
507
|
+
if(localIt != _varToAbsVal.end())
|
|
508
|
+
return localIt->second;
|
|
509
|
+
else
|
|
510
|
+
{
|
|
511
|
+
return globalES._varToAbsVal[varId];
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
/// whether the variable is in varToAddrs table
|
|
516
|
+
inline bool inVarToAddrsTable(u32_t id) const
|
|
517
|
+
{
|
|
518
|
+
if (_varToAbsVal.find(id)!= _varToAbsVal.end())
|
|
519
|
+
{
|
|
520
|
+
if (_varToAbsVal.at(id).isAddr())
|
|
521
|
+
{
|
|
522
|
+
return true;
|
|
523
|
+
}
|
|
524
|
+
else
|
|
525
|
+
{
|
|
526
|
+
return false;
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
else if (globalES._varToAbsVal.find(id)!= globalES._varToAbsVal.end())
|
|
530
|
+
{
|
|
531
|
+
if (globalES._varToAbsVal[id].isAddr())
|
|
532
|
+
{
|
|
533
|
+
return true;
|
|
534
|
+
}
|
|
535
|
+
else
|
|
536
|
+
{
|
|
537
|
+
return false;
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
else
|
|
541
|
+
{
|
|
542
|
+
return false;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
/// whether the variable is in varToVal table
|
|
547
|
+
inline bool inVarToValTable(u32_t id) const
|
|
548
|
+
{
|
|
549
|
+
if (_varToAbsVal.find(id)!= _varToAbsVal.end())
|
|
550
|
+
{
|
|
551
|
+
if (_varToAbsVal.at(id).isInterval())
|
|
552
|
+
{
|
|
553
|
+
return true;
|
|
554
|
+
}
|
|
555
|
+
else
|
|
556
|
+
{
|
|
557
|
+
return false;
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
else if (globalES._varToAbsVal.find(id)!= globalES._varToAbsVal.end())
|
|
561
|
+
{
|
|
562
|
+
if (globalES._varToAbsVal[id].isInterval())
|
|
563
|
+
{
|
|
564
|
+
return true;
|
|
565
|
+
}
|
|
566
|
+
else
|
|
567
|
+
{
|
|
568
|
+
return false;
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
else
|
|
572
|
+
{
|
|
573
|
+
return false;
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
/// whether the memory address stores memory addresses
|
|
578
|
+
inline bool inLocToAddrsTable(u32_t id) const
|
|
579
|
+
{
|
|
580
|
+
if (_locToAbsVal.find(id)!= _locToAbsVal.end())
|
|
581
|
+
{
|
|
582
|
+
if (_locToAbsVal.at(id).isAddr())
|
|
583
|
+
{
|
|
584
|
+
return true;
|
|
585
|
+
}
|
|
586
|
+
else
|
|
587
|
+
{
|
|
588
|
+
return false;
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
else if (globalES._locToAbsVal.find(id)!= globalES._locToAbsVal.end())
|
|
592
|
+
{
|
|
593
|
+
if (globalES._locToAbsVal[id].isAddr())
|
|
594
|
+
{
|
|
595
|
+
return true;
|
|
596
|
+
}
|
|
597
|
+
else
|
|
598
|
+
{
|
|
599
|
+
return false;
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
else
|
|
603
|
+
{
|
|
604
|
+
return false;
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
/// whether the memory address stores abstract value
|
|
609
|
+
inline bool inLocToValTable(u32_t id) const
|
|
610
|
+
{
|
|
611
|
+
if (_locToAbsVal.find(id)!= _locToAbsVal.end())
|
|
612
|
+
{
|
|
613
|
+
if (_locToAbsVal.at(id).isInterval())
|
|
614
|
+
{
|
|
615
|
+
return true;
|
|
616
|
+
}
|
|
617
|
+
else
|
|
618
|
+
{
|
|
619
|
+
return false;
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
else if (globalES._locToAbsVal.find(id)!= globalES._locToAbsVal.end())
|
|
623
|
+
{
|
|
624
|
+
if (globalES._locToAbsVal[id].isInterval())
|
|
625
|
+
{
|
|
626
|
+
return true;
|
|
627
|
+
}
|
|
628
|
+
else
|
|
629
|
+
{
|
|
630
|
+
return false;
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
else
|
|
634
|
+
{
|
|
635
|
+
return false;
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
inline bool inLocalLocToValTable(u32_t id) const
|
|
640
|
+
{
|
|
641
|
+
if (_locToAbsVal.find(id)!= _locToAbsVal.end())
|
|
642
|
+
{
|
|
643
|
+
return _locToAbsVal.at(id).isInterval();
|
|
644
|
+
}
|
|
645
|
+
else
|
|
646
|
+
return false;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
inline bool inLocalLocToAddrsTable(u32_t id) const
|
|
650
|
+
{
|
|
651
|
+
if (_locToAbsVal.find(id)!= _locToAbsVal.end())
|
|
652
|
+
{
|
|
653
|
+
return _locToAbsVal.at(id).isAddr();
|
|
654
|
+
}
|
|
655
|
+
else
|
|
656
|
+
return false;
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
public:
|
|
660
|
+
|
|
661
|
+
inline void cpyItvToLocal(u32_t varId)
|
|
662
|
+
{
|
|
663
|
+
auto localIt = _varToAbsVal.find(varId);
|
|
664
|
+
// local already have varId
|
|
665
|
+
if (localIt != _varToAbsVal.end()) return;
|
|
666
|
+
auto globIt = globalES._varToAbsVal.find(varId);
|
|
667
|
+
if (globIt != globalES._varToAbsVal.end())
|
|
668
|
+
{
|
|
669
|
+
_varToAbsVal[varId] = globIt->second;
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
/// domain widen with other, and return the widened domain
|
|
674
|
+
SparseAbstractState widening(const SparseAbstractState&other);
|
|
675
|
+
|
|
676
|
+
/// domain narrow with other, and return the narrowed domain
|
|
677
|
+
SparseAbstractState narrowing(const SparseAbstractState&other);
|
|
678
|
+
|
|
679
|
+
/// domain widen with other, important! other widen this.
|
|
680
|
+
void widenWith(const SparseAbstractState&other);
|
|
681
|
+
|
|
682
|
+
/// domain join with other, important! other widen this.
|
|
683
|
+
void joinWith(const SparseAbstractState&other);
|
|
684
|
+
|
|
685
|
+
/// domain narrow with other, important! other widen this.
|
|
686
|
+
void narrowWith(const SparseAbstractState&other);
|
|
687
|
+
|
|
688
|
+
/// domain meet with other, important! other widen this.
|
|
689
|
+
void meetWith(const SparseAbstractState&other);
|
|
690
|
+
|
|
691
|
+
u32_t hash() const;
|
|
692
|
+
|
|
693
|
+
public:
|
|
694
|
+
|
|
695
|
+
inline AbstractValue &load(u32_t addr)
|
|
696
|
+
{
|
|
697
|
+
assert(isVirtualMemAddress(addr) && "not virtual address?");
|
|
698
|
+
u32_t objId = getInternalID(addr);
|
|
699
|
+
auto it = _locToAbsVal.find(objId);
|
|
700
|
+
if(it != _locToAbsVal.end())
|
|
701
|
+
return it->second;
|
|
702
|
+
else
|
|
703
|
+
{
|
|
704
|
+
auto globIt = globalES._locToAbsVal.find(objId);
|
|
705
|
+
if(globIt != globalES._locToAbsVal.end())
|
|
706
|
+
return globIt->second;
|
|
707
|
+
else
|
|
708
|
+
{
|
|
709
|
+
return globalES._locToAbsVal[objId];
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
bool equals(const SparseAbstractState&other) const;
|
|
716
|
+
|
|
717
|
+
bool operator==(const SparseAbstractState&rhs) const
|
|
718
|
+
{
|
|
719
|
+
return eqVarToValMap(_varToAbsVal, rhs._varToAbsVal) &&
|
|
720
|
+
eqVarToValMap(_locToAbsVal, rhs._locToAbsVal);
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
bool operator!=(const SparseAbstractState&rhs) const
|
|
724
|
+
{
|
|
725
|
+
return !(*this == rhs);
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
bool operator<(const SparseAbstractState&rhs) const
|
|
729
|
+
{
|
|
730
|
+
return !(*this >= rhs);
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
|
|
734
|
+
bool operator>=(const SparseAbstractState&rhs) const
|
|
735
|
+
{
|
|
736
|
+
return geqVarToValMap(_varToAbsVal, rhs.getVarToVal()) && geqVarToValMap(_locToAbsVal, rhs._locToAbsVal);
|
|
737
|
+
}
|
|
738
|
+
};
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
template<>
|
|
742
|
+
struct std::hash<SVF::SparseAbstractState>
|
|
743
|
+
{
|
|
744
|
+
size_t operator()(const SVF::SparseAbstractState&exeState) const
|
|
745
|
+
{
|
|
746
|
+
return exeState.hash();
|
|
747
|
+
}
|
|
748
|
+
};
|
|
749
|
+
|
|
750
|
+
#endif //Z3_EXAMPLE_INTERVAL_DOMAIN_H
|