svf-tools 1.0.689 → 1.0.690

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svf-tools",
3
- "version": "1.0.689",
3
+ "version": "1.0.690",
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": {
@@ -17,24 +17,21 @@ namespace SVF
17
17
  */
18
18
  typedef WPASolver<ConstraintGraph*> WPAConstraintSolver;
19
19
 
20
- class Steensgaard: public AndersenBase
20
+ class Steensgaard : public AndersenBase
21
21
  {
22
22
 
23
23
  public:
24
-
25
24
  typedef Map<NodeID, NodeID> NodeToEquivClassMap;
26
25
  typedef Map<NodeID, Set<NodeID>> NodeToSubsMap;
26
+ typedef OrderedMap<CallSite, NodeID> CallSite2DummyValPN;
27
27
 
28
28
  /// Constructor
29
- Steensgaard(SVFIR* _pag)
30
- : AndersenBase(_pag, Steensgaard_WPA, true)
31
- {
32
- }
29
+ Steensgaard(SVFIR* _pag) : AndersenBase(_pag, Steensgaard_WPA, true) {}
33
30
 
34
31
  /// Create an singleton instance
35
32
  static Steensgaard* createSteensgaard(SVFIR* _pag)
36
33
  {
37
- if(steens==nullptr)
34
+ if (steens == nullptr)
38
35
  {
39
36
  steens = new Steensgaard(_pag);
40
37
  steens->analyze();
@@ -57,15 +54,15 @@ public:
57
54
 
58
55
  /// Methods for support type inquiry through isa, cast, and dyn_cast:
59
56
  //@{
60
- static inline bool classof(const Steensgaard *)
57
+ static inline bool classof(const Steensgaard*)
61
58
  {
62
59
  return true;
63
60
  }
64
- static inline bool classof(const AndersenBase *pta)
61
+ static inline bool classof(const AndersenBase* pta)
65
62
  {
66
63
  return (pta->getAnalysisTy() == Steensgaard_WPA);
67
64
  }
68
- static inline bool classof(const PointerAnalysis *pta)
65
+ static inline bool classof(const PointerAnalysis* pta)
69
66
  {
70
67
  return (pta->getAnalysisTy() == Steensgaard_WPA);
71
68
  }
@@ -87,7 +84,7 @@ public:
87
84
  {
88
85
  id = getEC(id);
89
86
  ptd = getEC(ptd);
90
- return getPTDataTy()->unionPts(id,ptd);
87
+ return getPTDataTy()->unionPts(id, ptd);
91
88
  }
92
89
 
93
90
  /// API for equivalence class operations
@@ -96,7 +93,7 @@ public:
96
93
  inline NodeID getEC(NodeID id) const
97
94
  {
98
95
  NodeToEquivClassMap::const_iterator it = nodeToECMap.find(id);
99
- if(it==nodeToECMap.end())
96
+ if (it == nodeToECMap.end())
100
97
  return id;
101
98
  else
102
99
  return it->second;
@@ -113,14 +110,32 @@ public:
113
110
  nodeToSubsMap[node].insert(sub);
114
111
  }
115
112
 
116
- private:
113
+ /// Add copy edge on constraint graph
114
+ virtual inline bool addCopyEdge(NodeID src, NodeID dst)
115
+ {
116
+ return consCG->addCopyCGEdge(src, dst);
117
+ }
117
118
 
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(CallSite 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(CallSite cs, const SVFFunction* F,
131
+ NodePairSet& cpySrcNodes);
132
+
133
+ private:
118
134
  static Steensgaard* steens; // static instance
119
135
  NodeToEquivClassMap nodeToECMap;
120
136
  NodeToSubsMap nodeToSubsMap;
121
137
  };
122
138
 
123
- } /// end of the namespace
124
-
139
+ } // namespace SVF
125
140
 
126
141
  #endif /* INCLUDE_WPA_STEENSGAARD_H_ */
@@ -1,4 +1,5 @@
1
- //===- Steensgaard.cpp -- Steensgaard's field-insensitive analysis--------------//
1
+ //===- Steensgaard.cpp -- Steensgaard's field-insensitive
2
+ // analysis--------------//
2
3
  //
3
4
  // SVF: Static Value-Flow Analysis
4
5
  //
@@ -32,7 +33,7 @@
32
33
  using namespace SVF;
33
34
  using namespace SVFUtil;
34
35
 
35
- Steensgaard *Steensgaard::steens = nullptr;
36
+ Steensgaard* Steensgaard::steens = nullptr;
36
37
 
37
38
  /*!
38
39
  * Steensgaard analysis
@@ -50,7 +51,7 @@ void Steensgaard::solveWorklist()
50
51
  ConstraintNode* node = consCG->getConstraintNode(nodeId);
51
52
 
52
53
  /// foreach o \in pts(p)
53
- for(NodeID o : getPts(nodeId))
54
+ for (NodeID o : getPts(nodeId))
54
55
  {
55
56
 
56
57
  /// *p = q : EC(o) == EC(q)
@@ -68,36 +69,34 @@ void Steensgaard::solveWorklist()
68
69
  /// q = p : EC(q) == EC(p)
69
70
  for (ConstraintEdge* edge : node->getCopyOutEdges())
70
71
  {
71
- ecUnion(edge->getSrcID(),edge->getDstID());
72
+ ecUnion(edge->getSrcID(), edge->getDstID());
72
73
  }
73
74
  /// q = &p->f : EC(q) == EC(p)
74
75
  for (ConstraintEdge* edge : node->getGepOutEdges())
75
76
  {
76
- ecUnion(edge->getSrcID(),edge->getDstID());
77
+ ecUnion(edge->getSrcID(), edge->getDstID());
77
78
  }
78
79
  }
79
80
  }
80
81
 
81
-
82
82
  void Steensgaard::setEC(NodeID node, NodeID rep)
83
83
  {
84
84
  rep = getEC(rep);
85
85
  Set<NodeID>& subNodes = getSubNodes(node);
86
- for(NodeID sub : subNodes)
86
+ for (NodeID sub : subNodes)
87
87
  {
88
88
  nodeToECMap[sub] = rep;
89
- addSubNode(rep,sub);
89
+ addSubNode(rep, sub);
90
90
  }
91
91
  subNodes.clear();
92
92
  }
93
93
 
94
-
95
94
  /// merge node into equiv class and merge node's pts into ec's pts
96
95
  void Steensgaard::ecUnion(NodeID node, NodeID ec)
97
96
  {
98
- if(unionPts(ec, node))
97
+ if (unionPts(ec, node))
99
98
  pushIntoWorklist(ec);
100
- setEC(node,ec);
99
+ setEC(node, ec);
101
100
  }
102
101
 
103
102
  /*!
@@ -105,10 +104,13 @@ void Steensgaard::ecUnion(NodeID node, NodeID ec)
105
104
  */
106
105
  void Steensgaard::processAllAddr()
107
106
  {
108
- for (ConstraintGraph::const_iterator nodeIt = consCG->begin(), nodeEit = consCG->end(); nodeIt != nodeEit; nodeIt++)
107
+ for (ConstraintGraph::const_iterator nodeIt = consCG->begin(),
108
+ nodeEit = consCG->end();
109
+ nodeIt != nodeEit; nodeIt++)
109
110
  {
110
- ConstraintNode * cgNode = nodeIt->second;
111
- for (ConstraintNode::const_iterator it = cgNode->incomingAddrsBegin(), eit = cgNode->incomingAddrsEnd();
111
+ ConstraintNode* cgNode = nodeIt->second;
112
+ for (ConstraintNode::const_iterator it = cgNode->incomingAddrsBegin(),
113
+ eit = cgNode->incomingAddrsEnd();
112
114
  it != eit; ++it)
113
115
  {
114
116
  numOfProcessedAddr++;
@@ -116,9 +118,174 @@ void Steensgaard::processAllAddr()
116
118
  const AddrCGEdge* addr = cast<AddrCGEdge>(*it);
117
119
  NodeID dst = addr->getDstID();
118
120
  NodeID src = addr->getSrcID();
119
- if(addPts(dst,src))
121
+ if (addPts(dst, src))
120
122
  pushIntoWorklist(dst);
121
123
  }
122
124
  }
123
125
  }
124
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
+ CallSite cs = SVFUtil::getSVFCallSite(it->first->getCallSite());
139
+ for (FunctionSet::iterator cit = it->second.begin(),
140
+ ecit = it->second.end();
141
+ cit != ecit; ++cit)
142
+ {
143
+ connectCaller2CalleeParams(cs, *cit, cpySrcNodes);
144
+ }
145
+ }
146
+ for (NodePairSet::iterator it = cpySrcNodes.begin(),
147
+ eit = cpySrcNodes.end();
148
+ it != eit; ++it)
149
+ {
150
+ pushIntoWorklist(it->first);
151
+ }
152
+
153
+ double cgUpdateEnd = stat->getClk();
154
+ timeOfUpdateCallGraph += (cgUpdateEnd - cgUpdateStart) / TIMEINTERVAL;
155
+
156
+ return (!newEdges.empty());
157
+ }
158
+
159
+ void Steensgaard::heapAllocatorViaIndCall(CallSite cs, NodePairSet& cpySrcNodes)
160
+ {
161
+ assert(SVFUtil::getCallee(cs) == nullptr && "not an indirect callsite?");
162
+ RetICFGNode* retBlockNode =
163
+ pag->getICFG()->getRetICFGNode(cs.getInstruction());
164
+ const PAGNode* cs_return = pag->getCallSiteRet(retBlockNode);
165
+ NodeID srcret;
166
+ CallSite2DummyValPN::const_iterator it = callsite2DummyValPN.find(cs);
167
+ if (it != callsite2DummyValPN.end())
168
+ {
169
+ srcret = getEC(it->second);
170
+ }
171
+ else
172
+ {
173
+ NodeID valNode = pag->addDummyValNode();
174
+ NodeID objNode = pag->addDummyObjNode(cs.getType());
175
+ addPts(valNode, objNode);
176
+ callsite2DummyValPN.insert(std::make_pair(cs, valNode));
177
+ consCG->addConstraintNode(new ConstraintNode(valNode), valNode);
178
+ consCG->addConstraintNode(new ConstraintNode(objNode), objNode);
179
+ srcret = valNode;
180
+ }
181
+
182
+ NodeID dstrec = getEC(cs_return->getId());
183
+ if (addCopyEdge(srcret, dstrec))
184
+ cpySrcNodes.insert(std::make_pair(srcret, dstrec));
185
+ }
186
+
187
+ /*!
188
+ * Connect formal and actual parameters for indirect callsites
189
+ */
190
+ void Steensgaard::connectCaller2CalleeParams(CallSite cs, const SVFFunction* F,
191
+ NodePairSet& cpySrcNodes)
192
+ {
193
+ assert(F);
194
+
195
+ DBOUT(DAndersen, outs() << "connect parameters from indirect callsite "
196
+ << cs.getInstruction()->toString() << " to callee "
197
+ << *F << "\n");
198
+
199
+ CallICFGNode* callBlockNode =
200
+ pag->getICFG()->getCallICFGNode(cs.getInstruction());
201
+ RetICFGNode* retBlockNode =
202
+ pag->getICFG()->getRetICFGNode(cs.getInstruction());
203
+
204
+ if (SVFUtil::isHeapAllocExtFunViaRet(F) &&
205
+ pag->callsiteHasRet(retBlockNode))
206
+ {
207
+ heapAllocatorViaIndCall(cs, cpySrcNodes);
208
+ }
209
+
210
+ if (pag->funHasRet(F) && pag->callsiteHasRet(retBlockNode))
211
+ {
212
+ const PAGNode* cs_return = pag->getCallSiteRet(retBlockNode);
213
+ const PAGNode* fun_return = pag->getFunRet(F);
214
+ if (cs_return->isPointer() && fun_return->isPointer())
215
+ {
216
+ NodeID dstrec = getEC(cs_return->getId());
217
+ NodeID srcret = getEC(fun_return->getId());
218
+ if (addCopyEdge(srcret, dstrec))
219
+ {
220
+ cpySrcNodes.insert(std::make_pair(srcret, dstrec));
221
+ }
222
+ }
223
+ else
224
+ {
225
+ DBOUT(DAndersen, outs() << "not a pointer ignored\n");
226
+ }
227
+ }
228
+
229
+ if (pag->hasCallSiteArgsMap(callBlockNode) && pag->hasFunArgsList(F))
230
+ {
231
+
232
+ // connect actual and formal param
233
+ const SVFIR::SVFVarList& csArgList =
234
+ pag->getCallSiteArgsList(callBlockNode);
235
+ const SVFIR::SVFVarList& funArgList = pag->getFunArgsList(F);
236
+ // Go through the fixed parameters.
237
+ DBOUT(DPAGBuild, outs() << " args:");
238
+ SVFIR::SVFVarList::const_iterator funArgIt = funArgList.begin(),
239
+ funArgEit = funArgList.end();
240
+ SVFIR::SVFVarList::const_iterator csArgIt = csArgList.begin(),
241
+ csArgEit = csArgList.end();
242
+ for (; funArgIt != funArgEit; ++csArgIt, ++funArgIt)
243
+ {
244
+ // Some programs (e.g. Linux kernel) leave unneeded parameters
245
+ // empty.
246
+ if (csArgIt == csArgEit)
247
+ {
248
+ DBOUT(DAndersen, outs() << " !! not enough args\n");
249
+ break;
250
+ }
251
+ const PAGNode* cs_arg = *csArgIt;
252
+ const PAGNode* fun_arg = *funArgIt;
253
+
254
+ if (cs_arg->isPointer() && fun_arg->isPointer())
255
+ {
256
+ DBOUT(DAndersen, outs() << "process actual parm "
257
+ << cs_arg->toString() << " \n");
258
+ NodeID srcAA = getEC(cs_arg->getId());
259
+ NodeID dstFA = getEC(fun_arg->getId());
260
+ if (addCopyEdge(srcAA, dstFA))
261
+ {
262
+ cpySrcNodes.insert(std::make_pair(srcAA, dstFA));
263
+ }
264
+ }
265
+ }
266
+
267
+ // Any remaining actual args must be varargs.
268
+ if (F->isVarArg())
269
+ {
270
+ NodeID vaF = getEC(pag->getVarargNode(F));
271
+ DBOUT(DPAGBuild, outs() << "\n varargs:");
272
+ for (; csArgIt != csArgEit; ++csArgIt)
273
+ {
274
+ const PAGNode* cs_arg = *csArgIt;
275
+ if (cs_arg->isPointer())
276
+ {
277
+ NodeID vnAA = getEC(cs_arg->getId());
278
+ if (addCopyEdge(vnAA, vaF))
279
+ {
280
+ cpySrcNodes.insert(std::make_pair(vnAA, vaF));
281
+ }
282
+ }
283
+ }
284
+ }
285
+ if (csArgIt != csArgEit)
286
+ {
287
+ writeWrnMsg("too many args to non-vararg func.");
288
+ writeWrnMsg("(" + cs.getInstruction()->getSourceLoc() + ")");
289
+ }
290
+ }
291
+ }