svf-lib 1.0.973 → 1.0.974
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/PathCondAllocator.h +4 -4
- package/SVF-linux/include/SABER/SrcSnkDDA.h +2 -2
- package/SVF-linux/include/SABER/SrcSnkSolver.h +186 -0
- package/SVF-linux/include/SVF-FE/IRAnnotator.h +321 -0
- package/SVF-linux/include/Util/BDDExpr.h +182 -0
- package/SVF-linux/include/Util/DPItem.h +1 -1
- package/SVF-linux/include/Util/ExeState.h +172 -0
- package/SVF-linux/include/Util/Options.h +0 -3
- package/SVF-linux/include/Util/Z3Expr.h +235 -0
- package/SVF-linux/include/WPA/FlowSensitiveTBHC.h +1 -1
- package/SVF-linux/include/WPA/TypeBasedHeapCloning.h +188 -0
- package/package.json +1 -1
|
Binary file
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
#include "Util/SVFModule.h"
|
|
34
34
|
#include "SVF-FE/DataFlowUtil.h"
|
|
35
35
|
#include "SVF-FE/BasicTypes.h"
|
|
36
|
-
#include "Util/
|
|
36
|
+
#include "Util/BDDExpr.h"
|
|
37
37
|
#include "Util/WorkList.h"
|
|
38
38
|
#include "Graphs/SVFG.h"
|
|
39
39
|
|
|
@@ -49,7 +49,7 @@ class PathCondAllocator
|
|
|
49
49
|
|
|
50
50
|
public:
|
|
51
51
|
|
|
52
|
-
typedef
|
|
52
|
+
typedef BDDExprManager::BDDExpr Condition; /// z3 condition
|
|
53
53
|
|
|
54
54
|
typedef Map<u32_t,Condition*> CondPosMap; ///< map a branch to its Condition
|
|
55
55
|
typedef Map<const BasicBlock*, CondPosMap > BBCondMap; // map bb to a Condition
|
|
@@ -133,7 +133,7 @@ public:
|
|
|
133
133
|
{
|
|
134
134
|
return condMgr->getCondInst(cond);
|
|
135
135
|
}
|
|
136
|
-
inline void setCondInst(const
|
|
136
|
+
inline void setCondInst(const Condition* cond, const Instruction* inst){
|
|
137
137
|
condMgr->setCondInst(cond, inst);
|
|
138
138
|
}
|
|
139
139
|
//@}
|
|
@@ -286,7 +286,7 @@ private:
|
|
|
286
286
|
const SVFGNode* curEvalSVFGNode{}; ///< current llvm value to evaluate branch condition when computing guards
|
|
287
287
|
|
|
288
288
|
protected:
|
|
289
|
-
|
|
289
|
+
BDDExprManager* condMgr; ///< z3 manager
|
|
290
290
|
BBCondMap bbConds; ///< map basic block to its successors/predecessors branch conditions
|
|
291
291
|
|
|
292
292
|
};
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
#ifndef SRCSNKANALYSIS_H_
|
|
31
31
|
#define SRCSNKANALYSIS_H_
|
|
32
32
|
|
|
33
|
-
#include "
|
|
33
|
+
#include "SrcSnkSolver.h"
|
|
34
34
|
#include "Graphs/SVFGOPT.h"
|
|
35
35
|
#include "SABER/ProgSlice.h"
|
|
36
36
|
#include "SABER/SaberSVFGBuilder.h"
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
namespace SVF
|
|
39
39
|
{
|
|
40
40
|
|
|
41
|
-
typedef
|
|
41
|
+
typedef SrcSnkSolver<SVFG*,CxtDPItem> CFLSrcSnkSolver;
|
|
42
42
|
|
|
43
43
|
/*!
|
|
44
44
|
* General source-sink analysis, which serves as a base analysis to be extended for various clients
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
//===- SrcSnkSolver.h -- CFL reachability solver---------------------------------//
|
|
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
|
+
* SrcSnkSolver.h
|
|
25
|
+
*
|
|
26
|
+
* Created on: Apr 1, 2014
|
|
27
|
+
* Author: Yulei Sui
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
#ifndef CFLSOLVER_H_
|
|
31
|
+
#define CFLSOLVER_H_
|
|
32
|
+
|
|
33
|
+
#include "Util/WorkList.h"
|
|
34
|
+
#include "Util/DPItem.h"
|
|
35
|
+
|
|
36
|
+
namespace SVF
|
|
37
|
+
{
|
|
38
|
+
|
|
39
|
+
/*
|
|
40
|
+
* Generic CFL solver for demand-driven analysis based on different graphs (e.g. SVFIR, VFG, ThreadVFG)
|
|
41
|
+
* Extend this class for sophisticated CFL-reachability resolution (e.g. field, flow, path)
|
|
42
|
+
*/
|
|
43
|
+
template<class GraphType, class DPIm = DPItem>
|
|
44
|
+
class SrcSnkSolver
|
|
45
|
+
{
|
|
46
|
+
|
|
47
|
+
public:
|
|
48
|
+
///Define the GTraits and node iterator
|
|
49
|
+
typedef llvm::GraphTraits<GraphType> GTraits;
|
|
50
|
+
typedef typename GTraits::NodeType GNODE;
|
|
51
|
+
typedef typename GTraits::EdgeType GEDGE;
|
|
52
|
+
typedef typename GTraits::nodes_iterator node_iterator;
|
|
53
|
+
typedef typename GTraits::ChildIteratorType child_iterator;
|
|
54
|
+
|
|
55
|
+
/// Define inverse GTraits and note iterator
|
|
56
|
+
typedef llvm::GraphTraits<llvm::Inverse<GNODE *> > InvGTraits;
|
|
57
|
+
typedef typename InvGTraits::ChildIteratorType inv_child_iterator;
|
|
58
|
+
|
|
59
|
+
/// Define worklist
|
|
60
|
+
typedef FIFOWorkList<DPIm> WorkList;
|
|
61
|
+
|
|
62
|
+
protected:
|
|
63
|
+
|
|
64
|
+
/// Constructor
|
|
65
|
+
SrcSnkSolver(): _graph(nullptr)
|
|
66
|
+
{
|
|
67
|
+
}
|
|
68
|
+
/// Destructor
|
|
69
|
+
virtual ~SrcSnkSolver()
|
|
70
|
+
{
|
|
71
|
+
}
|
|
72
|
+
/// Get/Set graph methods
|
|
73
|
+
//@{
|
|
74
|
+
const inline GraphType graph() const
|
|
75
|
+
{
|
|
76
|
+
return _graph;
|
|
77
|
+
}
|
|
78
|
+
inline void setGraph(GraphType g)
|
|
79
|
+
{
|
|
80
|
+
_graph = g;
|
|
81
|
+
}
|
|
82
|
+
//@}
|
|
83
|
+
|
|
84
|
+
inline GNODE* getNode(NodeID id) const
|
|
85
|
+
{
|
|
86
|
+
return _graph->getGNode(id);
|
|
87
|
+
}
|
|
88
|
+
virtual inline NodeID getNodeIDFromItem(const DPIm& item) const
|
|
89
|
+
{
|
|
90
|
+
return item.getCurNodeID();
|
|
91
|
+
}
|
|
92
|
+
/// CFL forward traverse solve
|
|
93
|
+
virtual void forwardTraverse(DPIm& it)
|
|
94
|
+
{
|
|
95
|
+
pushIntoWorklist(it);
|
|
96
|
+
|
|
97
|
+
while (!isWorklistEmpty())
|
|
98
|
+
{
|
|
99
|
+
DPIm item = popFromWorklist();
|
|
100
|
+
FWProcessCurNode(item);
|
|
101
|
+
|
|
102
|
+
GNODE* v = getNode(getNodeIDFromItem(item));
|
|
103
|
+
child_iterator EI = GTraits::child_begin(v);
|
|
104
|
+
child_iterator EE = GTraits::child_end(v);
|
|
105
|
+
for (; EI != EE; ++EI)
|
|
106
|
+
{
|
|
107
|
+
FWProcessOutgoingEdge(item,*(EI.getCurrent()) );
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/// CFL forward traverse solve
|
|
112
|
+
virtual void backwardTraverse(DPIm& it)
|
|
113
|
+
{
|
|
114
|
+
pushIntoWorklist(it);
|
|
115
|
+
|
|
116
|
+
while (!isWorklistEmpty())
|
|
117
|
+
{
|
|
118
|
+
DPIm item = popFromWorklist();
|
|
119
|
+
BWProcessCurNode(item);
|
|
120
|
+
|
|
121
|
+
GNODE* v = getNode(getNodeIDFromItem(item));
|
|
122
|
+
inv_child_iterator EI = InvGTraits::child_begin(v);
|
|
123
|
+
inv_child_iterator EE = InvGTraits::child_end(v);
|
|
124
|
+
for (; EI != EE; ++EI)
|
|
125
|
+
{
|
|
126
|
+
BWProcessIncomingEdge(item,*(EI.getCurrent()) );
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/// Process the DP item
|
|
131
|
+
//@{
|
|
132
|
+
virtual void FWProcessCurNode(const DPIm&)
|
|
133
|
+
{
|
|
134
|
+
}
|
|
135
|
+
virtual void BWProcessCurNode(const DPIm&)
|
|
136
|
+
{
|
|
137
|
+
}
|
|
138
|
+
//@}
|
|
139
|
+
/// Propagation for the solving, to be implemented in the child class
|
|
140
|
+
//@{
|
|
141
|
+
virtual void FWProcessOutgoingEdge(const DPIm& item, GEDGE* edge)
|
|
142
|
+
{
|
|
143
|
+
DPIm newItem(item);
|
|
144
|
+
newItem.setCurNodeID(edge->getDstID());
|
|
145
|
+
pushIntoWorklist(newItem);
|
|
146
|
+
}
|
|
147
|
+
virtual void BWProcessIncomingEdge(const DPIm& item, GEDGE* edge)
|
|
148
|
+
{
|
|
149
|
+
DPIm newItem(item);
|
|
150
|
+
newItem.setCurNodeID(edge->getSrcID());
|
|
151
|
+
pushIntoWorklist(newItem);
|
|
152
|
+
}
|
|
153
|
+
//@}
|
|
154
|
+
/// Worklist operations
|
|
155
|
+
//@{
|
|
156
|
+
inline DPIm popFromWorklist()
|
|
157
|
+
{
|
|
158
|
+
return worklist.pop();
|
|
159
|
+
}
|
|
160
|
+
inline bool pushIntoWorklist(DPIm& item)
|
|
161
|
+
{
|
|
162
|
+
return worklist.push(item);
|
|
163
|
+
}
|
|
164
|
+
inline bool isWorklistEmpty()
|
|
165
|
+
{
|
|
166
|
+
return worklist.empty();
|
|
167
|
+
}
|
|
168
|
+
inline bool isInWorklist(DPIm& item)
|
|
169
|
+
{
|
|
170
|
+
return worklist.find(item);
|
|
171
|
+
}
|
|
172
|
+
//@}
|
|
173
|
+
|
|
174
|
+
private:
|
|
175
|
+
|
|
176
|
+
/// Graph
|
|
177
|
+
GraphType _graph;
|
|
178
|
+
|
|
179
|
+
/// Worklist for resolution
|
|
180
|
+
WorkList worklist;
|
|
181
|
+
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
} // End namespace SVF
|
|
185
|
+
|
|
186
|
+
#endif /* CFLSOLVER_H_ */
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Annotator.h
|
|
3
|
+
*
|
|
4
|
+
* Created on: March 22, 2021
|
|
5
|
+
* Author: Nicholas Tsom
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
#ifndef IRANNOTATOR_H_
|
|
9
|
+
#define IRANNOTATOR_H_
|
|
10
|
+
|
|
11
|
+
#include "MemoryModel/SVFIR.h"
|
|
12
|
+
#include "MemoryModel/PointerAnalysisImpl.h"
|
|
13
|
+
#include "Util/SVFUtil.h"
|
|
14
|
+
#include "llvm/IR/Metadata.h"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
namespace SVF
|
|
18
|
+
{
|
|
19
|
+
/*!
|
|
20
|
+
* Program annotator to write metadata information on LLVM IR
|
|
21
|
+
*/
|
|
22
|
+
class IRAnnotator
|
|
23
|
+
{
|
|
24
|
+
public:
|
|
25
|
+
IRAnnotator():
|
|
26
|
+
mainModule(nullptr),
|
|
27
|
+
ptsTo(nullptr)
|
|
28
|
+
{}
|
|
29
|
+
~IRAnnotator() {}
|
|
30
|
+
|
|
31
|
+
void processAndersenResults(SVFIR *pag, BVDataPTAImpl *ptsTo, bool writeFlag)
|
|
32
|
+
{
|
|
33
|
+
this->ptsTo = ptsTo;
|
|
34
|
+
mainModule = LLVMModuleSet::getLLVMModuleSet()->getMainLLVMModule();
|
|
35
|
+
|
|
36
|
+
// Add a named metadata node used to check whether or not
|
|
37
|
+
// this IR has been annotated with Andersen information
|
|
38
|
+
if (writeFlag)
|
|
39
|
+
mainModule->getOrInsertNamedMetadata("SVFIR-Annotated");
|
|
40
|
+
|
|
41
|
+
for (auto it = pag->begin(); it != pag->end(); ++it)
|
|
42
|
+
{
|
|
43
|
+
auto nodeId = it->first;
|
|
44
|
+
auto pagNode = it->second;
|
|
45
|
+
auto gepNode = SVFUtil::dyn_cast<GepObjVar>(pagNode);
|
|
46
|
+
|
|
47
|
+
if (gepNode && writeFlag)
|
|
48
|
+
{
|
|
49
|
+
writePAGgepNode(nodeId, gepNode);
|
|
50
|
+
}
|
|
51
|
+
else if (pagNode->hasValue())
|
|
52
|
+
{
|
|
53
|
+
processPAGNode(pagNode->getValue(), nodeId, writeFlag);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (!writeFlag)
|
|
58
|
+
readPAGgepNodes(pag);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private:
|
|
62
|
+
// Write the PAGgepNode to the IR such that metadata name is the SVFIR node id and the operands
|
|
63
|
+
// are its base node's id and location offset
|
|
64
|
+
void writePAGgepNode(SVF::NodeID nodeId, GepObjVar* gepNode)
|
|
65
|
+
{
|
|
66
|
+
auto baseNodeId = gepNode->getBaseNode();
|
|
67
|
+
auto locationSetOffset = gepNode->getConstantFieldIdx();
|
|
68
|
+
|
|
69
|
+
LLVMContext &context = mainModule->getContext();
|
|
70
|
+
llvm::SmallVector<llvm::Metadata *, 32> operands;
|
|
71
|
+
operands.push_back(llvm::MDString::get(context, std::to_string(baseNodeId)));
|
|
72
|
+
operands.push_back(llvm::MDString::get(context, std::to_string(locationSetOffset)));
|
|
73
|
+
|
|
74
|
+
llvm::MDTuple *metadata = llvm::MDTuple::get(context, operands);
|
|
75
|
+
std::string label = "gepnode-" + std::to_string(nodeId);
|
|
76
|
+
|
|
77
|
+
mainModule->getOrInsertNamedMetadata(label)->addOperand(metadata);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Reads the PAGGepNodes in the annotated IR and creates a new SVFIR Node based on the
|
|
81
|
+
// data contained in the operands of the metadata node
|
|
82
|
+
void readPAGgepNodes(SVFIR *pag)
|
|
83
|
+
{
|
|
84
|
+
for (auto it = mainModule->named_metadata_begin(); it != mainModule->named_metadata_end(); ++it)
|
|
85
|
+
{
|
|
86
|
+
std::string label = it->getName().str();
|
|
87
|
+
std::string toErase = "gepnode-";
|
|
88
|
+
std::size_t pos = label.find(toErase);
|
|
89
|
+
if (pos == std::string::npos)
|
|
90
|
+
{
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
label.erase(pos, toErase.length());
|
|
94
|
+
|
|
95
|
+
SVF::NodeID nodeId = std::stoi(label);
|
|
96
|
+
auto mdNode = it->getOperand(0);
|
|
97
|
+
|
|
98
|
+
SVF::NodeID baseNodeId = std::stoi(llvm::cast<llvm::MDString>(mdNode->getOperand(0))->getString().str());
|
|
99
|
+
SVF::s32_t locationSetOffset = std::stoi(llvm::cast<llvm::MDString>(mdNode->getOperand(1))->getString().str());
|
|
100
|
+
|
|
101
|
+
LocationSet locationSet = LocationSet(locationSetOffset);
|
|
102
|
+
SVF::NodeID gepnodeId = pag->getGepObjVar(baseNodeId, locationSet);
|
|
103
|
+
|
|
104
|
+
assert(nodeId == gepnodeId && "nodeId != gepnodeId");
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Deduce the LLVM value's type, and process the metadata accordingly
|
|
109
|
+
void processPAGNode(const Value *value, SVF::NodeID nodeId, bool writeFlag)
|
|
110
|
+
{
|
|
111
|
+
if (auto instruction = const_cast<Instruction *>(SVFUtil::dyn_cast<Instruction>(value)))
|
|
112
|
+
{
|
|
113
|
+
processInstructionNode(instruction, nodeId, writeFlag);
|
|
114
|
+
}
|
|
115
|
+
else if (auto argument = const_cast<Argument *>(SVFUtil::dyn_cast<Argument>(value)))
|
|
116
|
+
{
|
|
117
|
+
processArgumentNode(argument, nodeId, writeFlag);
|
|
118
|
+
}
|
|
119
|
+
else if (auto function = const_cast<Function *>(SVFUtil::dyn_cast<Function>(value)))
|
|
120
|
+
{
|
|
121
|
+
processFunctionNode(function, nodeId, writeFlag);
|
|
122
|
+
}
|
|
123
|
+
else if (auto globalVar = const_cast<GlobalVariable *>(SVFUtil::dyn_cast<GlobalVariable>(value)))
|
|
124
|
+
{
|
|
125
|
+
processGlobalVarNode(globalVar, nodeId, writeFlag);
|
|
126
|
+
}
|
|
127
|
+
else if (auto basicBlock = const_cast<BasicBlock *>(SVFUtil::dyn_cast<BasicBlock>(value)))
|
|
128
|
+
{
|
|
129
|
+
processBasicBlockNode(basicBlock, nodeId, writeFlag);
|
|
130
|
+
}
|
|
131
|
+
else if (SVFUtil::isa<Constant>(value))
|
|
132
|
+
{
|
|
133
|
+
processConstantNode(nodeId, writeFlag);
|
|
134
|
+
}
|
|
135
|
+
else if (auto inlineAsm = const_cast<llvm::InlineAsm *>(SVFUtil::dyn_cast<llvm::InlineAsm>(value)))
|
|
136
|
+
{
|
|
137
|
+
processInlineAsmNode(inlineAsm, nodeId, writeFlag);
|
|
138
|
+
}
|
|
139
|
+
else
|
|
140
|
+
{
|
|
141
|
+
SVFUtil::outs() << "Value is NOT a Instruction, Argument, Function, GlobalVariable, BasicBlock, Constant or InlineAsm" << std::endl;
|
|
142
|
+
SVFUtil::outs() << SVFUtil::value2String(value) << "\n";
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
void processInstructionNode(Instruction *instruction, const SVF::NodeID &nodeId, bool writeFlag)
|
|
147
|
+
{
|
|
148
|
+
std::string label = "inode-" + std::to_string(nodeId);
|
|
149
|
+
|
|
150
|
+
if (writeFlag)
|
|
151
|
+
{
|
|
152
|
+
LLVMContext &context = instruction->getContext();
|
|
153
|
+
auto mdNodePts = getMdNodePts(nodeId, context);
|
|
154
|
+
instruction->setMetadata(label, mdNodePts);
|
|
155
|
+
}
|
|
156
|
+
else
|
|
157
|
+
{
|
|
158
|
+
auto mdNode = instruction->getMetadata(label);
|
|
159
|
+
assert(mdNode != nullptr && "Failed to retrive valid node id at instruction");
|
|
160
|
+
addAndersenMetadata(nodeId, mdNode);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
void processArgumentNode(Argument *argument, const SVF::NodeID &nodeId, bool writeFlag)
|
|
165
|
+
{
|
|
166
|
+
std::string label = "anode-" + std::to_string(nodeId);
|
|
167
|
+
|
|
168
|
+
if (writeFlag)
|
|
169
|
+
{
|
|
170
|
+
LLVMContext &context = argument->getContext();
|
|
171
|
+
auto mdNodePts = getMdNodePts(nodeId, context);
|
|
172
|
+
argument->getParent()->setMetadata(label, mdNodePts);
|
|
173
|
+
}
|
|
174
|
+
else
|
|
175
|
+
{
|
|
176
|
+
auto mdNode = argument->getParent()->getMetadata(label);
|
|
177
|
+
assert(mdNode != nullptr && "Failed to retrive valid node id at argument");
|
|
178
|
+
addAndersenMetadata(nodeId, mdNode);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
void processFunctionNode(Function *function, const SVF::NodeID &nodeId, bool writeFlag)
|
|
183
|
+
{
|
|
184
|
+
std::string label = "fnode-" + std::to_string(nodeId);
|
|
185
|
+
|
|
186
|
+
if (writeFlag)
|
|
187
|
+
{
|
|
188
|
+
LLVMContext &context = function->getContext();
|
|
189
|
+
auto mdNodePts = getMdNodePts(nodeId, context);
|
|
190
|
+
function->setMetadata(label, mdNodePts);
|
|
191
|
+
}
|
|
192
|
+
else
|
|
193
|
+
{
|
|
194
|
+
auto mdNode = function->getMetadata(label);
|
|
195
|
+
assert(mdNode != nullptr && "Failed to retrive valid node id at function");
|
|
196
|
+
addAndersenMetadata(nodeId, mdNode);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
void processGlobalVarNode(GlobalVariable *globalVar, const SVF::NodeID &nodeId, bool writeFlag)
|
|
201
|
+
{
|
|
202
|
+
std::string label = "gnode-" + std::to_string(nodeId);
|
|
203
|
+
|
|
204
|
+
if (writeFlag)
|
|
205
|
+
{
|
|
206
|
+
LLVMContext &context = globalVar->getContext();
|
|
207
|
+
auto mdNodePts = getMdNodePts(nodeId, context);
|
|
208
|
+
globalVar->setMetadata(label, mdNodePts);
|
|
209
|
+
}
|
|
210
|
+
else
|
|
211
|
+
{
|
|
212
|
+
auto mdNode = globalVar->getMetadata(label);
|
|
213
|
+
assert(mdNode != nullptr && "Failed to retrive valid node id at instruction");
|
|
214
|
+
addAndersenMetadata(nodeId, mdNode);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
void processBasicBlockNode(BasicBlock *basicBlock, const SVF::NodeID &nodeId, bool writeFlag)
|
|
219
|
+
{
|
|
220
|
+
std::string label = "bnode-" + std::to_string(nodeId);
|
|
221
|
+
|
|
222
|
+
if (writeFlag)
|
|
223
|
+
{
|
|
224
|
+
LLVMContext &context = basicBlock->getContext();
|
|
225
|
+
auto mdNodePts = getMdNodePts(nodeId, context);
|
|
226
|
+
basicBlock->getParent()->setMetadata(label, mdNodePts);
|
|
227
|
+
}
|
|
228
|
+
else
|
|
229
|
+
{
|
|
230
|
+
auto mdNode = basicBlock->getParent()->getMetadata(label);
|
|
231
|
+
assert(mdNode != nullptr && "Failed to retrive valid node id at basicBlock");
|
|
232
|
+
addAndersenMetadata(nodeId, mdNode);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
void processConstantNode(const SVF::NodeID &nodeId, bool writeFlag)
|
|
237
|
+
{
|
|
238
|
+
std::string label = "cnode-" + std::to_string(nodeId);
|
|
239
|
+
|
|
240
|
+
if (writeFlag)
|
|
241
|
+
{
|
|
242
|
+
LLVMContext &context = mainModule->getContext();
|
|
243
|
+
auto mdNodePts = getMdNodePts(nodeId, context);
|
|
244
|
+
mainModule->getOrInsertNamedMetadata(label)->addOperand(mdNodePts);
|
|
245
|
+
}
|
|
246
|
+
else
|
|
247
|
+
{
|
|
248
|
+
auto mdNode = mainModule->getNamedMetadata(label);
|
|
249
|
+
assert(mdNode != nullptr && "Failed to retrive valid node id at instruction");
|
|
250
|
+
addAndersenNamedMetdata(nodeId, mdNode);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
void processInlineAsmNode(llvm::InlineAsm *inlineAsm, const SVF::NodeID &nodeId, bool writeFlag)
|
|
255
|
+
{
|
|
256
|
+
std::string label = "iAsmnode-" + std::to_string(nodeId);
|
|
257
|
+
|
|
258
|
+
if (writeFlag)
|
|
259
|
+
{
|
|
260
|
+
LLVMContext &context = mainModule->getContext();
|
|
261
|
+
auto mdNodePts = getMdNodePts(nodeId, context);
|
|
262
|
+
mainModule->getOrInsertNamedMetadata(label)->addOperand(mdNodePts);
|
|
263
|
+
}
|
|
264
|
+
else
|
|
265
|
+
{
|
|
266
|
+
auto mdNode = mainModule->getNamedMetadata(label);
|
|
267
|
+
assert(mdNode != nullptr && "Failed to retrive valid node id at inlineAsm");
|
|
268
|
+
addAndersenNamedMetdata(nodeId, mdNode);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
void addAndersenMetadata(const SVF::NodeID &nodeId, MDNode *mdNode)
|
|
273
|
+
{
|
|
274
|
+
if (mdNode)
|
|
275
|
+
{
|
|
276
|
+
for (unsigned int i = 0; i < mdNode->getNumOperands(); i++)
|
|
277
|
+
{
|
|
278
|
+
auto anderNodeIdStr = llvm::cast<llvm::MDString>(mdNode->getOperand(i))->getString().str();
|
|
279
|
+
auto anderNodeId = SVF::NodeID(std::stoul(anderNodeIdStr));
|
|
280
|
+
ptsTo->addPts(nodeId, anderNodeId);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
void addAndersenNamedMetdata(const SVF::NodeID &nodeId, NamedMDNode *mdNode)
|
|
286
|
+
{
|
|
287
|
+
if (mdNode)
|
|
288
|
+
{
|
|
289
|
+
for (unsigned int i = 0; i < mdNode->getNumOperands(); i++)
|
|
290
|
+
{
|
|
291
|
+
auto node = mdNode->getOperand(i);
|
|
292
|
+
|
|
293
|
+
for (unsigned int j = 0; j < node->getNumOperands(); j++)
|
|
294
|
+
{
|
|
295
|
+
auto anderNodeIdStr = llvm::cast<llvm::MDString>(node->getOperand(j))->getString().str();
|
|
296
|
+
auto anderNodeId = SVF::NodeID(std::stoul(anderNodeIdStr));
|
|
297
|
+
ptsTo->addPts(nodeId, anderNodeId);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
inline llvm::MDTuple* getMdNodePts(const SVF::NodeID &nodeId, LLVMContext &context)
|
|
304
|
+
{
|
|
305
|
+
llvm::SmallVector<llvm::Metadata *, 32> operands;
|
|
306
|
+
auto &ptTo = ptsTo->getPts(nodeId);
|
|
307
|
+
for (const auto p : ptTo)
|
|
308
|
+
{
|
|
309
|
+
operands.push_back(llvm::MDString::get(context, std::to_string(p)));
|
|
310
|
+
}
|
|
311
|
+
return llvm::MDTuple::get(context, operands);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
Module* mainModule;
|
|
315
|
+
BVDataPTAImpl *ptsTo;
|
|
316
|
+
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
} // End namespace SVF
|
|
320
|
+
|
|
321
|
+
#endif /* IRANNOTATOR_H_ */
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
//===- BDDExpr.h -- Context/Path BDD conditions----------------------------//
|
|
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
|
+
* Condition.h
|
|
25
|
+
*
|
|
26
|
+
* Created on: Oct 19, 2021
|
|
27
|
+
* Author: Yulei and Xiao
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
#ifndef BITVECTORCOND_H_
|
|
31
|
+
#define BITVECTORCOND_H_
|
|
32
|
+
|
|
33
|
+
#include "Util/BasicTypes.h"
|
|
34
|
+
#include <cstdio>
|
|
35
|
+
|
|
36
|
+
#include "CUDD/cuddInt.h"
|
|
37
|
+
#include "z3++.h"
|
|
38
|
+
|
|
39
|
+
namespace SVF {
|
|
40
|
+
|
|
41
|
+
class BDDExprManager {
|
|
42
|
+
public:
|
|
43
|
+
typedef DdNode BDDExpr;
|
|
44
|
+
typedef Map<u32_t, BDDExpr *> IndexToBDDExpr;
|
|
45
|
+
private:
|
|
46
|
+
static BDDExprManager *bddExprMgr;
|
|
47
|
+
IndexToBDDExpr indexToBddCondMap;
|
|
48
|
+
DdManager *m_bdd_mgr;
|
|
49
|
+
|
|
50
|
+
inline BDDExpr *BddOne() const {
|
|
51
|
+
return Cudd_ReadOne(m_bdd_mgr);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
inline BDDExpr *BddZero() const {
|
|
55
|
+
return Cudd_ReadLogicZero(m_bdd_mgr);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/// Constructor
|
|
59
|
+
BDDExprManager();
|
|
60
|
+
|
|
61
|
+
public:
|
|
62
|
+
typedef Map<const BDDExpr *, const Instruction *> CondToTermInstMap; // map a condition to its branch instruction
|
|
63
|
+
static u32_t totalCondNum; // a counter for fresh condition
|
|
64
|
+
/// Singleton design here to make sure we only have one instance during any analysis
|
|
65
|
+
//@{
|
|
66
|
+
static BDDExprManager *getBDDExprMgr();
|
|
67
|
+
|
|
68
|
+
static void releaseBDDExprMgr() {
|
|
69
|
+
delete bddExprMgr;
|
|
70
|
+
bddExprMgr = nullptr;
|
|
71
|
+
}
|
|
72
|
+
//@}
|
|
73
|
+
|
|
74
|
+
/// Destructor
|
|
75
|
+
virtual ~BDDExprManager();
|
|
76
|
+
|
|
77
|
+
BDDExpr *createCond(u32_t i) {
|
|
78
|
+
assert(indexToBddCondMap.find(i) == indexToBddCondMap.end() &&
|
|
79
|
+
"This should be fresh index to create new BDD");
|
|
80
|
+
BDDExpr *bddCond = Cudd_bddIthVar(m_bdd_mgr, i);
|
|
81
|
+
return indexToBddCondMap.emplace(i, bddCond).first->second;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/// Create a fresh condition to encode each program branch
|
|
85
|
+
virtual BDDExpr *createFreshBranchCond(const Instruction *inst);
|
|
86
|
+
|
|
87
|
+
/// Return the number of condition expressions
|
|
88
|
+
virtual inline u32_t getCondNumber() {
|
|
89
|
+
return Cudd_ReadNodeCount(m_bdd_mgr);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
/// Return the unique true condition
|
|
94
|
+
inline BDDExpr *getTrueCond() const {
|
|
95
|
+
return trueCond;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/// Return the unique false condition
|
|
99
|
+
inline BDDExpr *getFalseCond() const {
|
|
100
|
+
return falseCond;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/// Operations on conditions.
|
|
104
|
+
//@{
|
|
105
|
+
virtual BDDExpr *AND(BDDExpr *lhs, BDDExpr *rhs);
|
|
106
|
+
|
|
107
|
+
virtual BDDExpr *OR(BDDExpr *lhs, BDDExpr *rhs);
|
|
108
|
+
|
|
109
|
+
virtual BDDExpr *NEG(BDDExpr *lhs);
|
|
110
|
+
//@}
|
|
111
|
+
|
|
112
|
+
virtual bool isNegCond(const BDDExpr *cond) {
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/// Whether the condition is satisfiable
|
|
117
|
+
virtual bool isSatisfiable(const BDDExpr *cond) {
|
|
118
|
+
return cond != getFalseCond();
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/// Whether lhs and rhs are equivalent branch conditions
|
|
122
|
+
virtual bool isEquivalentBranchCond(const BDDExpr *lhs, const BDDExpr *rhs){
|
|
123
|
+
return lhs == rhs;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/// Whether **All Paths** are reachable
|
|
127
|
+
bool isAllPathReachable(const BDDExpr *e);
|
|
128
|
+
|
|
129
|
+
/// Get condition using condition id (z3 ast id)
|
|
130
|
+
virtual BDDExpr *getCond(u32_t id) {
|
|
131
|
+
auto it = indexToBddCondMap.find(id);
|
|
132
|
+
assert(it != indexToBddCondMap.end() && "condition not found!");
|
|
133
|
+
return it->second;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/// Get/Set llvm conditional expression
|
|
137
|
+
//{@
|
|
138
|
+
inline const Instruction *getCondInst(const BDDExpr *cond) const {
|
|
139
|
+
CondToTermInstMap::const_iterator it = condToInstMap.find(cond);
|
|
140
|
+
assert(it != condToInstMap.end() && "this should be a fresh condition");
|
|
141
|
+
return it->second;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
inline void setCondInst(const BDDExpr *cond, const Instruction *inst) {
|
|
145
|
+
assert(condToInstMap.find(cond) == condToInstMap.end() && "this should be a fresh condition");
|
|
146
|
+
condToInstMap[cond] = inst;
|
|
147
|
+
}
|
|
148
|
+
//@}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Utilities for dumping conditions. These methods use global functions from CUDD
|
|
152
|
+
* package and they can be removed outside this class scope to be used by others.
|
|
153
|
+
*/
|
|
154
|
+
void ddClearFlag(BDDExpr *f) const;
|
|
155
|
+
|
|
156
|
+
void BddSupportStep(BDDExpr *f, NodeBS &support) const;
|
|
157
|
+
|
|
158
|
+
void extractSubConds(const BDDExpr *f, NodeBS &support) const;
|
|
159
|
+
|
|
160
|
+
void dump(const BDDExpr *lhs, OutStream &O);
|
|
161
|
+
|
|
162
|
+
std::string dumpStr(const BDDExpr *e) const;
|
|
163
|
+
|
|
164
|
+
inline std::string getMemUsage() {
|
|
165
|
+
return std::to_string(Cudd_ReadMemoryInUse(m_bdd_mgr));
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
protected:
|
|
169
|
+
static BDDExpr *trueCond;
|
|
170
|
+
static BDDExpr *falseCond;
|
|
171
|
+
|
|
172
|
+
private:
|
|
173
|
+
|
|
174
|
+
CondToTermInstMap condToInstMap; ///< map condition to llvm instruction
|
|
175
|
+
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
} // End namespace SVF
|
|
181
|
+
|
|
182
|
+
#endif /* BITVECTORCOND_H_ */
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
//===- ExeState.h -- Execution State ----------------------------//
|
|
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
|
+
* ExeState.h
|
|
24
|
+
*
|
|
25
|
+
* Created on: April 29, 2022
|
|
26
|
+
* Author: Xiao
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
#ifndef SVF_EXESTATE_H
|
|
30
|
+
#define SVF_EXESTATE_H
|
|
31
|
+
#include "Util/Z3Expr.h"
|
|
32
|
+
#include "MemoryModel/SVFVariables.h"
|
|
33
|
+
|
|
34
|
+
namespace SVF {
|
|
35
|
+
|
|
36
|
+
#define AddressMask 0x7f000000
|
|
37
|
+
#define FlippedAddressMask (AddressMask^0xffffffff)
|
|
38
|
+
|
|
39
|
+
class ExeState {
|
|
40
|
+
public:
|
|
41
|
+
typedef Map<u32_t, Z3Expr> VarToValMap;
|
|
42
|
+
typedef Map<u32_t, Z3Expr> LocToValMap;
|
|
43
|
+
|
|
44
|
+
protected:
|
|
45
|
+
VarToValMap varToVal;
|
|
46
|
+
LocToValMap locToVal;
|
|
47
|
+
Z3Expr pathConstraint;
|
|
48
|
+
|
|
49
|
+
public:
|
|
50
|
+
ExeState() : pathConstraint(getContext().bool_val(true)) {}
|
|
51
|
+
|
|
52
|
+
ExeState(const Z3Expr &_pc, VarToValMap &_varToValMap, LocToValMap &_locToValMap) : varToVal(_varToValMap),
|
|
53
|
+
locToVal(_locToValMap),
|
|
54
|
+
pathConstraint(_pc) {}
|
|
55
|
+
|
|
56
|
+
ExeState(const ExeState &rhs) : varToVal(rhs.getVarToVal()), locToVal(rhs.getLocToVal()),
|
|
57
|
+
pathConstraint(rhs.getPathConstraint()) {
|
|
58
|
+
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
virtual ~ExeState() = default;
|
|
62
|
+
|
|
63
|
+
ExeState &operator=(const ExeState &rhs);
|
|
64
|
+
|
|
65
|
+
/// Overloading Operator==
|
|
66
|
+
bool operator==(const ExeState &rhs) const;
|
|
67
|
+
|
|
68
|
+
/// Overloading Operator!=
|
|
69
|
+
inline bool operator!=(const ExeState &rhs) const {
|
|
70
|
+
return !(*this == rhs);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/// Overloading Operator==
|
|
74
|
+
bool operator<(const ExeState &rhs) const;
|
|
75
|
+
|
|
76
|
+
z3::context &getContext() {
|
|
77
|
+
return Z3Expr::getContext();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const VarToValMap &getVarToVal() const {
|
|
81
|
+
return varToVal;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const LocToValMap &getLocToVal() const {
|
|
85
|
+
return locToVal;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const Z3Expr &getPathConstraint() const {
|
|
89
|
+
return pathConstraint;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
void setPathConstraint(const Z3Expr &pc) {
|
|
93
|
+
pathConstraint = pc.simplify();
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
inline Z3Expr &operator[](u32_t varId) {
|
|
97
|
+
return getZ3Expr(varId);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/// Init Z3Expr for ValVar
|
|
101
|
+
void initValVar(const ValVar *valVar, Z3Expr &e);
|
|
102
|
+
|
|
103
|
+
/// Init Z3Expr for ObjVar
|
|
104
|
+
void initObjVar(const ObjVar *objVar, Z3Expr &e);
|
|
105
|
+
|
|
106
|
+
/// Return Z3 expression based on SVFVar ID
|
|
107
|
+
Z3Expr &getZ3Expr(u32_t varId);
|
|
108
|
+
|
|
109
|
+
/// Store value to location
|
|
110
|
+
void store(const Z3Expr &loc, const Z3Expr &value);
|
|
111
|
+
|
|
112
|
+
/// Load value at location
|
|
113
|
+
Z3Expr &load(const Z3Expr &loc);
|
|
114
|
+
|
|
115
|
+
/// The physical address starts with 0x7f...... + idx
|
|
116
|
+
inline u32_t getVirtualMemAddress(u32_t idx) const {
|
|
117
|
+
return AddressMask + idx;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/// Check bit value of val start with 0x7F000000, filter by 0xFF000000
|
|
121
|
+
inline bool isVirtualMemAddress(u32_t val) {
|
|
122
|
+
return (val & 0xff000000) == AddressMask;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/// Return the internal index if idx is an address otherwise return the value of idx
|
|
126
|
+
inline u32_t getInternalID(u32_t idx) const {
|
|
127
|
+
return (idx & FlippedAddressMask);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/// Return int value from an expression if it is a numeral, otherwise return an approximate value
|
|
131
|
+
inline s32_t z3Expr2NumValue(const Z3Expr &e) {
|
|
132
|
+
assert(e.is_numeral() && "not numeral?");
|
|
133
|
+
return e.get_numeral_int64();
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/// Print values of all expressions
|
|
137
|
+
void printExprValues();
|
|
138
|
+
|
|
139
|
+
protected:
|
|
140
|
+
inline void store(u32_t objId, const Z3Expr &z3Expr) {
|
|
141
|
+
locToVal[objId] = z3Expr.simplify();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
inline Z3Expr &load(u32_t objId) {
|
|
145
|
+
return locToVal[objId];
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
template<>
|
|
151
|
+
struct std::hash<SVF::ExeState> {
|
|
152
|
+
size_t operator()(const SVF::ExeState &exeState) const {
|
|
153
|
+
|
|
154
|
+
size_t h = exeState.getVarToVal().size() * 2;
|
|
155
|
+
SVF::Hash<SVF::u32_t> hf;
|
|
156
|
+
for (const auto &t: exeState.getVarToVal()) {
|
|
157
|
+
h ^= hf(t.first) + 0x9e3779b9 + (h << 6) + (h >> 2);
|
|
158
|
+
h ^= hf(t.second.id()) + 0x9e3779b9 + (h << 6) + (h >> 2);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
size_t h2 = exeState.getVarToVal().size() * 2;
|
|
162
|
+
|
|
163
|
+
for (const auto &t: exeState.getLocToVal()) {
|
|
164
|
+
h2 ^= hf(t.first) + 0x9e3779b9 + (h2 << 6) + (h2 >> 2);
|
|
165
|
+
h2 ^= hf(t.second.id()) + 0x9e3779b9 + (h2 << 6) + (h2 >> 2);
|
|
166
|
+
}
|
|
167
|
+
SVF::Hash<std::pair<SVF::u32_t, SVF::u32_t>> pairH;
|
|
168
|
+
|
|
169
|
+
return pairH(make_pair(pairH(make_pair(h, h2)), exeState.getPathConstraint().id()));
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
#endif //SVF_EXESTATE_H
|
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
#include "Util/NodeIDAllocator.h"
|
|
11
11
|
#include "MSSA/MemSSA.h"
|
|
12
12
|
#include "WPA/WPAPass.h"
|
|
13
|
-
#include "Util/Conditions.h"
|
|
14
13
|
|
|
15
14
|
namespace SVF
|
|
16
15
|
{
|
|
@@ -255,8 +254,6 @@ public:
|
|
|
255
254
|
// DOTGraphTraits
|
|
256
255
|
static const llvm::cl::opt<bool> ShowHiddenNode;
|
|
257
256
|
|
|
258
|
-
// Conditions
|
|
259
|
-
static const llvm::cl::opt<CondManager::CondMgrKind> ConditionType;
|
|
260
257
|
};
|
|
261
258
|
} // namespace SVF
|
|
262
259
|
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
//===- Z3Expr.h -- Z3 conditions----------------------------//
|
|
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
|
+
* Z3Expr.h
|
|
24
|
+
*
|
|
25
|
+
* Created on: April 29, 2022
|
|
26
|
+
* Author: Xiao
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
#ifndef Z3_EXAMPLE_Z3EXPR_H
|
|
30
|
+
#define Z3_EXAMPLE_Z3EXPR_H
|
|
31
|
+
|
|
32
|
+
#include "z3++.h"
|
|
33
|
+
#include "Util/SVFBasicTypes.h"
|
|
34
|
+
|
|
35
|
+
namespace SVF {
|
|
36
|
+
|
|
37
|
+
class Z3Expr {
|
|
38
|
+
public:
|
|
39
|
+
static z3::context *ctx;
|
|
40
|
+
|
|
41
|
+
private:
|
|
42
|
+
z3::expr e;
|
|
43
|
+
|
|
44
|
+
Z3Expr(float f); // placeholder don't support floating point expression
|
|
45
|
+
Z3Expr(double f); // placeholder don't support floating point expression
|
|
46
|
+
|
|
47
|
+
public:
|
|
48
|
+
|
|
49
|
+
Z3Expr() : e(nullExpr()) {
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
Z3Expr(const z3::expr &_e) : e(_e) {
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
Z3Expr(int i) : e(getContext().int_val(i)) {
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
Z3Expr(const Z3Expr &z3Expr) : e(z3Expr.getExpr()) {
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
virtual ~Z3Expr() = default;
|
|
62
|
+
|
|
63
|
+
inline Z3Expr &operator=(const Z3Expr &rhs) {
|
|
64
|
+
if (this->id() != rhs.id()) {
|
|
65
|
+
e = rhs.getExpr();
|
|
66
|
+
}
|
|
67
|
+
return *this;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const z3::expr &getExpr() const {
|
|
71
|
+
return e;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/// Get z3 context, singleton design here to make sure we only have one context
|
|
75
|
+
static z3::context &getContext() {
|
|
76
|
+
if (ctx == nullptr) {
|
|
77
|
+
ctx = new z3::context();
|
|
78
|
+
}
|
|
79
|
+
return *ctx;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/// release z3 context
|
|
83
|
+
static void releaseContext() {
|
|
84
|
+
delete ctx;
|
|
85
|
+
ctx = nullptr;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/// null expression
|
|
89
|
+
static z3::expr nullExpr() {
|
|
90
|
+
return getContext().int_const("null");
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/// get id
|
|
94
|
+
inline u32_t id() const {
|
|
95
|
+
return e.id();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
inline const std::string to_string() const {
|
|
99
|
+
return e.to_string();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
inline bool is_numeral() const {
|
|
103
|
+
return e.is_numeral();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
inline bool is_bool() const {
|
|
107
|
+
return e.is_bool();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
inline Z3Expr simplify() const {
|
|
111
|
+
return e.simplify();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
inline int64_t get_numeral_int64() const {
|
|
115
|
+
return e.get_numeral_int64();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
inline int get_numeral_int() const {
|
|
119
|
+
return e.get_numeral_int();
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
//{% reload operator
|
|
123
|
+
friend Z3Expr operator==(const Z3Expr &lhs, const Z3Expr &rhs) {
|
|
124
|
+
return lhs.getExpr() == rhs.getExpr();
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
friend Z3Expr operator!=(const Z3Expr &lhs, const Z3Expr &rhs) {
|
|
128
|
+
return lhs.getExpr() != rhs.getExpr();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
friend Z3Expr operator>(const Z3Expr &lhs, const Z3Expr &rhs) {
|
|
132
|
+
return lhs.getExpr() > rhs.getExpr();
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
friend Z3Expr operator<(const Z3Expr &lhs, const Z3Expr &rhs) {
|
|
136
|
+
return lhs.getExpr() < rhs.getExpr();
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
friend Z3Expr operator<=(const Z3Expr &lhs, const Z3Expr &rhs) {
|
|
140
|
+
return lhs.getExpr() <= rhs.getExpr();
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
friend Z3Expr operator>=(const Z3Expr &lhs, const Z3Expr &rhs) {
|
|
144
|
+
return lhs.getExpr() >= rhs.getExpr();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
friend Z3Expr operator+(const Z3Expr &lhs, const Z3Expr &rhs) {
|
|
148
|
+
return lhs.getExpr() + rhs.getExpr();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
friend Z3Expr operator-(const Z3Expr &lhs, const Z3Expr &rhs) {
|
|
152
|
+
return lhs.getExpr() - rhs.getExpr();
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
friend Z3Expr operator*(const Z3Expr &lhs, const Z3Expr &rhs) {
|
|
156
|
+
return lhs.getExpr() * rhs.getExpr();
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
friend Z3Expr operator/(const Z3Expr &lhs, const Z3Expr &rhs) {
|
|
160
|
+
return lhs.getExpr() / rhs.getExpr();
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
friend Z3Expr operator%(const Z3Expr &lhs, const Z3Expr &rhs) {
|
|
164
|
+
return lhs.getExpr() % rhs.getExpr();
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
friend Z3Expr operator^(const Z3Expr &lhs, const Z3Expr &rhs) {
|
|
168
|
+
return lhs.getExpr() ^ rhs.getExpr();
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
friend Z3Expr operator&(const Z3Expr &lhs, const Z3Expr &rhs) {
|
|
172
|
+
return lhs.getExpr() & rhs.getExpr();
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
friend Z3Expr operator|(const Z3Expr &lhs, const Z3Expr &rhs) {
|
|
176
|
+
return lhs.getExpr() | rhs.getExpr();
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
friend Z3Expr ashr(const Z3Expr &lhs, const Z3Expr &rhs) {
|
|
180
|
+
return ashr(lhs.getExpr(), rhs.getExpr());
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
friend Z3Expr shl(const Z3Expr &lhs, const Z3Expr &rhs) {
|
|
184
|
+
return shl(lhs.getExpr(), rhs.getExpr());
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
friend Z3Expr int2bv(u32_t n, const Z3Expr &e) {
|
|
188
|
+
return int2bv(n, e.getExpr());
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
friend Z3Expr bv2int(const Z3Expr &e, bool isSigned) {
|
|
192
|
+
return z3::bv2int(e.getExpr(), isSigned);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
friend Z3Expr operator&&(const Z3Expr &lhs, const Z3Expr &rhs) {
|
|
196
|
+
return lhs.getExpr() && rhs.getExpr();
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
friend Z3Expr operator||(const Z3Expr &lhs, const Z3Expr &rhs) {
|
|
200
|
+
return lhs.getExpr() || rhs.getExpr();
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
friend Z3Expr operator!(const Z3Expr &lhs) {
|
|
204
|
+
return !lhs.getExpr();
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
friend Z3Expr ite(const Z3Expr& cond, const Z3Expr& lhs, const Z3Expr& rhs) {
|
|
208
|
+
return ite(cond.getExpr(), lhs.getExpr(), rhs.getExpr());
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
friend std::ostream &operator<<(std::ostream &out, const Z3Expr &expr) {
|
|
212
|
+
out << expr.getExpr();
|
|
213
|
+
return out;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
friend bool eq(const Z3Expr &lhs, const Z3Expr &rhs) {
|
|
217
|
+
return eq(lhs.getExpr(), rhs.getExpr());
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
z3::sort get_sort() const {
|
|
221
|
+
return getExpr().get_sort();
|
|
222
|
+
}
|
|
223
|
+
//%}
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/// Specialise hash for AbsCxtDPItem.
|
|
228
|
+
template<>
|
|
229
|
+
struct std::hash<SVF::Z3Expr> {
|
|
230
|
+
size_t operator()(const SVF::Z3Expr &z3Expr) const {
|
|
231
|
+
return z3Expr.id();
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
#endif //Z3_EXAMPLE_Z3EXPR_H
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
//===- TypeBasedHeapCloning.h -- Type filter/type-based heap cloning base ------------//
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
* TypeBasedHeapCloning.h
|
|
5
|
+
*
|
|
6
|
+
* Contains data structures and functions to extend a pointer analysis
|
|
7
|
+
* with type-based heap cloning/type filtering.
|
|
8
|
+
*
|
|
9
|
+
* Created on: Feb 08, 2020
|
|
10
|
+
* Author: Mohamad Barbar
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
#include "SVF-FE/DCHG.h"
|
|
14
|
+
#include "MemoryModel/SVFIR.h"
|
|
15
|
+
#include "MemoryModel/PointerAnalysisImpl.h"
|
|
16
|
+
#include "Util/BasicTypes.h"
|
|
17
|
+
|
|
18
|
+
namespace SVF
|
|
19
|
+
{
|
|
20
|
+
|
|
21
|
+
class TypeBasedHeapCloning
|
|
22
|
+
{
|
|
23
|
+
public:
|
|
24
|
+
/// Returns raw ctir metadata of a Value. Returns null if it doesn't exist.
|
|
25
|
+
static const MDNode *getRawCTirMetadata(const Value *);
|
|
26
|
+
|
|
27
|
+
virtual ~TypeBasedHeapCloning() { };
|
|
28
|
+
|
|
29
|
+
protected:
|
|
30
|
+
/// The undefined type (•); void.
|
|
31
|
+
static const DIType *undefType;
|
|
32
|
+
|
|
33
|
+
/// deref function for TBHC alias tests.
|
|
34
|
+
static const std::string derefFnName;
|
|
35
|
+
/// deref function (mangled) for TBHC alias tests.
|
|
36
|
+
static const std::string mangledDerefFnName;
|
|
37
|
+
|
|
38
|
+
/// Constructor. pta is the pointer analysis using this object (i.e. that which is extending).
|
|
39
|
+
TypeBasedHeapCloning(BVDataPTAImpl *pta);
|
|
40
|
+
|
|
41
|
+
/// Required by user. Handles back-propagation of newly created clone after all
|
|
42
|
+
/// metadata has been set. Used by cloneObject.
|
|
43
|
+
virtual void backPropagate(NodeID clone) = 0;
|
|
44
|
+
|
|
45
|
+
/// Class hierarchy graph built from debug information. Required, CHG from
|
|
46
|
+
/// IR is insufficient.
|
|
47
|
+
DCHGraph *dchg = nullptr;
|
|
48
|
+
|
|
49
|
+
/// DCHG *must* be set by extending class once the DCHG is available.
|
|
50
|
+
void setDCHG(DCHGraph *dchg);
|
|
51
|
+
/// SVFIR *must* be set by extending class once the SVFIR is available.
|
|
52
|
+
void setPAG(SVFIR *pag);
|
|
53
|
+
|
|
54
|
+
/// Check if an object is a black hole obj or a constant object. Required since
|
|
55
|
+
/// other implementations obviously do not account for clones.
|
|
56
|
+
bool isBlkObjOrConstantObj(NodeID o) const;
|
|
57
|
+
|
|
58
|
+
/// Wrapper around DCHGraph::isBase. Purpose is to keep our conditions clean
|
|
59
|
+
/// by only passing two parameters like the rules.
|
|
60
|
+
bool isBase(const DIType *a, const DIType *b) const;
|
|
61
|
+
|
|
62
|
+
/// Returns true if o is a clone.
|
|
63
|
+
bool isClone(NodeID o) const;
|
|
64
|
+
|
|
65
|
+
/// Sets the type (in objToType) of o.
|
|
66
|
+
void setType(NodeID o, const DIType *t);
|
|
67
|
+
/// Returns the type (from objToType) of o. Asserts existence.
|
|
68
|
+
const DIType *getType(NodeID o) const;
|
|
69
|
+
|
|
70
|
+
/// Sets the allocation site (in objToAllocation) of o.
|
|
71
|
+
void setAllocationSite(NodeID o, NodeID site);
|
|
72
|
+
/// Returns the allocation site (from objToAllocation) of o. Asserts existence.
|
|
73
|
+
NodeID getAllocationSite(NodeID o) const;
|
|
74
|
+
|
|
75
|
+
/// Returns objects that have clones (any key in objToClones).
|
|
76
|
+
const NodeBS getObjsWithClones(void);
|
|
77
|
+
/// Add a clone c to object o.
|
|
78
|
+
void addClone(NodeID o, NodeID c);
|
|
79
|
+
/// Returns all the clones of o.
|
|
80
|
+
const NodeBS &getClones(NodeID o);
|
|
81
|
+
|
|
82
|
+
// Set o as the original object of clone c.
|
|
83
|
+
void setOriginalObj(NodeID c, NodeID o);
|
|
84
|
+
/// Returns the original object c is cloned from. If c is not a clone, returns itself.
|
|
85
|
+
NodeID getOriginalObj(NodeID c) const;
|
|
86
|
+
|
|
87
|
+
/// Returns the filter set of a location. Not const; could create empty PointsTo.
|
|
88
|
+
PointsTo &getFilterSet(NodeID loc);
|
|
89
|
+
|
|
90
|
+
/// Associates gep with base (through objToGeps and memObjToGeps).
|
|
91
|
+
void addGepToObj(NodeID gep, NodeID base, unsigned offset);
|
|
92
|
+
/// Returns all gep objects at a particular offset for memory object.
|
|
93
|
+
/// Not const; could create empty set.
|
|
94
|
+
const NodeBS &getGepObjsFromMemObj(const MemObj *memObj, unsigned offset);
|
|
95
|
+
/// Returns all gep objects under an object.
|
|
96
|
+
/// Not const; could create empty set.
|
|
97
|
+
const NodeBS &getGepObjs(NodeID base);
|
|
98
|
+
|
|
99
|
+
/// Returns the GEP object node(s) of base for ls. This may include clones.
|
|
100
|
+
/// If there are no GEP objects, then getGepObjVar is called on the SVFIR
|
|
101
|
+
/// (through base's getGepObjVar) which will create one.
|
|
102
|
+
const NodeBS getGepObjClones(NodeID base, unsigned offset);
|
|
103
|
+
|
|
104
|
+
/// Initialise the pointees of p at loc (which is type tildet *). reuse indicates
|
|
105
|
+
/// whether reuse is a possibility for this initialisation. Returns whether p changed.
|
|
106
|
+
bool init(NodeID loc, NodeID p, const DIType *tildet, bool reuse, bool gep=false);
|
|
107
|
+
|
|
108
|
+
/// Returns a clone of o with type type. reuse indicates whether we are cloning
|
|
109
|
+
/// as a result of reuse.
|
|
110
|
+
NodeID cloneObject(NodeID o, const DIType *type, bool reuse);
|
|
111
|
+
|
|
112
|
+
/// Add clone dummy object node to SVFIR.
|
|
113
|
+
inline NodeID addCloneDummyObjNode(const MemObj *mem);
|
|
114
|
+
/// Add clone GEP object node to SVFIR.
|
|
115
|
+
inline NodeID addCloneGepObjNode(const MemObj *mem, const LocationSet &l);
|
|
116
|
+
/// Add clone FI object node to SVFIR.
|
|
117
|
+
inline NodeID addCloneFIObjNode(const MemObj *mem);
|
|
118
|
+
|
|
119
|
+
/// Returns the ctir type attached to the value, nullptr if non-existant.
|
|
120
|
+
/// Not static because it needs the DCHG to return the canonical type.
|
|
121
|
+
/// Not static because we need dchg's getCanonicalType.
|
|
122
|
+
const DIType *getTypeFromCTirMetadata(const Value *);
|
|
123
|
+
|
|
124
|
+
/// Runs tests on MAYALIAS, NOALIAS, etc. built from TBHC_MAYALIAS,
|
|
125
|
+
/// TBHC_NOALIAS, etc. macros.
|
|
126
|
+
/// TBHC_XALIAS macros produce:
|
|
127
|
+
/// call XALIAS(...)
|
|
128
|
+
/// %1 = load ...
|
|
129
|
+
/// ...
|
|
130
|
+
/// %n = load %p
|
|
131
|
+
/// store ... %n-1, ...* %n !ctir !t1
|
|
132
|
+
/// call deref()
|
|
133
|
+
/// %n+1 = load ...
|
|
134
|
+
/// ...
|
|
135
|
+
/// %n+n = load %q
|
|
136
|
+
/// store ... %n+n-1, ...* %n+n !ctir !t2
|
|
137
|
+
/// call deref()
|
|
138
|
+
/// We want to test the points-to sets of %n and
|
|
139
|
+
/// %n+n after filtering with !t1 and !t2 respectively.
|
|
140
|
+
void validateTBHCTests(SVFModule *svfMod);
|
|
141
|
+
|
|
142
|
+
/// Dump some statistics we tracked.
|
|
143
|
+
void dumpStats(void);
|
|
144
|
+
|
|
145
|
+
private:
|
|
146
|
+
/// PTA extending this class.
|
|
147
|
+
BVDataPTAImpl *pta;
|
|
148
|
+
/// SVFIR the PTA uses. Just a shortcut for getPAG().
|
|
149
|
+
SVFIR *ppag = nullptr;
|
|
150
|
+
|
|
151
|
+
/// Object -> its type.
|
|
152
|
+
Map<NodeID, const DIType *> objToType;
|
|
153
|
+
/// Object -> allocation site.
|
|
154
|
+
/// The value NodeID depends on the pointer analysis (could be
|
|
155
|
+
/// an SVFG node or SVFIR node for example).
|
|
156
|
+
Map<NodeID, NodeID> objToAllocation;
|
|
157
|
+
/// (Original) object -> set of its clones.
|
|
158
|
+
Map<NodeID, NodeBS> objToClones;
|
|
159
|
+
/// (Clone) object -> original object (opposite of objToclones).
|
|
160
|
+
Map<NodeID, NodeID> cloneToOriginalObj;
|
|
161
|
+
/// Maps nodes (a location like a SVFIR node or SVFG node) to their filter set.
|
|
162
|
+
Map<NodeID, PointsTo> locToFilterSet;
|
|
163
|
+
/// Maps objects to the GEP nodes beneath them.
|
|
164
|
+
Map<NodeID, NodeBS> objToGeps;
|
|
165
|
+
/// Maps memory objects to their GEP objects. (memobj -> (fieldidx -> geps))
|
|
166
|
+
Map<const MemObj *, Map<unsigned, NodeBS>> memObjToGeps;
|
|
167
|
+
|
|
168
|
+
/// Test whether object is a GEP object. For convenience.
|
|
169
|
+
bool isGep(const PAGNode *n) const;
|
|
170
|
+
|
|
171
|
+
// Bunch of stats to keep track of.
|
|
172
|
+
unsigned numInit = 0;
|
|
173
|
+
unsigned numTBWU = 0;
|
|
174
|
+
unsigned numTBSSU = 0;
|
|
175
|
+
unsigned numTBSU = 0;
|
|
176
|
+
unsigned numReuse = 0;
|
|
177
|
+
unsigned numAgg = 0;
|
|
178
|
+
|
|
179
|
+
// Previous stats but only upon stack/global objects.
|
|
180
|
+
unsigned numSGInit = 0;
|
|
181
|
+
unsigned numSGTBWU = 0;
|
|
182
|
+
unsigned numSGTBSSU = 0;
|
|
183
|
+
unsigned numSGTBSU = 0;
|
|
184
|
+
unsigned numSGReuse = 0;
|
|
185
|
+
unsigned numSGAgg = 0;
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
} // End namespace SVF
|