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
31#include "SVFIR/SVFIR.h"
32#include "Util/SVFUtil.h"
33#include "Util/Options.h"
34
35using namespace SVF;
36using namespace SVFUtil;
37
39{
40 return *this == other;
41}
42
44{
45 size_t h = getVarToVal().size() * 2;
47 for (const auto &t: getVarToVal())
48 {
49 h ^= hf(t.first) + 0x9e3779b9 + (h << 6) + (h >> 2);
50 }
51 size_t h2 = getLocToVal().size() * 2;
52 for (const auto &t: getLocToVal())
53 {
54 h2 ^= hf(t.first) + 0x9e3779b9 + (h2 << 6) + (h2 >> 2);
55 }
57 return pairH({h, h2});
58}
59
61{
62 // widen interval
63 AbstractState es = *this;
64 for (auto it = es._varToAbsVal.begin(); it != es._varToAbsVal.end(); ++it)
65 {
66 auto key = it->first;
67 if (other._varToAbsVal.find(key) != other._varToAbsVal.end())
68 if (it->second.isInterval() && other._varToAbsVal.at(key).isInterval())
69 it->second.getInterval().widen_with(other._varToAbsVal.at(key).getInterval());
70 }
71 for (auto it = es._addrToAbsVal.begin(); it != es._addrToAbsVal.end(); ++it)
72 {
73 auto key = it->first;
74 if (other._addrToAbsVal.find(key) != other._addrToAbsVal.end())
75 if (it->second.isInterval() && other._addrToAbsVal.at(key).isInterval())
76 it->second.getInterval().widen_with(other._addrToAbsVal.at(key).getInterval());
77 }
78 return es;
79}
80
82{
83 AbstractState es = *this;
84 for (auto it = es._varToAbsVal.begin(); it != es._varToAbsVal.end(); ++it)
85 {
86 auto key = it->first;
87 if (other._varToAbsVal.find(key) != other._varToAbsVal.end())
88 if (it->second.isInterval() && other._varToAbsVal.at(key).isInterval())
89 it->second.getInterval().narrow_with(other._varToAbsVal.at(key).getInterval());
90 }
91 for (auto it = es._addrToAbsVal.begin(); it != es._addrToAbsVal.end(); ++it)
92 {
93 auto key = it->first;
94 if (other._addrToAbsVal.find(key) != other._addrToAbsVal.end())
95 if (it->second.isInterval() && other._addrToAbsVal.at(key).isInterval())
96 it->second.getInterval().narrow_with(other._addrToAbsVal.at(key).getInterval());
97 }
98 return es;
99
100}
101
104{
105 for (auto it = other._varToAbsVal.begin(); it != other._varToAbsVal.end(); ++it)
106 {
107 auto key = it->first;
108 auto oit = _varToAbsVal.find(key);
109 if (oit != _varToAbsVal.end())
110 {
111 oit->second.join_with(it->second);
112 }
113 else
114 {
115 _varToAbsVal.emplace(key, it->second);
116 }
117 }
118 for (auto it = other._addrToAbsVal.begin(); it != other._addrToAbsVal.end(); ++it)
119 {
120 auto key = it->first;
121 auto oit = _addrToAbsVal.find(key);
122 if (oit != _addrToAbsVal.end())
123 {
124 oit->second.join_with(it->second);
125 }
126 else
127 {
128 _addrToAbsVal.emplace(key, it->second);
129 }
130 }
131 _freedAddrs.insert(other._freedAddrs.begin(), other._freedAddrs.end());
132}
133
136{
137 for (auto it = other._varToAbsVal.begin(); it != other._varToAbsVal.end(); ++it)
138 {
139 auto key = it->first;
140 auto oit = _varToAbsVal.find(key);
141 if (oit != _varToAbsVal.end())
142 {
143 oit->second.meet_with(it->second);
144 }
145 }
146 for (auto it = other._addrToAbsVal.begin(); it != other._addrToAbsVal.end(); ++it)
147 {
148 auto key = it->first;
149 auto oit = _addrToAbsVal.find(key);
150 if (oit != _addrToAbsVal.end())
151 {
152 oit->second.meet_with(it->second);
153 }
154 }
156 std::set_intersection(_freedAddrs.begin(), _freedAddrs.end(),
157 other._freedAddrs.begin(), other._freedAddrs.end(),
158 std::inserter(intersection, intersection.begin()));
159 _freedAddrs = std::move(intersection);
160}
161
162// initObjVar
164{
165 NodeID varId = objVar->getId();
166
167 // Check if the object variable has an associated value
168
169 const BaseObjVar* obj = PAG::getPAG()->getBaseObject(objVar->getId());
170
171 // Handle constant data, arrays, and structures
172 if (obj->isConstDataOrConstGlobal() || obj->isConstantArray() || obj->isConstantStruct())
173 {
174 if (const ConstIntObjVar* consInt = SVFUtil::dyn_cast<ConstIntObjVar>(objVar))
175 {
176 s64_t numeral = consInt->getSExtValue();
177 (*this)[varId] = IntervalValue(numeral, numeral);
178 }
179 else if (const ConstFPObjVar* consFP = SVFUtil::dyn_cast<ConstFPObjVar>(objVar))
180 {
181 (*this)[varId] = IntervalValue(consFP->getFPValue(), consFP->getFPValue());
182 }
183 else if (SVFUtil::isa<ConstNullPtrObjVar>(objVar))
184 {
185 (*this)[varId] = IntervalValue(0, 0);
186 }
187 else if (SVFUtil::isa<GlobalObjVar>(objVar))
188 {
190 }
191 else if (obj->isConstantArray() || obj->isConstantStruct())
192 {
193 (*this)[varId] = IntervalValue::top();
194 }
195 else
196 {
197 (*this)[varId] = IntervalValue::top();
198 }
199 }
200 // Handle non-constant memory objects
201 else
202 {
204 }
205 return;
206}
207
209{
210 SVFUtil::outs() << "-----------Var and Value-----------\n";
211 u32_t fieldWidth = 20;
212 SVFUtil::outs().flags(std::ios::left);
213 std::vector<std::pair<u32_t, AbstractValue>> varToAbsValVec(_varToAbsVal.begin(), _varToAbsVal.end());
214 std::sort(varToAbsValVec.begin(), varToAbsValVec.end(), [](const auto &a, const auto &b)
215 {
216 return a.first < b.first;
217 });
218 for (const auto &item: varToAbsValVec)
219 {
220 SVFUtil::outs() << std::left << std::setw(fieldWidth) << ("Var" + std::to_string(item.first));
221 if (item.second.isInterval())
222 {
223 SVFUtil::outs() << " Value: " << item.second.getInterval().toString() << "\n";
224 }
225 else if (item.second.isAddr())
226 {
227 SVFUtil::outs() << " Value: {";
228 u32_t i = 0;
229 for (const auto& addr: item.second.getAddrs())
230 {
231 ++i;
232 if (i < item.second.getAddrs().size())
233 {
234 SVFUtil::outs() << "0x" << std::hex << addr << ", ";
235 }
236 else
237 {
238 SVFUtil::outs() << "0x" << std::hex << addr;
239 }
240 }
241 SVFUtil::outs() << "}\n";
242 }
243 else
244 {
245 SVFUtil::outs() << " Value: ⊥\n";
246 }
247 }
248
249 std::vector<std::pair<u32_t, AbstractValue>> addrToAbsValVec(_addrToAbsVal.begin(), _addrToAbsVal.end());
250 std::sort(addrToAbsValVec.begin(), addrToAbsValVec.end(), [](const auto &a, const auto &b)
251 {
252 return a.first < b.first;
253 });
254
255 for (const auto& item: addrToAbsValVec)
256 {
257 std::ostringstream oss;
258 oss << "0x" << std::hex << AbstractState::getVirtualMemAddress(item.first);
259 SVFUtil::outs() << std::left << std::setw(fieldWidth) << oss.str();
260 if (item.second.isInterval())
261 {
262 SVFUtil::outs() << " Value: " << item.second.getInterval().toString() << "\n";
263 }
264 else if (item.second.isAddr())
265 {
266 SVFUtil::outs() << " Value: {";
267 u32_t i = 0;
268 for (const auto& addr: item.second.getAddrs())
269 {
270 ++i;
271 if (i < item.second.getAddrs().size())
272 {
273 SVFUtil::outs() << "0x" << std::hex << addr << ", ";
274 }
275 else
276 {
277 SVFUtil::outs() << "0x" << std::hex << addr;
278 }
279 }
280 SVFUtil::outs() << "}\n";
281 }
282 else
283 {
284 SVFUtil::outs() << " Value: ⊥\n";
285 }
286 }
287 SVFUtil::outs() << "-----------------------------------------\n";
288}
289
290std::string AbstractState::toString() const
291{
292 u32_t varIntervals = 0, varAddrs = 0, varBottom = 0;
293 for (const auto& item : _varToAbsVal)
294 {
295 if (item.second.isInterval()) ++varIntervals;
296 else if (item.second.isAddr()) ++varAddrs;
297 else ++varBottom;
298 }
300 for (const auto& item : _addrToAbsVal)
301 {
302 if (item.second.isInterval()) ++addrIntervals;
303 else if (item.second.isAddr()) ++addrAddrs;
304 else ++addrBottom;
305 }
306 std::ostringstream oss;
307 oss << "AbstractState {\n"
308 << " VarToAbsVal: " << _varToAbsVal.size() << " entries ("
309 << varIntervals << " intervals, " << varAddrs << " addresses, " << varBottom << " bottom)\n"
310 << " AddrToAbsVal: " << _addrToAbsVal.size() << " entries ("
311 << addrIntervals << " intervals, " << addrAddrs << " addresses, " << addrBottom << " bottom)\n"
312 << " FreedAddrs: " << _freedAddrs.size() << "\n"
313 << "}";
314 return oss.str();
315}
316
317
319{
320 if (lhs.size() != rhs.size()) return false;
321 for (const auto &item: lhs)
322 {
323 auto it = rhs.find(item.first);
324 if (it == rhs.end())
325 return false;
326 if (!item.second.equals(it->second))
327 return false;
328 }
329 return true;
330}
331
333{
334 if (rhs.empty()) return true;
335 for (const auto &item: rhs)
336 {
337 auto it = lhs.find(item.first);
338 if (it == lhs.end()) return false;
339 if (!it->second.getInterval().contain(
340 item.second.getInterval()))
341 return false;
342 }
343 return true;
344}
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: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