svf-tools 1.0.677 → 1.0.679
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-doxygen/wiki/cpu2017-wllvm.cfg +999 -0
- package/package.json +1 -1
- package/svf/include/Graphs/CHG.h +27 -14
- package/svf/include/Graphs/GenericGraph.h +10 -4
- package/svf/include/Graphs/ICFG.h +6 -1
- package/svf/include/Graphs/ICFGEdge.h +41 -31
- package/svf/include/Graphs/ICFGNode.h +14 -2
- package/svf/include/Graphs/IRGraph.h +22 -14
- package/svf/include/MemoryModel/LocationSet.h +10 -8
- package/svf/include/MemoryModel/SVFLoop.h +2 -0
- package/svf/include/SVFIR/SVFIR.h +42 -23
- package/svf/include/SVFIR/SVFIRRW.h +624 -0
- package/svf/include/SVFIR/SVFModule.h +1 -0
- package/svf/include/SVFIR/SVFModuleRW.h +3 -6
- package/svf/include/SVFIR/SVFStatements.h +247 -185
- package/svf/include/SVFIR/SVFType.h +4 -0
- package/svf/include/SVFIR/SVFValue.h +28 -9
- package/svf/include/SVFIR/SVFVariables.h +75 -78
- package/svf/include/SVFIR/SymbolTableInfo.h +19 -11
- package/svf/include/Util/CommandLine.h +1 -1
- package/svf/include/Util/Options.h +1 -0
- package/svf/include/Util/SparseBitVector.h +6 -0
- package/svf/include/Util/ThreadAPI.h +15 -15
- package/svf/lib/AbstractExecution/SVFIR2ItvExeState.cpp +61 -17
- package/svf/lib/Graphs/ICFG.cpp +2 -3
- package/svf/lib/SVFIR/SVFIRRW.cpp +1118 -0
- package/svf/lib/SVFIR/SymbolTableInfo.cpp +1 -1
- package/svf/lib/Util/Options.cpp +6 -0
- package/svf-llvm/include/SVF-LLVM/DCHG.h +36 -35
- package/svf-llvm/lib/LLVMModule.cpp +0 -5
- package/svf-llvm/lib/SVFIRBuilder.cpp +10 -2
- package/svf-llvm/tools/WPA/wpa.cpp +4 -0
|
@@ -47,6 +47,7 @@ class StInfo;
|
|
|
47
47
|
class SymbolTableInfo
|
|
48
48
|
{
|
|
49
49
|
friend class SymbolTableBuilder;
|
|
50
|
+
friend class SVFIRWriter;
|
|
50
51
|
|
|
51
52
|
public:
|
|
52
53
|
|
|
@@ -69,7 +70,7 @@ public:
|
|
|
69
70
|
/// local (%) and global (@) identifiers are pointer types which have a value node id.
|
|
70
71
|
typedef OrderedMap<const SVFValue*, SymID> ValueToIDMapTy;
|
|
71
72
|
/// sym id to memory object map
|
|
72
|
-
typedef OrderedMap<SymID,MemObj*> IDToMemMapTy;
|
|
73
|
+
typedef OrderedMap<SymID, MemObj*> IDToMemMapTy;
|
|
73
74
|
/// function to sym id map
|
|
74
75
|
typedef OrderedMap<const SVFFunction*, SymID> FunToIDMapTy;
|
|
75
76
|
/// struct type to struct info map
|
|
@@ -77,11 +78,11 @@ public:
|
|
|
77
78
|
//@}
|
|
78
79
|
|
|
79
80
|
private:
|
|
80
|
-
ValueToIDMapTy valSymMap;
|
|
81
|
-
ValueToIDMapTy objSymMap;
|
|
82
|
-
FunToIDMapTy returnSymMap;
|
|
83
|
-
FunToIDMapTy varargSymMap;
|
|
84
|
-
IDToMemMapTy
|
|
81
|
+
ValueToIDMapTy valSymMap; ///< map a value to its sym id
|
|
82
|
+
ValueToIDMapTy objSymMap; ///< map a obj reference to its sym id
|
|
83
|
+
FunToIDMapTy returnSymMap; ///< return map
|
|
84
|
+
FunToIDMapTy varargSymMap; ///< vararg map
|
|
85
|
+
IDToMemMapTy objMap; ///< map a memory sym id to its obj
|
|
85
86
|
|
|
86
87
|
// Singleton pattern here to enable instance of SymbolTableInfo can only be created once.
|
|
87
88
|
static SymbolTableInfo* symInfo;
|
|
@@ -100,8 +101,9 @@ private:
|
|
|
100
101
|
|
|
101
102
|
protected:
|
|
102
103
|
/// Constructor
|
|
103
|
-
SymbolTableInfo(void)
|
|
104
|
-
mod(nullptr), modelConstants(false), totalSymNum(0),
|
|
104
|
+
SymbolTableInfo(void)
|
|
105
|
+
: mod(nullptr), modelConstants(false), totalSymNum(0),
|
|
106
|
+
maxStruct(nullptr), maxStSize(0)
|
|
105
107
|
{
|
|
106
108
|
}
|
|
107
109
|
|
|
@@ -269,6 +271,11 @@ public:
|
|
|
269
271
|
return objMap;
|
|
270
272
|
}
|
|
271
273
|
|
|
274
|
+
inline const IDToMemMapTy& idToObjMap() const
|
|
275
|
+
{
|
|
276
|
+
return objMap;
|
|
277
|
+
}
|
|
278
|
+
|
|
272
279
|
inline FunToIDMapTy& retSyms()
|
|
273
280
|
{
|
|
274
281
|
return returnSymMap;
|
|
@@ -347,6 +354,7 @@ protected:
|
|
|
347
354
|
*/
|
|
348
355
|
class MemObj
|
|
349
356
|
{
|
|
357
|
+
friend class SVFIRWriter;
|
|
350
358
|
|
|
351
359
|
private:
|
|
352
360
|
/// Type information of this object
|
|
@@ -424,7 +432,7 @@ public:
|
|
|
424
432
|
//@}
|
|
425
433
|
|
|
426
434
|
/// Operator overloading
|
|
427
|
-
inline bool operator==(const MemObj
|
|
435
|
+
inline bool operator==(const MemObj& mem) const
|
|
428
436
|
{
|
|
429
437
|
return getValue() == mem.getValue();
|
|
430
438
|
}
|
|
@@ -433,14 +441,14 @@ public:
|
|
|
433
441
|
void destroy();
|
|
434
442
|
};
|
|
435
443
|
|
|
436
|
-
|
|
437
|
-
|
|
438
444
|
/*!
|
|
439
445
|
* Type Info of an abstract memory object
|
|
440
446
|
*/
|
|
441
447
|
class ObjTypeInfo
|
|
442
448
|
{
|
|
449
|
+
friend class SVFIRWriter;
|
|
443
450
|
friend class SymbolTableBuilder;
|
|
451
|
+
|
|
444
452
|
public:
|
|
445
453
|
typedef enum
|
|
446
454
|
{
|
|
@@ -325,7 +325,7 @@ template <typename T>
|
|
|
325
325
|
class Option : public OptionBase
|
|
326
326
|
{
|
|
327
327
|
public:
|
|
328
|
-
Option(std::string name, std::string description, T init)
|
|
328
|
+
Option(const std::string& name, const std::string& description, T init)
|
|
329
329
|
: OptionBase(name, description), isExplicitlySet(false), value(init)
|
|
330
330
|
{
|
|
331
331
|
assert(!name.empty() && "Option: empty option name given");
|
|
@@ -134,6 +134,7 @@ public:
|
|
|
134
134
|
static const Option<bool> PAGDotGraph;
|
|
135
135
|
static const Option<bool> ShowSVFIRValue;
|
|
136
136
|
static const Option<bool> DumpICFG;
|
|
137
|
+
static const Option<std::string> DumpJson;
|
|
137
138
|
static const Option<bool> CallGraphDotGraph;
|
|
138
139
|
static const Option<bool> PAGPrint;
|
|
139
140
|
static const Option<u32_t> IndirectCallLimit;
|
|
@@ -216,12 +216,16 @@ inline unsigned countPopulation(T Value)
|
|
|
216
216
|
/// kept up to date. They are also significantly more memory intensive.
|
|
217
217
|
template <unsigned ElementSize = 128> struct SparseBitVectorElement
|
|
218
218
|
{
|
|
219
|
+
friend class SVFIRWriter;
|
|
220
|
+
|
|
219
221
|
public:
|
|
220
222
|
using BitWord = unsigned long;
|
|
221
223
|
using size_type = unsigned;
|
|
222
224
|
enum
|
|
223
225
|
{
|
|
224
226
|
BITWORD_SIZE = sizeof(BitWord) * CHAR_BIT,
|
|
227
|
+
// N.B. (+ BITWORD_SIZE - 1) is to round up, to ensure we can have
|
|
228
|
+
// sufficient bits to represent *at least* ElementSize bits.
|
|
225
229
|
BITWORDS_PER_ELEMENT = (ElementSize + BITWORD_SIZE - 1) / BITWORD_SIZE,
|
|
226
230
|
BITS_PER_ELEMENT = ElementSize
|
|
227
231
|
};
|
|
@@ -453,6 +457,8 @@ public:
|
|
|
453
457
|
template <unsigned ElementSize = 128>
|
|
454
458
|
class SparseBitVector
|
|
455
459
|
{
|
|
460
|
+
friend class SVFIRWriter;
|
|
461
|
+
|
|
456
462
|
using ElementList = std::list<SparseBitVectorElement<ElementSize>>;
|
|
457
463
|
using ElementListIter = typename ElementList::iterator;
|
|
458
464
|
using ElementListConstIter = typename ElementList::const_iterator;
|
|
@@ -46,24 +46,24 @@ class ThreadAPI
|
|
|
46
46
|
public:
|
|
47
47
|
enum TD_TYPE
|
|
48
48
|
{
|
|
49
|
-
TD_DUMMY = 0,
|
|
50
|
-
TD_FORK,
|
|
51
|
-
TD_JOIN,
|
|
52
|
-
TD_DETACH,
|
|
53
|
-
TD_ACQUIRE,
|
|
54
|
-
TD_TRY_ACQUIRE,
|
|
55
|
-
TD_RELEASE,
|
|
56
|
-
TD_EXIT,
|
|
57
|
-
TD_CANCEL,
|
|
58
|
-
TD_COND_WAIT,
|
|
59
|
-
TD_COND_SIGNAL,
|
|
60
|
-
TD_COND_BROADCAST,
|
|
61
|
-
TD_MUTEX_INI,
|
|
49
|
+
TD_DUMMY = 0, /// dummy type
|
|
50
|
+
TD_FORK, /// create a new thread
|
|
51
|
+
TD_JOIN, /// wait for a thread to join
|
|
52
|
+
TD_DETACH, /// detach a thread directly instead wait for it to join
|
|
53
|
+
TD_ACQUIRE, /// acquire a lock
|
|
54
|
+
TD_TRY_ACQUIRE, /// try to acquire a lock
|
|
55
|
+
TD_RELEASE, /// release a lock
|
|
56
|
+
TD_EXIT, /// exit/kill a thread
|
|
57
|
+
TD_CANCEL, /// cancel a thread by another
|
|
58
|
+
TD_COND_WAIT, /// wait a condition
|
|
59
|
+
TD_COND_SIGNAL, /// signal a condition
|
|
60
|
+
TD_COND_BROADCAST, /// broadcast a condition
|
|
61
|
+
TD_MUTEX_INI, /// initial a mutex variable
|
|
62
62
|
TD_MUTEX_DESTROY, /// initial a mutex variable
|
|
63
|
-
TD_CONDVAR_INI,
|
|
63
|
+
TD_CONDVAR_INI, /// initial a mutex variable
|
|
64
64
|
TD_CONDVAR_DESTROY, /// initial a mutex variable
|
|
65
65
|
TD_BAR_INIT, /// Barrier init
|
|
66
|
-
TD_BAR_WAIT,
|
|
66
|
+
TD_BAR_WAIT, /// Barrier wait
|
|
67
67
|
HARE_PAR_FOR
|
|
68
68
|
};
|
|
69
69
|
|
|
@@ -101,14 +101,17 @@ SVFIR2ItvExeState::VAddrs SVFIR2ItvExeState::getGepObjAddress(u32_t pointer, u32
|
|
|
101
101
|
return ret;
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
|
|
105
104
|
std::pair<s32_t, s32_t> SVFIR2ItvExeState::getGepOffset(const GepStmt *gep)
|
|
106
105
|
{
|
|
106
|
+
/// for instant constant index, e.g. gep arr, 1
|
|
107
107
|
if (gep->getOffsetVarAndGepTypePairVec().empty())
|
|
108
108
|
return std::make_pair(gep->getConstantFieldIdx(), gep->getConstantFieldIdx());
|
|
109
109
|
|
|
110
110
|
s32_t totalOffsetLb = 0;
|
|
111
111
|
s32_t totalOffsetUb = 0;
|
|
112
|
+
/// default value of MaxFieldLimit is 512
|
|
113
|
+
u32_t maxFieldLimit = Options::MaxFieldLimit() - 1;
|
|
114
|
+
/// for variable index and nested indexes, e.g. 1) gep arr, idx 2) gep arr idx0, idx1
|
|
112
115
|
for (int i = gep->getOffsetVarAndGepTypePairVec().size() - 1; i >= 0; i--)
|
|
113
116
|
{
|
|
114
117
|
const SVFValue *value = gep->getOffsetVarAndGepTypePairVec()[i].first->getValue();
|
|
@@ -116,50 +119,88 @@ std::pair<s32_t, s32_t> SVFIR2ItvExeState::getGepOffset(const GepStmt *gep)
|
|
|
116
119
|
const SVFConstantInt *op = SVFUtil::dyn_cast<SVFConstantInt>(value);
|
|
117
120
|
s32_t offsetLb = 0;
|
|
118
121
|
s32_t offsetUb = 0;
|
|
119
|
-
/// constant
|
|
122
|
+
/// offset is constant but stored in variable
|
|
120
123
|
if (op)
|
|
121
124
|
{
|
|
122
125
|
offsetLb = offsetUb = op->getSExtValue();
|
|
123
126
|
}
|
|
124
|
-
/// variable
|
|
127
|
+
/// offset is variable, the concrete value isn't sure util runtime, and maybe not a concrete value.
|
|
128
|
+
/// e.g.
|
|
125
129
|
else
|
|
126
130
|
{
|
|
127
131
|
u32_t idx = _svfir->getValueNode(value);
|
|
128
132
|
if (!inVarToIValTable(idx)) return std::make_pair(-1, -1);
|
|
129
133
|
IntervalValue &idxVal = _es[idx];
|
|
130
|
-
if(idxVal.isBottom() || idxVal.isTop()) return std::make_pair(0, (s32_t)Options::MaxFieldLimit());
|
|
134
|
+
if (idxVal.isBottom() || idxVal.isTop()) return std::make_pair(0, (s32_t)Options::MaxFieldLimit());
|
|
135
|
+
// if idxVal is a concrete value
|
|
131
136
|
if (idxVal.is_numeral())
|
|
132
137
|
{
|
|
133
138
|
offsetLb = offsetUb = idxVal.lb().getNumeral();
|
|
134
139
|
}
|
|
135
140
|
else
|
|
136
141
|
{
|
|
142
|
+
// if inxVal is an interval. we should make sure that idxVal.lb>0 && idxVal.ub<MaxFieldLimit
|
|
137
143
|
offsetLb = idxVal.lb().getNumeral() < 0 ? 0 : idxVal.lb().getNumeral();
|
|
144
|
+
offsetLb = idxVal.lb().getNumeral() > maxFieldLimit ? maxFieldLimit : offsetLb;
|
|
138
145
|
offsetUb = idxVal.ub().getNumeral() < 0 ? 0 : idxVal.ub().getNumeral();
|
|
146
|
+
offsetUb = idxVal.ub().getNumeral() > maxFieldLimit ? maxFieldLimit : offsetUb;
|
|
139
147
|
}
|
|
140
148
|
}
|
|
141
149
|
if (type == nullptr)
|
|
142
150
|
{
|
|
143
|
-
totalOffsetLb
|
|
144
|
-
|
|
151
|
+
if ((long long) (totalOffsetLb + offsetLb) > maxFieldLimit)
|
|
152
|
+
{
|
|
153
|
+
totalOffsetLb = maxFieldLimit;
|
|
154
|
+
}
|
|
155
|
+
else
|
|
156
|
+
{
|
|
157
|
+
totalOffsetLb += offsetLb;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if ((long long) (totalOffsetUb + offsetUb) > maxFieldLimit)
|
|
161
|
+
{
|
|
162
|
+
totalOffsetUb = maxFieldLimit;
|
|
163
|
+
}
|
|
164
|
+
else
|
|
165
|
+
{
|
|
166
|
+
totalOffsetUb += offsetUb;
|
|
167
|
+
}
|
|
145
168
|
continue;
|
|
146
169
|
}
|
|
147
|
-
|
|
170
|
+
|
|
148
171
|
if (const SVFPointerType *pty = SVFUtil::dyn_cast<SVFPointerType>(type))
|
|
149
172
|
{
|
|
150
|
-
|
|
151
|
-
|
|
173
|
+
offsetLb = offsetLb * gep->getLocationSet().getElementNum(pty->getPtrElementType());
|
|
174
|
+
offsetUb = offsetUb * gep->getLocationSet().getElementNum(pty->getPtrElementType());
|
|
175
|
+
|
|
152
176
|
}
|
|
153
177
|
else
|
|
154
178
|
{
|
|
155
179
|
const std::vector<u32_t> &so = SymbolTableInfo::SymbolInfo()->getTypeInfo(type)->getFlattenedElemIdxVec();
|
|
156
|
-
if(so.empty() || (u32_t)offsetUb >= so.size() || (u32_t)offsetLb >= so.size())
|
|
157
|
-
|
|
158
|
-
|
|
180
|
+
if (so.empty() || (u32_t) offsetUb >= so.size() || (u32_t) offsetLb >= so.size())
|
|
181
|
+
return std::make_pair(-1, -1);
|
|
182
|
+
offsetLb = SymbolTableInfo::SymbolInfo()->getFlattenedElemIdx(type, offsetLb);
|
|
183
|
+
offsetUb = SymbolTableInfo::SymbolInfo()->getFlattenedElemIdx(type, offsetUb);
|
|
184
|
+
}
|
|
185
|
+
if ((long long) (totalOffsetLb + offsetLb) > maxFieldLimit)
|
|
186
|
+
{
|
|
187
|
+
totalOffsetLb = maxFieldLimit;
|
|
188
|
+
}
|
|
189
|
+
else
|
|
190
|
+
{
|
|
191
|
+
totalOffsetLb += offsetLb;
|
|
192
|
+
}
|
|
193
|
+
if ((long long) (totalOffsetUb + offsetUb) > maxFieldLimit)
|
|
194
|
+
{
|
|
195
|
+
totalOffsetUb = maxFieldLimit;
|
|
196
|
+
}
|
|
197
|
+
else
|
|
198
|
+
{
|
|
199
|
+
totalOffsetUb += offsetUb;
|
|
159
200
|
}
|
|
160
201
|
}
|
|
161
202
|
std::pair<s32_t, s32_t> offSetPair;
|
|
162
|
-
offSetPair.first =
|
|
203
|
+
offSetPair.first = totalOffsetLb;
|
|
163
204
|
offSetPair.second = totalOffsetUb;
|
|
164
205
|
return offSetPair;
|
|
165
206
|
}
|
|
@@ -646,10 +687,12 @@ void SVFIR2ItvExeState::translateGep(const GepStmt *gep)
|
|
|
646
687
|
{
|
|
647
688
|
u32_t rhs = gep->getRHSVarID();
|
|
648
689
|
u32_t lhs = gep->getLHSVarID();
|
|
690
|
+
if (!inVarToAddrsTable(rhs)) return;
|
|
691
|
+
assert(!getVAddrs(rhs).empty());
|
|
649
692
|
VAddrs &rhsVal = getVAddrs(rhs);
|
|
650
693
|
if (rhsVal.empty()) return;
|
|
651
694
|
std::pair<s32_t, s32_t> offsetPair = getGepOffset(gep);
|
|
652
|
-
if(offsetPair.first == -1 && offsetPair.second == -1) return;
|
|
695
|
+
if (offsetPair.first == -1 && offsetPair.second == -1) return;
|
|
653
696
|
if (!isVirtualMemAddress(*rhsVal.begin()))
|
|
654
697
|
{
|
|
655
698
|
return;
|
|
@@ -658,15 +701,16 @@ void SVFIR2ItvExeState::translateGep(const GepStmt *gep)
|
|
|
658
701
|
{
|
|
659
702
|
VAddrs gepAddrs;
|
|
660
703
|
s32_t ub = offsetPair.second;
|
|
661
|
-
if (offsetPair.second
|
|
704
|
+
if (offsetPair.second > (s32_t) Options::MaxFieldLimit() - 1)
|
|
662
705
|
{
|
|
663
|
-
ub =
|
|
706
|
+
ub = Options::MaxFieldLimit() - 1;
|
|
664
707
|
}
|
|
665
708
|
for (s32_t i = offsetPair.first; i <= ub; i++)
|
|
666
709
|
{
|
|
667
710
|
gepAddrs.join_with(getGepObjAddress(rhs, i));
|
|
668
711
|
}
|
|
669
|
-
|
|
712
|
+
if(gepAddrs.empty()) return;
|
|
713
|
+
_es.getVAddrs(lhs) = gepAddrs;
|
|
670
714
|
return;
|
|
671
715
|
}
|
|
672
716
|
}
|
package/svf/lib/Graphs/ICFG.cpp
CHANGED
|
@@ -47,7 +47,8 @@ FunEntryICFGNode::FunEntryICFGNode(NodeID id, const SVFFunction* f) : InterICFGN
|
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
FunExitICFGNode::FunExitICFGNode(NodeID id, const SVFFunction* f)
|
|
50
|
+
FunExitICFGNode::FunExitICFGNode(NodeID id, const SVFFunction* f)
|
|
51
|
+
: InterICFGNode(id, FunExitBlock), formalRet(nullptr)
|
|
51
52
|
{
|
|
52
53
|
fun = f;
|
|
53
54
|
// if function is implemented
|
|
@@ -55,10 +56,8 @@ FunExitICFGNode::FunExitICFGNode(NodeID id, const SVFFunction* f) : InterICFGNod
|
|
|
55
56
|
{
|
|
56
57
|
bb = f->getExitBB();
|
|
57
58
|
}
|
|
58
|
-
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
|
|
62
61
|
const std::string ICFGNode::toString() const
|
|
63
62
|
{
|
|
64
63
|
std::string str;
|