svf-tools 1.0.993 → 1.0.994
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/package.json +1 -1
- package/svf/include/Graphs/ThreadCallGraph.h +5 -4
- package/svf/include/MemoryModel/PointerAnalysis.h +1 -1
- package/svf/include/MemoryModel/PointerAnalysisImpl.h +4 -0
- package/svf/include/Util/SVFUtil.h +1 -1
- package/svf/include/Util/ThreadAPI.h +8 -2
- package/svf/include/WPA/Andersen.h +26 -13
- package/svf/include/WPA/Steensgaard.h +10 -20
- package/svf/include/WPA/TypeAnalysis.h +10 -3
- package/svf/lib/Graphs/ThreadCallGraph.cpp +10 -2
- package/svf/lib/MemoryModel/PointerAnalysisImpl.cpp +37 -0
- package/svf/lib/Util/ThreadAPI.cpp +15 -5
- package/svf/lib/WPA/Andersen.cpp +205 -151
- package/svf/lib/WPA/Steensgaard.cpp +1 -163
- package/svf-llvm/lib/SVFIRExtAPI.cpp +3 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svf-tools",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.994",
|
|
4
4
|
"description": "* <b>[TypeClone](https://github.com/SVF-tools/SVF/wiki/TypeClone) published in our [ECOOP paper](https://yuleisui.github.io/publications/ecoop20.pdf) is now available in SVF </b> * <b>SVF now uses a single script for its build. Just type [`source ./build.sh`](https://github.com/SVF-tools/SVF/blob/master/build.sh) in your terminal, that's it!</b> * <b>SVF now supports LLVM-10.0.0! </b> * <b>We thank [bsauce](https://github.com/bsauce) for writing a user manual of SVF ([link1](https://www.jianshu.com/p/068a08ec749c) and [link2](https://www.jianshu.com/p/777c30d4240e)) in Chinese </b> * <b>SVF now supports LLVM-9.0.0 (Thank [Byoungyoung Lee](https://github.com/SVF-tools/SVF/issues/142) for his help!). </b> * <b>SVF now supports a set of [field-sensitive pointer analyses](https://yuleisui.github.io/publications/sas2019a.pdf). </b> * <b>[Use SVF as an external lib](https://github.com/SVF-tools/SVF/wiki/Using-SVF-as-a-lib-in-your-own-tool) for your own project (Contributed by [Hongxu Chen](https://github.com/HongxuChen)). </b> * <b>SVF now supports LLVM-7.0.0. </b> * <b>SVF now supports Docker. [Try SVF in Docker](https://github.com/SVF-tools/SVF/wiki/Try-SVF-in-Docker)! </b> * <b>SVF now supports [LLVM-6.0.0](https://github.com/svf-tools/SVF/pull/38) (Contributed by [Jack Anthony](https://github.com/jackanth)). </b> * <b>SVF now supports [LLVM-4.0.0](https://github.com/svf-tools/SVF/pull/23) (Contributed by Jared Carlson. Thank [Jared](https://github.com/jcarlson23) and [Will](https://github.com/dtzWill) for their in-depth [discussions](https://github.com/svf-tools/SVF/pull/18) about updating SVF!) </b> * <b>SVF now supports analysis for C++ programs.</b> <br />",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -31,13 +31,13 @@
|
|
|
31
31
|
#define RCG_H_
|
|
32
32
|
|
|
33
33
|
#include "Graphs/CallGraph.h"
|
|
34
|
-
#include "MemoryModel/PointerAnalysisImpl.h"
|
|
35
34
|
|
|
36
35
|
namespace SVF
|
|
37
36
|
{
|
|
38
37
|
|
|
39
38
|
class SVFModule;
|
|
40
39
|
class ThreadAPI;
|
|
40
|
+
class PointerAnalysis;
|
|
41
41
|
/*!
|
|
42
42
|
* PTA thread fork edge from fork site to the entry of a start routine function
|
|
43
43
|
*/
|
|
@@ -201,7 +201,8 @@ public:
|
|
|
201
201
|
/// whether this call instruction has a valid call graph edge
|
|
202
202
|
inline bool hasThreadForkEdge(const CallICFGNode* cs) const
|
|
203
203
|
{
|
|
204
|
-
return callinstToThreadForkEdgesMap.find(cs) !=
|
|
204
|
+
return callinstToThreadForkEdgesMap.find(cs) !=
|
|
205
|
+
callinstToThreadForkEdgesMap.end();
|
|
205
206
|
}
|
|
206
207
|
inline ForkEdgeSet::const_iterator getForkEdgeBegin(const CallICFGNode* cs) const
|
|
207
208
|
{
|
|
@@ -345,8 +346,8 @@ public:
|
|
|
345
346
|
|
|
346
347
|
/// Add direct/indirect thread fork edges
|
|
347
348
|
//@{
|
|
348
|
-
|
|
349
|
-
|
|
349
|
+
bool addDirectForkEdge(const CallICFGNode* cs);
|
|
350
|
+
bool addIndirectForkEdge(const CallICFGNode* cs, const SVFFunction* callee);
|
|
350
351
|
//@}
|
|
351
352
|
|
|
352
353
|
/// Add thread join edges
|
|
@@ -199,6 +199,10 @@ protected:
|
|
|
199
199
|
/// On the fly call graph construction
|
|
200
200
|
virtual void onTheFlyCallGraphSolve(const CallSiteToFunPtrMap& callsites, CallEdgeMap& newEdges);
|
|
201
201
|
|
|
202
|
+
/// On the fly thread call graph construction respecting forksite
|
|
203
|
+
virtual void onTheFlyThreadCallGraphSolve(const CallSiteToFunPtrMap& callsites,
|
|
204
|
+
CallEdgeMap& newForkEdges);
|
|
205
|
+
|
|
202
206
|
/// Normalize points-to information for field-sensitive analysis,
|
|
203
207
|
/// i.e., replace fieldObj with baseObj if it is field-insensitive
|
|
204
208
|
virtual void normalizePointsTo();
|
|
@@ -457,7 +457,7 @@ inline bool isBarrierWaitCall(const CallICFGNode* cs)
|
|
|
457
457
|
|
|
458
458
|
/// Return sole argument of the thread routine
|
|
459
459
|
//@{
|
|
460
|
-
inline const
|
|
460
|
+
inline const SVFVar* getActualParmAtForkSite(const CallICFGNode* cs)
|
|
461
461
|
{
|
|
462
462
|
return ThreadAPI::getThreadAPI()->getActualParmAtForkSite(cs);
|
|
463
463
|
}
|
|
@@ -38,6 +38,7 @@ namespace SVF
|
|
|
38
38
|
class SVFModule;
|
|
39
39
|
class ICFGNode;
|
|
40
40
|
class CallICFGNode;
|
|
41
|
+
class SVFVar;
|
|
41
42
|
|
|
42
43
|
/*
|
|
43
44
|
* ThreadAPI class contains interfaces for pthread programs
|
|
@@ -128,11 +129,16 @@ public:
|
|
|
128
129
|
/// Note that, it could be function type or a void* pointer
|
|
129
130
|
const SVFValue* getForkedFun(const CallICFGNode *inst) const;
|
|
130
131
|
|
|
131
|
-
/// Return the
|
|
132
|
+
/// Return the actual param of forksite
|
|
132
133
|
/// Note that, it is the sole argument of start routine ( a void* pointer )
|
|
133
|
-
const
|
|
134
|
+
const SVFVar* getActualParmAtForkSite(const CallICFGNode *inst) const;
|
|
135
|
+
|
|
136
|
+
/// Return the formal parm of forked function (the first arg in pthread)
|
|
137
|
+
const SVFVar* getFormalParmOfForkedFun(const SVFFunction* F) const;
|
|
134
138
|
//@}
|
|
135
139
|
|
|
140
|
+
|
|
141
|
+
|
|
136
142
|
/// Return true if this call create a new thread
|
|
137
143
|
//@{
|
|
138
144
|
bool isTDFork(const CallICFGNode *inst) const;
|
|
@@ -47,6 +47,8 @@ namespace SVF
|
|
|
47
47
|
|
|
48
48
|
class SVFModule;
|
|
49
49
|
|
|
50
|
+
class ThreadCallGraph;
|
|
51
|
+
|
|
50
52
|
/*!
|
|
51
53
|
* Abstract class of inclusion-based Pointer Analysis
|
|
52
54
|
*/
|
|
@@ -54,6 +56,9 @@ typedef WPASolver<ConstraintGraph*> WPAConstraintSolver;
|
|
|
54
56
|
|
|
55
57
|
class AndersenBase: public WPAConstraintSolver, public BVDataPTAImpl
|
|
56
58
|
{
|
|
59
|
+
public:
|
|
60
|
+
typedef OrderedMap<const CallICFGNode*, NodeID> CallSite2DummyValPN;
|
|
61
|
+
|
|
57
62
|
public:
|
|
58
63
|
|
|
59
64
|
/// Constructor
|
|
@@ -81,11 +86,19 @@ public:
|
|
|
81
86
|
/// Finalize analysis
|
|
82
87
|
virtual void finalize() override;
|
|
83
88
|
|
|
84
|
-
///
|
|
85
|
-
virtual
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
+
/// Update call graph
|
|
90
|
+
virtual bool updateCallGraph(const CallSiteToFunPtrMap&) override;
|
|
91
|
+
|
|
92
|
+
/// Update thread call graph
|
|
93
|
+
virtual bool updateThreadCallGraph(const CallSiteToFunPtrMap&, NodePairSet&);
|
|
94
|
+
|
|
95
|
+
/// Connect formal and actual parameters for indirect forksites
|
|
96
|
+
virtual void connectCaller2ForkedFunParams(const CallICFGNode* cs, const SVFFunction* F,
|
|
97
|
+
NodePairSet& cpySrcNodes);
|
|
98
|
+
|
|
99
|
+
/// Connect formal and actual parameters for indirect callsites
|
|
100
|
+
virtual void connectCaller2CalleeParams(const CallICFGNode* cs, const SVFFunction* F,
|
|
101
|
+
NodePairSet& cpySrcNodes);
|
|
89
102
|
|
|
90
103
|
/// Methods for support type inquiry through isa, cast, and dyn_cast:
|
|
91
104
|
//@{
|
|
@@ -123,6 +136,9 @@ public:
|
|
|
123
136
|
}
|
|
124
137
|
//@}
|
|
125
138
|
|
|
139
|
+
/// Add copy edge on constraint graph
|
|
140
|
+
virtual inline bool addCopyEdge(NodeID src, NodeID dst) = 0;
|
|
141
|
+
|
|
126
142
|
/// dump statistics
|
|
127
143
|
inline void printStat()
|
|
128
144
|
{
|
|
@@ -160,6 +176,11 @@ public:
|
|
|
160
176
|
protected:
|
|
161
177
|
/// Constraint Graph
|
|
162
178
|
ConstraintGraph* consCG;
|
|
179
|
+
CallSite2DummyValPN
|
|
180
|
+
callsite2DummyValPN; ///< Map an instruction to a dummy obj which
|
|
181
|
+
///< created at an indirect callsite, which invokes
|
|
182
|
+
///< a heap allocator
|
|
183
|
+
void heapAllocatorViaIndCall(const CallICFGNode* cs, NodePairSet& cpySrcNodes);
|
|
163
184
|
};
|
|
164
185
|
|
|
165
186
|
/*!
|
|
@@ -171,7 +192,6 @@ class Andersen: public AndersenBase
|
|
|
171
192
|
|
|
172
193
|
public:
|
|
173
194
|
typedef SCCDetection<ConstraintGraph*> CGSCC;
|
|
174
|
-
typedef OrderedMap<const CallICFGNode*, NodeID> CallSite2DummyValPN;
|
|
175
195
|
|
|
176
196
|
/// Constructor
|
|
177
197
|
Andersen(SVFIR* _pag, PTATY type = Andersen_WPA, bool alias_check = true)
|
|
@@ -243,7 +263,6 @@ public:
|
|
|
243
263
|
protected:
|
|
244
264
|
|
|
245
265
|
CallSite2DummyValPN callsite2DummyValPN; ///< Map an instruction to a dummy obj which created at an indirect callsite, which invokes a heap allocator
|
|
246
|
-
void heapAllocatorViaIndCall(const CallICFGNode* cs,NodePairSet &cpySrcNodes);
|
|
247
266
|
|
|
248
267
|
/// Handle diff points-to set.
|
|
249
268
|
virtual inline void computeDiffPts(NodeID id)
|
|
@@ -311,12 +330,6 @@ protected:
|
|
|
311
330
|
return false;
|
|
312
331
|
}
|
|
313
332
|
|
|
314
|
-
/// Update call graph for the input indirect callsites
|
|
315
|
-
virtual bool updateCallGraph(const CallSiteToFunPtrMap& callsites);
|
|
316
|
-
|
|
317
|
-
/// Connect formal and actual parameters for indirect callsites
|
|
318
|
-
void connectCaller2CalleeParams(const CallICFGNode* cs, const SVFFunction* F, NodePairSet& cpySrcNodes);
|
|
319
|
-
|
|
320
333
|
/// Merge sub node to its rep
|
|
321
334
|
virtual void mergeNodeToRep(NodeID nodeId,NodeID newRepId);
|
|
322
335
|
|
|
@@ -23,7 +23,6 @@ class Steensgaard : public AndersenBase
|
|
|
23
23
|
public:
|
|
24
24
|
typedef Map<NodeID, NodeID> NodeToEquivClassMap;
|
|
25
25
|
typedef Map<NodeID, Set<NodeID>> NodeToSubsMap;
|
|
26
|
-
typedef OrderedMap<const CallICFGNode*, NodeID> CallSite2DummyValPN;
|
|
27
26
|
|
|
28
27
|
/// Constructor
|
|
29
28
|
Steensgaard(SVFIR* _pag) : AndersenBase(_pag, Steensgaard_WPA, true) {}
|
|
@@ -46,7 +45,7 @@ public:
|
|
|
46
45
|
steens = nullptr;
|
|
47
46
|
}
|
|
48
47
|
|
|
49
|
-
virtual void solveWorklist();
|
|
48
|
+
virtual void solveWorklist() override;
|
|
50
49
|
|
|
51
50
|
void processAllAddr();
|
|
52
51
|
|
|
@@ -69,18 +68,18 @@ public:
|
|
|
69
68
|
//@}
|
|
70
69
|
|
|
71
70
|
/// Operation of points-to set
|
|
72
|
-
virtual inline const PointsTo& getPts(NodeID id)
|
|
71
|
+
virtual inline const PointsTo& getPts(NodeID id) override
|
|
73
72
|
{
|
|
74
73
|
return getPTDataTy()->getPts(getEC(id));
|
|
75
74
|
}
|
|
76
75
|
/// pts(id) = pts(id) U target
|
|
77
|
-
virtual inline bool unionPts(NodeID id, const PointsTo& target)
|
|
76
|
+
virtual inline bool unionPts(NodeID id, const PointsTo& target) override
|
|
78
77
|
{
|
|
79
78
|
id = getEC(id);
|
|
80
79
|
return getPTDataTy()->unionPts(id, target);
|
|
81
80
|
}
|
|
82
81
|
/// pts(id) = pts(id) U pts(ptd)
|
|
83
|
-
virtual inline bool unionPts(NodeID id, NodeID ptd)
|
|
82
|
+
virtual inline bool unionPts(NodeID id, NodeID ptd) override
|
|
84
83
|
{
|
|
85
84
|
id = getEC(id);
|
|
86
85
|
ptd = getEC(ptd);
|
|
@@ -98,6 +97,11 @@ public:
|
|
|
98
97
|
else
|
|
99
98
|
return it->second;
|
|
100
99
|
}
|
|
100
|
+
/// Return getEC(id)
|
|
101
|
+
inline NodeID sccRepNode(NodeID id) const override
|
|
102
|
+
{
|
|
103
|
+
return getEC(id);
|
|
104
|
+
}
|
|
101
105
|
void setEC(NodeID node, NodeID rep);
|
|
102
106
|
|
|
103
107
|
inline Set<NodeID>& getSubNodes(NodeID id)
|
|
@@ -111,25 +115,11 @@ public:
|
|
|
111
115
|
}
|
|
112
116
|
|
|
113
117
|
/// Add copy edge on constraint graph
|
|
114
|
-
virtual inline bool addCopyEdge(NodeID src, NodeID dst)
|
|
118
|
+
virtual inline bool addCopyEdge(NodeID src, NodeID dst) override
|
|
115
119
|
{
|
|
116
120
|
return consCG->addCopyCGEdge(src, dst);
|
|
117
121
|
}
|
|
118
122
|
|
|
119
|
-
protected:
|
|
120
|
-
CallSite2DummyValPN
|
|
121
|
-
callsite2DummyValPN; ///< Map an instruction to a dummy obj which
|
|
122
|
-
///< created at an indirect callsite, which invokes
|
|
123
|
-
///< a heap allocator
|
|
124
|
-
void heapAllocatorViaIndCall(const CallICFGNode* cs, NodePairSet& cpySrcNodes);
|
|
125
|
-
|
|
126
|
-
/// Update call graph for the input indirect callsites
|
|
127
|
-
virtual bool updateCallGraph(const CallSiteToFunPtrMap& callsites);
|
|
128
|
-
|
|
129
|
-
/// Connect formal and actual parameters for indirect callsites
|
|
130
|
-
void connectCaller2CalleeParams(const CallICFGNode* cs, const SVFFunction* F,
|
|
131
|
-
NodePairSet& cpySrcNodes);
|
|
132
|
-
|
|
133
123
|
private:
|
|
134
124
|
static Steensgaard* steens; // static instance
|
|
135
125
|
NodeToEquivClassMap nodeToECMap;
|
|
@@ -51,13 +51,20 @@ public:
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
/// Type analysis
|
|
54
|
-
void analyze();
|
|
54
|
+
void analyze() override;
|
|
55
55
|
|
|
56
56
|
/// Initialize analysis
|
|
57
|
-
void initialize();
|
|
57
|
+
void initialize() override;
|
|
58
58
|
|
|
59
59
|
/// Finalize analysis
|
|
60
|
-
virtual inline void finalize();
|
|
60
|
+
virtual inline void finalize() override;
|
|
61
|
+
|
|
62
|
+
/// Add copy edge on constraint graph
|
|
63
|
+
inline bool addCopyEdge(NodeID src, NodeID dst) override
|
|
64
|
+
{
|
|
65
|
+
assert(false && "this function should never be executed!");
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
61
68
|
|
|
62
69
|
/// Resolve callgraph based on CHA
|
|
63
70
|
void callGraphSolveBasedOnCHA(const CallSiteToFunPtrMap& callsites, CallEdgeMap& newEdges);
|
|
@@ -30,6 +30,8 @@
|
|
|
30
30
|
#include "SVFIR/SVFModule.h"
|
|
31
31
|
#include "Graphs/ThreadCallGraph.h"
|
|
32
32
|
#include "Util/ThreadAPI.h"
|
|
33
|
+
#include "SVFIR/SVFIR.h"
|
|
34
|
+
#include "MemoryModel/PointerAnalysisImpl.h"
|
|
33
35
|
|
|
34
36
|
using namespace SVF;
|
|
35
37
|
using namespace SVFUtil;
|
|
@@ -119,7 +121,7 @@ void ThreadCallGraph::updateJoinEdge(PointerAnalysis* pta)
|
|
|
119
121
|
/*!
|
|
120
122
|
* Add direct fork edges
|
|
121
123
|
*/
|
|
122
|
-
|
|
124
|
+
bool ThreadCallGraph::addDirectForkEdge(const CallICFGNode* cs)
|
|
123
125
|
{
|
|
124
126
|
|
|
125
127
|
CallGraphNode* caller = getCallGraphNode(cs->getCaller());
|
|
@@ -137,13 +139,16 @@ void ThreadCallGraph::addDirectForkEdge(const CallICFGNode* cs)
|
|
|
137
139
|
|
|
138
140
|
addEdge(edge);
|
|
139
141
|
addThreadForkEdgeSetMap(cs, edge);
|
|
142
|
+
return true;
|
|
140
143
|
}
|
|
144
|
+
else
|
|
145
|
+
return false;
|
|
141
146
|
}
|
|
142
147
|
|
|
143
148
|
/*!
|
|
144
149
|
* Add indirect fork edge to update call graph
|
|
145
150
|
*/
|
|
146
|
-
|
|
151
|
+
bool ThreadCallGraph::addIndirectForkEdge(const CallICFGNode* cs, const SVFFunction* calleefun)
|
|
147
152
|
{
|
|
148
153
|
CallGraphNode* caller = getCallGraphNode(cs->getCaller());
|
|
149
154
|
CallGraphNode* callee = getCallGraphNode(calleefun);
|
|
@@ -159,7 +164,10 @@ void ThreadCallGraph::addIndirectForkEdge(const CallICFGNode* cs, const SVFFunct
|
|
|
159
164
|
|
|
160
165
|
addEdge(edge);
|
|
161
166
|
addThreadForkEdgeSetMap(cs, edge);
|
|
167
|
+
return true;
|
|
162
168
|
}
|
|
169
|
+
else
|
|
170
|
+
return false;
|
|
163
171
|
}
|
|
164
172
|
|
|
165
173
|
/*!
|
|
@@ -507,6 +507,43 @@ void BVDataPTAImpl::onTheFlyCallGraphSolve(const CallSiteToFunPtrMap& callsites,
|
|
|
507
507
|
}
|
|
508
508
|
}
|
|
509
509
|
|
|
510
|
+
/*!
|
|
511
|
+
* On the fly call graph construction respecting forksite
|
|
512
|
+
* callsites is candidate indirect callsites need to be analyzed based on points-to results
|
|
513
|
+
* newEdges is the new indirect call edges discovered
|
|
514
|
+
*/
|
|
515
|
+
void BVDataPTAImpl::onTheFlyThreadCallGraphSolve(const CallSiteToFunPtrMap& callsites,
|
|
516
|
+
CallEdgeMap& newForkEdges)
|
|
517
|
+
{
|
|
518
|
+
// add indirect fork edges
|
|
519
|
+
if(ThreadCallGraph *tdCallGraph = SVFUtil::dyn_cast<ThreadCallGraph>(callgraph))
|
|
520
|
+
{
|
|
521
|
+
for(CallSiteSet::const_iterator it = tdCallGraph->forksitesBegin(),
|
|
522
|
+
eit = tdCallGraph->forksitesEnd(); it != eit; ++it)
|
|
523
|
+
{
|
|
524
|
+
const SVFValue* forkedVal =tdCallGraph->getThreadAPI()->getForkedFun(*it);
|
|
525
|
+
if(SVFUtil::dyn_cast<SVFFunction>(forkedVal) == nullptr)
|
|
526
|
+
{
|
|
527
|
+
SVFIR *pag = this->getPAG();
|
|
528
|
+
const NodeBS targets = this->getPts(pag->getValueNode(forkedVal)).toNodeBS();
|
|
529
|
+
for(NodeBS::iterator ii = targets.begin(), ie = targets.end(); ii != ie; ++ii)
|
|
530
|
+
{
|
|
531
|
+
if(ObjVar *objPN = SVFUtil::dyn_cast<ObjVar>(pag->getGNode(*ii)))
|
|
532
|
+
{
|
|
533
|
+
const MemObj *obj = pag->getObject(objPN);
|
|
534
|
+
if(obj->isFunction())
|
|
535
|
+
{
|
|
536
|
+
const SVFFunction *svfForkedFun = SVFUtil::cast<SVFFunction>(obj->getValue());
|
|
537
|
+
if(tdCallGraph->addIndirectForkEdge(*it, svfForkedFun))
|
|
538
|
+
newForkEdges[*it].insert(svfForkedFun);
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
|
|
510
547
|
/*!
|
|
511
548
|
* Normalize points-to information for field-sensitive analysis
|
|
512
549
|
*/
|
|
@@ -172,12 +172,22 @@ const SVFValue* ThreadAPI::getForkedFun(const CallICFGNode *inst) const
|
|
|
172
172
|
return inst->getArgument(2);
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
-
|
|
176
|
-
/// Note that, it is the sole argument of start routine ( a void* pointer )
|
|
177
|
-
const SVFValue* ThreadAPI::getActualParmAtForkSite(const CallICFGNode *inst) const
|
|
175
|
+
const SVFVar* ThreadAPI::getActualParmAtForkSite(const CallICFGNode* inst) const
|
|
178
176
|
{
|
|
179
|
-
assert(
|
|
180
|
-
|
|
177
|
+
assert(PAG::getPAG()->hasCallSiteArgsMap(inst) && "forksite has no args list!");
|
|
178
|
+
const SVFIR::SVFVarList& csArgList = PAG::getPAG()->getCallSiteArgsList(inst);
|
|
179
|
+
// pthread_create has 4 parameters
|
|
180
|
+
assert(csArgList.size() == 4 && "num of forksite args is not 4");
|
|
181
|
+
return csArgList[3];
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const SVFVar* ThreadAPI::getFormalParmOfForkedFun(const SVFFunction* F) const
|
|
185
|
+
{
|
|
186
|
+
assert(PAG::getPAG()->hasFunArgsList(F) && "forked function has no args list!");
|
|
187
|
+
const SVFIR::SVFVarList& funArgList = PAG::getPAG()->getFunArgsList(F);
|
|
188
|
+
// in pthread, forked functions are of type void *()(void *args)
|
|
189
|
+
assert(funArgList.size() == 1 && "num of pthread forked function args is not 1!");
|
|
190
|
+
return funArgList[0];
|
|
181
191
|
}
|
|
182
192
|
|
|
183
193
|
const SVFValue* ThreadAPI::getRetParmAtJoinedSite(const CallICFGNode *inst) const
|
package/svf/lib/WPA/Andersen.cpp
CHANGED
|
@@ -187,6 +187,211 @@ void AndersenBase::cleanConsCG(NodeID id)
|
|
|
187
187
|
assert(!consCG->hasGNode(id) && "this is either a rep nodeid or a sub nodeid should have already been merged to its field-insensitive base! ");
|
|
188
188
|
}
|
|
189
189
|
|
|
190
|
+
bool AndersenBase::updateCallGraph(const CallSiteToFunPtrMap& callsites)
|
|
191
|
+
{
|
|
192
|
+
|
|
193
|
+
double cgUpdateStart = stat->getClk();
|
|
194
|
+
|
|
195
|
+
CallEdgeMap newEdges;
|
|
196
|
+
onTheFlyCallGraphSolve(callsites, newEdges);
|
|
197
|
+
NodePairSet cpySrcNodes; /// nodes as a src of a generated new copy edge
|
|
198
|
+
for (CallEdgeMap::iterator it = newEdges.begin(), eit = newEdges.end();
|
|
199
|
+
it != eit; ++it)
|
|
200
|
+
{
|
|
201
|
+
for (FunctionSet::iterator cit = it->second.begin(),
|
|
202
|
+
ecit = it->second.end();
|
|
203
|
+
cit != ecit; ++cit)
|
|
204
|
+
{
|
|
205
|
+
connectCaller2CalleeParams(it->first, *cit, cpySrcNodes);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
bool hasNewForkEdges = updateThreadCallGraph(callsites, cpySrcNodes);
|
|
210
|
+
|
|
211
|
+
for (NodePairSet::iterator it = cpySrcNodes.begin(),
|
|
212
|
+
eit = cpySrcNodes.end();
|
|
213
|
+
it != eit; ++it)
|
|
214
|
+
{
|
|
215
|
+
pushIntoWorklist(it->first);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
double cgUpdateEnd = stat->getClk();
|
|
219
|
+
timeOfUpdateCallGraph += (cgUpdateEnd - cgUpdateStart) / TIMEINTERVAL;
|
|
220
|
+
|
|
221
|
+
return ((!newEdges.empty()) || hasNewForkEdges);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
bool AndersenBase::updateThreadCallGraph(const CallSiteToFunPtrMap& callsites,
|
|
225
|
+
NodePairSet& cpySrcNodes)
|
|
226
|
+
{
|
|
227
|
+
CallEdgeMap newForkEdges;
|
|
228
|
+
onTheFlyThreadCallGraphSolve(callsites, newForkEdges);
|
|
229
|
+
for (CallEdgeMap::iterator it = newForkEdges.begin(), eit = newForkEdges.end(); it != eit; it++)
|
|
230
|
+
{
|
|
231
|
+
for (FunctionSet::iterator cit = it->second.begin(),
|
|
232
|
+
ecit = it->second.end();
|
|
233
|
+
cit != ecit; ++cit)
|
|
234
|
+
{
|
|
235
|
+
connectCaller2ForkedFunParams(it->first, *cit, cpySrcNodes);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return !newForkEdges.empty();
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/*!
|
|
242
|
+
* Connect formal and actual parameters for indirect forksites
|
|
243
|
+
*/
|
|
244
|
+
void AndersenBase::connectCaller2ForkedFunParams(const CallICFGNode* cs, const SVFFunction* F,
|
|
245
|
+
NodePairSet& cpySrcNodes)
|
|
246
|
+
{
|
|
247
|
+
assert(F);
|
|
248
|
+
|
|
249
|
+
DBOUT(DAndersen, outs() << "connect parameters from indirect forksite "
|
|
250
|
+
<< cs.getInstruction()->toString() << " to forked function "
|
|
251
|
+
<< *F << "\n");
|
|
252
|
+
|
|
253
|
+
ThreadCallGraph *tdCallGraph = SVFUtil::dyn_cast<ThreadCallGraph>(callgraph);
|
|
254
|
+
|
|
255
|
+
const PAGNode *cs_arg = tdCallGraph->getThreadAPI()->getActualParmAtForkSite(cs);
|
|
256
|
+
const PAGNode *fun_arg = tdCallGraph->getThreadAPI()->getFormalParmOfForkedFun(F);
|
|
257
|
+
|
|
258
|
+
if(cs_arg->isPointer() && fun_arg->isPointer())
|
|
259
|
+
{
|
|
260
|
+
DBOUT(DAndersen, outs() << "process actual parm"
|
|
261
|
+
<< cs_arg->toString() << "\n");
|
|
262
|
+
NodeID srcAA = sccRepNode(cs_arg->getId());
|
|
263
|
+
NodeID dstFA = sccRepNode(fun_arg->getId());
|
|
264
|
+
if (addCopyEdge(srcAA, dstFA))
|
|
265
|
+
{
|
|
266
|
+
cpySrcNodes.insert(std::make_pair(srcAA, dstFA));
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
///*!
|
|
272
|
+
// * Connect formal and actual parameters for indirect callsites
|
|
273
|
+
// */
|
|
274
|
+
void AndersenBase::connectCaller2CalleeParams(const CallICFGNode* cs,
|
|
275
|
+
const SVFFunction* F, NodePairSet &cpySrcNodes)
|
|
276
|
+
{
|
|
277
|
+
assert(F);
|
|
278
|
+
|
|
279
|
+
DBOUT(DAndersen, outs() << "connect parameters from indirect callsite " <<
|
|
280
|
+
cs.getInstruction()->toString() << " to callee " << *F << "\n");
|
|
281
|
+
|
|
282
|
+
const CallICFGNode* callBlockNode = cs;
|
|
283
|
+
const RetICFGNode* retBlockNode = cs->getRetICFGNode();
|
|
284
|
+
|
|
285
|
+
if(SVFUtil::isHeapAllocExtFunViaRet(F) && pag->callsiteHasRet(retBlockNode))
|
|
286
|
+
{
|
|
287
|
+
heapAllocatorViaIndCall(cs,cpySrcNodes);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
if (pag->funHasRet(F) && pag->callsiteHasRet(retBlockNode))
|
|
291
|
+
{
|
|
292
|
+
const PAGNode* cs_return = pag->getCallSiteRet(retBlockNode);
|
|
293
|
+
const PAGNode* fun_return = pag->getFunRet(F);
|
|
294
|
+
if (cs_return->isPointer() && fun_return->isPointer())
|
|
295
|
+
{
|
|
296
|
+
NodeID dstrec = sccRepNode(cs_return->getId());
|
|
297
|
+
NodeID srcret = sccRepNode(fun_return->getId());
|
|
298
|
+
if(addCopyEdge(srcret, dstrec))
|
|
299
|
+
{
|
|
300
|
+
cpySrcNodes.insert(std::make_pair(srcret,dstrec));
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
else
|
|
304
|
+
{
|
|
305
|
+
DBOUT(DAndersen, outs() << "not a pointer ignored\n");
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
if (pag->hasCallSiteArgsMap(callBlockNode) && pag->hasFunArgsList(F))
|
|
310
|
+
{
|
|
311
|
+
|
|
312
|
+
// connect actual and formal param
|
|
313
|
+
const SVFIR::SVFVarList& csArgList = pag->getCallSiteArgsList(callBlockNode);
|
|
314
|
+
const SVFIR::SVFVarList& funArgList = pag->getFunArgsList(F);
|
|
315
|
+
//Go through the fixed parameters.
|
|
316
|
+
DBOUT(DPAGBuild, outs() << " args:");
|
|
317
|
+
SVFIR::SVFVarList::const_iterator funArgIt = funArgList.begin(), funArgEit = funArgList.end();
|
|
318
|
+
SVFIR::SVFVarList::const_iterator csArgIt = csArgList.begin(), csArgEit = csArgList.end();
|
|
319
|
+
for (; funArgIt != funArgEit; ++csArgIt, ++funArgIt)
|
|
320
|
+
{
|
|
321
|
+
//Some programs (e.g. Linux kernel) leave unneeded parameters empty.
|
|
322
|
+
if (csArgIt == csArgEit)
|
|
323
|
+
{
|
|
324
|
+
DBOUT(DAndersen, outs() << " !! not enough args\n");
|
|
325
|
+
break;
|
|
326
|
+
}
|
|
327
|
+
const PAGNode *cs_arg = *csArgIt ;
|
|
328
|
+
const PAGNode *fun_arg = *funArgIt;
|
|
329
|
+
|
|
330
|
+
if (cs_arg->isPointer() && fun_arg->isPointer())
|
|
331
|
+
{
|
|
332
|
+
DBOUT(DAndersen, outs() << "process actual parm " << cs_arg->toString() << " \n");
|
|
333
|
+
NodeID srcAA = sccRepNode(cs_arg->getId());
|
|
334
|
+
NodeID dstFA = sccRepNode(fun_arg->getId());
|
|
335
|
+
if(addCopyEdge(srcAA, dstFA))
|
|
336
|
+
{
|
|
337
|
+
cpySrcNodes.insert(std::make_pair(srcAA,dstFA));
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
//Any remaining actual args must be varargs.
|
|
343
|
+
if (F->isVarArg())
|
|
344
|
+
{
|
|
345
|
+
NodeID vaF = sccRepNode(pag->getVarargNode(F));
|
|
346
|
+
DBOUT(DPAGBuild, outs() << "\n varargs:");
|
|
347
|
+
for (; csArgIt != csArgEit; ++csArgIt)
|
|
348
|
+
{
|
|
349
|
+
const PAGNode *cs_arg = *csArgIt;
|
|
350
|
+
if (cs_arg->isPointer())
|
|
351
|
+
{
|
|
352
|
+
NodeID vnAA = sccRepNode(cs_arg->getId());
|
|
353
|
+
if (addCopyEdge(vnAA,vaF))
|
|
354
|
+
{
|
|
355
|
+
cpySrcNodes.insert(std::make_pair(vnAA,vaF));
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
if(csArgIt != csArgEit)
|
|
361
|
+
{
|
|
362
|
+
writeWrnMsg("too many args to non-vararg func.");
|
|
363
|
+
writeWrnMsg("(" + cs->getSourceLoc() + ")");
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
void AndersenBase::heapAllocatorViaIndCall(const CallICFGNode* cs, NodePairSet &cpySrcNodes)
|
|
369
|
+
{
|
|
370
|
+
assert(cs->getCalledFunction() == nullptr && "not an indirect callsite?");
|
|
371
|
+
const RetICFGNode* retBlockNode = cs->getRetICFGNode();
|
|
372
|
+
const PAGNode* cs_return = pag->getCallSiteRet(retBlockNode);
|
|
373
|
+
NodeID srcret;
|
|
374
|
+
CallSite2DummyValPN::const_iterator it = callsite2DummyValPN.find(cs);
|
|
375
|
+
if(it != callsite2DummyValPN.end())
|
|
376
|
+
{
|
|
377
|
+
srcret = sccRepNode(it->second);
|
|
378
|
+
}
|
|
379
|
+
else
|
|
380
|
+
{
|
|
381
|
+
NodeID valNode = pag->addDummyValNode();
|
|
382
|
+
NodeID objNode = pag->addDummyObjNode(cs->getCallSite()->getType());
|
|
383
|
+
addPts(valNode,objNode);
|
|
384
|
+
callsite2DummyValPN.insert(std::make_pair(cs,valNode));
|
|
385
|
+
consCG->addConstraintNode(new ConstraintNode(valNode),valNode);
|
|
386
|
+
consCG->addConstraintNode(new ConstraintNode(objNode),objNode);
|
|
387
|
+
srcret = valNode;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
NodeID dstrec = sccRepNode(cs_return->getId());
|
|
391
|
+
if(addCopyEdge(srcret, dstrec))
|
|
392
|
+
cpySrcNodes.insert(std::make_pair(srcret,dstrec));
|
|
393
|
+
}
|
|
394
|
+
|
|
190
395
|
void AndersenBase::normalizePointsTo()
|
|
191
396
|
{
|
|
192
397
|
SVFIR::MemObjToFieldsMap &memToFieldsMap = pag->getMemToFieldsMap();
|
|
@@ -648,157 +853,6 @@ NodeStack& Andersen::SCCDetect()
|
|
|
648
853
|
return getSCCDetector()->topoNodeStack();
|
|
649
854
|
}
|
|
650
855
|
|
|
651
|
-
/*!
|
|
652
|
-
* Update call graph for the input indirect callsites
|
|
653
|
-
*/
|
|
654
|
-
bool Andersen::updateCallGraph(const CallSiteToFunPtrMap& callsites)
|
|
655
|
-
{
|
|
656
|
-
|
|
657
|
-
double cgUpdateStart = stat->getClk();
|
|
658
|
-
|
|
659
|
-
CallEdgeMap newEdges;
|
|
660
|
-
onTheFlyCallGraphSolve(callsites,newEdges);
|
|
661
|
-
NodePairSet cpySrcNodes; /// nodes as a src of a generated new copy edge
|
|
662
|
-
for(CallEdgeMap::iterator it = newEdges.begin(), eit = newEdges.end(); it!=eit; ++it )
|
|
663
|
-
{
|
|
664
|
-
for(FunctionSet::iterator cit = it->second.begin(), ecit = it->second.end(); cit!=ecit; ++cit)
|
|
665
|
-
{
|
|
666
|
-
connectCaller2CalleeParams(it->first,*cit,cpySrcNodes);
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
for(NodePairSet::iterator it = cpySrcNodes.begin(), eit = cpySrcNodes.end(); it!=eit; ++it)
|
|
670
|
-
{
|
|
671
|
-
pushIntoWorklist(it->first);
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
double cgUpdateEnd = stat->getClk();
|
|
675
|
-
timeOfUpdateCallGraph += (cgUpdateEnd - cgUpdateStart) / TIMEINTERVAL;
|
|
676
|
-
|
|
677
|
-
return (!newEdges.empty());
|
|
678
|
-
}
|
|
679
|
-
|
|
680
|
-
void Andersen::heapAllocatorViaIndCall(const CallICFGNode* cs, NodePairSet &cpySrcNodes)
|
|
681
|
-
{
|
|
682
|
-
assert(cs->getCalledFunction() == nullptr && "not an indirect callsite?");
|
|
683
|
-
const RetICFGNode* retBlockNode = cs->getRetICFGNode();
|
|
684
|
-
const PAGNode* cs_return = pag->getCallSiteRet(retBlockNode);
|
|
685
|
-
NodeID srcret;
|
|
686
|
-
CallSite2DummyValPN::const_iterator it = callsite2DummyValPN.find(cs);
|
|
687
|
-
if(it != callsite2DummyValPN.end())
|
|
688
|
-
{
|
|
689
|
-
srcret = sccRepNode(it->second);
|
|
690
|
-
}
|
|
691
|
-
else
|
|
692
|
-
{
|
|
693
|
-
NodeID valNode = pag->addDummyValNode();
|
|
694
|
-
NodeID objNode = pag->addDummyObjNode(cs->getCallSite()->getType());
|
|
695
|
-
addPts(valNode,objNode);
|
|
696
|
-
callsite2DummyValPN.insert(std::make_pair(cs,valNode));
|
|
697
|
-
consCG->addConstraintNode(new ConstraintNode(valNode),valNode);
|
|
698
|
-
consCG->addConstraintNode(new ConstraintNode(objNode),objNode);
|
|
699
|
-
srcret = valNode;
|
|
700
|
-
}
|
|
701
|
-
|
|
702
|
-
NodeID dstrec = sccRepNode(cs_return->getId());
|
|
703
|
-
if(addCopyEdge(srcret, dstrec))
|
|
704
|
-
cpySrcNodes.insert(std::make_pair(srcret,dstrec));
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
/*!
|
|
708
|
-
* Connect formal and actual parameters for indirect callsites
|
|
709
|
-
*/
|
|
710
|
-
void Andersen::connectCaller2CalleeParams(const CallICFGNode* cs, const SVFFunction* F, NodePairSet &cpySrcNodes)
|
|
711
|
-
{
|
|
712
|
-
assert(F);
|
|
713
|
-
|
|
714
|
-
DBOUT(DAndersen, outs() << "connect parameters from indirect callsite " << cs.getInstruction()->toString() << " to callee " << *F << "\n");
|
|
715
|
-
|
|
716
|
-
const CallICFGNode* callBlockNode = cs;
|
|
717
|
-
const RetICFGNode* retBlockNode = cs->getRetICFGNode();
|
|
718
|
-
|
|
719
|
-
if(SVFUtil::isHeapAllocExtFunViaRet(F) && pag->callsiteHasRet(retBlockNode))
|
|
720
|
-
{
|
|
721
|
-
heapAllocatorViaIndCall(cs,cpySrcNodes);
|
|
722
|
-
}
|
|
723
|
-
|
|
724
|
-
if (pag->funHasRet(F) && pag->callsiteHasRet(retBlockNode))
|
|
725
|
-
{
|
|
726
|
-
const PAGNode* cs_return = pag->getCallSiteRet(retBlockNode);
|
|
727
|
-
const PAGNode* fun_return = pag->getFunRet(F);
|
|
728
|
-
if (cs_return->isPointer() && fun_return->isPointer())
|
|
729
|
-
{
|
|
730
|
-
NodeID dstrec = sccRepNode(cs_return->getId());
|
|
731
|
-
NodeID srcret = sccRepNode(fun_return->getId());
|
|
732
|
-
if(addCopyEdge(srcret, dstrec))
|
|
733
|
-
{
|
|
734
|
-
cpySrcNodes.insert(std::make_pair(srcret,dstrec));
|
|
735
|
-
}
|
|
736
|
-
}
|
|
737
|
-
else
|
|
738
|
-
{
|
|
739
|
-
DBOUT(DAndersen, outs() << "not a pointer ignored\n");
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
|
|
743
|
-
if (pag->hasCallSiteArgsMap(callBlockNode) && pag->hasFunArgsList(F))
|
|
744
|
-
{
|
|
745
|
-
|
|
746
|
-
// connect actual and formal param
|
|
747
|
-
const SVFIR::SVFVarList& csArgList = pag->getCallSiteArgsList(callBlockNode);
|
|
748
|
-
const SVFIR::SVFVarList& funArgList = pag->getFunArgsList(F);
|
|
749
|
-
//Go through the fixed parameters.
|
|
750
|
-
DBOUT(DPAGBuild, outs() << " args:");
|
|
751
|
-
SVFIR::SVFVarList::const_iterator funArgIt = funArgList.begin(), funArgEit = funArgList.end();
|
|
752
|
-
SVFIR::SVFVarList::const_iterator csArgIt = csArgList.begin(), csArgEit = csArgList.end();
|
|
753
|
-
for (; funArgIt != funArgEit; ++csArgIt, ++funArgIt)
|
|
754
|
-
{
|
|
755
|
-
//Some programs (e.g. Linux kernel) leave unneeded parameters empty.
|
|
756
|
-
if (csArgIt == csArgEit)
|
|
757
|
-
{
|
|
758
|
-
DBOUT(DAndersen, outs() << " !! not enough args\n");
|
|
759
|
-
break;
|
|
760
|
-
}
|
|
761
|
-
const PAGNode *cs_arg = *csArgIt ;
|
|
762
|
-
const PAGNode *fun_arg = *funArgIt;
|
|
763
|
-
|
|
764
|
-
if (cs_arg->isPointer() && fun_arg->isPointer())
|
|
765
|
-
{
|
|
766
|
-
DBOUT(DAndersen, outs() << "process actual parm " << cs_arg->toString() << " \n");
|
|
767
|
-
NodeID srcAA = sccRepNode(cs_arg->getId());
|
|
768
|
-
NodeID dstFA = sccRepNode(fun_arg->getId());
|
|
769
|
-
if(addCopyEdge(srcAA, dstFA))
|
|
770
|
-
{
|
|
771
|
-
cpySrcNodes.insert(std::make_pair(srcAA,dstFA));
|
|
772
|
-
}
|
|
773
|
-
}
|
|
774
|
-
}
|
|
775
|
-
|
|
776
|
-
//Any remaining actual args must be varargs.
|
|
777
|
-
if (F->isVarArg())
|
|
778
|
-
{
|
|
779
|
-
NodeID vaF = sccRepNode(pag->getVarargNode(F));
|
|
780
|
-
DBOUT(DPAGBuild, outs() << "\n varargs:");
|
|
781
|
-
for (; csArgIt != csArgEit; ++csArgIt)
|
|
782
|
-
{
|
|
783
|
-
const PAGNode *cs_arg = *csArgIt;
|
|
784
|
-
if (cs_arg->isPointer())
|
|
785
|
-
{
|
|
786
|
-
NodeID vnAA = sccRepNode(cs_arg->getId());
|
|
787
|
-
if (addCopyEdge(vnAA,vaF))
|
|
788
|
-
{
|
|
789
|
-
cpySrcNodes.insert(std::make_pair(vnAA,vaF));
|
|
790
|
-
}
|
|
791
|
-
}
|
|
792
|
-
}
|
|
793
|
-
}
|
|
794
|
-
if(csArgIt != csArgEit)
|
|
795
|
-
{
|
|
796
|
-
writeWrnMsg("too many args to non-vararg func.");
|
|
797
|
-
writeWrnMsg("(" + cs->getSourceLoc() + ")");
|
|
798
|
-
}
|
|
799
|
-
}
|
|
800
|
-
}
|
|
801
|
-
|
|
802
856
|
/*!
|
|
803
857
|
* merge nodeId to newRepId. Return true if the newRepId is a PWC node
|
|
804
858
|
*/
|
|
@@ -122,166 +122,4 @@ void Steensgaard::processAllAddr()
|
|
|
122
122
|
pushIntoWorklist(dst);
|
|
123
123
|
}
|
|
124
124
|
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
bool Steensgaard::updateCallGraph(const CallSiteToFunPtrMap& callsites)
|
|
128
|
-
{
|
|
129
|
-
|
|
130
|
-
double cgUpdateStart = stat->getClk();
|
|
131
|
-
|
|
132
|
-
CallEdgeMap newEdges;
|
|
133
|
-
onTheFlyCallGraphSolve(callsites, newEdges);
|
|
134
|
-
NodePairSet cpySrcNodes; /// nodes as a src of a generated new copy edge
|
|
135
|
-
for (CallEdgeMap::iterator it = newEdges.begin(), eit = newEdges.end();
|
|
136
|
-
it != eit; ++it)
|
|
137
|
-
{
|
|
138
|
-
for (FunctionSet::iterator cit = it->second.begin(),
|
|
139
|
-
ecit = it->second.end();
|
|
140
|
-
cit != ecit; ++cit)
|
|
141
|
-
{
|
|
142
|
-
connectCaller2CalleeParams(it->first, *cit, cpySrcNodes);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
for (NodePairSet::iterator it = cpySrcNodes.begin(),
|
|
146
|
-
eit = cpySrcNodes.end();
|
|
147
|
-
it != eit; ++it)
|
|
148
|
-
{
|
|
149
|
-
pushIntoWorklist(it->first);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
double cgUpdateEnd = stat->getClk();
|
|
153
|
-
timeOfUpdateCallGraph += (cgUpdateEnd - cgUpdateStart) / TIMEINTERVAL;
|
|
154
|
-
|
|
155
|
-
return (!newEdges.empty());
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
void Steensgaard::heapAllocatorViaIndCall(const CallICFGNode* cs, NodePairSet& cpySrcNodes)
|
|
159
|
-
{
|
|
160
|
-
assert(cs->getCalledFunction() == nullptr && "not an indirect callsite?");
|
|
161
|
-
const RetICFGNode* retBlockNode = cs->getRetICFGNode();
|
|
162
|
-
const PAGNode* cs_return = pag->getCallSiteRet(retBlockNode);
|
|
163
|
-
NodeID srcret;
|
|
164
|
-
CallSite2DummyValPN::const_iterator it = callsite2DummyValPN.find(cs);
|
|
165
|
-
if (it != callsite2DummyValPN.end())
|
|
166
|
-
{
|
|
167
|
-
srcret = getEC(it->second);
|
|
168
|
-
}
|
|
169
|
-
else
|
|
170
|
-
{
|
|
171
|
-
NodeID valNode = pag->addDummyValNode();
|
|
172
|
-
NodeID objNode = pag->addDummyObjNode(cs->getCallSite()->getType());
|
|
173
|
-
addPts(valNode, objNode);
|
|
174
|
-
callsite2DummyValPN.insert(std::make_pair(cs, valNode));
|
|
175
|
-
consCG->addConstraintNode(new ConstraintNode(valNode), valNode);
|
|
176
|
-
consCG->addConstraintNode(new ConstraintNode(objNode), objNode);
|
|
177
|
-
srcret = valNode;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
NodeID dstrec = getEC(cs_return->getId());
|
|
181
|
-
if (addCopyEdge(srcret, dstrec))
|
|
182
|
-
cpySrcNodes.insert(std::make_pair(srcret, dstrec));
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/*!
|
|
186
|
-
* Connect formal and actual parameters for indirect callsites
|
|
187
|
-
*/
|
|
188
|
-
void Steensgaard::connectCaller2CalleeParams(const CallICFGNode* cs, const SVFFunction* F,
|
|
189
|
-
NodePairSet& cpySrcNodes)
|
|
190
|
-
{
|
|
191
|
-
assert(F);
|
|
192
|
-
|
|
193
|
-
DBOUT(DAndersen, outs() << "connect parameters from indirect callsite "
|
|
194
|
-
<< cs.getInstruction()->toString() << " to callee "
|
|
195
|
-
<< *F << "\n");
|
|
196
|
-
|
|
197
|
-
const CallICFGNode* callBlockNode = cs;
|
|
198
|
-
const RetICFGNode* retBlockNode = cs->getRetICFGNode();
|
|
199
|
-
|
|
200
|
-
if (SVFUtil::isHeapAllocExtFunViaRet(F) &&
|
|
201
|
-
pag->callsiteHasRet(retBlockNode))
|
|
202
|
-
{
|
|
203
|
-
heapAllocatorViaIndCall(cs, cpySrcNodes);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
if (pag->funHasRet(F) && pag->callsiteHasRet(retBlockNode))
|
|
207
|
-
{
|
|
208
|
-
const PAGNode* cs_return = pag->getCallSiteRet(retBlockNode);
|
|
209
|
-
const PAGNode* fun_return = pag->getFunRet(F);
|
|
210
|
-
if (cs_return->isPointer() && fun_return->isPointer())
|
|
211
|
-
{
|
|
212
|
-
NodeID dstrec = getEC(cs_return->getId());
|
|
213
|
-
NodeID srcret = getEC(fun_return->getId());
|
|
214
|
-
if (addCopyEdge(srcret, dstrec))
|
|
215
|
-
{
|
|
216
|
-
cpySrcNodes.insert(std::make_pair(srcret, dstrec));
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
else
|
|
220
|
-
{
|
|
221
|
-
DBOUT(DAndersen, outs() << "not a pointer ignored\n");
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
if (pag->hasCallSiteArgsMap(callBlockNode) && pag->hasFunArgsList(F))
|
|
226
|
-
{
|
|
227
|
-
|
|
228
|
-
// connect actual and formal param
|
|
229
|
-
const SVFIR::SVFVarList& csArgList =
|
|
230
|
-
pag->getCallSiteArgsList(callBlockNode);
|
|
231
|
-
const SVFIR::SVFVarList& funArgList = pag->getFunArgsList(F);
|
|
232
|
-
// Go through the fixed parameters.
|
|
233
|
-
DBOUT(DPAGBuild, outs() << " args:");
|
|
234
|
-
SVFIR::SVFVarList::const_iterator funArgIt = funArgList.begin(),
|
|
235
|
-
funArgEit = funArgList.end();
|
|
236
|
-
SVFIR::SVFVarList::const_iterator csArgIt = csArgList.begin(),
|
|
237
|
-
csArgEit = csArgList.end();
|
|
238
|
-
for (; funArgIt != funArgEit; ++csArgIt, ++funArgIt)
|
|
239
|
-
{
|
|
240
|
-
// Some programs (e.g. Linux kernel) leave unneeded parameters
|
|
241
|
-
// empty.
|
|
242
|
-
if (csArgIt == csArgEit)
|
|
243
|
-
{
|
|
244
|
-
DBOUT(DAndersen, outs() << " !! not enough args\n");
|
|
245
|
-
break;
|
|
246
|
-
}
|
|
247
|
-
const PAGNode* cs_arg = *csArgIt;
|
|
248
|
-
const PAGNode* fun_arg = *funArgIt;
|
|
249
|
-
|
|
250
|
-
if (cs_arg->isPointer() && fun_arg->isPointer())
|
|
251
|
-
{
|
|
252
|
-
DBOUT(DAndersen, outs() << "process actual parm "
|
|
253
|
-
<< cs_arg->toString() << " \n");
|
|
254
|
-
NodeID srcAA = getEC(cs_arg->getId());
|
|
255
|
-
NodeID dstFA = getEC(fun_arg->getId());
|
|
256
|
-
if (addCopyEdge(srcAA, dstFA))
|
|
257
|
-
{
|
|
258
|
-
cpySrcNodes.insert(std::make_pair(srcAA, dstFA));
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
// Any remaining actual args must be varargs.
|
|
264
|
-
if (F->isVarArg())
|
|
265
|
-
{
|
|
266
|
-
NodeID vaF = getEC(pag->getVarargNode(F));
|
|
267
|
-
DBOUT(DPAGBuild, outs() << "\n varargs:");
|
|
268
|
-
for (; csArgIt != csArgEit; ++csArgIt)
|
|
269
|
-
{
|
|
270
|
-
const PAGNode* cs_arg = *csArgIt;
|
|
271
|
-
if (cs_arg->isPointer())
|
|
272
|
-
{
|
|
273
|
-
NodeID vnAA = getEC(cs_arg->getId());
|
|
274
|
-
if (addCopyEdge(vnAA, vaF))
|
|
275
|
-
{
|
|
276
|
-
cpySrcNodes.insert(std::make_pair(vnAA, vaF));
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
if (csArgIt != csArgEit)
|
|
282
|
-
{
|
|
283
|
-
writeWrnMsg("too many args to non-vararg func.");
|
|
284
|
-
writeWrnMsg("(" + cs->getSourceLoc() + ")");
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
}
|
|
125
|
+
}
|
|
@@ -259,7 +259,7 @@ void SVFIRBuilder::handleExtCall(const CallBase* cs, const SVFFunction* svfCalle
|
|
|
259
259
|
if (const SVFFunction* forkedFun = SVFUtil::dyn_cast<SVFFunction>(getForkedFun(callICFGNode)))
|
|
260
260
|
{
|
|
261
261
|
forkedFun = forkedFun->getDefFunForMultipleModule();
|
|
262
|
-
const
|
|
262
|
+
const SVFVar* actualParm = getActualParmAtForkSite(callICFGNode);
|
|
263
263
|
/// pthread_create has 1 arg.
|
|
264
264
|
/// apr_thread_create has 2 arg.
|
|
265
265
|
assert((forkedFun->arg_size() <= 2) && "Size of formal parameter of start routine should be one");
|
|
@@ -267,10 +267,10 @@ void SVFIRBuilder::handleExtCall(const CallBase* cs, const SVFFunction* svfCalle
|
|
|
267
267
|
{
|
|
268
268
|
const SVFArgument* formalParm = forkedFun->getArg(0);
|
|
269
269
|
/// Connect actual parameter to formal parameter of the start routine
|
|
270
|
-
if (actualParm->
|
|
270
|
+
if (actualParm->isPointer() && formalParm->getType()->isPointerTy())
|
|
271
271
|
{
|
|
272
272
|
FunEntryICFGNode *entry = pag->getICFG()->getFunEntryICFGNode(forkedFun);
|
|
273
|
-
addThreadForkEdge(
|
|
273
|
+
addThreadForkEdge(actualParm->getId(), pag->getValueNode(formalParm), callICFGNode, entry);
|
|
274
274
|
}
|
|
275
275
|
}
|
|
276
276
|
}
|