svf-lib 1.0.1111 → 1.0.1114
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/lib/libSvf.a +0 -0
- package/SVF-linux/include/SABER/ProgSlice.h +20 -20
- package/SVF-linux/include/SABER/SaberCondAllocator.h +305 -0
- package/SVF-linux/include/SABER/SrcSnkDDA.h +6 -6
- package/SVF-linux/include/Util/DPItem.h +0 -1
- package/SVF-linux/include/Util/Options.h +2 -2
- package/SVF-linux/include/Util/Z3Expr.h +49 -14
- package/SVF-osx/Release-build/lib/libSvf.a +0 -0
- package/SVF-osx/include/SABER/ProgSlice.h +20 -20
- package/SVF-osx/include/SABER/SaberCondAllocator.h +305 -0
- package/SVF-osx/include/SABER/SrcSnkDDA.h +6 -6
- package/SVF-osx/include/Util/DPItem.h +0 -1
- package/SVF-osx/include/Util/Options.h +2 -2
- package/SVF-osx/include/Util/Z3Expr.h +46 -14
- package/package.json +1 -1
|
Binary file
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
#ifndef PROGSLICE_H_
|
|
31
31
|
#define PROGSLICE_H_
|
|
32
32
|
|
|
33
|
-
#include "SABER/
|
|
33
|
+
#include "SABER/SaberCondAllocator.h"
|
|
34
34
|
#include "Util/WorkList.h"
|
|
35
35
|
#include "Graphs/SVFG.h"
|
|
36
36
|
#include "Util/DPItem.h"
|
|
@@ -44,14 +44,14 @@ class ProgSlice
|
|
|
44
44
|
public:
|
|
45
45
|
typedef Set<const SVFGNode*> SVFGNodeSet;
|
|
46
46
|
typedef SVFGNodeSet::const_iterator SVFGNodeSetIter;
|
|
47
|
-
typedef
|
|
48
|
-
typedef Map<const SVFGNode*, Condition
|
|
47
|
+
typedef SaberCondAllocator::Condition Condition;
|
|
48
|
+
typedef Map<const SVFGNode*, Condition> SVFGNodeToCondMap; ///< map a SVFGNode to its condition during value-flow guard computation
|
|
49
49
|
|
|
50
50
|
typedef FIFOWorkList<const SVFGNode*> VFWorkList; ///< worklist for value-flow guard computation
|
|
51
51
|
typedef FIFOWorkList<const BasicBlock*> CFWorkList; ///< worklist for control-flow guard computation
|
|
52
52
|
|
|
53
53
|
/// Constructor
|
|
54
|
-
ProgSlice(const SVFGNode* src,
|
|
54
|
+
ProgSlice(const SVFGNode* src, SaberCondAllocator* pa, const SVFG* graph):
|
|
55
55
|
root(src), partialReachable(false), fullReachable(false), reachGlob(false),
|
|
56
56
|
pathAllocator(pa), _curSVFGNode(nullptr), finalCond(pa->getFalseCond()), svfg(graph)
|
|
57
57
|
{
|
|
@@ -168,27 +168,27 @@ public:
|
|
|
168
168
|
|
|
169
169
|
/// Condition operations
|
|
170
170
|
//@{
|
|
171
|
-
inline Condition
|
|
171
|
+
inline Condition condAnd(const Condition &lhs, const Condition &rhs)
|
|
172
172
|
{
|
|
173
173
|
return pathAllocator->condAnd(lhs,rhs);
|
|
174
174
|
}
|
|
175
|
-
inline Condition
|
|
175
|
+
inline Condition condOr(const Condition &lhs, const Condition &rhs)
|
|
176
176
|
{
|
|
177
177
|
return pathAllocator->condOr(lhs,rhs);
|
|
178
178
|
}
|
|
179
|
-
inline Condition
|
|
179
|
+
inline Condition condNeg(const Condition &cond)
|
|
180
180
|
{
|
|
181
181
|
return pathAllocator->condNeg(cond);
|
|
182
182
|
}
|
|
183
|
-
inline Condition
|
|
183
|
+
inline Condition getTrueCond() const
|
|
184
184
|
{
|
|
185
185
|
return pathAllocator->getTrueCond();
|
|
186
186
|
}
|
|
187
|
-
inline Condition
|
|
187
|
+
inline Condition getFalseCond() const
|
|
188
188
|
{
|
|
189
189
|
return pathAllocator->getFalseCond();
|
|
190
190
|
}
|
|
191
|
-
inline std::string dumpCond(Condition
|
|
191
|
+
inline std::string dumpCond(const Condition& cond) const
|
|
192
192
|
{
|
|
193
193
|
return pathAllocator->dumpCond(cond);
|
|
194
194
|
}
|
|
@@ -210,13 +210,13 @@ protected:
|
|
|
210
210
|
/// Clear Control flow conditions before each VF computation
|
|
211
211
|
inline void clearCFCond()
|
|
212
212
|
{
|
|
213
|
-
/// TODO: how to clean
|
|
213
|
+
/// TODO: how to clean z3 memory
|
|
214
214
|
pathAllocator->clearCFCond();
|
|
215
215
|
}
|
|
216
216
|
|
|
217
217
|
/// Get/set VF (value-flow) and CF (control-flow) conditions
|
|
218
218
|
//@{
|
|
219
|
-
inline Condition
|
|
219
|
+
inline Condition getVFCond(const SVFGNode* node) const
|
|
220
220
|
{
|
|
221
221
|
SVFGNodeToCondMap::const_iterator it = svfgNodeToCondMap.find(node);
|
|
222
222
|
if(it==svfgNodeToCondMap.end())
|
|
@@ -225,7 +225,7 @@ protected:
|
|
|
225
225
|
}
|
|
226
226
|
return it->second;
|
|
227
227
|
}
|
|
228
|
-
inline bool setVFCond(const SVFGNode* node, Condition
|
|
228
|
+
inline bool setVFCond(const SVFGNode* node, const Condition &cond)
|
|
229
229
|
{
|
|
230
230
|
SVFGNodeToCondMap::iterator it = svfgNodeToCondMap.find(node);
|
|
231
231
|
// until a fixed-point is reached (condition is not changed)
|
|
@@ -239,21 +239,21 @@ protected:
|
|
|
239
239
|
|
|
240
240
|
/// Compute guards for value-flows
|
|
241
241
|
//@{
|
|
242
|
-
inline Condition
|
|
242
|
+
inline Condition ComputeIntraVFGGuard(const BasicBlock* src, const BasicBlock* dst)
|
|
243
243
|
{
|
|
244
244
|
return pathAllocator->ComputeIntraVFGGuard(src,dst);
|
|
245
245
|
}
|
|
246
|
-
inline Condition
|
|
246
|
+
inline Condition ComputeInterCallVFGGuard(const BasicBlock* src, const BasicBlock* dst, const BasicBlock* callBB)
|
|
247
247
|
{
|
|
248
248
|
return pathAllocator->ComputeInterCallVFGGuard(src,dst,callBB);
|
|
249
249
|
}
|
|
250
|
-
inline Condition
|
|
250
|
+
inline Condition ComputeInterRetVFGGuard(const BasicBlock* src, const BasicBlock* dst, const BasicBlock* retBB)
|
|
251
251
|
{
|
|
252
252
|
return pathAllocator->ComputeInterRetVFGGuard(src,dst,retBB);
|
|
253
253
|
}
|
|
254
254
|
//@}
|
|
255
255
|
|
|
256
|
-
inline bool isEquivalentBranchCond(const Condition
|
|
256
|
+
inline bool isEquivalentBranchCond(const Condition &lhs, const Condition &rhs) const
|
|
257
257
|
{
|
|
258
258
|
return pathAllocator->isEquivalentBranchCond(lhs, rhs);
|
|
259
259
|
};
|
|
@@ -284,7 +284,7 @@ protected:
|
|
|
284
284
|
}
|
|
285
285
|
//@}
|
|
286
286
|
/// Set final condition after all path reachability analysis
|
|
287
|
-
inline void setFinalCond(Condition
|
|
287
|
+
inline void setFinalCond(const Condition &cond)
|
|
288
288
|
{
|
|
289
289
|
finalCond = cond;
|
|
290
290
|
}
|
|
@@ -298,9 +298,9 @@ private:
|
|
|
298
298
|
bool partialReachable; ///< reachable from some paths
|
|
299
299
|
bool fullReachable; ///< reachable from all paths
|
|
300
300
|
bool reachGlob; ///< Whether slice reach a global
|
|
301
|
-
|
|
301
|
+
SaberCondAllocator* pathAllocator; ///< path condition allocator
|
|
302
302
|
const SVFGNode* _curSVFGNode; ///< current svfg node during guard computation
|
|
303
|
-
Condition
|
|
303
|
+
Condition finalCond; ///< final condition
|
|
304
304
|
const SVFG* svfg; ///< SVFG
|
|
305
305
|
};
|
|
306
306
|
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
//===- SaberCondAllocator.h -- Path condition manipulation---------------------//
|
|
2
|
+
//
|
|
3
|
+
// SVF: Static Value-Flow Analysis
|
|
4
|
+
//
|
|
5
|
+
// Copyright (C) <2013-2017> <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 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 General Public License for more details.
|
|
17
|
+
|
|
18
|
+
// You should have received a copy of the GNU General Public License
|
|
19
|
+
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
20
|
+
//
|
|
21
|
+
//===----------------------------------------------------------------------===//
|
|
22
|
+
|
|
23
|
+
/*
|
|
24
|
+
* PathAllocator.h
|
|
25
|
+
*
|
|
26
|
+
* Created on: Apr 3, 2014
|
|
27
|
+
* Author: Yulei Sui
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
#ifndef PATHALLOCATOR_H_
|
|
31
|
+
#define PATHALLOCATOR_H_
|
|
32
|
+
|
|
33
|
+
#include "Util/SVFModule.h"
|
|
34
|
+
#include "SVF-FE/DataFlowUtil.h"
|
|
35
|
+
#include "SVF-FE/BasicTypes.h"
|
|
36
|
+
#include "Util/WorkList.h"
|
|
37
|
+
#include "Graphs/SVFG.h"
|
|
38
|
+
#include "Util/Z3Expr.h"
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
namespace SVF
|
|
42
|
+
{
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* SaberCondAllocator allocates conditions for each basic block of a certain CFG.
|
|
46
|
+
*/
|
|
47
|
+
class SaberCondAllocator
|
|
48
|
+
{
|
|
49
|
+
|
|
50
|
+
public:
|
|
51
|
+
|
|
52
|
+
typedef Z3Expr Condition; /// z3 condition
|
|
53
|
+
typedef Map<u32_t, const Instruction *> IndexToTermInstMap; /// id to instruction map for z3
|
|
54
|
+
typedef Map<u32_t,Condition> CondPosMap; ///< map a branch to its Condition
|
|
55
|
+
typedef Map<const BasicBlock*, CondPosMap > BBCondMap; /// map bb to a Condition
|
|
56
|
+
typedef Set<const BasicBlock*> BasicBlockSet;
|
|
57
|
+
typedef Map<const Function*, BasicBlockSet> FunToExitBBsMap; ///< map a function to all its basic blocks calling program exit
|
|
58
|
+
typedef Map<const BasicBlock*, Condition> BBToCondMap; ///< map a basic block to its condition during control-flow guard computation
|
|
59
|
+
typedef FIFOWorkList<const BasicBlock*> CFWorkList; ///< worklist for control-flow guard computation
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
/// Constructor
|
|
63
|
+
SaberCondAllocator();
|
|
64
|
+
|
|
65
|
+
/// Destructor
|
|
66
|
+
virtual ~SaberCondAllocator()
|
|
67
|
+
{
|
|
68
|
+
}
|
|
69
|
+
/// Statistics
|
|
70
|
+
//@{
|
|
71
|
+
inline std::string getMemUsage()
|
|
72
|
+
{
|
|
73
|
+
return "";
|
|
74
|
+
}
|
|
75
|
+
inline u32_t getCondNum()
|
|
76
|
+
{
|
|
77
|
+
return totalCondNum;
|
|
78
|
+
}
|
|
79
|
+
//@}
|
|
80
|
+
|
|
81
|
+
/// Condition operations
|
|
82
|
+
//@{
|
|
83
|
+
inline Condition condAnd(const Condition& lhs, const Condition& rhs)
|
|
84
|
+
{
|
|
85
|
+
return Condition::AND(lhs,rhs);
|
|
86
|
+
}
|
|
87
|
+
inline Condition condOr(const Condition& lhs, const Condition& rhs)
|
|
88
|
+
{
|
|
89
|
+
return Condition::OR(lhs,rhs);
|
|
90
|
+
}
|
|
91
|
+
inline Condition condNeg(const Condition& cond)
|
|
92
|
+
{
|
|
93
|
+
return Condition::NEG(cond);
|
|
94
|
+
}
|
|
95
|
+
inline Condition getTrueCond() const
|
|
96
|
+
{
|
|
97
|
+
return Condition::getTrueCond();
|
|
98
|
+
}
|
|
99
|
+
inline Condition getFalseCond() const
|
|
100
|
+
{
|
|
101
|
+
return Condition::getFalseCond();
|
|
102
|
+
}
|
|
103
|
+
/// Iterator every element of the condition
|
|
104
|
+
inline NodeBS exactCondElem(const Condition& cond)
|
|
105
|
+
{
|
|
106
|
+
NodeBS elems;
|
|
107
|
+
extractSubConds(cond, elems);
|
|
108
|
+
return elems;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
inline std::string dumpCond(const Condition& cond) const
|
|
112
|
+
{
|
|
113
|
+
return Condition::dumpStr(cond);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/// Allocate a new condition
|
|
117
|
+
Condition newCond(const Instruction* inst);
|
|
118
|
+
|
|
119
|
+
/// Perform path allocation
|
|
120
|
+
void allocate(const SVFModule* module);
|
|
121
|
+
|
|
122
|
+
/// Get/Set instruction based on Z3 expression id
|
|
123
|
+
//{@
|
|
124
|
+
inline const Instruction *getCondInst(u32_t id) const
|
|
125
|
+
{
|
|
126
|
+
IndexToTermInstMap::const_iterator it = idToTermInstMap.find(id);
|
|
127
|
+
assert(it != idToTermInstMap.end() && "this should be a fresh condition");
|
|
128
|
+
return it->second;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
inline void setCondInst(const Condition &condition, const Instruction *inst)
|
|
132
|
+
{
|
|
133
|
+
assert(idToTermInstMap.find(condition.id()) == idToTermInstMap.end() && "this should be a fresh condition");
|
|
134
|
+
idToTermInstMap[condition.id()] = inst;
|
|
135
|
+
}
|
|
136
|
+
//@}
|
|
137
|
+
|
|
138
|
+
bool isNegCond(u32_t id) const
|
|
139
|
+
{
|
|
140
|
+
return negConds.test(id);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/// Get dominators
|
|
144
|
+
inline DominatorTree* getDT(const Function* fun)
|
|
145
|
+
{
|
|
146
|
+
return cfInfoBuilder.getDT(fun);
|
|
147
|
+
}
|
|
148
|
+
/// Get Postdominators
|
|
149
|
+
inline PostDominatorTree* getPostDT(const Function* fun)
|
|
150
|
+
{
|
|
151
|
+
return cfInfoBuilder.getPostDT(fun);
|
|
152
|
+
}
|
|
153
|
+
/// Get LoopInfo
|
|
154
|
+
inline LoopInfo* getLoopInfo(const Function* f)
|
|
155
|
+
{
|
|
156
|
+
return cfInfoBuilder.getLoopInfo(f);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
/// Guard Computation for a value-flow (between two basic blocks)
|
|
161
|
+
//@{
|
|
162
|
+
virtual Condition ComputeIntraVFGGuard(const BasicBlock* src, const BasicBlock* dst);
|
|
163
|
+
virtual Condition ComputeInterCallVFGGuard(const BasicBlock* src, const BasicBlock* dst, const BasicBlock* callBB);
|
|
164
|
+
virtual Condition ComputeInterRetVFGGuard(const BasicBlock* src, const BasicBlock* dst, const BasicBlock* retBB);
|
|
165
|
+
|
|
166
|
+
/// Get complement condition (from B1 to B0) according to a complementBB (BB2) at a phi
|
|
167
|
+
/// e.g., B0: dstBB; B1:incomingBB; B2:complementBB
|
|
168
|
+
virtual Condition getPHIComplementCond(const BasicBlock* BB1, const BasicBlock* BB2, const BasicBlock* BB0);
|
|
169
|
+
|
|
170
|
+
inline void clearCFCond()
|
|
171
|
+
{
|
|
172
|
+
bbToCondMap.clear();
|
|
173
|
+
}
|
|
174
|
+
/// Set current value for branch condition evaluation
|
|
175
|
+
inline void setCurEvalSVFGNode(const SVFGNode* node)
|
|
176
|
+
{
|
|
177
|
+
curEvalSVFGNode = node;
|
|
178
|
+
}
|
|
179
|
+
/// Get current value for branch condition evaluation
|
|
180
|
+
inline const SVFGNode* getCurEvalSVFGNode() const
|
|
181
|
+
{
|
|
182
|
+
return curEvalSVFGNode;
|
|
183
|
+
}
|
|
184
|
+
//@}
|
|
185
|
+
|
|
186
|
+
/// Print out the path condition information
|
|
187
|
+
void printPathCond();
|
|
188
|
+
|
|
189
|
+
/// whether condition is satisfiable
|
|
190
|
+
bool isSatisfiable(const Condition& condition);
|
|
191
|
+
|
|
192
|
+
/// whether condition is satisfiable for all possible boolean guards
|
|
193
|
+
inline bool isAllPathReachable(Condition& condition)
|
|
194
|
+
{
|
|
195
|
+
return isEquivalentBranchCond(condition, Condition::getTrueCond());
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/// Whether lhs and rhs are equivalent branch conditions
|
|
199
|
+
bool isEquivalentBranchCond(const Condition &lhs, const Condition &rhs) const;
|
|
200
|
+
|
|
201
|
+
inline ICFG* getICFG() const
|
|
202
|
+
{
|
|
203
|
+
return PAG::getPAG()->getICFG();
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/// Get/Set control-flow conditions
|
|
207
|
+
//@{
|
|
208
|
+
inline bool setCFCond(const BasicBlock* bb, const Condition& cond)
|
|
209
|
+
{
|
|
210
|
+
BBToCondMap::iterator it = bbToCondMap.find(bb);
|
|
211
|
+
// until a fixed-point is reached (condition is not changed)
|
|
212
|
+
if(it!=bbToCondMap.end() && isEquivalentBranchCond(it->second, cond))
|
|
213
|
+
return false;
|
|
214
|
+
|
|
215
|
+
bbToCondMap[bb] = cond;
|
|
216
|
+
return true;
|
|
217
|
+
}
|
|
218
|
+
inline Condition getCFCond(const BasicBlock* bb) const
|
|
219
|
+
{
|
|
220
|
+
BBToCondMap::const_iterator it = bbToCondMap.find(bb);
|
|
221
|
+
if(it==bbToCondMap.end())
|
|
222
|
+
{
|
|
223
|
+
return getFalseCond();
|
|
224
|
+
}
|
|
225
|
+
return it->second;
|
|
226
|
+
}
|
|
227
|
+
//@}
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
/// mark neg Z3 expression
|
|
231
|
+
inline void setNegCondInst(const Condition &condition, const Instruction *inst)
|
|
232
|
+
{
|
|
233
|
+
setCondInst(condition, inst);
|
|
234
|
+
negConds.set(condition.id());
|
|
235
|
+
}
|
|
236
|
+
private:
|
|
237
|
+
|
|
238
|
+
/// Allocate path condition for every basic block
|
|
239
|
+
virtual void allocateForBB(const BasicBlock& bb);
|
|
240
|
+
|
|
241
|
+
/// Get/Set a branch condition, and its terminator instruction
|
|
242
|
+
//@{
|
|
243
|
+
/// Set branch condition
|
|
244
|
+
void setBranchCond(const BasicBlock *bb, const BasicBlock *succ, const Condition& cond);
|
|
245
|
+
/// Get branch condition
|
|
246
|
+
Condition getBranchCond(const BasicBlock * bb, const BasicBlock *succ) const;
|
|
247
|
+
///Get a condition, evaluate the value for conditions if necessary (e.g., testNull like express)
|
|
248
|
+
Condition getEvalBrCond(const BasicBlock * bb, const BasicBlock *succ);
|
|
249
|
+
//@}
|
|
250
|
+
/// Evaluate branch conditions
|
|
251
|
+
//@{
|
|
252
|
+
/// Evaluate the branch condtion
|
|
253
|
+
Condition evaluateBranchCond(const BasicBlock * bb, const BasicBlock *succ) ;
|
|
254
|
+
/// Evaluate loop exit branch
|
|
255
|
+
Condition evaluateLoopExitBranch(const BasicBlock * bb, const BasicBlock *succ);
|
|
256
|
+
/// Return branch condition after evaluating test null like expression
|
|
257
|
+
Condition evaluateTestNullLikeExpr(const BranchStmt* branchStmt, const BasicBlock *succ);
|
|
258
|
+
/// Return condition when there is a branch calls program exit
|
|
259
|
+
Condition evaluateProgExit(const BranchStmt* branchStmt, const BasicBlock *succ);
|
|
260
|
+
/// Collect basic block contains program exit function call
|
|
261
|
+
void collectBBCallingProgExit(const BasicBlock& bb);
|
|
262
|
+
bool isBBCallsProgExit(const BasicBlock* bb);
|
|
263
|
+
//@}
|
|
264
|
+
|
|
265
|
+
/// Evaluate test null/not null like expressions
|
|
266
|
+
//@{
|
|
267
|
+
/// Return true if the predicate of this compare instruction is equal
|
|
268
|
+
bool isEQCmp(const CmpInst* cmp) const;
|
|
269
|
+
/// Return true if the predicate of this compare instruction is not equal
|
|
270
|
+
bool isNECmp(const CmpInst* cmp) const;
|
|
271
|
+
/// Return true if this is a test null expression
|
|
272
|
+
bool isTestNullExpr(const Value* test) const;
|
|
273
|
+
/// Return true if this is a test not null expression
|
|
274
|
+
bool isTestNotNullExpr(const Value* test) const;
|
|
275
|
+
/// Return true if two values on the predicate are what we want
|
|
276
|
+
bool isTestContainsNullAndTheValue(const CmpInst* cmp) const;
|
|
277
|
+
//@}
|
|
278
|
+
|
|
279
|
+
/// Release memory
|
|
280
|
+
void destroy()
|
|
281
|
+
{
|
|
282
|
+
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/// extract subexpression from a Z3 expression
|
|
286
|
+
void extractSubConds(const Condition &condition, NodeBS &support) const;
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
PTACFInfoBuilder cfInfoBuilder; ///< map a function to its loop info
|
|
290
|
+
FunToExitBBsMap funToExitBBsMap; ///< map a function to all its basic blocks calling program exit
|
|
291
|
+
BBToCondMap bbToCondMap; ///< map a basic block to its path condition starting from root
|
|
292
|
+
const SVFGNode* curEvalSVFGNode{}; ///< current llvm value to evaluate branch condition when computing guards
|
|
293
|
+
IndexToTermInstMap idToTermInstMap; ///key: z3 expression id, value: instruction
|
|
294
|
+
NodeBS negConds; ///bit vector for distinguish neg
|
|
295
|
+
std::vector<Condition> conditionVec; /// vector storing z3expression
|
|
296
|
+
static u32_t totalCondNum; /// a counter for fresh condition
|
|
297
|
+
|
|
298
|
+
protected:
|
|
299
|
+
BBCondMap bbConds; ///< map basic block to its successors/predecessors branch conditions
|
|
300
|
+
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
} // End namespace SVF
|
|
304
|
+
|
|
305
|
+
#endif /* PATHALLOCATOR_H_ */
|
|
@@ -62,7 +62,7 @@ private:
|
|
|
62
62
|
ProgSlice* _curSlice; /// current program slice
|
|
63
63
|
SVFGNodeSet sources; /// source nodes
|
|
64
64
|
SVFGNodeSet sinks; /// source nodes
|
|
65
|
-
|
|
65
|
+
SaberCondAllocator* saberCondAllocator;
|
|
66
66
|
SVFGNodeToDPItemsMap nodeToDPItemsMap; ///< record forward visited dpitems
|
|
67
67
|
SVFGNodeSet visitedSet; ///< record backward visited nodes
|
|
68
68
|
|
|
@@ -76,7 +76,7 @@ public:
|
|
|
76
76
|
/// Constructor
|
|
77
77
|
SrcSnkDDA() : _curSlice(nullptr), svfg(nullptr), ptaCallGraph(nullptr)
|
|
78
78
|
{
|
|
79
|
-
|
|
79
|
+
saberCondAllocator = new SaberCondAllocator();
|
|
80
80
|
}
|
|
81
81
|
/// Destructor
|
|
82
82
|
virtual ~SrcSnkDDA()
|
|
@@ -232,10 +232,10 @@ public:
|
|
|
232
232
|
}
|
|
233
233
|
//@}
|
|
234
234
|
|
|
235
|
-
/// Get
|
|
236
|
-
|
|
235
|
+
/// Get saber condition allocator
|
|
236
|
+
SaberCondAllocator* getSaberCondAllocator() const
|
|
237
237
|
{
|
|
238
|
-
return
|
|
238
|
+
return saberCondAllocator;
|
|
239
239
|
}
|
|
240
240
|
|
|
241
241
|
protected:
|
|
@@ -307,7 +307,7 @@ protected:
|
|
|
307
307
|
//@{
|
|
308
308
|
void dumpSlices();
|
|
309
309
|
void annotateSlice(ProgSlice* slice);
|
|
310
|
-
void
|
|
310
|
+
void printZ3Stat();
|
|
311
311
|
//@}
|
|
312
312
|
|
|
313
313
|
};
|
|
@@ -218,9 +218,9 @@ public:
|
|
|
218
218
|
static const llvm::cl::opt<bool> SymTabPrint;
|
|
219
219
|
|
|
220
220
|
// Conditions.cpp
|
|
221
|
-
static const llvm::cl::opt<unsigned>
|
|
221
|
+
static const llvm::cl::opt<unsigned> MaxZ3Size;
|
|
222
222
|
|
|
223
|
-
//
|
|
223
|
+
// SaberCondAllocator.cpp
|
|
224
224
|
static const llvm::cl::opt<bool> PrintPathCond;
|
|
225
225
|
|
|
226
226
|
// SVFUtil.cpp
|
|
@@ -39,6 +39,7 @@ class Z3Expr
|
|
|
39
39
|
{
|
|
40
40
|
public:
|
|
41
41
|
static z3::context *ctx;
|
|
42
|
+
static z3::solver* solver;
|
|
42
43
|
|
|
43
44
|
private:
|
|
44
45
|
z3::expr e;
|
|
@@ -80,22 +81,18 @@ public:
|
|
|
80
81
|
return e;
|
|
81
82
|
}
|
|
82
83
|
|
|
84
|
+
/// Get z3 solver, singleton design here to make sure we only have one context
|
|
85
|
+
static z3::solver &getSolver();
|
|
86
|
+
|
|
83
87
|
/// Get z3 context, singleton design here to make sure we only have one context
|
|
84
|
-
static z3::context &getContext()
|
|
85
|
-
{
|
|
86
|
-
if (ctx == nullptr)
|
|
87
|
-
{
|
|
88
|
-
ctx = new z3::context();
|
|
89
|
-
}
|
|
90
|
-
return *ctx;
|
|
91
|
-
}
|
|
88
|
+
static z3::context &getContext();
|
|
92
89
|
|
|
93
90
|
/// release z3 context
|
|
94
|
-
static void releaseContext()
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
91
|
+
static void releaseContext();
|
|
92
|
+
|
|
93
|
+
/// release z3 solver
|
|
94
|
+
static void releaseSolver();
|
|
95
|
+
|
|
99
96
|
|
|
100
97
|
/// null expression
|
|
101
98
|
static z3::expr nullExpr()
|
|
@@ -109,6 +106,12 @@ public:
|
|
|
109
106
|
return e.id();
|
|
110
107
|
}
|
|
111
108
|
|
|
109
|
+
/// get hash id
|
|
110
|
+
inline u32_t hash() const
|
|
111
|
+
{
|
|
112
|
+
return e.hash();
|
|
113
|
+
}
|
|
114
|
+
|
|
112
115
|
inline const std::string to_string() const
|
|
113
116
|
{
|
|
114
117
|
return e.to_string();
|
|
@@ -245,7 +248,7 @@ public:
|
|
|
245
248
|
return !lhs.getExpr();
|
|
246
249
|
}
|
|
247
250
|
|
|
248
|
-
friend Z3Expr ite(const Z3Expr&
|
|
251
|
+
friend Z3Expr ite(const Z3Expr &cond, const Z3Expr &lhs, const Z3Expr &rhs)
|
|
249
252
|
{
|
|
250
253
|
return ite(cond.getExpr(), lhs.getExpr(), rhs.getExpr());
|
|
251
254
|
}
|
|
@@ -266,6 +269,38 @@ public:
|
|
|
266
269
|
return getExpr().get_sort();
|
|
267
270
|
}
|
|
268
271
|
//%}
|
|
272
|
+
|
|
273
|
+
/// output Z3 expression as a string
|
|
274
|
+
static std::string dumpStr(const Z3Expr &z3Expr);
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
/// get the number of subexpression of a Z3 expression
|
|
278
|
+
static u32_t getExprSize(const Z3Expr &z3Expr);
|
|
279
|
+
|
|
280
|
+
/// Return the unique true condition
|
|
281
|
+
static inline Z3Expr getTrueCond()
|
|
282
|
+
{
|
|
283
|
+
return getContext().bool_val(true);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
/// Return the unique false condition
|
|
288
|
+
static inline Z3Expr getFalseCond()
|
|
289
|
+
{
|
|
290
|
+
return getContext().bool_val(false);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/// compute NEG
|
|
294
|
+
static inline Z3Expr NEG(const Z3Expr &z3Expr)
|
|
295
|
+
{
|
|
296
|
+
return !z3Expr;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/// compute AND, used for branch condition
|
|
300
|
+
static Z3Expr AND(const Z3Expr &lhs, const Z3Expr &rhs);
|
|
301
|
+
|
|
302
|
+
/// compute OR, used for branch condition
|
|
303
|
+
static Z3Expr OR(const Z3Expr &lhs, const Z3Expr &rhs);
|
|
269
304
|
};
|
|
270
305
|
}
|
|
271
306
|
|
|
Binary file
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
#ifndef PROGSLICE_H_
|
|
31
31
|
#define PROGSLICE_H_
|
|
32
32
|
|
|
33
|
-
#include "SABER/
|
|
33
|
+
#include "SABER/SaberCondAllocator.h"
|
|
34
34
|
#include "Util/WorkList.h"
|
|
35
35
|
#include "Graphs/SVFG.h"
|
|
36
36
|
#include "Util/DPItem.h"
|
|
@@ -44,14 +44,14 @@ class ProgSlice
|
|
|
44
44
|
public:
|
|
45
45
|
typedef Set<const SVFGNode*> SVFGNodeSet;
|
|
46
46
|
typedef SVFGNodeSet::const_iterator SVFGNodeSetIter;
|
|
47
|
-
typedef
|
|
48
|
-
typedef Map<const SVFGNode*, Condition
|
|
47
|
+
typedef SaberCondAllocator::Condition Condition;
|
|
48
|
+
typedef Map<const SVFGNode*, Condition> SVFGNodeToCondMap; ///< map a SVFGNode to its condition during value-flow guard computation
|
|
49
49
|
|
|
50
50
|
typedef FIFOWorkList<const SVFGNode*> VFWorkList; ///< worklist for value-flow guard computation
|
|
51
51
|
typedef FIFOWorkList<const BasicBlock*> CFWorkList; ///< worklist for control-flow guard computation
|
|
52
52
|
|
|
53
53
|
/// Constructor
|
|
54
|
-
ProgSlice(const SVFGNode* src,
|
|
54
|
+
ProgSlice(const SVFGNode* src, SaberCondAllocator* pa, const SVFG* graph):
|
|
55
55
|
root(src), partialReachable(false), fullReachable(false), reachGlob(false),
|
|
56
56
|
pathAllocator(pa), _curSVFGNode(nullptr), finalCond(pa->getFalseCond()), svfg(graph)
|
|
57
57
|
{
|
|
@@ -168,27 +168,27 @@ public:
|
|
|
168
168
|
|
|
169
169
|
/// Condition operations
|
|
170
170
|
//@{
|
|
171
|
-
inline Condition
|
|
171
|
+
inline Condition condAnd(const Condition &lhs, const Condition &rhs)
|
|
172
172
|
{
|
|
173
173
|
return pathAllocator->condAnd(lhs,rhs);
|
|
174
174
|
}
|
|
175
|
-
inline Condition
|
|
175
|
+
inline Condition condOr(const Condition &lhs, const Condition &rhs)
|
|
176
176
|
{
|
|
177
177
|
return pathAllocator->condOr(lhs,rhs);
|
|
178
178
|
}
|
|
179
|
-
inline Condition
|
|
179
|
+
inline Condition condNeg(const Condition &cond)
|
|
180
180
|
{
|
|
181
181
|
return pathAllocator->condNeg(cond);
|
|
182
182
|
}
|
|
183
|
-
inline Condition
|
|
183
|
+
inline Condition getTrueCond() const
|
|
184
184
|
{
|
|
185
185
|
return pathAllocator->getTrueCond();
|
|
186
186
|
}
|
|
187
|
-
inline Condition
|
|
187
|
+
inline Condition getFalseCond() const
|
|
188
188
|
{
|
|
189
189
|
return pathAllocator->getFalseCond();
|
|
190
190
|
}
|
|
191
|
-
inline std::string dumpCond(Condition
|
|
191
|
+
inline std::string dumpCond(const Condition& cond) const
|
|
192
192
|
{
|
|
193
193
|
return pathAllocator->dumpCond(cond);
|
|
194
194
|
}
|
|
@@ -210,13 +210,13 @@ protected:
|
|
|
210
210
|
/// Clear Control flow conditions before each VF computation
|
|
211
211
|
inline void clearCFCond()
|
|
212
212
|
{
|
|
213
|
-
/// TODO: how to clean
|
|
213
|
+
/// TODO: how to clean z3 memory
|
|
214
214
|
pathAllocator->clearCFCond();
|
|
215
215
|
}
|
|
216
216
|
|
|
217
217
|
/// Get/set VF (value-flow) and CF (control-flow) conditions
|
|
218
218
|
//@{
|
|
219
|
-
inline Condition
|
|
219
|
+
inline Condition getVFCond(const SVFGNode* node) const
|
|
220
220
|
{
|
|
221
221
|
SVFGNodeToCondMap::const_iterator it = svfgNodeToCondMap.find(node);
|
|
222
222
|
if(it==svfgNodeToCondMap.end())
|
|
@@ -225,7 +225,7 @@ protected:
|
|
|
225
225
|
}
|
|
226
226
|
return it->second;
|
|
227
227
|
}
|
|
228
|
-
inline bool setVFCond(const SVFGNode* node, Condition
|
|
228
|
+
inline bool setVFCond(const SVFGNode* node, const Condition &cond)
|
|
229
229
|
{
|
|
230
230
|
SVFGNodeToCondMap::iterator it = svfgNodeToCondMap.find(node);
|
|
231
231
|
// until a fixed-point is reached (condition is not changed)
|
|
@@ -239,21 +239,21 @@ protected:
|
|
|
239
239
|
|
|
240
240
|
/// Compute guards for value-flows
|
|
241
241
|
//@{
|
|
242
|
-
inline Condition
|
|
242
|
+
inline Condition ComputeIntraVFGGuard(const BasicBlock* src, const BasicBlock* dst)
|
|
243
243
|
{
|
|
244
244
|
return pathAllocator->ComputeIntraVFGGuard(src,dst);
|
|
245
245
|
}
|
|
246
|
-
inline Condition
|
|
246
|
+
inline Condition ComputeInterCallVFGGuard(const BasicBlock* src, const BasicBlock* dst, const BasicBlock* callBB)
|
|
247
247
|
{
|
|
248
248
|
return pathAllocator->ComputeInterCallVFGGuard(src,dst,callBB);
|
|
249
249
|
}
|
|
250
|
-
inline Condition
|
|
250
|
+
inline Condition ComputeInterRetVFGGuard(const BasicBlock* src, const BasicBlock* dst, const BasicBlock* retBB)
|
|
251
251
|
{
|
|
252
252
|
return pathAllocator->ComputeInterRetVFGGuard(src,dst,retBB);
|
|
253
253
|
}
|
|
254
254
|
//@}
|
|
255
255
|
|
|
256
|
-
inline bool isEquivalentBranchCond(const Condition
|
|
256
|
+
inline bool isEquivalentBranchCond(const Condition &lhs, const Condition &rhs) const
|
|
257
257
|
{
|
|
258
258
|
return pathAllocator->isEquivalentBranchCond(lhs, rhs);
|
|
259
259
|
};
|
|
@@ -284,7 +284,7 @@ protected:
|
|
|
284
284
|
}
|
|
285
285
|
//@}
|
|
286
286
|
/// Set final condition after all path reachability analysis
|
|
287
|
-
inline void setFinalCond(Condition
|
|
287
|
+
inline void setFinalCond(const Condition &cond)
|
|
288
288
|
{
|
|
289
289
|
finalCond = cond;
|
|
290
290
|
}
|
|
@@ -298,9 +298,9 @@ private:
|
|
|
298
298
|
bool partialReachable; ///< reachable from some paths
|
|
299
299
|
bool fullReachable; ///< reachable from all paths
|
|
300
300
|
bool reachGlob; ///< Whether slice reach a global
|
|
301
|
-
|
|
301
|
+
SaberCondAllocator* pathAllocator; ///< path condition allocator
|
|
302
302
|
const SVFGNode* _curSVFGNode; ///< current svfg node during guard computation
|
|
303
|
-
Condition
|
|
303
|
+
Condition finalCond; ///< final condition
|
|
304
304
|
const SVFG* svfg; ///< SVFG
|
|
305
305
|
};
|
|
306
306
|
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
//===- SaberCondAllocator.h -- Path condition manipulation---------------------//
|
|
2
|
+
//
|
|
3
|
+
// SVF: Static Value-Flow Analysis
|
|
4
|
+
//
|
|
5
|
+
// Copyright (C) <2013-2017> <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 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 General Public License for more details.
|
|
17
|
+
|
|
18
|
+
// You should have received a copy of the GNU General Public License
|
|
19
|
+
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
20
|
+
//
|
|
21
|
+
//===----------------------------------------------------------------------===//
|
|
22
|
+
|
|
23
|
+
/*
|
|
24
|
+
* PathAllocator.h
|
|
25
|
+
*
|
|
26
|
+
* Created on: Apr 3, 2014
|
|
27
|
+
* Author: Yulei Sui
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
#ifndef PATHALLOCATOR_H_
|
|
31
|
+
#define PATHALLOCATOR_H_
|
|
32
|
+
|
|
33
|
+
#include "Util/SVFModule.h"
|
|
34
|
+
#include "SVF-FE/DataFlowUtil.h"
|
|
35
|
+
#include "SVF-FE/BasicTypes.h"
|
|
36
|
+
#include "Util/WorkList.h"
|
|
37
|
+
#include "Graphs/SVFG.h"
|
|
38
|
+
#include "Util/Z3Expr.h"
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
namespace SVF
|
|
42
|
+
{
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* SaberCondAllocator allocates conditions for each basic block of a certain CFG.
|
|
46
|
+
*/
|
|
47
|
+
class SaberCondAllocator
|
|
48
|
+
{
|
|
49
|
+
|
|
50
|
+
public:
|
|
51
|
+
|
|
52
|
+
typedef Z3Expr Condition; /// z3 condition
|
|
53
|
+
typedef Map<u32_t, const Instruction *> IndexToTermInstMap; /// id to instruction map for z3
|
|
54
|
+
typedef Map<u32_t,Condition> CondPosMap; ///< map a branch to its Condition
|
|
55
|
+
typedef Map<const BasicBlock*, CondPosMap > BBCondMap; /// map bb to a Condition
|
|
56
|
+
typedef Set<const BasicBlock*> BasicBlockSet;
|
|
57
|
+
typedef Map<const Function*, BasicBlockSet> FunToExitBBsMap; ///< map a function to all its basic blocks calling program exit
|
|
58
|
+
typedef Map<const BasicBlock*, Condition> BBToCondMap; ///< map a basic block to its condition during control-flow guard computation
|
|
59
|
+
typedef FIFOWorkList<const BasicBlock*> CFWorkList; ///< worklist for control-flow guard computation
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
/// Constructor
|
|
63
|
+
SaberCondAllocator();
|
|
64
|
+
|
|
65
|
+
/// Destructor
|
|
66
|
+
virtual ~SaberCondAllocator()
|
|
67
|
+
{
|
|
68
|
+
}
|
|
69
|
+
/// Statistics
|
|
70
|
+
//@{
|
|
71
|
+
inline std::string getMemUsage()
|
|
72
|
+
{
|
|
73
|
+
return "";
|
|
74
|
+
}
|
|
75
|
+
inline u32_t getCondNum()
|
|
76
|
+
{
|
|
77
|
+
return totalCondNum;
|
|
78
|
+
}
|
|
79
|
+
//@}
|
|
80
|
+
|
|
81
|
+
/// Condition operations
|
|
82
|
+
//@{
|
|
83
|
+
inline Condition condAnd(const Condition& lhs, const Condition& rhs)
|
|
84
|
+
{
|
|
85
|
+
return Condition::AND(lhs,rhs);
|
|
86
|
+
}
|
|
87
|
+
inline Condition condOr(const Condition& lhs, const Condition& rhs)
|
|
88
|
+
{
|
|
89
|
+
return Condition::OR(lhs,rhs);
|
|
90
|
+
}
|
|
91
|
+
inline Condition condNeg(const Condition& cond)
|
|
92
|
+
{
|
|
93
|
+
return Condition::NEG(cond);
|
|
94
|
+
}
|
|
95
|
+
inline Condition getTrueCond() const
|
|
96
|
+
{
|
|
97
|
+
return Condition::getTrueCond();
|
|
98
|
+
}
|
|
99
|
+
inline Condition getFalseCond() const
|
|
100
|
+
{
|
|
101
|
+
return Condition::getFalseCond();
|
|
102
|
+
}
|
|
103
|
+
/// Iterator every element of the condition
|
|
104
|
+
inline NodeBS exactCondElem(const Condition& cond)
|
|
105
|
+
{
|
|
106
|
+
NodeBS elems;
|
|
107
|
+
extractSubConds(cond, elems);
|
|
108
|
+
return elems;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
inline std::string dumpCond(const Condition& cond) const
|
|
112
|
+
{
|
|
113
|
+
return Condition::dumpStr(cond);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/// Allocate a new condition
|
|
117
|
+
Condition newCond(const Instruction* inst);
|
|
118
|
+
|
|
119
|
+
/// Perform path allocation
|
|
120
|
+
void allocate(const SVFModule* module);
|
|
121
|
+
|
|
122
|
+
/// Get/Set instruction based on Z3 expression id
|
|
123
|
+
//{@
|
|
124
|
+
inline const Instruction *getCondInst(u32_t id) const
|
|
125
|
+
{
|
|
126
|
+
IndexToTermInstMap::const_iterator it = idToTermInstMap.find(id);
|
|
127
|
+
assert(it != idToTermInstMap.end() && "this should be a fresh condition");
|
|
128
|
+
return it->second;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
inline void setCondInst(const Condition &condition, const Instruction *inst)
|
|
132
|
+
{
|
|
133
|
+
assert(idToTermInstMap.find(condition.id()) == idToTermInstMap.end() && "this should be a fresh condition");
|
|
134
|
+
idToTermInstMap[condition.id()] = inst;
|
|
135
|
+
}
|
|
136
|
+
//@}
|
|
137
|
+
|
|
138
|
+
bool isNegCond(u32_t id) const
|
|
139
|
+
{
|
|
140
|
+
return negConds.test(id);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/// Get dominators
|
|
144
|
+
inline DominatorTree* getDT(const Function* fun)
|
|
145
|
+
{
|
|
146
|
+
return cfInfoBuilder.getDT(fun);
|
|
147
|
+
}
|
|
148
|
+
/// Get Postdominators
|
|
149
|
+
inline PostDominatorTree* getPostDT(const Function* fun)
|
|
150
|
+
{
|
|
151
|
+
return cfInfoBuilder.getPostDT(fun);
|
|
152
|
+
}
|
|
153
|
+
/// Get LoopInfo
|
|
154
|
+
inline LoopInfo* getLoopInfo(const Function* f)
|
|
155
|
+
{
|
|
156
|
+
return cfInfoBuilder.getLoopInfo(f);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
/// Guard Computation for a value-flow (between two basic blocks)
|
|
161
|
+
//@{
|
|
162
|
+
virtual Condition ComputeIntraVFGGuard(const BasicBlock* src, const BasicBlock* dst);
|
|
163
|
+
virtual Condition ComputeInterCallVFGGuard(const BasicBlock* src, const BasicBlock* dst, const BasicBlock* callBB);
|
|
164
|
+
virtual Condition ComputeInterRetVFGGuard(const BasicBlock* src, const BasicBlock* dst, const BasicBlock* retBB);
|
|
165
|
+
|
|
166
|
+
/// Get complement condition (from B1 to B0) according to a complementBB (BB2) at a phi
|
|
167
|
+
/// e.g., B0: dstBB; B1:incomingBB; B2:complementBB
|
|
168
|
+
virtual Condition getPHIComplementCond(const BasicBlock* BB1, const BasicBlock* BB2, const BasicBlock* BB0);
|
|
169
|
+
|
|
170
|
+
inline void clearCFCond()
|
|
171
|
+
{
|
|
172
|
+
bbToCondMap.clear();
|
|
173
|
+
}
|
|
174
|
+
/// Set current value for branch condition evaluation
|
|
175
|
+
inline void setCurEvalSVFGNode(const SVFGNode* node)
|
|
176
|
+
{
|
|
177
|
+
curEvalSVFGNode = node;
|
|
178
|
+
}
|
|
179
|
+
/// Get current value for branch condition evaluation
|
|
180
|
+
inline const SVFGNode* getCurEvalSVFGNode() const
|
|
181
|
+
{
|
|
182
|
+
return curEvalSVFGNode;
|
|
183
|
+
}
|
|
184
|
+
//@}
|
|
185
|
+
|
|
186
|
+
/// Print out the path condition information
|
|
187
|
+
void printPathCond();
|
|
188
|
+
|
|
189
|
+
/// whether condition is satisfiable
|
|
190
|
+
bool isSatisfiable(const Condition& condition);
|
|
191
|
+
|
|
192
|
+
/// whether condition is satisfiable for all possible boolean guards
|
|
193
|
+
inline bool isAllPathReachable(Condition& condition)
|
|
194
|
+
{
|
|
195
|
+
return isEquivalentBranchCond(condition, Condition::getTrueCond());
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/// Whether lhs and rhs are equivalent branch conditions
|
|
199
|
+
bool isEquivalentBranchCond(const Condition &lhs, const Condition &rhs) const;
|
|
200
|
+
|
|
201
|
+
inline ICFG* getICFG() const
|
|
202
|
+
{
|
|
203
|
+
return PAG::getPAG()->getICFG();
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/// Get/Set control-flow conditions
|
|
207
|
+
//@{
|
|
208
|
+
inline bool setCFCond(const BasicBlock* bb, const Condition& cond)
|
|
209
|
+
{
|
|
210
|
+
BBToCondMap::iterator it = bbToCondMap.find(bb);
|
|
211
|
+
// until a fixed-point is reached (condition is not changed)
|
|
212
|
+
if(it!=bbToCondMap.end() && isEquivalentBranchCond(it->second, cond))
|
|
213
|
+
return false;
|
|
214
|
+
|
|
215
|
+
bbToCondMap[bb] = cond;
|
|
216
|
+
return true;
|
|
217
|
+
}
|
|
218
|
+
inline Condition getCFCond(const BasicBlock* bb) const
|
|
219
|
+
{
|
|
220
|
+
BBToCondMap::const_iterator it = bbToCondMap.find(bb);
|
|
221
|
+
if(it==bbToCondMap.end())
|
|
222
|
+
{
|
|
223
|
+
return getFalseCond();
|
|
224
|
+
}
|
|
225
|
+
return it->second;
|
|
226
|
+
}
|
|
227
|
+
//@}
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
/// mark neg Z3 expression
|
|
231
|
+
inline void setNegCondInst(const Condition &condition, const Instruction *inst)
|
|
232
|
+
{
|
|
233
|
+
setCondInst(condition, inst);
|
|
234
|
+
negConds.set(condition.id());
|
|
235
|
+
}
|
|
236
|
+
private:
|
|
237
|
+
|
|
238
|
+
/// Allocate path condition for every basic block
|
|
239
|
+
virtual void allocateForBB(const BasicBlock& bb);
|
|
240
|
+
|
|
241
|
+
/// Get/Set a branch condition, and its terminator instruction
|
|
242
|
+
//@{
|
|
243
|
+
/// Set branch condition
|
|
244
|
+
void setBranchCond(const BasicBlock *bb, const BasicBlock *succ, const Condition& cond);
|
|
245
|
+
/// Get branch condition
|
|
246
|
+
Condition getBranchCond(const BasicBlock * bb, const BasicBlock *succ) const;
|
|
247
|
+
///Get a condition, evaluate the value for conditions if necessary (e.g., testNull like express)
|
|
248
|
+
Condition getEvalBrCond(const BasicBlock * bb, const BasicBlock *succ);
|
|
249
|
+
//@}
|
|
250
|
+
/// Evaluate branch conditions
|
|
251
|
+
//@{
|
|
252
|
+
/// Evaluate the branch condtion
|
|
253
|
+
Condition evaluateBranchCond(const BasicBlock * bb, const BasicBlock *succ) ;
|
|
254
|
+
/// Evaluate loop exit branch
|
|
255
|
+
Condition evaluateLoopExitBranch(const BasicBlock * bb, const BasicBlock *succ);
|
|
256
|
+
/// Return branch condition after evaluating test null like expression
|
|
257
|
+
Condition evaluateTestNullLikeExpr(const BranchStmt* branchStmt, const BasicBlock *succ);
|
|
258
|
+
/// Return condition when there is a branch calls program exit
|
|
259
|
+
Condition evaluateProgExit(const BranchStmt* branchStmt, const BasicBlock *succ);
|
|
260
|
+
/// Collect basic block contains program exit function call
|
|
261
|
+
void collectBBCallingProgExit(const BasicBlock& bb);
|
|
262
|
+
bool isBBCallsProgExit(const BasicBlock* bb);
|
|
263
|
+
//@}
|
|
264
|
+
|
|
265
|
+
/// Evaluate test null/not null like expressions
|
|
266
|
+
//@{
|
|
267
|
+
/// Return true if the predicate of this compare instruction is equal
|
|
268
|
+
bool isEQCmp(const CmpInst* cmp) const;
|
|
269
|
+
/// Return true if the predicate of this compare instruction is not equal
|
|
270
|
+
bool isNECmp(const CmpInst* cmp) const;
|
|
271
|
+
/// Return true if this is a test null expression
|
|
272
|
+
bool isTestNullExpr(const Value* test) const;
|
|
273
|
+
/// Return true if this is a test not null expression
|
|
274
|
+
bool isTestNotNullExpr(const Value* test) const;
|
|
275
|
+
/// Return true if two values on the predicate are what we want
|
|
276
|
+
bool isTestContainsNullAndTheValue(const CmpInst* cmp) const;
|
|
277
|
+
//@}
|
|
278
|
+
|
|
279
|
+
/// Release memory
|
|
280
|
+
void destroy()
|
|
281
|
+
{
|
|
282
|
+
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/// extract subexpression from a Z3 expression
|
|
286
|
+
void extractSubConds(const Condition &condition, NodeBS &support) const;
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
PTACFInfoBuilder cfInfoBuilder; ///< map a function to its loop info
|
|
290
|
+
FunToExitBBsMap funToExitBBsMap; ///< map a function to all its basic blocks calling program exit
|
|
291
|
+
BBToCondMap bbToCondMap; ///< map a basic block to its path condition starting from root
|
|
292
|
+
const SVFGNode* curEvalSVFGNode{}; ///< current llvm value to evaluate branch condition when computing guards
|
|
293
|
+
IndexToTermInstMap idToTermInstMap; ///key: z3 expression id, value: instruction
|
|
294
|
+
NodeBS negConds; ///bit vector for distinguish neg
|
|
295
|
+
std::vector<Condition> conditionVec; /// vector storing z3expression
|
|
296
|
+
static u32_t totalCondNum; /// a counter for fresh condition
|
|
297
|
+
|
|
298
|
+
protected:
|
|
299
|
+
BBCondMap bbConds; ///< map basic block to its successors/predecessors branch conditions
|
|
300
|
+
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
} // End namespace SVF
|
|
304
|
+
|
|
305
|
+
#endif /* PATHALLOCATOR_H_ */
|
|
@@ -62,7 +62,7 @@ private:
|
|
|
62
62
|
ProgSlice* _curSlice; /// current program slice
|
|
63
63
|
SVFGNodeSet sources; /// source nodes
|
|
64
64
|
SVFGNodeSet sinks; /// source nodes
|
|
65
|
-
|
|
65
|
+
SaberCondAllocator* saberCondAllocator;
|
|
66
66
|
SVFGNodeToDPItemsMap nodeToDPItemsMap; ///< record forward visited dpitems
|
|
67
67
|
SVFGNodeSet visitedSet; ///< record backward visited nodes
|
|
68
68
|
|
|
@@ -76,7 +76,7 @@ public:
|
|
|
76
76
|
/// Constructor
|
|
77
77
|
SrcSnkDDA() : _curSlice(nullptr), svfg(nullptr), ptaCallGraph(nullptr)
|
|
78
78
|
{
|
|
79
|
-
|
|
79
|
+
saberCondAllocator = new SaberCondAllocator();
|
|
80
80
|
}
|
|
81
81
|
/// Destructor
|
|
82
82
|
virtual ~SrcSnkDDA()
|
|
@@ -232,10 +232,10 @@ public:
|
|
|
232
232
|
}
|
|
233
233
|
//@}
|
|
234
234
|
|
|
235
|
-
/// Get
|
|
236
|
-
|
|
235
|
+
/// Get saber condition allocator
|
|
236
|
+
SaberCondAllocator* getSaberCondAllocator() const
|
|
237
237
|
{
|
|
238
|
-
return
|
|
238
|
+
return saberCondAllocator;
|
|
239
239
|
}
|
|
240
240
|
|
|
241
241
|
protected:
|
|
@@ -307,7 +307,7 @@ protected:
|
|
|
307
307
|
//@{
|
|
308
308
|
void dumpSlices();
|
|
309
309
|
void annotateSlice(ProgSlice* slice);
|
|
310
|
-
void
|
|
310
|
+
void printZ3Stat();
|
|
311
311
|
//@}
|
|
312
312
|
|
|
313
313
|
};
|
|
@@ -218,9 +218,9 @@ public:
|
|
|
218
218
|
static const llvm::cl::opt<bool> SymTabPrint;
|
|
219
219
|
|
|
220
220
|
// Conditions.cpp
|
|
221
|
-
static const llvm::cl::opt<unsigned>
|
|
221
|
+
static const llvm::cl::opt<unsigned> MaxZ3Size;
|
|
222
222
|
|
|
223
|
-
//
|
|
223
|
+
// SaberCondAllocator.cpp
|
|
224
224
|
static const llvm::cl::opt<bool> PrintPathCond;
|
|
225
225
|
|
|
226
226
|
// SVFUtil.cpp
|
|
@@ -39,6 +39,7 @@ class Z3Expr
|
|
|
39
39
|
{
|
|
40
40
|
public:
|
|
41
41
|
static z3::context *ctx;
|
|
42
|
+
static std::unique_ptr<z3::solver> solver;
|
|
42
43
|
|
|
43
44
|
private:
|
|
44
45
|
z3::expr e;
|
|
@@ -80,22 +81,15 @@ public:
|
|
|
80
81
|
return e;
|
|
81
82
|
}
|
|
82
83
|
|
|
84
|
+
/// Get z3 solver, singleton design here to make sure we only have one context
|
|
85
|
+
static z3::solver &getSolver();
|
|
86
|
+
|
|
83
87
|
/// Get z3 context, singleton design here to make sure we only have one context
|
|
84
|
-
static z3::context &getContext()
|
|
85
|
-
{
|
|
86
|
-
if (ctx == nullptr)
|
|
87
|
-
{
|
|
88
|
-
ctx = new z3::context();
|
|
89
|
-
}
|
|
90
|
-
return *ctx;
|
|
91
|
-
}
|
|
88
|
+
static z3::context &getContext();
|
|
92
89
|
|
|
93
90
|
/// release z3 context
|
|
94
|
-
static void releaseContext()
|
|
95
|
-
|
|
96
|
-
delete ctx;
|
|
97
|
-
ctx = nullptr;
|
|
98
|
-
}
|
|
91
|
+
static void releaseContext();
|
|
92
|
+
|
|
99
93
|
|
|
100
94
|
/// null expression
|
|
101
95
|
static z3::expr nullExpr()
|
|
@@ -109,6 +103,12 @@ public:
|
|
|
109
103
|
return e.id();
|
|
110
104
|
}
|
|
111
105
|
|
|
106
|
+
/// get hash id
|
|
107
|
+
inline u32_t hash() const
|
|
108
|
+
{
|
|
109
|
+
return e.hash();
|
|
110
|
+
}
|
|
111
|
+
|
|
112
112
|
inline const std::string to_string() const
|
|
113
113
|
{
|
|
114
114
|
return e.to_string();
|
|
@@ -245,7 +245,7 @@ public:
|
|
|
245
245
|
return !lhs.getExpr();
|
|
246
246
|
}
|
|
247
247
|
|
|
248
|
-
friend Z3Expr ite(const Z3Expr&
|
|
248
|
+
friend Z3Expr ite(const Z3Expr &cond, const Z3Expr &lhs, const Z3Expr &rhs)
|
|
249
249
|
{
|
|
250
250
|
return ite(cond.getExpr(), lhs.getExpr(), rhs.getExpr());
|
|
251
251
|
}
|
|
@@ -266,6 +266,38 @@ public:
|
|
|
266
266
|
return getExpr().get_sort();
|
|
267
267
|
}
|
|
268
268
|
//%}
|
|
269
|
+
|
|
270
|
+
/// output Z3 expression as a string
|
|
271
|
+
static std::string dumpStr(const Z3Expr &z3Expr);
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
/// get the number of subexpression of a Z3 expression
|
|
275
|
+
static u32_t getExprSize(const Z3Expr &z3Expr);
|
|
276
|
+
|
|
277
|
+
/// Return the unique true condition
|
|
278
|
+
static inline Z3Expr getTrueCond()
|
|
279
|
+
{
|
|
280
|
+
return getContext().bool_val(true);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
/// Return the unique false condition
|
|
285
|
+
static inline Z3Expr getFalseCond()
|
|
286
|
+
{
|
|
287
|
+
return getContext().bool_val(false);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/// compute NEG
|
|
291
|
+
static inline Z3Expr NEG(const Z3Expr &z3Expr)
|
|
292
|
+
{
|
|
293
|
+
return !z3Expr;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/// compute AND, used for branch condition
|
|
297
|
+
static Z3Expr AND(const Z3Expr &lhs, const Z3Expr &rhs);
|
|
298
|
+
|
|
299
|
+
/// compute OR, used for branch condition
|
|
300
|
+
static Z3Expr OR(const Z3Expr &lhs, const Z3Expr &rhs);
|
|
269
301
|
};
|
|
270
302
|
}
|
|
271
303
|
|