svf-lib 1.0.1056 → 1.0.1059
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/Util/ExtAPI.h +59 -42
- package/SVF-osx/Release-build/lib/CUDD/libCudd.a +0 -0
- package/SVF-osx/Release-build/lib/libSvf.a +0 -0
- package/SVF-osx/include/CFL/CFGNormalizer.h +14 -9
- package/SVF-osx/include/CFL/CFLAlias.h +1 -40
- package/SVF-osx/include/CFL/CFLGrammar.h +246 -31
- package/SVF-osx/include/CFL/CFLGrammar.txt +13 -15
- package/SVF-osx/include/CFL/CFLGraphBuilder.h +27 -29
- package/SVF-osx/include/CFL/GrammarBuilder.h +34 -14
- package/SVF-osx/include/Graphs/CFLGraph.h +12 -0
- package/SVF-osx/include/Graphs/ConsGEdge.h +1 -0
- package/SVF-osx/include/SVF-FE/CallGraphBuilder.h +2 -2
- package/SVF-osx/include/Util/ExtAPI.h +59 -42
- package/package.json +1 -1
|
Binary file
|
|
@@ -40,54 +40,66 @@
|
|
|
40
40
|
#include <map>
|
|
41
41
|
|
|
42
42
|
#define EXTAPI_JSON_PATH "/lib/Util/ExtAPI.json"
|
|
43
|
+
#define JSON_OPT_OVERWRITE "overwrite_app_function"
|
|
44
|
+
#define JSON_OPT_FUNCTIONTYPE "type"
|
|
43
45
|
|
|
44
46
|
namespace SVF
|
|
45
47
|
{
|
|
46
48
|
|
|
47
49
|
/*
|
|
48
50
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
51
|
+
** Specifications in ExtAPI.json
|
|
52
|
+
|
|
53
|
+
*** [1] Overview of the Specification Language
|
|
54
|
+
The specification language of external functions is based on the JSON format. And every function defined by the Specification Language is an object that represents the specification rules. These Specification Language objects for functions contain four parts:
|
|
55
|
+
1. the name of the function,
|
|
56
|
+
2. the switch that controls whether the specification rules defined in the ExtAPI.json overwrite the functions defined in the user code,
|
|
57
|
+
3. the type of the function,
|
|
58
|
+
4. the operations conducted by the function.
|
|
59
|
+
|
|
60
|
+
*** [2] Overwriting the user-defined functions
|
|
61
|
+
The switch *overwrite_app_function* controls whether the specification rules defined in the ExtAPI.json overwrite the functions defined in the user code (e.g., CPP files). When the switch *overwrite_app_function* is set to a value of 1, SVF will use the specification rules in ExtAPI.json to conduct the analysis and ignore the user-defined functions in the input CPP/bc files.
|
|
62
|
+
overwrite_app_function = 0: Analyze the user-defined functions.
|
|
63
|
+
overwrite_app_function = 1: Use specifications in ExtAPI.json to overwrite the user-defined functions.
|
|
64
|
+
|
|
65
|
+
*** [3] Function types
|
|
66
|
+
Function type represents the properties of the function.
|
|
67
|
+
For example,
|
|
68
|
+
"EFT_ALLOC" represents if this external function allocates a new object and assigns it to one of its arguments,
|
|
69
|
+
For the selection of function type and a more detailed explanation, please refer to the definition of enum *extf_t* in ExtAPI.h.
|
|
70
|
+
|
|
71
|
+
*** [4] Function operations
|
|
72
|
+
Function operations indicate the relationships between input and output,
|
|
73
|
+
mainly between function parameters or between parameters and return values after the execution.
|
|
74
|
+
For example,
|
|
75
|
+
"copy": ["A2", "L"] indicates that after this external function is executed, the value of the 2nd parameter is copied into the return value.
|
|
76
|
+
For the selection of function type and a more detailed explanation, please refer to the definition of enum *extType* in ExtAPI.h.
|
|
77
|
+
|
|
78
|
+
For operands of function operation, e.g., "A2", "L", there are the following options:
|
|
79
|
+
"A": represents a parameter;
|
|
80
|
+
"N": represents a number;
|
|
81
|
+
"R": represents a reference;
|
|
82
|
+
"L": represents a return value;
|
|
83
|
+
"V": represents a dummy node;
|
|
84
|
+
|
|
85
|
+
Among them, a parameter may have multiple forms because there may be various parameters, and the parameter may be a reference or complex structure,
|
|
86
|
+
|
|
87
|
+
Here we use regular expressions "(AN)(R|RN)^*" to represent parameters, for example,
|
|
88
|
+
"A0": represents the 1st parameter;
|
|
89
|
+
"A2R": represents that the 3rd parameter is a reference;
|
|
90
|
+
"A1R2": represents the 3rd substructure of the 2nd parameter "A1R", where "A1R" is a complex structure;
|
|
91
|
+
"A2R3R": represents the 4th substructure of the 3rd parameter "A2R" is a reference, where "A2R" is a complex structure;
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
** Specification format:
|
|
95
|
+
"functionName": {
|
|
96
|
+
"type": "functional type",
|
|
97
|
+
"overwrite_app_function:" 0/1,
|
|
98
|
+
"function operation_1": [ operand_1, operand_2, ... , operand_n],
|
|
99
|
+
"function operation_2": [ operand_1, operand_2, ... , operand_n],
|
|
100
|
+
...
|
|
101
|
+
"function operation_n": [ operand_1, operand_2, ... , operand_n]
|
|
102
|
+
}
|
|
91
103
|
*/
|
|
92
104
|
|
|
93
105
|
|
|
@@ -233,6 +245,11 @@ public:
|
|
|
233
245
|
// Get property of the operation, e.g. "EFT_A1R_A0R"
|
|
234
246
|
extType get_type(const SVF::SVFFunction *callee);
|
|
235
247
|
|
|
248
|
+
// Get priority of he function, return value
|
|
249
|
+
// 0: Apply user-defined functions
|
|
250
|
+
// 1: Apply function specification in ExtAPI.json
|
|
251
|
+
u32_t isOverwrittenAppFunction(const SVF::SVFFunction *callee);
|
|
252
|
+
|
|
236
253
|
// Does (F) have a static var X (unavailable to us) that its return points to?
|
|
237
254
|
bool has_static(const SVFFunction *F);
|
|
238
255
|
|
|
Binary file
|
|
Binary file
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
* Author: Pei Xu
|
|
28
28
|
*/
|
|
29
29
|
|
|
30
|
-
#ifndef
|
|
31
|
-
#define
|
|
30
|
+
#ifndef INCLUDE_CFL_CFGNormalizer_H_
|
|
31
|
+
#define INCLUDE_CFL_CFGNormalizer_H_
|
|
32
32
|
|
|
33
33
|
#include "CFLGrammar.h"
|
|
34
34
|
|
|
@@ -36,7 +36,12 @@ namespace SVF
|
|
|
36
36
|
{
|
|
37
37
|
|
|
38
38
|
/*!
|
|
39
|
-
*
|
|
39
|
+
* Generate Normalized Grammar from a grammarbase
|
|
40
|
+
*
|
|
41
|
+
* To Do:
|
|
42
|
+
* Error Notice for ill formed production,
|
|
43
|
+
* e.g. not end with ';' and '*' not preceding with '()' and extra space before ';'
|
|
44
|
+
* '|' sign support
|
|
40
45
|
*/
|
|
41
46
|
|
|
42
47
|
class CFGNormalizer
|
|
@@ -47,23 +52,23 @@ public:
|
|
|
47
52
|
{
|
|
48
53
|
}
|
|
49
54
|
|
|
50
|
-
///
|
|
55
|
+
/// Binary Normal Form(BNF) normalization with variable attribute expanded
|
|
51
56
|
CFLGrammar* normalize(GrammarBase *generalGrammar);
|
|
52
57
|
|
|
53
|
-
///
|
|
58
|
+
/// Expand every variable attribute in rawProductions of grammarbase
|
|
54
59
|
CFLGrammar* fillAttribute(CFLGrammar *grammar, const Map<CFLGrammar::Kind, Set<CFLGrammar::Attribute>>& kind2AttrsMap);
|
|
55
60
|
|
|
56
61
|
private:
|
|
57
62
|
/// Add nonterminal to tranfer long rules to binary rules
|
|
58
63
|
void ebnf_bin(CFLGrammar *grammar);
|
|
59
64
|
|
|
60
|
-
void
|
|
65
|
+
void ebnfSignReplace(char sign, CFLGrammar *grammar);
|
|
61
66
|
|
|
62
67
|
void insertToCFLGrammar(CFLGrammar *grammar, GrammarBase::Production &prod);
|
|
63
68
|
|
|
64
|
-
int
|
|
69
|
+
int ebnfBracketMatch(GrammarBase::Production& prod, int i, CFLGrammar *grammar) ;
|
|
65
70
|
|
|
66
|
-
|
|
71
|
+
GrammarBase::Symbol check_head(GrammarBase::SymbolMap<GrammarBase::Symbol, GrammarBase::Productions>& grammar, GrammarBase::Production& rule);
|
|
67
72
|
|
|
68
73
|
GrammarBase::Production strTrans(std::string strPro, CFLGrammar *grammar);
|
|
69
74
|
|
|
@@ -74,4 +79,4 @@ private:
|
|
|
74
79
|
|
|
75
80
|
} // End namespace SVF
|
|
76
81
|
|
|
77
|
-
#endif /*
|
|
82
|
+
#endif /* INCLUDE_CFL_CFGNormalizer_H_*/
|
|
@@ -51,50 +51,11 @@ public:
|
|
|
51
51
|
/// Destructor
|
|
52
52
|
virtual ~CFLAlias()
|
|
53
53
|
{
|
|
54
|
-
delete graph;
|
|
55
|
-
delete grammar;
|
|
56
54
|
delete solver;
|
|
57
55
|
}
|
|
58
56
|
|
|
59
57
|
/// Start Analysis here (main part of pointer analysis).
|
|
60
|
-
virtual void analyze()
|
|
61
|
-
{
|
|
62
|
-
GrammarBuilder gReader = GrammarBuilder(Options::GrammarFilename);
|
|
63
|
-
CFGNormalizer normalizer = CFGNormalizer();
|
|
64
|
-
CFLGraphBuilder cflGraphBuilder = CFLGraphBuilder();
|
|
65
|
-
CFLGramGraphChecker cflChecker = CFLGramGraphChecker();
|
|
66
|
-
/// Assume Read From Const Graph, associate label symbol is hard coded
|
|
67
|
-
if (Options::GraphIsFromDot == false)
|
|
68
|
-
{
|
|
69
|
-
PointerAnalysis::initialize();
|
|
70
|
-
Map<std::string, SVF::CFLGraph::Symbol> ConstMap = {{"Addr",0}, {"Copy", 1},{"Store", 2},{"Load", 3},{"Gep_i", 4},{"Vgep", 5},{"Addrbar",6}, {"Copybar", 7},{"Storebar", 8},{"Loadbar", 9},{"Gepbar_i", 10},{"Vgepbar", 11}};
|
|
71
|
-
GrammarBase *generalGrammar = gReader.build(ConstMap);
|
|
72
|
-
ConstraintGraph *consCG = new ConstraintGraph(svfir);
|
|
73
|
-
graph = cflGraphBuilder.buildBigraph(consCG, generalGrammar->getStartKind());
|
|
74
|
-
cflChecker.check(generalGrammar, &cflGraphBuilder, graph);
|
|
75
|
-
grammar = normalizer.normalize(generalGrammar);
|
|
76
|
-
cflChecker.check(grammar, &cflGraphBuilder, graph);
|
|
77
|
-
svfir->dump("SVFIR");
|
|
78
|
-
grammar->dump();
|
|
79
|
-
delete consCG;
|
|
80
|
-
delete generalGrammar;
|
|
81
|
-
}
|
|
82
|
-
else
|
|
83
|
-
{
|
|
84
|
-
GrammarBase *generalGrammar = gReader.build();
|
|
85
|
-
graph = cflGraphBuilder.buildFromDot(Options::InputFilename, generalGrammar);
|
|
86
|
-
cflChecker.check(generalGrammar, &cflGraphBuilder, graph);
|
|
87
|
-
grammar = normalizer.normalize(generalGrammar);
|
|
88
|
-
cflChecker.check(grammar, &cflGraphBuilder, graph);
|
|
89
|
-
delete generalGrammar;
|
|
90
|
-
}
|
|
91
|
-
solver = new CFLSolver(graph, grammar);
|
|
92
|
-
solver->solve();
|
|
93
|
-
if (Options::GraphIsFromDot == false)
|
|
94
|
-
{
|
|
95
|
-
PointerAnalysis::finalize();
|
|
96
|
-
}
|
|
97
|
-
}
|
|
58
|
+
virtual void analyze();
|
|
98
59
|
|
|
99
60
|
/// Interface exposed to users of our pointer analysis, given Value infos
|
|
100
61
|
virtual AliasResult alias(const Value* v1, const Value* v2)
|
|
@@ -28,20 +28,155 @@
|
|
|
28
28
|
*/
|
|
29
29
|
#ifndef CFLGrammar_H_
|
|
30
30
|
#define CFLGrammar_H_
|
|
31
|
-
#include "Util/
|
|
31
|
+
#include "Util/SVFBasicTypes.h"
|
|
32
32
|
|
|
33
33
|
namespace SVF
|
|
34
34
|
{
|
|
35
|
+
|
|
35
36
|
class GrammarBase
|
|
36
37
|
{
|
|
37
38
|
public:
|
|
38
|
-
typedef u32_t Symbol;
|
|
39
|
-
typedef std::vector<Symbol> Production;
|
|
40
|
-
typedef Set<Production> Productions;
|
|
41
|
-
typedef u32_t Attribute;
|
|
42
39
|
typedef u32_t Kind;
|
|
40
|
+
typedef u32_t Attribute;
|
|
41
|
+
typedef u32_t VariableAttribute;
|
|
42
|
+
typedef struct Symbol
|
|
43
|
+
{
|
|
44
|
+
Kind kind: 8;
|
|
45
|
+
Attribute attribute: 16;
|
|
46
|
+
VariableAttribute variableAttribute: 8;
|
|
47
|
+
|
|
48
|
+
/// Default Value for Symbol is 0.
|
|
49
|
+
Symbol() : kind(0), attribute(0), variableAttribute(0) {}
|
|
50
|
+
|
|
51
|
+
/// Contruct from u32_t move the bit to right field
|
|
52
|
+
Symbol(const u32_t& num) : kind(num & 0xFF), attribute((num >> 8 ) & 0xFFFF), variableAttribute((num >> 24)) {}
|
|
53
|
+
|
|
54
|
+
/// Conversion of u32_t
|
|
55
|
+
operator u32_t()
|
|
56
|
+
{
|
|
57
|
+
u32_t num = 0;
|
|
58
|
+
num += this->variableAttribute << 24;
|
|
59
|
+
num += this->attribute << 8;
|
|
60
|
+
num += this->kind;
|
|
61
|
+
return num;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/// Conversion of u64_t
|
|
65
|
+
operator u64_t()
|
|
66
|
+
{
|
|
67
|
+
u64_t num = 0;
|
|
68
|
+
num += this->variableAttribute << 24;
|
|
69
|
+
num += this->attribute << 8;
|
|
70
|
+
num += this->kind;
|
|
71
|
+
return num;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
operator s64_t() const
|
|
75
|
+
{
|
|
76
|
+
s64_t num = 0;
|
|
77
|
+
num += this->variableAttribute << 24;
|
|
78
|
+
num += this->attribute << 8;
|
|
79
|
+
num += this->kind;
|
|
80
|
+
return num;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
bool operator<(const Symbol& rhs)
|
|
84
|
+
{
|
|
85
|
+
return this->kind < rhs.kind;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
void operator=(const int& i)
|
|
89
|
+
{
|
|
90
|
+
this->kind = EdgeKindMask & i;
|
|
91
|
+
this->attribute = i >> EdgeKindMaskBits;
|
|
92
|
+
this->variableAttribute = i >> AttributedKindMaskBits;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
void operator=(unsigned long long num)
|
|
96
|
+
{
|
|
97
|
+
this->kind = num & 0xFF;
|
|
98
|
+
this->attribute = (num >> 8 ) & 0xFFFF;
|
|
99
|
+
this->variableAttribute = num >> 24;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
void operator=(const Kind& kind)
|
|
103
|
+
{
|
|
104
|
+
this->kind = kind;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
bool operator==(const Symbol& s)
|
|
108
|
+
{
|
|
109
|
+
return ((this->kind == s.kind) && (this->attribute == s.attribute) && (this->variableAttribute == s.variableAttribute));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
bool operator==(const Symbol& s) const
|
|
113
|
+
{
|
|
114
|
+
return ((kind == s.kind) && (attribute == s.attribute) && (variableAttribute == s.variableAttribute));
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
bool operator!=(const Symbol& s) const
|
|
118
|
+
{
|
|
119
|
+
return ! (*this == s) ;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
bool operator==(const int& i)
|
|
124
|
+
{
|
|
125
|
+
return ((this->kind == (EdgeKindMask & i)) && (this->attribute == (i >> EdgeKindMaskBits)) && (this->variableAttribute == (i >> AttributedKindMaskBits)));
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
bool operator==(const Kind& k) const
|
|
129
|
+
{
|
|
130
|
+
return (this->kind == k);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
bool operator==(const Kind& k)
|
|
134
|
+
{
|
|
135
|
+
return (this->kind == k);
|
|
136
|
+
}
|
|
137
|
+
} Symbol;
|
|
138
|
+
|
|
139
|
+
class SymbolHash
|
|
140
|
+
{
|
|
141
|
+
public:
|
|
142
|
+
size_t operator()(const Symbol &s) const
|
|
143
|
+
{
|
|
144
|
+
std::hash<u32_t> h;
|
|
145
|
+
return h(u32_t(s));
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
|
|
43
149
|
|
|
44
|
-
|
|
150
|
+
struct SymbolVectorHash
|
|
151
|
+
{
|
|
152
|
+
size_t operator()(const std::vector<Symbol> &v) const
|
|
153
|
+
{
|
|
154
|
+
size_t h = v.size();
|
|
155
|
+
|
|
156
|
+
SymbolHash hf;
|
|
157
|
+
for (const Symbol &t : v)
|
|
158
|
+
{
|
|
159
|
+
h ^= hf(t) + 0x9e3779b9 + (h << 6) + (h >> 2);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return h;
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
template<typename Key, typename Value, typename Hash = SymbolHash,
|
|
167
|
+
typename KeyEqual = std::equal_to<Key>,
|
|
168
|
+
typename Allocator = std::allocator<std::pair<const Key, Value>>>
|
|
169
|
+
using SymbolMap = std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>;
|
|
170
|
+
|
|
171
|
+
template <typename Key, typename Hash = SymbolVectorHash, typename KeyEqual = std::equal_to<Key>,
|
|
172
|
+
typename Allocator = std::allocator<Key>>
|
|
173
|
+
using SymbolSet = std::unordered_set<Key, Hash, KeyEqual, Allocator>;
|
|
174
|
+
|
|
175
|
+
typedef std::vector<Symbol> Production;
|
|
176
|
+
typedef SymbolSet<Production> Productions;
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
inline Map<std::string, Kind>& getNonterminals()
|
|
45
180
|
{
|
|
46
181
|
return this->nonterminals;
|
|
47
182
|
}
|
|
@@ -61,7 +196,7 @@ public:
|
|
|
61
196
|
this->terminals = terminals;
|
|
62
197
|
}
|
|
63
198
|
|
|
64
|
-
inline
|
|
199
|
+
inline SymbolMap<Symbol, Productions>& getRawProductions()
|
|
65
200
|
{
|
|
66
201
|
return this->rawProductions;
|
|
67
202
|
}
|
|
@@ -91,7 +226,11 @@ public:
|
|
|
91
226
|
this->totalKind = totalKind;
|
|
92
227
|
}
|
|
93
228
|
|
|
94
|
-
|
|
229
|
+
std::string extractKindStrFromSymbolStr(const std::string symbolStr) const;
|
|
230
|
+
|
|
231
|
+
std::string extractAttributeStrFromSymbolStr(const std::string symbolStr) const;
|
|
232
|
+
|
|
233
|
+
void setRawProductions(SymbolMap<Symbol, Productions>& rawProductions);
|
|
95
234
|
|
|
96
235
|
void setKind2AttrsMap(const Map<Kind, Set<Attribute>>& kind2AttrsMap);
|
|
97
236
|
|
|
@@ -99,6 +238,8 @@ public:
|
|
|
99
238
|
|
|
100
239
|
Kind str2Kind(std::string str) const;
|
|
101
240
|
|
|
241
|
+
Symbol str2Symbol(const std::string str) const;
|
|
242
|
+
|
|
102
243
|
std::string kind2Str(Kind kind) const;
|
|
103
244
|
|
|
104
245
|
std::string sym2StrDump(Symbol sym) const;
|
|
@@ -108,41 +249,46 @@ public:
|
|
|
108
249
|
return prod.at(pos);
|
|
109
250
|
}
|
|
110
251
|
|
|
111
|
-
inline const Set<
|
|
252
|
+
inline const Set<Kind>& getAttrSyms() const
|
|
112
253
|
{
|
|
113
254
|
return this->attributeKinds;
|
|
114
255
|
}
|
|
115
256
|
|
|
257
|
+
/// Insert kind to nonterminal and return kind.
|
|
258
|
+
Kind insertNonterminalKind(std::string const kindStr);
|
|
259
|
+
|
|
260
|
+
/// From SymbolStr extract kind to inserted in nonterminal
|
|
261
|
+
/// symbolStr = <kindStr> [_] [ attributeStr | variableattributeStr ]
|
|
116
262
|
Kind insertTerminalKind(std::string strLit);
|
|
117
|
-
Kind insertNonTerminalKind(std::string strLit);
|
|
118
|
-
void insertAttribute(Kind kind, Attribute a);
|
|
119
263
|
|
|
120
|
-
|
|
121
|
-
{
|
|
122
|
-
return (EdgeKindMask & sym);
|
|
123
|
-
}
|
|
264
|
+
Symbol insertSymbol(std::string strLit);
|
|
124
265
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
}
|
|
266
|
+
Symbol insertNonTerminalSymbol(std::string strLit);
|
|
267
|
+
|
|
268
|
+
void insertAttribute(Kind kind, Attribute a);
|
|
129
269
|
|
|
130
270
|
inline static Kind getAttributedKind(Attribute attribute, Kind kind)
|
|
131
271
|
{
|
|
132
272
|
return ((attribute << EdgeKindMaskBits)| kind );
|
|
133
273
|
}
|
|
134
274
|
|
|
275
|
+
inline static Kind getVariabledKind(VariableAttribute variableAttribute, Kind kind)
|
|
276
|
+
{
|
|
277
|
+
return ((variableAttribute << AttributedKindMaskBits) | kind);
|
|
278
|
+
}
|
|
279
|
+
|
|
135
280
|
protected:
|
|
136
281
|
static constexpr unsigned char EdgeKindMaskBits = 8; ///< We use the lower 8 bits to denote edge kind
|
|
282
|
+
static constexpr unsigned char AttributedKindMaskBits = 24; ///< We use the lower 24 bits to denote attributed kind
|
|
137
283
|
static constexpr u64_t EdgeKindMask = (~0ULL) >> (64 - EdgeKindMaskBits);
|
|
138
284
|
Kind startKind;
|
|
139
285
|
private:
|
|
140
|
-
Set<Kind> attributeKinds;
|
|
141
|
-
Map<Kind, Set<Attribute>> kind2AttrsMap;
|
|
142
|
-
Map<Symbol, Productions> rawProductions;
|
|
143
|
-
Kind totalKind;
|
|
144
286
|
Map<std::string, Kind> nonterminals;
|
|
145
287
|
Map<std::string, Kind> terminals;
|
|
288
|
+
Set<Kind> attributeKinds;
|
|
289
|
+
Map<Kind, Set<Attribute>> kind2AttrsMap;
|
|
290
|
+
SymbolMap<Symbol, Productions> rawProductions;
|
|
291
|
+
u32_t totalKind;
|
|
146
292
|
};
|
|
147
293
|
|
|
148
294
|
class CFLGrammar : public GrammarBase
|
|
@@ -168,17 +314,17 @@ public:
|
|
|
168
314
|
return epsilonProds;
|
|
169
315
|
}
|
|
170
316
|
|
|
171
|
-
|
|
317
|
+
SymbolMap<Symbol, Productions>& getSingleRHS2Prods()
|
|
172
318
|
{
|
|
173
319
|
return singleRHS2Prods;
|
|
174
320
|
}
|
|
175
321
|
|
|
176
|
-
|
|
322
|
+
SymbolMap<Symbol, Productions>& getFirstRHS2Prods()
|
|
177
323
|
{
|
|
178
324
|
return firstRHS2Prods;
|
|
179
325
|
}
|
|
180
326
|
|
|
181
|
-
|
|
327
|
+
SymbolMap<Symbol, Productions>& getSecondRHS2Prods()
|
|
182
328
|
{
|
|
183
329
|
return secondRHS2Prods;
|
|
184
330
|
}
|
|
@@ -240,17 +386,86 @@ public:
|
|
|
240
386
|
|
|
241
387
|
void dump() const;
|
|
242
388
|
|
|
389
|
+
void dump(std::string fileName) const;
|
|
390
|
+
|
|
391
|
+
|
|
243
392
|
const inline int num_generator()
|
|
244
393
|
{
|
|
245
394
|
return newTerminalSubscript++;
|
|
246
395
|
}
|
|
247
396
|
|
|
248
397
|
private:
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
398
|
+
SymbolSet<Production> epsilonProds;
|
|
399
|
+
SymbolMap<Symbol, Productions> singleRHS2Prods;
|
|
400
|
+
SymbolMap<Symbol, Productions> firstRHS2Prods;
|
|
401
|
+
SymbolMap<Symbol, Productions> secondRHS2Prods;
|
|
402
|
+
u32_t newTerminalSubscript;
|
|
403
|
+
};
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* Worklist with "first in first out" order.
|
|
407
|
+
* New nodes will be pushed at back and popped from front.
|
|
408
|
+
* Elements in the list are unique as they're recorded by Set.
|
|
409
|
+
*/
|
|
410
|
+
template<class Data>
|
|
411
|
+
class CFLFIFOWorkList
|
|
412
|
+
{
|
|
413
|
+
typedef GrammarBase::SymbolSet<Data> DataSet;
|
|
414
|
+
typedef std::deque<Data> DataDeque;
|
|
415
|
+
public:
|
|
416
|
+
CFLFIFOWorkList() {}
|
|
417
|
+
|
|
418
|
+
~CFLFIFOWorkList() {}
|
|
419
|
+
|
|
420
|
+
inline bool empty() const
|
|
421
|
+
{
|
|
422
|
+
return data_list.empty();
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
inline bool find(Data data) const
|
|
426
|
+
{
|
|
427
|
+
return (data_set.find(data) == data_set.end() ? false : true);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* Push a data into the work list.
|
|
432
|
+
*/
|
|
433
|
+
inline bool push(Data data)
|
|
434
|
+
{
|
|
435
|
+
if (data_set.find(data) == data_set.end())
|
|
436
|
+
{
|
|
437
|
+
data_list.push_back(data);
|
|
438
|
+
data_set.insert(data);
|
|
439
|
+
return true;
|
|
440
|
+
}
|
|
441
|
+
else
|
|
442
|
+
return false;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* Pop a data from the END of work list.
|
|
447
|
+
*/
|
|
448
|
+
inline Data pop()
|
|
449
|
+
{
|
|
450
|
+
assert(!empty() && "work list is empty");
|
|
451
|
+
Data data = data_list.front();
|
|
452
|
+
data_list.pop_front();
|
|
453
|
+
data_set.erase(data);
|
|
454
|
+
return data;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
/*!
|
|
458
|
+
* Clear all the data
|
|
459
|
+
*/
|
|
460
|
+
inline void clear()
|
|
461
|
+
{
|
|
462
|
+
data_list.clear();
|
|
463
|
+
data_set.clear();
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
private:
|
|
467
|
+
DataSet data_set; ///< store all data in the work list.
|
|
468
|
+
DataDeque data_list; ///< work list using std::vector.
|
|
254
469
|
};
|
|
255
470
|
|
|
256
471
|
}
|
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
Start:
|
|
2
|
-
V
|
|
2
|
+
V
|
|
3
|
+
Terminal:
|
|
4
|
+
Addr Copy Store Load Gep Vgep
|
|
3
5
|
Productions:
|
|
4
|
-
F ->
|
|
5
|
-
F ->
|
|
6
|
-
F ->
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
Fbar ->
|
|
10
|
-
Fbar ->
|
|
11
|
-
Fbar -> Addrbar ( Loadbar V Storebar ) *;
|
|
12
|
-
Fbar -> ( Copybar ) *;
|
|
13
|
-
Fbar -> ( Loadbar V Storebar ) *;
|
|
6
|
+
F -> epsilon;
|
|
7
|
+
F -> F Copy;
|
|
8
|
+
F -> F Store V Load;
|
|
9
|
+
Gepbar_j -> Vgepbar Fbar Gepbar_i;
|
|
10
|
+
Fbar -> epsilon;
|
|
11
|
+
Fbar -> Copybar Fbar;
|
|
12
|
+
Fbar -> Loadbar V Storebar Fbar;
|
|
14
13
|
V -> Fbar V F;
|
|
15
|
-
V -> Gepbar_i V Gep_i;
|
|
16
14
|
V -> Addrbar Addr;
|
|
17
|
-
V ->
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
V -> Gepbar_i V Gep_i;
|
|
16
|
+
Gep_j -> Gep_i F Vgep;
|
|
17
|
+
|
|
@@ -39,14 +39,14 @@ namespace SVF
|
|
|
39
39
|
|
|
40
40
|
class CFLGraphBuilder
|
|
41
41
|
{
|
|
42
|
-
|
|
42
|
+
protected:
|
|
43
43
|
typedef CFLGrammar::Kind Kind;
|
|
44
44
|
typedef CFLGrammar::Symbol Symbol;
|
|
45
45
|
Map<std::string, Kind> label2KindMap;
|
|
46
46
|
Map<Kind, std::string> kind2LabelMap;
|
|
47
47
|
Map<CFLGrammar::Kind, Set<CFLGrammar::Attribute>> kind2AttrsMap;
|
|
48
48
|
bool externMap;
|
|
49
|
-
|
|
49
|
+
Kind current;
|
|
50
50
|
|
|
51
51
|
public:
|
|
52
52
|
/// add attribute to kind2Attribute Map
|
|
@@ -73,12 +73,22 @@ public:
|
|
|
73
73
|
|
|
74
74
|
/// Build Bidirectional graph by copying nodes and edges from any graph inherited from GenericGraph
|
|
75
75
|
template<class N, class E>
|
|
76
|
-
CFLGraph* buildBigraph(GenericGraph<N,E>* graph, Kind startKind)
|
|
76
|
+
CFLGraph* buildBigraph(GenericGraph<N,E>* graph, Kind startKind, GrammarBase *grammar)
|
|
77
77
|
{
|
|
78
78
|
CFLGraph *cflGraph = new CFLGraph(startKind);
|
|
79
|
-
Map<std::string, SVF::CFLGraph::Symbol> ConstMap = {{"Addr",0}, {"Copy", 1},{"Store", 2},{"Load", 3},{"Gep_i", 4},{"Vgep", 5},{"Addrbar",6}, {"Copybar", 7},{"Storebar", 8},{"Loadbar", 9},{"Gepbar_i", 10},{"Vgepbar", 11}};
|
|
80
79
|
externMap = true;
|
|
81
|
-
for(auto pairV :
|
|
80
|
+
for(auto pairV : grammar->getTerminals())
|
|
81
|
+
{
|
|
82
|
+
if(label2KindMap.find(pairV.first) == label2KindMap.end())
|
|
83
|
+
{
|
|
84
|
+
label2KindMap.insert(pairV);
|
|
85
|
+
}
|
|
86
|
+
if(kind2LabelMap.find(pairV.second) == kind2LabelMap.end())
|
|
87
|
+
{
|
|
88
|
+
kind2LabelMap.insert(make_pair(pairV.second, pairV.first));
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
for(auto pairV : grammar->getNonterminals())
|
|
82
92
|
{
|
|
83
93
|
if(label2KindMap.find(pairV.first) == label2KindMap.end())
|
|
84
94
|
{
|
|
@@ -100,29 +110,10 @@ public:
|
|
|
100
110
|
for(E* edge : node->getOutEdges())
|
|
101
111
|
{
|
|
102
112
|
CFLGrammar::Kind edgeLabel = edge->getEdgeKind();
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
NormalGepCGEdge *nGepEdge = SVFUtil::dyn_cast<NormalGepCGEdge>(edge);
|
|
108
|
-
CFLGrammar::Attribute attr = nGepEdge->getConstantFieldIdx();
|
|
109
|
-
addAttribute(edgeLabel, attr);
|
|
110
|
-
edgeLabel = CFLGrammar::getAttributedKind(attr, edgeLabel);
|
|
111
|
-
cflGraph->addCFLEdge(cflGraph->getGNode(edge->getSrcID()), cflGraph->getGNode(edge->getDstID()), edgeLabel);
|
|
112
|
-
std::string key = kind2LabelMap[edge->getEdgeKind()];
|
|
113
|
-
key.pop_back();
|
|
114
|
-
key.pop_back(); // _i standsfor attribute variable should place at last
|
|
115
|
-
key.append("bar_i"); // for example Gep_i should be Gepbar_i, not Gep_ibar
|
|
116
|
-
cflGraph->addCFLEdge(cflGraph->getGNode(edge->getDstID()), cflGraph->getGNode(edge->getSrcID()), CFLGrammar::getAttributedKind(attr, label2KindMap[key]));
|
|
117
|
-
addAttribute(label2KindMap[key], attr);
|
|
118
|
-
}
|
|
119
|
-
else
|
|
120
|
-
{
|
|
121
|
-
cflGraph->addCFLEdge(cflGraph->getGNode(edge->getSrcID()), cflGraph->getGNode(edge->getDstID()), edgeLabel);
|
|
122
|
-
std::string key = kind2LabelMap[edge->getEdgeKind()];
|
|
123
|
-
key.append("bar");
|
|
124
|
-
cflGraph->addCFLEdge(cflGraph->getGNode(edge->getDstID()), cflGraph->getGNode(edge->getSrcID()), label2KindMap[key]);
|
|
125
|
-
}
|
|
113
|
+
cflGraph->addCFLEdge(cflGraph->getGNode(edge->getSrcID()), cflGraph->getGNode(edge->getDstID()), edgeLabel);
|
|
114
|
+
std::string key = kind2LabelMap[edge->getEdgeKind()];
|
|
115
|
+
key.append("bar");
|
|
116
|
+
cflGraph->addCFLEdge(cflGraph->getGNode(edge->getDstID()), cflGraph->getGNode(edge->getSrcID()), label2KindMap[key]);
|
|
126
117
|
}
|
|
127
118
|
}
|
|
128
119
|
return cflGraph;
|
|
@@ -147,8 +138,15 @@ public:
|
|
|
147
138
|
{
|
|
148
139
|
return this->kind2AttrsMap;
|
|
149
140
|
}
|
|
141
|
+
};
|
|
150
142
|
|
|
151
|
-
|
|
143
|
+
class AliasCFLGraphBuilder : public CFLGraphBuilder
|
|
144
|
+
{
|
|
145
|
+
public:
|
|
146
|
+
/// Build Bidirectional graph by copying nodes and edges from const graph inherited from GenericGraph
|
|
147
|
+
CFLGraph* buildBigraph(ConstraintGraph *graph, Kind startKind, GrammarBase *grammar);
|
|
152
148
|
};
|
|
149
|
+
|
|
153
150
|
}// SVF
|
|
154
151
|
|
|
152
|
+
|
|
@@ -27,54 +27,74 @@
|
|
|
27
27
|
* Author: Pei Xu
|
|
28
28
|
*/
|
|
29
29
|
|
|
30
|
+
#ifndef INCLUDE_CFL_GRAMMARBUILDER_H_
|
|
31
|
+
#define INCLUDE_CFL_GRAMMARBUILDER_H_
|
|
30
32
|
|
|
31
33
|
#include "CFL/CFLGrammar.h"
|
|
32
|
-
|
|
34
|
+
|
|
33
35
|
namespace SVF
|
|
34
36
|
{
|
|
35
37
|
|
|
36
|
-
|
|
38
|
+
/**
|
|
37
39
|
* Build Grammar from a user specified grammar text
|
|
40
|
+
*
|
|
41
|
+
* Symbol Format:
|
|
42
|
+
* <kind> [bar] [ _alpha | _number ]
|
|
43
|
+
* kind: any nonspace string start with alphabet, epsilon stand for empty string
|
|
44
|
+
* bar: stand for reverse edge
|
|
45
|
+
* alpha: any single alpha
|
|
46
|
+
* number: any number
|
|
47
|
+
* start with capital: nonterminal
|
|
48
|
+
* start with noncapital: terminal
|
|
49
|
+
*
|
|
50
|
+
* Production Format:
|
|
51
|
+
* <symbol> -> <symbol> *;
|
|
52
|
+
* LHS and RHS, Seperate by '->', symbol seperate by ' ', end by ';'
|
|
53
|
+
* support '*', '?', '(', ')'
|
|
54
|
+
*
|
|
38
55
|
* Input Format:
|
|
39
|
-
* Start:
|
|
56
|
+
* Start:
|
|
40
57
|
* M // Specify Start Symbol in Second Line
|
|
58
|
+
* Terminal:
|
|
59
|
+
* Addr Copy Store Load Gep Vgep // Specify the order of terminal Addr->0, Copy->1 ..
|
|
41
60
|
* Productions: // Each Symbol seperate by 'Space', production end with ';'
|
|
42
61
|
* M -> V d; // Terminal in NonCapital
|
|
43
62
|
* M -> dbar V d; // NonTerminal in Capital
|
|
44
63
|
* V -> M abar M a M; // LHS and RHS, Seperate by '->'
|
|
45
64
|
* V -> ( M ? abar ) * M ? ( a M ? ) *; // Support '(' ')' '?' '*' four regular expression sign
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
65
|
+
* Gep_j -> Gep_i F vgep; // Support variable attribute with variable attribute
|
|
66
|
+
* Gep_1 -> Gep_2; // Support fix number attribute
|
|
67
|
+
*
|
|
49
68
|
*/
|
|
50
69
|
|
|
51
70
|
class GrammarBuilder
|
|
52
71
|
{
|
|
53
72
|
private:
|
|
54
|
-
|
|
55
|
-
|
|
73
|
+
std::string fileName;
|
|
74
|
+
GrammarBase *grammar;
|
|
56
75
|
|
|
57
76
|
/// Parse start symbol and production from file string
|
|
58
|
-
const inline std::string
|
|
77
|
+
const inline std::string parseProductionsString() const;
|
|
59
78
|
|
|
60
79
|
/// Parse whole production string to production vector
|
|
61
80
|
const inline std::vector<std::string> loadWordProductions() const;
|
|
62
81
|
|
|
63
|
-
/// Strip
|
|
82
|
+
/// Strip front and tail space
|
|
64
83
|
const inline std::string stripSpace(std::string s) const;
|
|
65
84
|
|
|
66
85
|
public:
|
|
67
|
-
std::string fileName;
|
|
68
|
-
GrammarBase *grammar;
|
|
69
|
-
|
|
70
86
|
GrammarBuilder(std::string fileName): fileName(fileName), grammar(nullptr)
|
|
71
87
|
{
|
|
72
88
|
grammar = new GrammarBase();
|
|
73
89
|
};
|
|
74
90
|
|
|
91
|
+
/// Build grammarBase from fileName
|
|
75
92
|
GrammarBase* build() const;
|
|
76
93
|
|
|
77
|
-
|
|
94
|
+
/// Build grammarBase from fileName with preset str2KindMap
|
|
95
|
+
GrammarBase* build(Map<std::string, SVF::GrammarBase::Symbol> &preMap) const;
|
|
78
96
|
};
|
|
79
97
|
|
|
80
98
|
} // SVF
|
|
99
|
+
|
|
100
|
+
#endif /* INCLUDE_CFL_GRAMMARBUILDER_H_ */
|
|
@@ -57,6 +57,16 @@ public:
|
|
|
57
57
|
{
|
|
58
58
|
return this->getEdgeKindWithoutMask();
|
|
59
59
|
}
|
|
60
|
+
|
|
61
|
+
inline GEdgeKind getEdgeKindWithMask() const
|
|
62
|
+
{
|
|
63
|
+
return (EdgeKindMask & this->getEdgeKindWithoutMask());
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
inline GEdgeKind getEdgeAttri() const
|
|
67
|
+
{
|
|
68
|
+
return (getEdgeKind() >> this->EdgeKindMaskBits);
|
|
69
|
+
}
|
|
60
70
|
};
|
|
61
71
|
|
|
62
72
|
|
|
@@ -87,6 +97,8 @@ public:
|
|
|
87
97
|
}
|
|
88
98
|
~CFLGraph() override = default;
|
|
89
99
|
|
|
100
|
+
Kind getStartKind() const;
|
|
101
|
+
|
|
90
102
|
virtual void addCFLNode(NodeID id, CFLNode* node);
|
|
91
103
|
|
|
92
104
|
virtual const CFLEdge* addCFLEdge(CFLNode* src, CFLNode* dst, CFLEdge::GEdgeFlag label);
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
* Author: Yulei Sui
|
|
29
29
|
*/
|
|
30
30
|
|
|
31
|
-
#ifndef
|
|
32
|
-
#define
|
|
31
|
+
#ifndef INCLUDE_SVF_FE_CALLGRAPHBUILDER_H_
|
|
32
|
+
#define INCLUDE_SVF_FE_CALLGRAPHBUILDER_H_
|
|
33
33
|
|
|
34
34
|
#include "Graphs/PTACallGraph.h"
|
|
35
35
|
#include "Graphs/ThreadCallGraph.h"
|
|
@@ -40,54 +40,66 @@
|
|
|
40
40
|
#include <map>
|
|
41
41
|
|
|
42
42
|
#define EXTAPI_JSON_PATH "/lib/Util/ExtAPI.json"
|
|
43
|
+
#define JSON_OPT_OVERWRITE "overwrite_app_function"
|
|
44
|
+
#define JSON_OPT_FUNCTIONTYPE "type"
|
|
43
45
|
|
|
44
46
|
namespace SVF
|
|
45
47
|
{
|
|
46
48
|
|
|
47
49
|
/*
|
|
48
50
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
51
|
+
** Specifications in ExtAPI.json
|
|
52
|
+
|
|
53
|
+
*** [1] Overview of the Specification Language
|
|
54
|
+
The specification language of external functions is based on the JSON format. And every function defined by the Specification Language is an object that represents the specification rules. These Specification Language objects for functions contain four parts:
|
|
55
|
+
1. the name of the function,
|
|
56
|
+
2. the switch that controls whether the specification rules defined in the ExtAPI.json overwrite the functions defined in the user code,
|
|
57
|
+
3. the type of the function,
|
|
58
|
+
4. the operations conducted by the function.
|
|
59
|
+
|
|
60
|
+
*** [2] Overwriting the user-defined functions
|
|
61
|
+
The switch *overwrite_app_function* controls whether the specification rules defined in the ExtAPI.json overwrite the functions defined in the user code (e.g., CPP files). When the switch *overwrite_app_function* is set to a value of 1, SVF will use the specification rules in ExtAPI.json to conduct the analysis and ignore the user-defined functions in the input CPP/bc files.
|
|
62
|
+
overwrite_app_function = 0: Analyze the user-defined functions.
|
|
63
|
+
overwrite_app_function = 1: Use specifications in ExtAPI.json to overwrite the user-defined functions.
|
|
64
|
+
|
|
65
|
+
*** [3] Function types
|
|
66
|
+
Function type represents the properties of the function.
|
|
67
|
+
For example,
|
|
68
|
+
"EFT_ALLOC" represents if this external function allocates a new object and assigns it to one of its arguments,
|
|
69
|
+
For the selection of function type and a more detailed explanation, please refer to the definition of enum *extf_t* in ExtAPI.h.
|
|
70
|
+
|
|
71
|
+
*** [4] Function operations
|
|
72
|
+
Function operations indicate the relationships between input and output,
|
|
73
|
+
mainly between function parameters or between parameters and return values after the execution.
|
|
74
|
+
For example,
|
|
75
|
+
"copy": ["A2", "L"] indicates that after this external function is executed, the value of the 2nd parameter is copied into the return value.
|
|
76
|
+
For the selection of function type and a more detailed explanation, please refer to the definition of enum *extType* in ExtAPI.h.
|
|
77
|
+
|
|
78
|
+
For operands of function operation, e.g., "A2", "L", there are the following options:
|
|
79
|
+
"A": represents a parameter;
|
|
80
|
+
"N": represents a number;
|
|
81
|
+
"R": represents a reference;
|
|
82
|
+
"L": represents a return value;
|
|
83
|
+
"V": represents a dummy node;
|
|
84
|
+
|
|
85
|
+
Among them, a parameter may have multiple forms because there may be various parameters, and the parameter may be a reference or complex structure,
|
|
86
|
+
|
|
87
|
+
Here we use regular expressions "(AN)(R|RN)^*" to represent parameters, for example,
|
|
88
|
+
"A0": represents the 1st parameter;
|
|
89
|
+
"A2R": represents that the 3rd parameter is a reference;
|
|
90
|
+
"A1R2": represents the 3rd substructure of the 2nd parameter "A1R", where "A1R" is a complex structure;
|
|
91
|
+
"A2R3R": represents the 4th substructure of the 3rd parameter "A2R" is a reference, where "A2R" is a complex structure;
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
** Specification format:
|
|
95
|
+
"functionName": {
|
|
96
|
+
"type": "functional type",
|
|
97
|
+
"overwrite_app_function:" 0/1,
|
|
98
|
+
"function operation_1": [ operand_1, operand_2, ... , operand_n],
|
|
99
|
+
"function operation_2": [ operand_1, operand_2, ... , operand_n],
|
|
100
|
+
...
|
|
101
|
+
"function operation_n": [ operand_1, operand_2, ... , operand_n]
|
|
102
|
+
}
|
|
91
103
|
*/
|
|
92
104
|
|
|
93
105
|
|
|
@@ -233,6 +245,11 @@ public:
|
|
|
233
245
|
// Get property of the operation, e.g. "EFT_A1R_A0R"
|
|
234
246
|
extType get_type(const SVF::SVFFunction *callee);
|
|
235
247
|
|
|
248
|
+
// Get priority of he function, return value
|
|
249
|
+
// 0: Apply user-defined functions
|
|
250
|
+
// 1: Apply function specification in ExtAPI.json
|
|
251
|
+
u32_t isOverwrittenAppFunction(const SVF::SVFFunction *callee);
|
|
252
|
+
|
|
236
253
|
// Does (F) have a static var X (unavailable to us) that its return points to?
|
|
237
254
|
bool has_static(const SVFFunction *F);
|
|
238
255
|
|