svf-tools 1.0.727 → 1.0.729
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/package.json +1 -1
- package/svf/include/AbstractExecution/ConsExeState.h +446 -0
- package/svf/include/AbstractExecution/ExeState.h +72 -5
- package/svf/include/AbstractExecution/IntervalExeState.h +13 -0
- package/svf/include/AbstractExecution/SVFIR2ConsExeState.h +149 -0
- package/svf/include/AbstractExecution/SymState.h +221 -0
- package/svf/lib/AbstractExecution/ConsExeState.cpp +606 -0
- package/svf/lib/AbstractExecution/ExeState.cpp +16 -7
- package/svf/lib/AbstractExecution/SVFIR2ConsExeState.cpp +808 -0
- package/svf/lib/AbstractExecution/SymState.cpp +37 -0
- package/svf-llvm/tools/LLVM2SVF/llvm2svf.cpp +3 -2
|
@@ -0,0 +1,808 @@
|
|
|
1
|
+
//===- SVFIR2ConsExeState.cpp ----SVFIR2ConsExeState-------------------------//
|
|
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
|
+
//
|
|
24
|
+
// Created by jiawei and xiao on 6/1/23.
|
|
25
|
+
//
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
#include "AbstractExecution/SVFIR2ConsExeState.h"
|
|
29
|
+
#include "Util/Options.h"
|
|
30
|
+
|
|
31
|
+
using namespace SVF;
|
|
32
|
+
using namespace SVFUtil;
|
|
33
|
+
using namespace std;
|
|
34
|
+
|
|
35
|
+
SVFIR2ConsExeState::~SVFIR2ConsExeState()
|
|
36
|
+
{
|
|
37
|
+
ConsExeState::globalConsES._varToVal.clear();
|
|
38
|
+
ConsExeState::globalConsES._varToVAddrs.clear();
|
|
39
|
+
ConsExeState::globalConsES._locToVal.clear();
|
|
40
|
+
ConsExeState::globalConsES._locToVAddrs.clear();
|
|
41
|
+
}
|
|
42
|
+
/// Translator for llvm ir
|
|
43
|
+
//{%
|
|
44
|
+
/*!
|
|
45
|
+
* https://llvm.org/docs/LangRef.html#alloca-instruction
|
|
46
|
+
* @param addr
|
|
47
|
+
* @return
|
|
48
|
+
*/
|
|
49
|
+
void SVFIR2ConsExeState::translateAddr(const AddrStmt *addr)
|
|
50
|
+
{
|
|
51
|
+
initSVFVar(addr->getRHSVarID());
|
|
52
|
+
if (inVarToValTable(addr->getRHSVarID()))
|
|
53
|
+
{
|
|
54
|
+
_es->globalConsES._varToVal[addr->getLHSVarID()] = _es->globalConsES._varToVal[addr->getRHSVarID()];
|
|
55
|
+
}
|
|
56
|
+
else if (inVarToAddrsTable(addr->getRHSVarID()))
|
|
57
|
+
{
|
|
58
|
+
_es->globalConsES._varToVAddrs[addr->getLHSVarID()] = _es->globalConsES._varToVAddrs[addr->getRHSVarID()];
|
|
59
|
+
}
|
|
60
|
+
else
|
|
61
|
+
{
|
|
62
|
+
assert(false && "not number or virtual addrs?");
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/*!
|
|
67
|
+
* https://llvm.org/docs/LangRef.html#binary-operations
|
|
68
|
+
* @param binary
|
|
69
|
+
* @return
|
|
70
|
+
*/
|
|
71
|
+
void SVFIR2ConsExeState::translateBinary(const BinaryOPStmt *binary)
|
|
72
|
+
{
|
|
73
|
+
u32_t op0 = binary->getOpVarID(0);
|
|
74
|
+
u32_t op1 = binary->getOpVarID(1);
|
|
75
|
+
u32_t res = binary->getResID();
|
|
76
|
+
// rhs is not initialized
|
|
77
|
+
if (!_es->inVarToVal(op0) || !_es->inVarToVal(op1))
|
|
78
|
+
return;
|
|
79
|
+
|
|
80
|
+
SingleAbsValue &lhs = (*_es)[op0], &rhs = (*_es)[op1];
|
|
81
|
+
SingleAbsValue resVal;
|
|
82
|
+
switch (binary->getOpcode())
|
|
83
|
+
{
|
|
84
|
+
case BinaryOPStmt::Add:
|
|
85
|
+
case BinaryOPStmt::FAdd:
|
|
86
|
+
resVal = (lhs + rhs).simplify();
|
|
87
|
+
break;
|
|
88
|
+
case BinaryOPStmt::Sub:
|
|
89
|
+
case BinaryOPStmt::FSub:
|
|
90
|
+
resVal = (lhs - rhs).simplify();
|
|
91
|
+
break;
|
|
92
|
+
case BinaryOPStmt::Mul:
|
|
93
|
+
case BinaryOPStmt::FMul:
|
|
94
|
+
resVal = (lhs * rhs).simplify();
|
|
95
|
+
break;
|
|
96
|
+
case BinaryOPStmt::SDiv:
|
|
97
|
+
case BinaryOPStmt::FDiv:
|
|
98
|
+
case BinaryOPStmt::UDiv:
|
|
99
|
+
resVal = (lhs / rhs).simplify();
|
|
100
|
+
break;
|
|
101
|
+
case BinaryOPStmt::SRem:
|
|
102
|
+
case BinaryOPStmt::FRem:
|
|
103
|
+
case BinaryOPStmt::URem:
|
|
104
|
+
resVal = (lhs % rhs).simplify();
|
|
105
|
+
break;
|
|
106
|
+
case BinaryOPStmt::Xor:
|
|
107
|
+
resVal = (lhs ^ rhs).simplify();
|
|
108
|
+
break;
|
|
109
|
+
case BinaryOPStmt::And:
|
|
110
|
+
resVal = (lhs & rhs).simplify();
|
|
111
|
+
break;
|
|
112
|
+
case BinaryOPStmt::Or:
|
|
113
|
+
resVal = (lhs | rhs).simplify();
|
|
114
|
+
break;
|
|
115
|
+
case BinaryOPStmt::AShr:
|
|
116
|
+
resVal = ashr(lhs, rhs).simplify();
|
|
117
|
+
break;
|
|
118
|
+
case BinaryOPStmt::Shl:
|
|
119
|
+
resVal = shl(lhs, rhs).simplify();
|
|
120
|
+
break;
|
|
121
|
+
case BinaryOPStmt::LShr:
|
|
122
|
+
resVal = lshr(lhs, rhs).simplify();
|
|
123
|
+
break;
|
|
124
|
+
default:
|
|
125
|
+
{
|
|
126
|
+
assert(false && "undefined binary");
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
(*_es)[res] = resVal;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/*!
|
|
133
|
+
* https://llvm.org/docs/LangRef.html#icmp-instruction
|
|
134
|
+
* @param cmp
|
|
135
|
+
* @return
|
|
136
|
+
*/
|
|
137
|
+
void SVFIR2ConsExeState::translateCmp(const CmpStmt *cmp)
|
|
138
|
+
{
|
|
139
|
+
u32_t op0 = cmp->getOpVarID(0);
|
|
140
|
+
u32_t op1 = cmp->getOpVarID(1);
|
|
141
|
+
u32_t res = cmp->getResID();
|
|
142
|
+
if (inVarToValTable(op0) && inVarToValTable(op1))
|
|
143
|
+
{
|
|
144
|
+
SingleAbsValue &lhs = (*_es)[op0], &rhs = (*_es)[op1];
|
|
145
|
+
SingleAbsValue resVal;
|
|
146
|
+
auto predicate = cmp->getPredicate();
|
|
147
|
+
switch (predicate)
|
|
148
|
+
{
|
|
149
|
+
case CmpStmt::ICMP_EQ:
|
|
150
|
+
case CmpStmt::FCMP_OEQ:
|
|
151
|
+
case CmpStmt::FCMP_UEQ:
|
|
152
|
+
resVal = ite(lhs == rhs, 1, 0).simplify();
|
|
153
|
+
break;
|
|
154
|
+
case CmpStmt::ICMP_NE:
|
|
155
|
+
case CmpStmt::FCMP_ONE:
|
|
156
|
+
case CmpStmt::FCMP_UNE:
|
|
157
|
+
resVal = ite(lhs != rhs, 1, 0).simplify();
|
|
158
|
+
break;
|
|
159
|
+
case CmpStmt::ICMP_UGT:
|
|
160
|
+
case CmpStmt::ICMP_SGT:
|
|
161
|
+
case CmpStmt::FCMP_OGT:
|
|
162
|
+
case CmpStmt::FCMP_UGT:
|
|
163
|
+
resVal = ite(lhs > rhs, 1, 0).simplify();
|
|
164
|
+
break;
|
|
165
|
+
case CmpStmt::ICMP_UGE:
|
|
166
|
+
case CmpStmt::ICMP_SGE:
|
|
167
|
+
case CmpStmt::FCMP_OGE:
|
|
168
|
+
case CmpStmt::FCMP_UGE:
|
|
169
|
+
resVal = ite(lhs >= rhs, 1, 0).simplify();
|
|
170
|
+
break;
|
|
171
|
+
case CmpStmt::ICMP_ULT:
|
|
172
|
+
case CmpStmt::ICMP_SLT:
|
|
173
|
+
case CmpStmt::FCMP_OLT:
|
|
174
|
+
case CmpStmt::FCMP_ULT:
|
|
175
|
+
resVal = ite(lhs < rhs, 1, 0).simplify();
|
|
176
|
+
break;
|
|
177
|
+
case CmpStmt::ICMP_ULE:
|
|
178
|
+
case CmpStmt::ICMP_SLE:
|
|
179
|
+
case CmpStmt::FCMP_OLE:
|
|
180
|
+
case CmpStmt::FCMP_ULE:
|
|
181
|
+
resVal = ite(lhs <= rhs, 1, 0).simplify();
|
|
182
|
+
break;
|
|
183
|
+
case CmpStmt::FCMP_FALSE:
|
|
184
|
+
resVal = 0;
|
|
185
|
+
break;
|
|
186
|
+
case CmpStmt::FCMP_TRUE:
|
|
187
|
+
resVal = 1;
|
|
188
|
+
break;
|
|
189
|
+
default:
|
|
190
|
+
{
|
|
191
|
+
assert(false && "undefined compare");
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
(*_es)[res] = resVal;
|
|
195
|
+
}
|
|
196
|
+
else if (inVarToAddrsTable(op0) && inVarToAddrsTable(op1))
|
|
197
|
+
{
|
|
198
|
+
|
|
199
|
+
VAddrs &lhs = _es->getVAddrs(op0), &rhs = _es->getVAddrs(op1);
|
|
200
|
+
if (lhs.size() == 1)
|
|
201
|
+
{
|
|
202
|
+
(*_es)[res] = SingleAbsValue::topConstant();
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
if (rhs.size() == 1)
|
|
206
|
+
{
|
|
207
|
+
(*_es)[res] = SingleAbsValue::topConstant();
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
assert(!lhs.empty() && !rhs.empty() && "empty address?");
|
|
211
|
+
auto predicate = cmp->getPredicate();
|
|
212
|
+
switch (predicate)
|
|
213
|
+
{
|
|
214
|
+
case CmpStmt::ICMP_EQ:
|
|
215
|
+
case CmpStmt::FCMP_OEQ:
|
|
216
|
+
case CmpStmt::FCMP_UEQ:
|
|
217
|
+
{
|
|
218
|
+
if (lhs.size() == 1 && rhs.size() == 1)
|
|
219
|
+
{
|
|
220
|
+
(*_es)[res] = lhs == rhs;
|
|
221
|
+
}
|
|
222
|
+
else
|
|
223
|
+
{
|
|
224
|
+
if (lhs.hasIntersect(rhs))
|
|
225
|
+
{
|
|
226
|
+
(*_es)[res] = SingleAbsValue::topConstant();
|
|
227
|
+
}
|
|
228
|
+
else
|
|
229
|
+
{
|
|
230
|
+
(*_es)[res] = 0;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
case CmpStmt::ICMP_NE:
|
|
236
|
+
case CmpStmt::FCMP_ONE:
|
|
237
|
+
case CmpStmt::FCMP_UNE:
|
|
238
|
+
{
|
|
239
|
+
if (lhs.size() == 1 && rhs.size() == 1)
|
|
240
|
+
{
|
|
241
|
+
(*_es)[res] = lhs != rhs;
|
|
242
|
+
}
|
|
243
|
+
else
|
|
244
|
+
{
|
|
245
|
+
if (lhs.hasIntersect(rhs))
|
|
246
|
+
{
|
|
247
|
+
(*_es)[res] = SingleAbsValue::topConstant();
|
|
248
|
+
}
|
|
249
|
+
else
|
|
250
|
+
{
|
|
251
|
+
(*_es)[res] = 1;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
case CmpStmt::ICMP_UGT:
|
|
257
|
+
case CmpStmt::ICMP_SGT:
|
|
258
|
+
case CmpStmt::FCMP_OGT:
|
|
259
|
+
case CmpStmt::FCMP_UGT:
|
|
260
|
+
{
|
|
261
|
+
if (lhs.size() == 1 && rhs.size() == 1)
|
|
262
|
+
{
|
|
263
|
+
(*_es)[res] = *lhs.begin() > *rhs.begin();
|
|
264
|
+
}
|
|
265
|
+
else
|
|
266
|
+
{
|
|
267
|
+
(*_es)[res] = SingleAbsValue::topConstant();
|
|
268
|
+
}
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
case CmpStmt::ICMP_UGE:
|
|
272
|
+
case CmpStmt::ICMP_SGE:
|
|
273
|
+
case CmpStmt::FCMP_OGE:
|
|
274
|
+
case CmpStmt::FCMP_UGE:
|
|
275
|
+
{
|
|
276
|
+
if (lhs.size() == 1 && rhs.size() == 1)
|
|
277
|
+
{
|
|
278
|
+
(*_es)[res] = *lhs.begin() >= *rhs.begin();
|
|
279
|
+
}
|
|
280
|
+
else
|
|
281
|
+
{
|
|
282
|
+
(*_es)[res] = SingleAbsValue::topConstant();
|
|
283
|
+
}
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
case CmpStmt::ICMP_ULT:
|
|
287
|
+
case CmpStmt::ICMP_SLT:
|
|
288
|
+
case CmpStmt::FCMP_OLT:
|
|
289
|
+
case CmpStmt::FCMP_ULT:
|
|
290
|
+
{
|
|
291
|
+
if (lhs.size() == 1 && rhs.size() == 1)
|
|
292
|
+
{
|
|
293
|
+
(*_es)[res] = *lhs.begin() < *rhs.begin();
|
|
294
|
+
}
|
|
295
|
+
else
|
|
296
|
+
{
|
|
297
|
+
(*_es)[res] = SingleAbsValue::topConstant();
|
|
298
|
+
}
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
case CmpStmt::ICMP_ULE:
|
|
302
|
+
case CmpStmt::ICMP_SLE:
|
|
303
|
+
case CmpStmt::FCMP_OLE:
|
|
304
|
+
case CmpStmt::FCMP_ULE:
|
|
305
|
+
{
|
|
306
|
+
if (lhs.size() == 1 && rhs.size() == 1)
|
|
307
|
+
{
|
|
308
|
+
(*_es)[res] = *lhs.begin() <= *rhs.begin();
|
|
309
|
+
}
|
|
310
|
+
else
|
|
311
|
+
{
|
|
312
|
+
(*_es)[res] = SingleAbsValue::topConstant();
|
|
313
|
+
}
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
case CmpStmt::FCMP_FALSE:
|
|
317
|
+
(*_es)[res] = 0;
|
|
318
|
+
return;
|
|
319
|
+
case CmpStmt::FCMP_TRUE:
|
|
320
|
+
(*_es)[res] = 1;
|
|
321
|
+
return;
|
|
322
|
+
default:
|
|
323
|
+
{
|
|
324
|
+
assert(false && "undefined compare");
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
else if (inVarToAddrsTable(op0))
|
|
329
|
+
{
|
|
330
|
+
(*_es)[res] = SingleAbsValue::topConstant();
|
|
331
|
+
}
|
|
332
|
+
else if (inVarToAddrsTable(op1))
|
|
333
|
+
{
|
|
334
|
+
(*_es)[res] = SingleAbsValue::topConstant();
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/*!
|
|
339
|
+
* https://llvm.org/docs/LangRef.html#load-instruction
|
|
340
|
+
* @param load
|
|
341
|
+
* @return
|
|
342
|
+
*/
|
|
343
|
+
void SVFIR2ConsExeState::translateLoad(const LoadStmt *load)
|
|
344
|
+
{
|
|
345
|
+
u32_t rhs = load->getRHSVarID();
|
|
346
|
+
u32_t lhs = load->getLHSVarID();
|
|
347
|
+
if (inVarToAddrsTable(rhs))
|
|
348
|
+
{
|
|
349
|
+
const VAddrs &addrs = _es->getVAddrs(rhs);
|
|
350
|
+
for (const auto &addr: addrs)
|
|
351
|
+
{
|
|
352
|
+
assert(isVirtualMemAddress(addr) && "not addr?");
|
|
353
|
+
u32_t objId = getInternalID(addr);
|
|
354
|
+
if (load->getLHSVar()->getType() && load->getLHSVar()->getType()->isPointerTy())
|
|
355
|
+
{
|
|
356
|
+
if (inLocToAddrsTable(objId))
|
|
357
|
+
{
|
|
358
|
+
_es->getVAddrs(lhs).setBottom();
|
|
359
|
+
}
|
|
360
|
+
break;
|
|
361
|
+
}
|
|
362
|
+
else if (!load->getLHSVar()->getType() && inLocToAddrsTable(objId))
|
|
363
|
+
{
|
|
364
|
+
_es->getVAddrs(lhs).setBottom();
|
|
365
|
+
break;
|
|
366
|
+
}
|
|
367
|
+
else if (inLocToValTable(objId))
|
|
368
|
+
{
|
|
369
|
+
(*_es)[lhs] = SingleAbsValue::bottomConstant();
|
|
370
|
+
break;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
for (const auto &addr: addrs)
|
|
375
|
+
{
|
|
376
|
+
assert(isVirtualMemAddress(addr) && "not addr?");
|
|
377
|
+
u32_t objId = getInternalID(addr);
|
|
378
|
+
if (load->getLHSVar()->getType() && load->getLHSVar()->getType()->isPointerTy())
|
|
379
|
+
{
|
|
380
|
+
if (inLocToAddrsTable(objId))
|
|
381
|
+
{
|
|
382
|
+
if (!inVarToAddrsTable(lhs))
|
|
383
|
+
{
|
|
384
|
+
_es->getVAddrs(lhs) = _es->loadVAddrs(addr);
|
|
385
|
+
}
|
|
386
|
+
else
|
|
387
|
+
{
|
|
388
|
+
_es->getVAddrs(lhs).join_with(_es->loadVAddrs(addr));
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
else if (!load->getLHSVar()->getType() && inLocToAddrsTable(objId))
|
|
393
|
+
{
|
|
394
|
+
if (!inVarToAddrsTable(lhs))
|
|
395
|
+
{
|
|
396
|
+
_es->getVAddrs(lhs) = _es->loadVAddrs(addr);
|
|
397
|
+
}
|
|
398
|
+
else
|
|
399
|
+
{
|
|
400
|
+
_es->getVAddrs(lhs).join_with(_es->loadVAddrs(addr));
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
else if (inLocToValTable(objId))
|
|
404
|
+
{
|
|
405
|
+
if (!inVarToValTable(lhs))
|
|
406
|
+
{
|
|
407
|
+
(*_es)[lhs] = _es->load(SingleAbsValue(getVirtualMemAddress(objId)));
|
|
408
|
+
}
|
|
409
|
+
else
|
|
410
|
+
{
|
|
411
|
+
(*_es)[lhs].join_with(_es->load(SingleAbsValue(getVirtualMemAddress(objId))));
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/*!
|
|
419
|
+
* https://llvm.org/docs/LangRef.html#store-instruction
|
|
420
|
+
* @param store
|
|
421
|
+
* @return
|
|
422
|
+
*/
|
|
423
|
+
void SVFIR2ConsExeState::translateStore(const StoreStmt *store)
|
|
424
|
+
{
|
|
425
|
+
u32_t rhs = store->getRHSVarID();
|
|
426
|
+
u32_t lhs = store->getLHSVarID();
|
|
427
|
+
if (inVarToAddrsTable(lhs))
|
|
428
|
+
{
|
|
429
|
+
if (inVarToValTable(rhs))
|
|
430
|
+
{
|
|
431
|
+
const VAddrs &addrs = _es->getVAddrs(lhs);
|
|
432
|
+
for (const auto &addr: addrs)
|
|
433
|
+
{
|
|
434
|
+
assert(isVirtualMemAddress(addr) && "not addr?");
|
|
435
|
+
_es->store(SingleAbsValue(addr), (*_es)[rhs]);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
else if (inVarToAddrsTable(rhs))
|
|
439
|
+
{
|
|
440
|
+
const VAddrs &addrs = _es->getVAddrs(lhs);
|
|
441
|
+
for (const auto &addr: addrs)
|
|
442
|
+
{
|
|
443
|
+
assert(isVirtualMemAddress(addr) && "not addr?");
|
|
444
|
+
_es->storeVAddrs(addr, _es->getVAddrs(rhs));
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/*!
|
|
451
|
+
* https://llvm.org/docs/LangRef.html#conversion-operations
|
|
452
|
+
* @param copy
|
|
453
|
+
* @return
|
|
454
|
+
*/
|
|
455
|
+
void SVFIR2ConsExeState::translateCopy(const CopyStmt *copy)
|
|
456
|
+
{
|
|
457
|
+
u32_t lhs = copy->getLHSVarID();
|
|
458
|
+
u32_t rhs = copy->getRHSVarID();
|
|
459
|
+
if (PAG::getPAG()->isBlkPtr(lhs))
|
|
460
|
+
{
|
|
461
|
+
_es->globalConsES._varToVal[lhs] = SingleAbsValue::topConstant();
|
|
462
|
+
}
|
|
463
|
+
else
|
|
464
|
+
{
|
|
465
|
+
if (inVarToValTable(rhs))
|
|
466
|
+
{
|
|
467
|
+
(*_es)[lhs] = (*_es)[rhs];
|
|
468
|
+
}
|
|
469
|
+
else if (inVarToAddrsTable(rhs))
|
|
470
|
+
{
|
|
471
|
+
_es->getVAddrs(lhs) = _es->getVAddrs(rhs);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/*!
|
|
477
|
+
* https://llvm.org/docs/LangRef.html#call-instruction
|
|
478
|
+
* @param callPE
|
|
479
|
+
* @return
|
|
480
|
+
*/
|
|
481
|
+
void SVFIR2ConsExeState::translateCall(const CallPE *callPE)
|
|
482
|
+
{
|
|
483
|
+
NodeID lhs = callPE->getLHSVarID();
|
|
484
|
+
NodeID rhs = callPE->getRHSVarID();
|
|
485
|
+
if (inVarToValTable(rhs))
|
|
486
|
+
{
|
|
487
|
+
(*_es)[lhs] = (*_es)[rhs];
|
|
488
|
+
}
|
|
489
|
+
else if (inVarToAddrsTable(rhs))
|
|
490
|
+
{
|
|
491
|
+
_es->getVAddrs(lhs) = _es->getVAddrs(rhs);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
void SVFIR2ConsExeState::translateRet(const RetPE *retPE)
|
|
496
|
+
{
|
|
497
|
+
NodeID lhs = retPE->getLHSVarID();
|
|
498
|
+
NodeID rhs = retPE->getRHSVarID();
|
|
499
|
+
if (inVarToValTable(rhs))
|
|
500
|
+
{
|
|
501
|
+
(*_es)[lhs] = (*_es)[rhs];
|
|
502
|
+
}
|
|
503
|
+
else if (inVarToAddrsTable(rhs))
|
|
504
|
+
{
|
|
505
|
+
_es->getVAddrs(lhs) = _es->getVAddrs(rhs);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
/*!
|
|
510
|
+
* https://llvm.org/docs/LangRef.html#getelementptr-instruction
|
|
511
|
+
* @param gep
|
|
512
|
+
* @return
|
|
513
|
+
*/
|
|
514
|
+
void SVFIR2ConsExeState::translateGep(const GepStmt *gep, bool isGlobal)
|
|
515
|
+
{
|
|
516
|
+
u32_t rhs = gep->getRHSVarID();
|
|
517
|
+
u32_t lhs = gep->getLHSVarID();
|
|
518
|
+
// rhs is not initialized
|
|
519
|
+
if (!inVarToAddrsTable(rhs)) return;
|
|
520
|
+
const VAddrs &rhsVal = _es->getVAddrs(rhs);
|
|
521
|
+
if (rhsVal.empty()) return;
|
|
522
|
+
std::pair<s32_t, s32_t> offset = getGepOffset(gep);
|
|
523
|
+
if (offset.first == -1 && offset.second == -1) return;
|
|
524
|
+
if (!isVirtualMemAddress(*rhsVal.begin()))
|
|
525
|
+
{
|
|
526
|
+
return;
|
|
527
|
+
}
|
|
528
|
+
VAddrs gepAddrs;
|
|
529
|
+
s32_t ub = offset.second;
|
|
530
|
+
if (offset.second > (s32_t) Options::MaxFieldLimit() - 1)
|
|
531
|
+
{
|
|
532
|
+
ub = Options::MaxFieldLimit() - 1;
|
|
533
|
+
}
|
|
534
|
+
for (s32_t i = offset.first; i <= ub; i++)
|
|
535
|
+
{
|
|
536
|
+
gepAddrs.join_with(getGepObjAddress(rhs, i));
|
|
537
|
+
}
|
|
538
|
+
if (gepAddrs.empty()) return;
|
|
539
|
+
_es->getVAddrs(lhs) = gepAddrs;
|
|
540
|
+
return;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
/*!
|
|
544
|
+
* https://llvm.org/docs/LangRef.html#select-instruction
|
|
545
|
+
* @param select
|
|
546
|
+
* @return
|
|
547
|
+
*/
|
|
548
|
+
void SVFIR2ConsExeState::translateSelect(const SelectStmt *select)
|
|
549
|
+
{
|
|
550
|
+
u32_t res = select->getResID();
|
|
551
|
+
u32_t tval = select->getTrueValue()->getId();
|
|
552
|
+
u32_t fval = select->getFalseValue()->getId();
|
|
553
|
+
u32_t cond = select->getCondition()->getId();
|
|
554
|
+
_es->applySelect(res, cond, tval, fval);
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
/*!
|
|
558
|
+
* https://llvm.org/docs/LangRef.html#i-phi
|
|
559
|
+
* @param phi
|
|
560
|
+
* @return
|
|
561
|
+
*/
|
|
562
|
+
void SVFIR2ConsExeState::translatePhi(const PhiStmt *phi)
|
|
563
|
+
{
|
|
564
|
+
u32_t res = phi->getResID();
|
|
565
|
+
std::vector<u32_t> ops;
|
|
566
|
+
for (u32_t i = 0; i < phi->getOpVarNum(); i++)
|
|
567
|
+
{
|
|
568
|
+
ops.push_back(phi->getOpVarID(i));
|
|
569
|
+
}
|
|
570
|
+
_es->applyPhi(res, ops);
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
//%}
|
|
574
|
+
//%}
|
|
575
|
+
|
|
576
|
+
/*!
|
|
577
|
+
* Return the expr of gep object given a base and offset
|
|
578
|
+
* @param base
|
|
579
|
+
* @param offset
|
|
580
|
+
* @return
|
|
581
|
+
*/
|
|
582
|
+
SVFIR2ConsExeState::VAddrs SVFIR2ConsExeState::getGepObjAddress(u32_t base, u32_t offset)
|
|
583
|
+
{
|
|
584
|
+
const VAddrs &addrs = _es->getVAddrs(base);
|
|
585
|
+
VAddrs ret;
|
|
586
|
+
for (const auto &addr: addrs)
|
|
587
|
+
{
|
|
588
|
+
int64_t baseObj = getInternalID(addr);
|
|
589
|
+
if (baseObj == 0)
|
|
590
|
+
{
|
|
591
|
+
ret.insert(getVirtualMemAddress(0));
|
|
592
|
+
continue;
|
|
593
|
+
}
|
|
594
|
+
assert(SVFUtil::isa<ObjVar>(PAG::getPAG()->getGNode(baseObj)) && "Fail to get the base object address!");
|
|
595
|
+
NodeID gepObj = PAG::getPAG()->getGepObjVar(baseObj, offset);
|
|
596
|
+
initSVFVar(gepObj);
|
|
597
|
+
if (offset == 0 && baseObj != gepObj) _es->getVAddrs(gepObj) = _es->getVAddrs(base);
|
|
598
|
+
ret.insert(getVirtualMemAddress(gepObj));
|
|
599
|
+
}
|
|
600
|
+
return ret;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
/*!
|
|
604
|
+
* Return the offset expression of a GepStmt
|
|
605
|
+
* @param gep
|
|
606
|
+
* @return
|
|
607
|
+
*/
|
|
608
|
+
std::pair<s32_t, s32_t> SVFIR2ConsExeState::getGepOffset(const SVF::GepStmt *gep)
|
|
609
|
+
{
|
|
610
|
+
/// for instant constant index, e.g. gep arr, 1
|
|
611
|
+
if (gep->getOffsetVarAndGepTypePairVec().empty())
|
|
612
|
+
return std::make_pair(gep->getConstantFieldIdx(), gep->getConstantFieldIdx());
|
|
613
|
+
|
|
614
|
+
s32_t totalOffset = 0;
|
|
615
|
+
/// default value of MaxFieldLimit is 512
|
|
616
|
+
u32_t maxFieldLimit = Options::MaxFieldLimit() - 1;
|
|
617
|
+
/// for variable index and nested indexes, e.g. 1) gep arr, idx 2) gep arr idx0, idx1
|
|
618
|
+
for (int i = gep->getOffsetVarAndGepTypePairVec().size() - 1; i >= 0; i--)
|
|
619
|
+
{
|
|
620
|
+
const SVFValue *value = gep->getOffsetVarAndGepTypePairVec()[i].first->getValue();
|
|
621
|
+
const SVFType *type = gep->getOffsetVarAndGepTypePairVec()[i].second;
|
|
622
|
+
const SVFConstantInt *op = SVFUtil::dyn_cast<SVFConstantInt>(value);
|
|
623
|
+
s32_t offset = 0;
|
|
624
|
+
/// offset is constant but stored in variable
|
|
625
|
+
if (op)
|
|
626
|
+
{
|
|
627
|
+
offset = op->getSExtValue();
|
|
628
|
+
}
|
|
629
|
+
/// offset is variable, the concrete value isn't sure util runtime, and maybe not a concrete value.
|
|
630
|
+
/// e.g.
|
|
631
|
+
else
|
|
632
|
+
{
|
|
633
|
+
u32_t idx = PAG::getPAG()->getValueNode(value);
|
|
634
|
+
if (!inVarToValTable(idx)) return std::make_pair(-1, -1);
|
|
635
|
+
if ((*_es)[idx].isBottom() || (*_es)[idx].isTop() || (*_es)[idx].isSym())
|
|
636
|
+
{
|
|
637
|
+
return std::make_pair(0, (s32_t) Options::MaxFieldLimit());
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
// if idxVal is a concrete value
|
|
641
|
+
offset = ConsExeState::z3Expr2NumValue((*_es)[idx]);
|
|
642
|
+
}
|
|
643
|
+
if (type == nullptr)
|
|
644
|
+
{
|
|
645
|
+
if ((long long) (totalOffset + offset) > maxFieldLimit)
|
|
646
|
+
{
|
|
647
|
+
totalOffset = maxFieldLimit;
|
|
648
|
+
}
|
|
649
|
+
else
|
|
650
|
+
{
|
|
651
|
+
totalOffset += offset;
|
|
652
|
+
}
|
|
653
|
+
continue;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
if (const SVFPointerType *pty = SVFUtil::dyn_cast<SVFPointerType>(type))
|
|
657
|
+
{
|
|
658
|
+
offset = offset * gep->getLocationSet().getElementNum(pty->getPtrElementType());
|
|
659
|
+
}
|
|
660
|
+
else
|
|
661
|
+
{
|
|
662
|
+
const std::vector<u32_t> &so = SymbolTableInfo::SymbolInfo()->getTypeInfo(
|
|
663
|
+
type)->getFlattenedElemIdxVec();
|
|
664
|
+
if (so.empty() || (u32_t) offset >= so.size())
|
|
665
|
+
return std::make_pair(-1, -1);
|
|
666
|
+
offset = SymbolTableInfo::SymbolInfo()->getFlattenedElemIdx(type, offset);
|
|
667
|
+
}
|
|
668
|
+
if ((long long) (totalOffset + offset) > maxFieldLimit)
|
|
669
|
+
{
|
|
670
|
+
totalOffset = maxFieldLimit;
|
|
671
|
+
}
|
|
672
|
+
else
|
|
673
|
+
{
|
|
674
|
+
totalOffset += offset;
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
std::pair<s32_t, s32_t> offSetPair;
|
|
678
|
+
offSetPair.first = totalOffset;
|
|
679
|
+
offSetPair.second = totalOffset;
|
|
680
|
+
return offSetPair;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
|
|
684
|
+
void SVFIR2ConsExeState::initValVar(const ValVar *valVar, u32_t varId)
|
|
685
|
+
{
|
|
686
|
+
|
|
687
|
+
SVFIR *svfir = PAG::getPAG();
|
|
688
|
+
|
|
689
|
+
if (const SVFType *type = valVar->getType())
|
|
690
|
+
{
|
|
691
|
+
// TODO:miss floatpointerty, voidty, labelty, matadataty
|
|
692
|
+
if (type->getKind() == SVFType::SVFIntegerTy ||
|
|
693
|
+
type->getKind() == SVFType::SVFPointerTy ||
|
|
694
|
+
type->getKind() == SVFType::SVFFunctionTy ||
|
|
695
|
+
type->getKind() == SVFType::SVFStructTy ||
|
|
696
|
+
type->getKind() == SVFType::SVFArrayTy)
|
|
697
|
+
// continue with null expression
|
|
698
|
+
(*_es)[varId] = SingleAbsValue::topConstant();
|
|
699
|
+
else
|
|
700
|
+
{
|
|
701
|
+
|
|
702
|
+
SVFUtil::errs() << valVar->getValue()->toString() << "\n" << " type: " << type->toString() << "\n";
|
|
703
|
+
assert(false && "what other types we have");
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
else
|
|
707
|
+
{
|
|
708
|
+
if (svfir->getNullPtr() == valVar->getId())
|
|
709
|
+
(*_es)[varId] = 0;
|
|
710
|
+
else
|
|
711
|
+
(*_es)[varId] = SingleAbsValue::topConstant();
|
|
712
|
+
assert(SVFUtil::isa<DummyValVar>(valVar) && "not a DummValVar if it has no type?");
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
/*!
|
|
717
|
+
* Init Z3Expr for ObjVar
|
|
718
|
+
* @param objVar
|
|
719
|
+
* @param valExprIdToCondValPairMap
|
|
720
|
+
*/
|
|
721
|
+
void SVFIR2ConsExeState::initObjVar(const ObjVar *objVar, u32_t varId)
|
|
722
|
+
{
|
|
723
|
+
if (objVar->hasValue())
|
|
724
|
+
{
|
|
725
|
+
const MemObj *obj = objVar->getMemObj();
|
|
726
|
+
/// constant data
|
|
727
|
+
if (obj->isConstDataOrAggData() || obj->isConstantArray() || obj->isConstantStruct())
|
|
728
|
+
{
|
|
729
|
+
if (const SVFConstantInt *consInt = SVFUtil::dyn_cast<SVFConstantInt>(obj->getValue()))
|
|
730
|
+
{
|
|
731
|
+
_es->globalConsES._varToVal[varId] = consInt->getSExtValue();
|
|
732
|
+
}
|
|
733
|
+
else if (const SVFConstantFP *consFP = SVFUtil::dyn_cast<SVFConstantFP>(obj->getValue()))
|
|
734
|
+
_es->globalConsES._varToVal[varId] = consFP->getFPValue();
|
|
735
|
+
else if (SVFUtil::isa<SVFConstantNullPtr>(obj->getValue()))
|
|
736
|
+
_es->globalConsES._varToVal[varId] = 0;
|
|
737
|
+
else if (SVFUtil::isa<SVFGlobalValue>(obj->getValue()))
|
|
738
|
+
_es->globalConsES._varToVAddrs[varId] = getVirtualMemAddress(varId);
|
|
739
|
+
else if (obj->isConstDataOrAggData())
|
|
740
|
+
{
|
|
741
|
+
// TODO
|
|
742
|
+
// assert(false && "implement this part");
|
|
743
|
+
_es->globalConsES._varToVal[varId] = SingleAbsValue::topConstant();
|
|
744
|
+
}
|
|
745
|
+
else
|
|
746
|
+
{
|
|
747
|
+
_es->globalConsES._varToVal[varId] = SingleAbsValue::topConstant();
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
else
|
|
751
|
+
{
|
|
752
|
+
_es->globalConsES._varToVAddrs[varId] = getVirtualMemAddress(varId);
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
else
|
|
756
|
+
{
|
|
757
|
+
_es->globalConsES._varToVAddrs[varId] = getVirtualMemAddress(varId);
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
|
|
762
|
+
void SVFIR2ConsExeState::initSVFVar(u32_t varId)
|
|
763
|
+
{
|
|
764
|
+
if (_es->inVarToVal(varId)) return;
|
|
765
|
+
SVFIR *svfir = PAG::getPAG();
|
|
766
|
+
SVFVar *svfVar = svfir->getGNode(varId);
|
|
767
|
+
// write objvar into cache instead of exestate
|
|
768
|
+
if (const ObjVar *objVar = dyn_cast<ObjVar>(svfVar))
|
|
769
|
+
{
|
|
770
|
+
initObjVar(objVar, varId);
|
|
771
|
+
return;
|
|
772
|
+
}
|
|
773
|
+
else if (const ValVar *valVar = dyn_cast<ValVar>(svfVar))
|
|
774
|
+
{
|
|
775
|
+
initValVar(valVar, varId);
|
|
776
|
+
return;
|
|
777
|
+
}
|
|
778
|
+
else
|
|
779
|
+
{
|
|
780
|
+
initValVar(valVar, varId);
|
|
781
|
+
return;
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
void SVFIR2ConsExeState::moveToGlobal()
|
|
786
|
+
{
|
|
787
|
+
for (const auto &it: _es->_varToVal)
|
|
788
|
+
{
|
|
789
|
+
ConsExeState::globalConsES._varToVal.insert(it);
|
|
790
|
+
}
|
|
791
|
+
for (const auto &it: _es->_locToVal)
|
|
792
|
+
{
|
|
793
|
+
ConsExeState::globalConsES._locToVal.insert(it);
|
|
794
|
+
}
|
|
795
|
+
for (const auto &it: _es->_varToVAddrs)
|
|
796
|
+
{
|
|
797
|
+
ConsExeState::globalConsES._varToVAddrs.insert(it);
|
|
798
|
+
}
|
|
799
|
+
for (const auto &it: _es->_locToVAddrs)
|
|
800
|
+
{
|
|
801
|
+
ConsExeState::globalConsES._locToVAddrs.insert(it);
|
|
802
|
+
}
|
|
803
|
+
ConsExeState::globalConsES._varToVAddrs[0] = ConsExeState::getVirtualMemAddress(0);
|
|
804
|
+
_es->_varToVal.clear();
|
|
805
|
+
_es->_locToVal.clear();
|
|
806
|
+
_es->_varToVAddrs.clear();
|
|
807
|
+
_es->_locToVAddrs.clear();
|
|
808
|
+
}
|