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
30#include <iomanip>
32#include "SVFIR/SVFIR.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 for (auto it = other._varToAbsVal.begin(); it != other._varToAbsVal.end(); ++it)
107 {
108 auto key = it->first;
109 auto oit = _varToAbsVal.find(key);
110 if (oit != _varToAbsVal.end())
111 {
112 oit->second.join_with(it->second);
113 }
114 else
115 {
116 _varToAbsVal.emplace(key, it->second);
117 }
118 }
119 for (auto it = other._addrToAbsVal.begin(); it != other._addrToAbsVal.end(); ++it)
120 {
121 auto key = it->first;
122 auto oit = _addrToAbsVal.find(key);
123 if (oit != _addrToAbsVal.end())
124 {
125 oit->second.join_with(it->second);
126 }
127 else
128 {
129 _addrToAbsVal.emplace(key, it->second);
130 }
131 }
132 _freedAddrs.insert(other._freedAddrs.begin(), other._freedAddrs.end());
133}
134
137{
138 for (auto it = other._varToAbsVal.begin(); it != other._varToAbsVal.end(); ++it)
139 {
140 auto key = it->first;
141 auto oit = _varToAbsVal.find(key);
142 if (oit != _varToAbsVal.end())
143 {
144 oit->second.meet_with(it->second);
145 }
146 }
147 for (auto it = other._addrToAbsVal.begin(); it != other._addrToAbsVal.end(); ++it)
148 {
149 auto key = it->first;
150 auto oit = _addrToAbsVal.find(key);
151 if (oit != _addrToAbsVal.end())
152 {
153 oit->second.meet_with(it->second);
154 }
155 }
157 std::set_intersection(_freedAddrs.begin(), _freedAddrs.end(),
158 other._freedAddrs.begin(), other._freedAddrs.end(),
159 std::inserter(intersection, intersection.begin()));
160 _freedAddrs = std::move(intersection);
161}
162
163// initObjVar
165{
166 NodeID varId = objVar->getId();
167
168 // Check if the object variable has an associated value
169
170 const BaseObjVar* obj = PAG::getPAG()->getBaseObject(objVar->getId());
171
172 // Handle constant data, arrays, and structures
173 if (obj->isConstDataOrConstGlobal() || obj->isConstantArray() || obj->isConstantStruct())
174 {
175 if (const ConstIntObjVar* consInt = SVFUtil::dyn_cast<ConstIntObjVar>(objVar))
176 {
177 s64_t numeral = consInt->getSExtValue();
178 (*this)[varId] = IntervalValue(numeral, numeral);
179 }
180 else if (const ConstFPObjVar* consFP = SVFUtil::dyn_cast<ConstFPObjVar>(objVar))
181 {
182 (*this)[varId] = IntervalValue(consFP->getFPValue(), consFP->getFPValue());
183 }
184 else if (SVFUtil::isa<ConstNullPtrObjVar>(objVar))
185 {
186 (*this)[varId] = IntervalValue(0, 0);
187 }
188 else if (SVFUtil::isa<GlobalObjVar>(objVar))
189 {
191 }
192 else if (obj->isConstantArray() || obj->isConstantStruct())
193 {
194 (*this)[varId] = IntervalValue::top();
195 }
196 else
197 {
198 (*this)[varId] = IntervalValue::top();
199 }
200 }
201 // Handle non-constant memory objects
202 else
203 {
205 }
206 return;
207}
208
210{
211 SVFUtil::outs() << "-----------Var and Value-----------\n";
212 u32_t fieldWidth = 20;
213 SVFUtil::outs().flags(std::ios::left);
214 std::vector<std::pair<u32_t, AbstractValue>> varToAbsValVec(_varToAbsVal.begin(), _varToAbsVal.end());
215 std::sort(varToAbsValVec.begin(), varToAbsValVec.end(), [](const auto &a, const auto &b)
216 {
217 return a.first < b.first;
218 });
219 for (const auto &item: varToAbsValVec)
220 {
221 SVFUtil::outs() << std::left << std::setw(fieldWidth) << ("Var" + std::to_string(item.first));
222 if (item.second.isInterval())
223 {
224 SVFUtil::outs() << " Value: " << item.second.getInterval().toString() << "\n";
225 }
226 else if (item.second.isAddr())
227 {
228 SVFUtil::outs() << " Value: {";
229 u32_t i = 0;
230 for (const auto& addr: item.second.getAddrs())
231 {
232 ++i;
233 if (i < item.second.getAddrs().size())
234 {
235 SVFUtil::outs() << "0x" << std::hex << addr << ", ";
236 }
237 else
238 {
239 SVFUtil::outs() << "0x" << std::hex << addr;
240 }
241 }
242 SVFUtil::outs() << "}\n";
243 }
244 else
245 {
246 SVFUtil::outs() << " Value: ⊥\n";
247 }
248 }
249
250 std::vector<std::pair<u32_t, AbstractValue>> addrToAbsValVec(_addrToAbsVal.begin(), _addrToAbsVal.end());
251 std::sort(addrToAbsValVec.begin(), addrToAbsValVec.end(), [](const auto &a, const auto &b)
252 {
253 return a.first < b.first;
254 });
255
256 for (const auto& item: addrToAbsValVec)
257 {
258 std::ostringstream oss;
259 oss << "0x" << std::hex << AbstractState::getVirtualMemAddress(item.first);
260 SVFUtil::outs() << std::left << std::setw(fieldWidth) << oss.str();
261 if (item.second.isInterval())
262 {
263 SVFUtil::outs() << " Value: " << item.second.getInterval().toString() << "\n";
264 }
265 else if (item.second.isAddr())
266 {
267 SVFUtil::outs() << " Value: {";
268 u32_t i = 0;
269 for (const auto& addr: item.second.getAddrs())
270 {
271 ++i;
272 if (i < item.second.getAddrs().size())
273 {
274 SVFUtil::outs() << "0x" << std::hex << addr << ", ";
275 }
276 else
277 {
278 SVFUtil::outs() << "0x" << std::hex << addr;
279 }
280 }
281 SVFUtil::outs() << "}\n";
282 }
283 else
284 {
285 SVFUtil::outs() << " Value: ⊥\n";
286 }
287 }
288 SVFUtil::outs() << "-----------------------------------------\n";
289}
290
291std::string AbstractState::toString() const
292{
293 u32_t varIntervals = 0, varAddrs = 0, varBottom = 0;
294 for (const auto& item : _varToAbsVal)
295 {
296 if (item.second.isInterval()) ++varIntervals;
297 else if (item.second.isAddr()) ++varAddrs;
298 else ++varBottom;
299 }
301 for (const auto& item : _addrToAbsVal)
302 {
303 if (item.second.isInterval()) ++addrIntervals;
304 else if (item.second.isAddr()) ++addrAddrs;
305 else ++addrBottom;
306 }
307 std::ostringstream oss;
308 oss << "AbstractState {\n"
309 << " VarToAbsVal: " << _varToAbsVal.size() << " entries ("
310 << varIntervals << " intervals, " << varAddrs << " addresses, " << varBottom << " bottom)\n"
311 << " AddrToAbsVal: " << _addrToAbsVal.size() << " entries ("
312 << addrIntervals << " intervals, " << addrAddrs << " addresses, " << addrBottom << " bottom)\n"
313 << " FreedAddrs: " << _freedAddrs.size() << "\n"
314 << "}";
315 return oss.str();
316}
317
318
320{
321 if (lhs.size() != rhs.size()) return false;
322 for (const auto &item: lhs)
323 {
324 auto it = rhs.find(item.first);
325 if (it == rhs.end())
326 return false;
327 if (!item.second.equals(it->second))
328 return false;
329 }
330 return true;
331}
332
334{
335 if (rhs.empty()) return true;
336 for (const auto &item: rhs)
337 {
338 auto it = lhs.find(item.first);
339 if (it == lhs.end()) return false;
340 if (!it->second.getInterval().contain(
341 item.second.getInterval()))
342 return false;
343 }
344 return true;
345}
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].
const BaseObjVar * getBaseObject(NodeID id) const
Definition SVFIR.h:498
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::ostream & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:52
for isBitcode
Definition BasicTypes.h:70
u32_t NodeID
Definition GeneralType.h:76
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:76
unsigned u32_t
Definition GeneralType.h:67
signed long long s64_t
Definition GeneralType.h:70