Static Value-Flow Analysis
Loading...
Searching...
No Matches
AbstractState.cpp
Go to the documentation of this file.
1//===- IntervalExeState.cpp----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 * AbstractExeState.cpp
24 *
25 * Created on: Jul 9, 2022
26 * Author: Xiao Cheng, Jiawei Wang
27 *
28 */
29
32#include "Util/Options.h"
33#include "Util/SVFUtil.h"
34#include "Util/Options.h"
35
36using namespace SVF;
37using namespace SVFUtil;
38
40{
41 return *this == other;
42}
43
45{
46 size_t h = getVarToVal().size() * 2;
48 for (const auto &t: getVarToVal())
49 {
50 h ^= hf(t.first) + 0x9e3779b9 + (h << 6) + (h >> 2);
51 }
52 size_t h2 = getLocToVal().size() * 2;
53 for (const auto &t: getLocToVal())
54 {
55 h2 ^= hf(t.first) + 0x9e3779b9 + (h2 << 6) + (h2 >> 2);
56 }
58 return pairH({h, h2});
59}
60
62{
63 // widen interval
64 AbstractState es = *this;
65 for (auto it = es._varToAbsVal.begin(); it != es._varToAbsVal.end(); ++it)
66 {
67 auto key = it->first;
68 if (other._varToAbsVal.find(key) != other._varToAbsVal.end())
69 if (it->second.isInterval() && other._varToAbsVal.at(key).isInterval())
70 it->second.getInterval().widen_with(other._varToAbsVal.at(key).getInterval());
71 }
72 for (auto it = es._addrToAbsVal.begin(); it != es._addrToAbsVal.end(); ++it)
73 {
74 auto key = it->first;
75 if (other._addrToAbsVal.find(key) != other._addrToAbsVal.end())
76 if (it->second.isInterval() && other._addrToAbsVal.at(key).isInterval())
77 it->second.getInterval().widen_with(other._addrToAbsVal.at(key).getInterval());
78 }
79 return es;
80}
81
83{
84 AbstractState es = *this;
85 for (auto it = es._varToAbsVal.begin(); it != es._varToAbsVal.end(); ++it)
86 {
87 auto key = it->first;
88 if (other._varToAbsVal.find(key) != other._varToAbsVal.end())
89 if (it->second.isInterval() && other._varToAbsVal.at(key).isInterval())
90 it->second.getInterval().narrow_with(other._varToAbsVal.at(key).getInterval());
91 }
92 for (auto it = es._addrToAbsVal.begin(); it != es._addrToAbsVal.end(); ++it)
93 {
94 auto key = it->first;
95 if (other._addrToAbsVal.find(key) != other._addrToAbsVal.end())
96 if (it->second.isInterval() && other._addrToAbsVal.at(key).isInterval())
97 it->second.getInterval().narrow_with(other._addrToAbsVal.at(key).getInterval());
98 }
99 return es;
100
101}
102
105{
106 // In semi-sparse mode, skip ValVar (_varToAbsVal) merge — ValVars are
107 // pulled on demand from def-sites via getAbstractValue.
108 // In dense mode, merge everything.
110 {
111 for (auto it = other._varToAbsVal.begin(); it != other._varToAbsVal.end(); ++it)
112 {
113 auto key = it->first;
114 auto oit = _varToAbsVal.find(key);
115 if (oit != _varToAbsVal.end())
116 {
117 oit->second.join_with(it->second);
118 }
119 else
120 {
121 _varToAbsVal.emplace(key, it->second);
122 }
123 }
124 }
125 for (auto it = other._addrToAbsVal.begin(); it != other._addrToAbsVal.end(); ++it)
126 {
127 auto key = it->first;
128 auto oit = _addrToAbsVal.find(key);
129 if (oit != _addrToAbsVal.end())
130 {
131 oit->second.join_with(it->second);
132 }
133 else
134 {
135 _addrToAbsVal.emplace(key, it->second);
136 }
137 }
138 _freedAddrs.insert(other._freedAddrs.begin(), other._freedAddrs.end());
139}
140
143{
144 for (auto it = other._varToAbsVal.begin(); it != other._varToAbsVal.end(); ++it)
145 {
146 auto key = it->first;
147 auto oit = _varToAbsVal.find(key);
148 if (oit != _varToAbsVal.end())
149 {
150 oit->second.meet_with(it->second);
151 }
152 }
153 for (auto it = other._addrToAbsVal.begin(); it != other._addrToAbsVal.end(); ++it)
154 {
155 auto key = it->first;
156 auto oit = _addrToAbsVal.find(key);
157 if (oit != _addrToAbsVal.end())
158 {
159 oit->second.meet_with(it->second);
160 }
161 }
163 std::set_intersection(_freedAddrs.begin(), _freedAddrs.end(),
164 other._freedAddrs.begin(), other._freedAddrs.end(),
165 std::inserter(intersection, intersection.begin()));
166 _freedAddrs = std::move(intersection);
167}
168
169// initObjVar
171{
172 NodeID varId = objVar->getId();
173
174 // Check if the object variable has an associated value
175
176 const BaseObjVar* obj = PAG::getPAG()->getBaseObject(objVar->getId());
177
178 // Handle constant data, arrays, and structures
179 if (obj->isConstDataOrConstGlobal() || obj->isConstantArray() || obj->isConstantStruct())
180 {
181 if (const ConstIntObjVar* consInt = SVFUtil::dyn_cast<ConstIntObjVar>(objVar))
182 {
183 s64_t numeral = consInt->getSExtValue();
184 (*this)[varId] = IntervalValue(numeral, numeral);
185 }
186 else if (const ConstFPObjVar* consFP = SVFUtil::dyn_cast<ConstFPObjVar>(objVar))
187 {
188 (*this)[varId] = IntervalValue(consFP->getFPValue(), consFP->getFPValue());
189 }
190 else if (SVFUtil::isa<ConstNullPtrObjVar>(objVar))
191 {
192 (*this)[varId] = IntervalValue(0, 0);
193 }
194 else if (SVFUtil::isa<GlobalObjVar>(objVar))
195 {
197 }
198 else if (obj->isConstantArray() || obj->isConstantStruct())
199 {
200 (*this)[varId] = IntervalValue::top();
201 }
202 else
203 {
204 (*this)[varId] = IntervalValue::top();
205 }
206 }
207 // Handle non-constant memory objects
208 else
209 {
211 }
212 return;
213}
214
216{
217 SVFUtil::outs() << "-----------Var and Value-----------\n";
218 u32_t fieldWidth = 20;
219 SVFUtil::outs().flags(std::ios::left);
220 std::vector<std::pair<u32_t, AbstractValue>> varToAbsValVec(_varToAbsVal.begin(), _varToAbsVal.end());
221 std::sort(varToAbsValVec.begin(), varToAbsValVec.end(), [](const auto &a, const auto &b)
222 {
223 return a.first < b.first;
224 });
225 for (const auto &item: varToAbsValVec)
226 {
227 SVFUtil::outs() << std::left << std::setw(fieldWidth) << ("Var" + std::to_string(item.first));
228 if (item.second.isInterval())
229 {
230 SVFUtil::outs() << " Value: " << item.second.getInterval().toString() << "\n";
231 }
232 else if (item.second.isAddr())
233 {
234 SVFUtil::outs() << " Value: {";
235 u32_t i = 0;
236 for (const auto& addr: item.second.getAddrs())
237 {
238 ++i;
239 if (i < item.second.getAddrs().size())
240 {
241 SVFUtil::outs() << "0x" << std::hex << addr << ", ";
242 }
243 else
244 {
245 SVFUtil::outs() << "0x" << std::hex << addr;
246 }
247 }
248 SVFUtil::outs() << "}\n";
249 }
250 else
251 {
252 SVFUtil::outs() << " Value: ⊥\n";
253 }
254 }
255
256 std::vector<std::pair<u32_t, AbstractValue>> addrToAbsValVec(_addrToAbsVal.begin(), _addrToAbsVal.end());
257 std::sort(addrToAbsValVec.begin(), addrToAbsValVec.end(), [](const auto &a, const auto &b)
258 {
259 return a.first < b.first;
260 });
261
262 for (const auto& item: addrToAbsValVec)
263 {
264 std::ostringstream oss;
265 oss << "0x" << std::hex << AbstractState::getVirtualMemAddress(item.first);
266 SVFUtil::outs() << std::left << std::setw(fieldWidth) << oss.str();
267 if (item.second.isInterval())
268 {
269 SVFUtil::outs() << " Value: " << item.second.getInterval().toString() << "\n";
270 }
271 else if (item.second.isAddr())
272 {
273 SVFUtil::outs() << " Value: {";
274 u32_t i = 0;
275 for (const auto& addr: item.second.getAddrs())
276 {
277 ++i;
278 if (i < item.second.getAddrs().size())
279 {
280 SVFUtil::outs() << "0x" << std::hex << addr << ", ";
281 }
282 else
283 {
284 SVFUtil::outs() << "0x" << std::hex << addr;
285 }
286 }
287 SVFUtil::outs() << "}\n";
288 }
289 else
290 {
291 SVFUtil::outs() << " Value: ⊥\n";
292 }
293 }
294 SVFUtil::outs() << "-----------------------------------------\n";
295}
296
297std::string AbstractState::toString() const
298{
299 u32_t varIntervals = 0, varAddrs = 0, varBottom = 0;
300 for (const auto& item : _varToAbsVal)
301 {
302 if (item.second.isInterval()) ++varIntervals;
303 else if (item.second.isAddr()) ++varAddrs;
304 else ++varBottom;
305 }
307 for (const auto& item : _addrToAbsVal)
308 {
309 if (item.second.isInterval()) ++addrIntervals;
310 else if (item.second.isAddr()) ++addrAddrs;
311 else ++addrBottom;
312 }
313 std::ostringstream oss;
314 oss << "AbstractState {\n"
315 << " VarToAbsVal: " << _varToAbsVal.size() << " entries ("
316 << varIntervals << " intervals, " << varAddrs << " addresses, " << varBottom << " bottom)\n"
317 << " AddrToAbsVal: " << _addrToAbsVal.size() << " entries ("
318 << addrIntervals << " intervals, " << addrAddrs << " addresses, " << addrBottom << " bottom)\n"
319 << " FreedAddrs: " << _freedAddrs.size() << "\n"
320 << "}";
321 return oss.str();
322}
323
324
326{
327 if (lhs.size() != rhs.size()) return false;
328 for (const auto &item: lhs)
329 {
330 auto it = rhs.find(item.first);
331 if (it == rhs.end())
332 return false;
333 if (!item.second.equals(it->second))
334 return false;
335 }
336 return true;
337}
338
340{
341 if (rhs.empty()) return true;
342 for (const auto &item: rhs)
343 {
344 auto it = lhs.find(item.first);
345 if (it == lhs.end()) return false;
346 if (!it->second.getInterval().contain(
347 item.second.getInterval()))
348 return false;
349 }
350 return true;
351}
cJSON * a
Definition cJSON.cpp:2560
const cJSON *const b
Definition cJSON.h:255
cJSON * item
Definition cJSON.h:222
const AddrToAbsValMap & getLocToVal() const
get loc2val map
const VarToAbsValMap & getVarToVal() const
get var2val map
std::string toString() const
void printAbstractState() const
void joinWith(const AbstractState &other)
domain join with other, important! other widen this.
bool eqVarToValMap(const VarToAbsValMap &lhs, const VarToAbsValMap &rhs) const
bool equals(const AbstractState &other) const
bool geqVarToValMap(const VarToAbsValMap &lhs, const VarToAbsValMap &rhs) const
VarToAbsValMap _varToAbsVal
Map a variable (symbol) to its abstract value.
Set< NodeID > _freedAddrs
void initObjVar(const ObjVar *objVar)
AddrToAbsValMap _addrToAbsVal
Map a memory address to its stored abstract value.
static u32_t getVirtualMemAddress(u32_t idx)
The physical address starts with 0x7f...... + idx.
AbstractState narrowing(const AbstractState &other)
domain narrow with other, and return the narrowed domain
Map< u32_t, AbstractValue > VarToAbsValMap
void meetWith(const AbstractState &other)
domain meet with other, important! other widen this.
AbstractState widening(const AbstractState &other)
domain widen with other, and return the widened domain
static IntervalValue top()
Create the IntervalValue [-inf, +inf].
static const OptionMap< u32_t > AESparsity
Definition Options.h:243
const BaseObjVar * getBaseObject(NodeID id) const
Definition SVFIR.h:496
static SVFIR * getPAG(bool buildFromFile=false)
Singleton design here to make sure we only have one instance during any analysis.
Definition SVFIR.h:118
std::ostream & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:52
for isBitcode
Definition BasicTypes.h:70
u32_t NodeID
Definition GeneralType.h:56
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:76
unsigned u32_t
Definition GeneralType.h:47
signed long long s64_t
Definition GeneralType.h:50