Static Value-Flow Analysis
SVFGOPT.cpp
Go to the documentation of this file.
1 //===- SVFGOPT.cpp -- SVFG optimizer------------------------------------------//
2 //
3 // SVF: Static Value-Flow Analysis
4 //
5 // Copyright (C) <2013-2017> <Yulei Sui>
6 //
7 
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as published by
10 // the Free Software Foundation, either version 3 of the License, or
11 // (at your option) any later version.
12 
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
17 
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 //
21 //===----------------------------------------------------------------------===//
22 
23 /*
24  * @file: SVFGOPT.cpp
25  * @author: yesen
26  * @date: 31/03/2014
27  * @version: 1.0
28  *
29  * @section LICENSE
30  *
31  * @section DESCRIPTION
32  *
33  */
34 
35 #include "Util/Options.h"
36 #include "Graphs/SVFGOPT.h"
37 #include "Graphs/SVFGStat.h"
38 
39 using namespace SVF;
40 using namespace SVFUtil;
41 
43 static std::string KeepContextSelfCycle = "context";
45 
46 
48 {
50 
51  if(Options::DumpVFG())
52  dump("SVFG_before_opt");
53 
54  DBOUT(DGENERAL, outs() << SVFUtil::pasMsg("\tSVFG Optimisation\n"));
55 
56  keepActualOutFormalIn = Options::KeepAOFI();
57 
58  stat->sfvgOptStart();
59  handleInterValueFlow();
60 
61  handleIntraValueFlow();
62  stat->sfvgOptEnd();
63 
64 }
69 {
71  return addIntraIndirectVFEdge(srcId, dstId, cpts);
72  else
73  return addCallIndirectVFEdge(srcId, dstId, cpts, csid);
74 }
75 
80 {
82  return addIntraIndirectVFEdge(srcId, dstId, cpts);
83  else
84  return addRetIndirectVFEdge(srcId, dstId, cpts, csid);
85 }
86 
91 {
92  SVFGNodeSet candidates;
93  for (SVFGNodeIDToNodeMapTy::iterator it = SVFG::begin(), eit = SVFG::end();
94  it!=eit; ++it)
95  {
96  SVFGNode* node = it->second;
100  candidates.insert(node);
101  }
102 
103  SVFGNodeSet nodesToBeDeleted;
104  for (SVFGNodeSet::const_iterator it = candidates.begin(), eit = candidates.end();
105  it!=eit; ++it)
106  {
107  SVFGNode* node = *it;
108  if (FormalParmSVFGNode* fp = SVFUtil::dyn_cast<FormalParmSVFGNode>(node))
109  {
110  replaceFParamARetWithPHI(addInterPHIForFP(fp), fp);
111  nodesToBeDeleted.insert(fp);
112  }
113  else if (ActualRetSVFGNode* ar = SVFUtil::dyn_cast<ActualRetSVFGNode>(node))
114  {
115  replaceFParamARetWithPHI(addInterPHIForAR(ar), ar);
116  nodesToBeDeleted.insert(ar);
117  }
118  else if (SVFUtil::isa<ActualParmSVFGNode, FormalRetSVFGNode>(node))
119  {
120  nodesToBeDeleted.insert(node);
121  }
122  else if (SVFUtil::isa<ActualINSVFGNode, FormalOUTSVFGNode>(node))
123  {
124  retargetEdgesOfAInFOut(node);
125  nodesToBeDeleted.insert(node);
126  }
127  else if (SVFUtil::isa<ActualOUTSVFGNode, FormalINSVFGNode>(node))
128  {
129  if(keepActualOutFormalIn == false)
130  nodesToBeDeleted.insert(node);
131  }
132  }
133 
134  for (SVFGNodeSet::iterator it = nodesToBeDeleted.begin(), eit = nodesToBeDeleted.end(); it != eit; ++it)
135  {
136  SVFGNode* node = *it;
137  if (canBeRemoved(node))
138  {
139  if (SVFUtil::isa<ActualOUTSVFGNode, FormalINSVFGNode>(node))
140  retargetEdgesOfAOutFIn(node);
141 
142  removeAllEdges(node);
143  removeSVFGNode(node);
144  }
145  }
146 }
147 
152 {
153  assert((SVFUtil::isa<FormalParmSVFGNode, ActualRetSVFGNode>(svfgNode))
154  && "expecting a formal param or actual ret svfg node");
155 
157  NodeID phiId = phi->getId();
159  for (SVFGNode::const_iterator it = svfgNode->OutEdgeBegin(), eit = svfgNode->OutEdgeEnd();
160  it != eit; ++it)
161  {
162  const SVFGEdge* outEdge = *it;
163  SVFGNode* dstNode = outEdge->getDstNode();
164  NodeID dstId = dstNode->getId();
165  if (const CallDirSVFGEdge* callEdge = SVFUtil::dyn_cast<CallDirSVFGEdge>(outEdge))
166  addCallEdge(phiId, dstId, callEdge->getCallSiteId());
167  else if (const RetDirSVFGEdge* retEdge = SVFUtil::dyn_cast<RetDirSVFGEdge>(outEdge))
168  addRetEdge(phiId, dstId, retEdge->getCallSiteId());
169  else
170  addIntraDirectVFEdge(phiId, dstId);
171  }
172 
174  if (FormalParmSVFGNode* fp = SVFUtil::dyn_cast<FormalParmSVFGNode>(svfgNode))
175  {
176  for (SVFGNode::iterator it = svfgNode->InEdgeBegin(), eit = svfgNode->InEdgeEnd();
177  it != eit; ++it)
178  {
179  ActualParmSVFGNode* ap = SVFUtil::cast<ActualParmSVFGNode>((*it)->getSrcNode());
180  addInterPHIOperands(phi, ap->getParam());
181  // connect actual param's def node to phi node
182  addCallEdge(getDef(ap->getParam()), phiId, getCallSiteID(ap->getCallSite(), fp->getFun()));
183  }
184  }
185  else if (ActualRetSVFGNode* ar = SVFUtil::dyn_cast<ActualRetSVFGNode>(svfgNode))
186  {
187  for (SVFGNode::iterator it = svfgNode->InEdgeBegin(), eit = svfgNode->InEdgeEnd();
188  it != eit; ++it)
189  {
190  FormalRetSVFGNode* fr = SVFUtil::cast<FormalRetSVFGNode>((*it)->getSrcNode());
191  addInterPHIOperands(phi, fr->getRet());
192  // connect formal return's def node to phi node
193  addRetEdge(getDef(fr->getRet()), phiId, getCallSiteID(ar->getCallSite(), fr->getFun()));
194  }
195  }
196 
197  removeAllEdges(svfgNode);
198 }
199 
205 {
206  assert(node->getInEdges().size() == 1 && "actual-in/formal-out can only have one incoming edge as its def size");
207 
208  SVFGNode* def = nullptr;
209  NodeBS inPointsTo;
210 
212  SVFGNode::const_iterator eit = node->InEdgeEnd();
213  for (; it != eit; ++it)
214  {
215  const IndirectSVFGEdge* inEdge = SVFUtil::cast<IndirectSVFGEdge>(*it);
216  inPointsTo = inEdge->getPointsTo();
217 
218  def = inEdge->getSrcNode();
219  if (SVFUtil::isa<ActualINSVFGNode>(node))
220  setActualINDef(node->getId(), def->getId());
221  else if (SVFUtil::isa<FormalOUTSVFGNode>(node))
222  setFormalOUTDef(node->getId(), def->getId());
223  }
224 
225  it = node->OutEdgeBegin(), eit = node->OutEdgeEnd();
226  for (; it != eit; ++it)
227  {
228  const IndirectSVFGEdge* outEdge = SVFUtil::cast<IndirectSVFGEdge>(*it);
229  NodeBS intersection = inPointsTo;
230  intersection &= outEdge->getPointsTo();
231 
232  if (intersection.empty())
233  continue;
234 
235  SVFGNode* dstNode = outEdge->getDstNode();
236  if (const CallIndSVFGEdge* callEdge = SVFUtil::dyn_cast<CallIndSVFGEdge>(outEdge))
237  addCallIndirectSVFGEdge(def->getId(), dstNode->getId(), callEdge->getCallSiteId(), intersection);
238  else if (const RetIndSVFGEdge* retEdge = SVFUtil::dyn_cast<RetIndSVFGEdge>(outEdge))
239  addRetIndirectSVFGEdge(def->getId(), dstNode->getId(), retEdge->getCallSiteId(), intersection);
240  else
241  assert(false && "expecting an inter-procedural SVFG edge");
242  }
243 
244  removeAllEdges(node);
245 }
246 
251 {
252  SVFGNode::const_iterator inIt = node->InEdgeBegin();
253  SVFGNode::const_iterator inEit = node->InEdgeEnd();
254  for (; inIt != inEit; ++inIt)
255  {
256  const IndirectSVFGEdge* inEdge = SVFUtil::cast<IndirectSVFGEdge>(*inIt);
257  NodeID srcId = inEdge->getSrcID();
258 
259  SVFGNode::const_iterator outIt = node->OutEdgeBegin();
260  SVFGNode::const_iterator outEit = node->OutEdgeEnd();
261  for (; outIt != outEit; ++outIt)
262  {
263  const IndirectSVFGEdge* outEdge = SVFUtil::cast<IndirectSVFGEdge>(*outIt);
264 
265  NodeBS intersection = inEdge->getPointsTo();
266  intersection &= outEdge->getPointsTo();
267  if (intersection.empty())
268  continue;
269 
270  NodeID dstId = outEdge->getDstID();
271  if (const RetIndSVFGEdge* retEdge = SVFUtil::dyn_cast<RetIndSVFGEdge>(inEdge))
272  {
273  addRetIndirectSVFGEdge(srcId, dstId, retEdge->getCallSiteId(), intersection);
274  }
275  else if (const CallIndSVFGEdge* callEdge = SVFUtil::dyn_cast<CallIndSVFGEdge>(inEdge))
276  {
277  addCallIndirectSVFGEdge(srcId, dstId, callEdge->getCallSiteId(), intersection);
278  }
279  else
280  {
281  addIntraIndirectVFEdge(srcId, dstId, intersection);
282  }
283  }
284  }
285 
286  removeAllEdges(node);
287 }
288 
293 {
294  bool hasInCallRet = false;
295  bool hasOutCallRet = false;
296 
297  SVFGNode::const_iterator edgeIt = node->InEdgeBegin();
298  SVFGNode::const_iterator edgeEit = node->InEdgeEnd();
299  for (; edgeIt != edgeEit; ++edgeIt)
300  {
301  if (SVFUtil::isa<CallIndSVFGEdge, RetIndSVFGEdge>(*edgeIt))
302  {
303  hasInCallRet = true;
304  break;
305  }
306  }
307 
308  edgeIt = node->OutEdgeBegin();
309  edgeEit = node->OutEdgeEnd();
310  for (; edgeIt != edgeEit; ++edgeIt)
311  {
312  if (SVFUtil::isa<CallIndSVFGEdge, RetIndSVFGEdge>(*edgeIt))
313  {
314  hasOutCallRet = true;
315  break;
316  }
317  }
318 
319  if (hasInCallRet && hasOutCallRet)
320  return true;
321  else
322  return false;
323 }
324 
334 bool SVFGOPT::canBeRemoved(const SVFGNode * node)
335 {
338  return true;
341  {
345  if (isConnectingTwoCallSites(node))
346  return false;
347 
348  if (const ActualINSVFGNode* ai = SVFUtil::dyn_cast<ActualINSVFGNode>(node))
349  {
350  return (actualInOfIndCS(ai) == false);
351  }
352  else if (const ActualOUTSVFGNode* ao = SVFUtil::dyn_cast<ActualOUTSVFGNode>(node))
353  {
354  return (actualOutOfIndCS(ao) == false && isDefOfAInFOut(node) == false);
355  }
356  else if (const FormalINSVFGNode* fi = SVFUtil::dyn_cast<FormalINSVFGNode>(node))
357  {
358  return (formalInOfAddressTakenFunc(fi) == false && isDefOfAInFOut(node) == false);
359  }
360  else if (const FormalOUTSVFGNode* fo = SVFUtil::dyn_cast<FormalOUTSVFGNode>(node))
361  {
362  return (formalOutOfAddressTakenFunc(fo) == false);
363  }
364  }
365 
366  return false;
367 }
368 
373 {
374  std::string choice = (Options::SelfCycle().empty()) ? "" : Options::SelfCycle();
375  if (choice.empty() || choice == KeepAllSelfCycle)
376  keepAllSelfCycle = true;
377  else if (choice == KeepContextSelfCycle)
378  keepContextSelfCycle = true;
379  else if (choice == KeepNoneSelfCycle)
380  keepAllSelfCycle = keepContextSelfCycle = false;
381  else
382  {
383  SVFUtil::writeWrnMsg("Unrecognised option. All self cycle edges will be kept.");
384  keepAllSelfCycle = true;
385  }
386 }
387 
392 {
393  parseSelfCycleHandleOption();
394 
395  initialWorkList();
396 
397  while (!worklist.empty())
398  {
399  const MSSAPHISVFGNode* node = worklist.pop();
400 
402  if (checkSelfCycleEdges(node))
403  continue;
404 
405  if (node->hasOutgoingEdge() && node->hasIncomingEdge())
406  bypassMSSAPHINode(node);
407 
409  if (node->hasIncomingEdge() && node->hasOutgoingEdge() == false)
410  {
412  SVFGNode::const_iterator edgeIt = node->InEdgeBegin();
413  SVFGNode::const_iterator edgeEit = node->InEdgeEnd();
414  for (; edgeIt != edgeEit; ++edgeIt)
415  addIntoWorklist((*edgeIt)->getSrcNode());
416 
417  removeInEdges(node);
418  }
419  else if (node->hasOutgoingEdge() && node->hasIncomingEdge() == false)
420  {
422  SVFGNode::const_iterator edgeIt = node->OutEdgeBegin();
423  SVFGNode::const_iterator edgeEit = node->OutEdgeEnd();
424  for (; edgeIt != edgeEit; ++edgeIt)
425  addIntoWorklist((*edgeIt)->getDstNode());
426 
427  removeOutEdges(node);
428  }
429 
431  if (node->hasIncomingEdge() == false && node->hasOutgoingEdge() == false)
432  removeSVFGNode(const_cast<MSSAPHISVFGNode*>(node));
433  }
434 }
435 
436 
443 {
444  bool hasSelfCycle = false;
445 
446  SVFGEdge::SVFGEdgeSetTy inEdges = node->getInEdges();
447  SVFGNode::const_iterator inEdgeIt = inEdges.begin();
448  SVFGNode::const_iterator inEdgeEit = inEdges.end();
449  for (; inEdgeIt != inEdgeEit; ++inEdgeIt)
450  {
451  SVFGEdge* preEdge = *inEdgeIt;
452 
453  if (preEdge->getSrcID() == preEdge->getDstID())
454  {
455  if (keepAllSelfCycle)
456  {
457  hasSelfCycle = true;
458  break;
459  }
460  else if (keepContextSelfCycle &&
461  SVFUtil::isa<CallIndSVFGEdge, RetIndSVFGEdge>(preEdge))
462  {
463  hasSelfCycle = true;
464  continue;
465  }
466  else
467  {
468  assert(SVFUtil::isa<IndirectSVFGEdge>(preEdge) && "can only remove indirect SVFG edge");
469  removeSVFGEdge(preEdge);
470  }
471  }
472  }
473 
474  return hasSelfCycle;
475 }
476 
481 {
482  SVFGNode::const_iterator inEdgeIt = node->InEdgeBegin();
483  SVFGNode::const_iterator inEdgeEit = node->InEdgeEnd();
484  for (; inEdgeIt != inEdgeEit; ++inEdgeIt)
485  {
486  const SVFGEdge* preEdge = *inEdgeIt;
487  const SVFGNode* srcNode = preEdge->getSrcNode();
488 
489  bool added = false;
491  SVFGNode::const_iterator outEdgeIt = node->OutEdgeBegin();
492  SVFGNode::const_iterator outEdgeEit = node->OutEdgeEnd();
493  for (; outEdgeIt != outEdgeEit; ++outEdgeIt)
494  {
495  const SVFGEdge* succEdge = *outEdgeIt;
496  const SVFGNode* dstNode = (*outEdgeIt)->getDstNode();
497  if (srcNode->getId() != dstNode->getId()
498  && addNewSVFGEdge(srcNode->getId(), dstNode->getId(), preEdge, succEdge))
499  added = true;
500  else
501  {
504  addIntoWorklist(dstNode);
505  }
506  }
507 
508  if (added == false)
509  {
512  addIntoWorklist(srcNode);
513  }
514  }
515 
516  removeAllEdges(node);
517 }
518 
523 bool SVFGOPT::addNewSVFGEdge(NodeID srcId, NodeID dstId, const SVFGEdge* preEdge, const SVFGEdge* succEdge)
524 {
525  assert(SVFUtil::isa<IndirectSVFGEdge>(preEdge) && SVFUtil::isa<IndirectSVFGEdge>(succEdge)
526  && "either pre or succ edge is not indirect SVFG edge");
527 
528  const IndirectSVFGEdge* preIndEdge = SVFUtil::cast<IndirectSVFGEdge>(preEdge);
529  const IndirectSVFGEdge* succIndEdge = SVFUtil::cast<IndirectSVFGEdge>(succEdge);
530 
531  NodeBS intersection = preIndEdge->getPointsTo();
532  intersection &= succIndEdge->getPointsTo();
533 
534  if (intersection.empty())
535  return false;
536 
537  assert(bothInterEdges(preEdge, succEdge) == false && "both edges are inter edges");
538 
539  if (const CallIndSVFGEdge* preCallEdge = SVFUtil::dyn_cast<CallIndSVFGEdge>(preEdge))
540  {
541  return addCallIndirectSVFGEdge(srcId, dstId, preCallEdge->getCallSiteId(), intersection);
542  }
543  else if (const CallIndSVFGEdge* succCallEdge = SVFUtil::dyn_cast<CallIndSVFGEdge>(succEdge))
544  {
545  return addCallIndirectSVFGEdge(srcId, dstId, succCallEdge->getCallSiteId(), intersection);
546  }
547  else if (const RetIndSVFGEdge* preRetEdge = SVFUtil::dyn_cast<RetIndSVFGEdge>(preEdge))
548  {
549  return addRetIndirectSVFGEdge(srcId, dstId, preRetEdge->getCallSiteId(), intersection);
550  }
551  else if (const RetIndSVFGEdge* succRetEdge = SVFUtil::dyn_cast<RetIndSVFGEdge>(succEdge))
552  {
553  return addRetIndirectSVFGEdge(srcId, dstId, succRetEdge->getCallSiteId(), intersection);
554  }
555  else
556  {
557  return addIntraIndirectVFEdge(srcId, dstId, intersection);
558  }
559 
560  return false;
561 }
static std::string KeepNoneSelfCycle
Definition: SVFGOPT.cpp:44
static std::string KeepContextSelfCycle
Definition: SVFGOPT.cpp:43
static std::string KeepAllSelfCycle
Definition: SVFGOPT.cpp:42
#define DBOUT(TYPE, X)
LLVM debug macros, define type of your DBUG model of each pass.
Definition: SVFType.h:484
#define DGENERAL
Definition: SVFType.h:490
const char *const string
Definition: cJSON.h:172
const PAGNode * getParam() const
Return parameter.
Definition: VFGNode.h:907
const CallICFGNode * getCallSite() const
Return callsite.
Definition: VFGNode.h:901
const PAGNode * getRet() const
Return value at callee.
Definition: VFGNode.h:1095
const SVFFunction * getFun() const override
Function.
Definition: VFGNode.h:1100
NodeType * getSrcNode() const
Definition: GenericGraph.h:97
NodeID getDstID() const
Definition: GenericGraph.h:85
NodeID getSrcID() const
get methods of the components
Definition: GenericGraph.h:81
NodeType * getDstNode() const
Definition: GenericGraph.h:101
iterator begin()
Iterators.
Definition: GenericGraph.h:627
bool hasIncomingEdge() const
Has incoming/outgoing edge set.
Definition: GenericGraph.h:442
bool hasOutgoingEdge() const
Definition: GenericGraph.h:446
iterator OutEdgeEnd()
Definition: GenericGraph.h:458
iterator OutEdgeBegin()
iterators
Definition: GenericGraph.h:454
iterator InEdgeBegin()
Definition: GenericGraph.h:462
const GEdgeSetTy & getInEdges() const
Definition: GenericGraph.h:434
iterator InEdgeEnd()
Definition: GenericGraph.h:466
virtual const SVFFunction * getFun() const
Return the function of this ICFGNode.
Definition: ICFGNode.h:76
const NodeBS & getPointsTo() const
Definition: SVFGEdge.h:60
static const Option< bool > KeepAOFI
Definition: Options.h:107
static const Option< std::string > SelfCycle
Definition: Options.h:108
static const Option< bool > DumpVFG
Definition: Options.h:111
static const Option< bool > ContextInsensitive
Definition: Options.h:106
NodeID getId() const
Get ID.
Definition: GenericGraph.h:260
Set< SVFGNode * > SVFGNodeSet
Definition: SVFGOPT.h:58
SVFGEdge * addCallIndirectSVFGEdge(NodeID srcId, NodeID dstId, CallSiteID csid, const NodeBS &cpts)
Add inter-procedural value flow edge.
Definition: SVFGOPT.cpp:68
void replaceFParamARetWithPHI(PHISVFGNode *phi, SVFGNode *svfgNode)
Replace FormalParam/ActualRet node with PHI node.
Definition: SVFGOPT.cpp:151
void handleIntraValueFlow()
Remove MSSAPHI SVFG nodes.
Definition: SVFGOPT.cpp:391
void retargetEdgesOfAOutFIn(SVFGNode *node)
Connect actual-out/formal-in's predecessors to their successors directly.
Definition: SVFGOPT.cpp:250
void handleInterValueFlow()
Definition: SVFGOPT.cpp:90
void bypassMSSAPHINode(const MSSAPHISVFGNode *node)
Remove MSSAPHI node if possible.
Definition: SVFGOPT.cpp:480
bool addNewSVFGEdge(NodeID srcId, NodeID dstId, const SVFGEdge *preEdge, const SVFGEdge *succEdge)
Add new SVFG edge from src to dst.
Definition: SVFGOPT.cpp:523
void buildSVFG() override
Start building SVFG.
Definition: SVFGOPT.cpp:47
bool isConnectingTwoCallSites(const SVFGNode *node) const
Return TRUE if this node has both incoming call/ret and outgoing call/ret edges.
Definition: SVFGOPT.cpp:292
bool canBeRemoved(const SVFGNode *node)
Definition: SVFGOPT.cpp:334
void retargetEdgesOfAInFOut(SVFGNode *node)
Retarget edges related to actual-in/-out and formal-in/-out.
Definition: SVFGOPT.cpp:204
void parseSelfCycleHandleOption()
Definition: SVFGOPT.cpp:372
SVFGEdge * addRetIndirectSVFGEdge(NodeID srcId, NodeID dstId, CallSiteID csid, const NodeBS &cpts)
Add indirect ret edge from src to dst with one call site ID.
Definition: SVFGOPT.cpp:79
bool checkSelfCycleEdges(const MSSAPHISVFGNode *node)
Remove self cycle edges if needed. Return TRUE if some self cycle edges remained.
Definition: SVFGOPT.cpp:442
virtual void buildSVFG()
Start building SVFG.
Definition: SVFG.cpp:228
VFGEdgeSetTy SVFGEdgeSetTy
Definition: VFGEdge.h:118
VFGEdge::VFGEdgeSetTy::const_iterator const_iterator
Definition: VFGNode.h:55
VFGEdge::VFGEdgeSetTy::iterator iterator
Definition: VFGNode.h:54
std::string pasMsg(const std::string &msg)
Print each pass/phase message by converting a string into blue string output.
Definition: SVFUtil.cpp:99
LLVM_NODISCARD bool isa(const Y &Val)
Definition: Casting.h:241
void writeWrnMsg(const std::string &msg)
Writes a message run through wrnMsg.
Definition: SVFUtil.cpp:66
std::ostream & outs()
Overwrite llvm::outs()
Definition: SVFUtil.h:50
for isBitcode
Definition: BasicTypes.h:68
unsigned CallSiteID
Definition: GeneralType.h:58
u32_t NodeID
Definition: GeneralType.h:55
void dump(const SparseBitVector< ElementSize > &LHS, std::ostream &out)