Static Value-Flow Analysis
FlowSensitive.cpp
Go to the documentation of this file.
1 //===- FlowSensitive.cpp -- Sparse flow-sensitive pointer analysis------------//
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  * FlowSensitive.cpp
25  *
26  * Created on: Oct 28, 2013
27  * Author: Yulei Sui
28  */
29 
30 #include "Util/Options.h"
31 #include "SVFIR/SVFModule.h"
32 #include "WPA/WPAStat.h"
33 #include "WPA/FlowSensitive.h"
34 #include "WPA/Andersen.h"
35 #include "MemoryModel/PointsTo.h"
36 
37 using namespace SVF;
38 using namespace SVFUtil;
39 
40 std::unique_ptr<FlowSensitive> FlowSensitive::fspta;
41 
46 {
48 
49  stat = new FlowSensitiveStat(this);
50 
51  // TODO: support clustered aux. Andersen's.
52  assert(!Options::ClusterAnder() && "FlowSensitive::initialize: clustering auxiliary Andersen's unsupported.");
54 
55  // If cluster option is not set, it will give us a no-mapping points-to set.
57  && "FS::init: plain-mapping and cluster-fs are mutually exclusive.");
58  if (Options::ClusterFs())
59  {
60  cluster();
61  // Reset the points-to cache although empty so the new mapping could
62  // be applied to the inserted empty set.
63  getPtCache().reset();
64  }
65  else if (Options::PlainMappingFs())
66  {
67  plainMap();
68  // As above.
69  getPtCache().reset();
70  }
71 
72  svfg = memSSA.buildPTROnlySVFG(ander);
73 
74  setGraph(svfg);
75  //AndersenWaveDiff::releaseAndersenWaveDiff();
76 }
78 {
80 
81  double start = stat->getClk(true);
83  DBOUT(DGENERAL, outs() << SVFUtil::pasMsg("Start Solving Constraints\n"));
84 
85  do
86  {
87  numOfIteration++;
88 
89  if(0 == numOfIteration % OnTheFlyIterBudgetForStat)
90  dumpStat();
91 
92  callGraphSCC->find();
93 
94  initWorklist();
95  solveWorklist();
96  }
97  while (updateCallGraph(getIndirectCallsites()));
98 
99  DBOUT(DGENERAL, outs() << SVFUtil::pasMsg("Finish Solving Constraints\n"));
100 
101  // Reset the time-up alarm; analysis is done.
102  SVFUtil::stopAnalysisLimitTimer(limitTimerSet);
103 
104  double end = stat->getClk(true);
105  solveTime += (end - start) / TIMEINTERVAL;
106 
107 }
108 
113 {
115  initialize();
116  if(!filename.empty())
117  writeObjVarToFile(filename);
118  solveConstraints();
119  if(!filename.empty())
120  writeToFile(filename);
122  finalize();
123 }
124 
129 {
130  if(!Options::ReadAnder().empty())
131  {
132  readPtsFromFile(Options::ReadAnder());
133  }
134  else
135  {
136  if(Options::WriteAnder().empty())
137  {
138  initialize();
139  solveConstraints();
140  finalize();
141  }
142  else
143  {
144  solveAndwritePtsToFile(Options::WriteAnder());
145  }
146  }
147 }
148 
150 {
152  initialize();
154  if(!filename.empty())
155  this->readFromFile(filename);
157  finalize();
158 }
159 
164 {
165  if(Options::DumpVFG())
166  svfg->dump("fs_solved", true);
167 
168  NodeStack& nodeStack = WPASolver<SVFG*>::SCCDetect();
169  while (nodeStack.empty() == false)
170  {
171  NodeID rep = nodeStack.top();
172  nodeStack.pop();
173  const NodeBS& subNodes = getSCCDetector()->subNodes(rep);
174  if (subNodes.count() > maxSCCSize)
175  maxSCCSize = subNodes.count();
176  if (subNodes.count() > 1)
177  {
178  numOfNodesInSCC += subNodes.count();
179  numOfSCC++;
180  }
181  }
182 
183  // TODO: check -stat too.
184  if (Options::ClusterFs())
185  {
187  const PTDataTy *ptd = getPTDataTy();
188  // TODO: should we use liveOnly?
189  Map<PointsTo, unsigned> allPts = ptd->getAllPts(true);
190  // TODO: parameterise final arg.
192  NodeIDAllocator::Clusterer::printStats("post-main: best", stats);
193 
194  // Do the same for the candidates. TODO: probably temporary for eval. purposes.
195  for (std::pair<hclust_fast_methods, std::vector<NodeID>> &candidate : candidateMappings)
196  {
197  // Can reuse stats, since we're always filling it with `evaluate`, it will always be overwritten.
198  NodeIDAllocator::Clusterer::evaluate(candidate.second, allPts, stats, true);
199  NodeIDAllocator::Clusterer::printStats("post-main: candidate " + SVFUtil::hclustMethodToString(candidate.first), stats);
200  }
201  }
202 
204 }
205 
210 {
211  double start = stat->getClk();
212  NodeStack& nodeStack = WPASVFGFSSolver::SCCDetect();
213  double end = stat->getClk();
214  sccTime += (end - start) / TIMEINTERVAL;
215  return nodeStack;
216 }
217 
222 {
223  SVFGNode* node = svfg->getSVFGNode(nodeId);
224  if (processSVFGNode(node))
225  propagate(&node);
226 
227  clearAllDFOutVarFlag(node);
228 }
229 
234 {
235  double start = stat->getClk();
236  bool changed = false;
237  if (AddrSVFGNode* addr = SVFUtil::dyn_cast<AddrSVFGNode>(node))
238  {
239  numOfProcessedAddr++;
240  if (processAddr(addr))
241  changed = true;
242  }
243  else if (CopySVFGNode* copy = SVFUtil::dyn_cast<CopySVFGNode>(node))
244  {
245  numOfProcessedCopy++;
246  if (processCopy(copy))
247  changed = true;
248  }
249  else if (GepSVFGNode* gep = SVFUtil::dyn_cast<GepSVFGNode>(node))
250  {
251  numOfProcessedGep++;
252  if(processGep(gep))
253  changed = true;
254  }
255  else if (LoadSVFGNode* load = SVFUtil::dyn_cast<LoadSVFGNode>(node))
256  {
257  numOfProcessedLoad++;
258  if(processLoad(load))
259  changed = true;
260  }
261  else if (StoreSVFGNode* store = SVFUtil::dyn_cast<StoreSVFGNode>(node))
262  {
263  numOfProcessedStore++;
264  if (processStore(store))
265  changed = true;
266  }
267  else if (PHISVFGNode* phi = SVFUtil::dyn_cast<PHISVFGNode>(node))
268  {
269  numOfProcessedPhi++;
270  if (processPhi(phi))
271  changed = true;
272  }
275  ActualOUTSVFGNode>(node))
276  {
277  numOfProcessedMSSANode++;
278  changed = true;
279  }
282  NullPtrSVFGNode>(node))
283  {
284  changed = true;
285  }
286  else if (SVFUtil::isa<CmpVFGNode, BinaryOPVFGNode>(node) ||
287  SVFUtil::dyn_cast<UnaryOPVFGNode>(node))
288  {
289  }
290  else
291  {
292  assert(false && "unexpected kind of SVFG nodes");
293  }
294 
295  double end = stat->getClk();
296  processTime += (end - start) / TIMEINTERVAL;
297 
298  return changed;
299 }
300 
310 {
311  double start = stat->getClk();
312  bool changed = false;
313 
314  if (DirectSVFGEdge* dirEdge = SVFUtil::dyn_cast<DirectSVFGEdge>(edge))
315  changed = propAlongDirectEdge(dirEdge);
316  else if (IndirectSVFGEdge* indEdge = SVFUtil::dyn_cast<IndirectSVFGEdge>(edge))
317  changed = propAlongIndirectEdge(indEdge);
318  else
319  assert(false && "new kind of svfg edge?");
320 
321  double end = stat->getClk();
322  propagationTime += (end - start) /TIMEINTERVAL;
323  return changed;
324 }
325 
330 {
331  double start = stat->getClk();
332  bool changed = false;
333 
334  SVFGNode* src = edge->getSrcNode();
335  SVFGNode* dst = edge->getDstNode();
336  // If this is an actual-param or formal-ret, top-level pointer's pts must be
337  // propagated from src to dst.
338  if (ActualParmSVFGNode* ap = SVFUtil::dyn_cast<ActualParmSVFGNode>(src))
339  changed = propagateFromAPToFP(ap, dst);
340  else if (FormalRetSVFGNode* fp = SVFUtil::dyn_cast<FormalRetSVFGNode>(src))
341  changed = propagateFromFRToAR(fp, dst);
342  else
343  {
344  // Direct SVFG edge links between def and use of a top-level pointer.
345  // There's no points-to information propagated along direct edge.
346  // Since the top-level pointer's value has been changed at src node,
347  // return TRUE to put dst node into the work list.
348  changed = true;
349  }
350 
351  double end = stat->getClk();
352  directPropaTime += (end - start) / TIMEINTERVAL;
353  return changed;
354 }
355 
361 {
362  const FormalParmSVFGNode* fp = SVFUtil::dyn_cast<FormalParmSVFGNode>(dst);
363  assert(fp && "expecting a formal param node");
364 
365  NodeID pagDst = fp->getParam()->getId();
366  const PointsTo &srcCPts = getPts(ap->getParam()->getId());
367  bool changed = unionPts(pagDst, srcCPts);
368 
369  return changed;
370 }
371 
377 {
378  const ActualRetSVFGNode* ar = SVFUtil::dyn_cast<ActualRetSVFGNode>(dst);
379  assert(ar && "expecting an actual return node");
380 
381  NodeID pagDst = ar->getRev()->getId();
382  const PointsTo & srcCPts = getPts(fr->getRet()->getId());
383  bool changed = unionPts(pagDst, srcCPts);
384 
385  return changed;
386 }
387 
392 {
393  double start = stat->getClk();
394 
395  SVFGNode* src = edge->getSrcNode();
396  SVFGNode* dst = edge->getDstNode();
397 
398  bool changed = false;
399 
400  // Get points-to targets may be used by next SVFG node.
401  // Propagate points-to set for node used in dst.
402  const NodeBS& pts = edge->getPointsTo();
403  for (NodeBS::iterator ptdIt = pts.begin(), ptdEit = pts.end(); ptdIt != ptdEit; ++ptdIt)
404  {
405  NodeID ptd = *ptdIt;
406 
407  if (propVarPtsFromSrcToDst(ptd, src, dst))
408  changed = true;
409 
410  if (isFieldInsensitive(ptd))
411  {
413  const NodeBS& allFields = getAllFieldsObjVars(ptd);
414  for (NodeBS::iterator fieldIt = allFields.begin(), fieldEit = allFields.end();
415  fieldIt != fieldEit; ++fieldIt)
416  {
417  if (propVarPtsFromSrcToDst(*fieldIt, src, dst))
418  changed = true;
419  }
420  }
421  }
422 
423  double end = stat->getClk();
424  indirectPropaTime += (end - start) / TIMEINTERVAL;
425  return changed;
426 }
427 
432 {
433  bool changed = false;
434  if (SVFUtil::isa<StoreSVFGNode>(src))
435  {
436  if (updateInFromOut(src, var, dst, var))
437  changed = true;
438  }
439  else
440  {
441  if (updateInFromIn(src, var, dst, var))
442  changed = true;
443  }
444  return changed;
445 }
446 
451 {
452  double start = stat->getClk();
453  NodeID srcID = addr->getPAGSrcNodeID();
456  if (isFieldInsensitive(srcID))
457  srcID = getFIObjVar(srcID);
458  bool changed = addPts(addr->getPAGDstNodeID(), srcID);
459  double end = stat->getClk();
460  addrTime += (end - start) / TIMEINTERVAL;
461  return changed;
462 }
463 
468 {
469  double start = stat->getClk();
470  bool changed = unionPts(copy->getPAGDstNodeID(), copy->getPAGSrcNodeID());
471  double end = stat->getClk();
472  copyTime += (end - start) / TIMEINTERVAL;
473  return changed;
474 }
475 
480 {
481  double start = stat->getClk();
482  bool changed = false;
483  NodeID pagDst = phi->getRes()->getId();
484  for (PHISVFGNode::OPVers::const_iterator it = phi->opVerBegin(), eit = phi->opVerEnd(); it != eit; ++it)
485  {
486  NodeID src = it->second->getId();
487  const PointsTo& srcPts = getPts(src);
488  if (unionPts(pagDst, srcPts))
489  changed = true;
490  }
491 
492  double end = stat->getClk();
493  phiTime += (end - start) / TIMEINTERVAL;
494  return changed;
495 }
496 
501 {
502  double start = stat->getClk();
503  bool changed = false;
504  const PointsTo& srcPts = getPts(edge->getPAGSrcNodeID());
505 
506  PointsTo tmpDstPts;
507  const GepStmt* gepStmt = SVFUtil::cast<GepStmt>(edge->getPAGEdge());
508  if (gepStmt->isVariantFieldGep())
509  {
510  for (NodeID o : srcPts)
511  {
512  if (isBlkObjOrConstantObj(o))
513  {
514  tmpDstPts.set(o);
515  continue;
516  }
517 
518  setObjFieldInsensitive(o);
519  tmpDstPts.set(getFIObjVar(o));
520  }
521  }
522  else
523  {
524  for (NodeID o : srcPts)
525  {
526  if (isBlkObjOrConstantObj(o) || isFieldInsensitive(o))
527  {
528  tmpDstPts.set(o);
529  continue;
530  }
531 
532  NodeID fieldSrcPtdNode = getGepObjVar(o, gepStmt->getAccessPath().getConstantStructFldIdx());
533  tmpDstPts.set(fieldSrcPtdNode);
534  }
535  }
536 
537  if (unionPts(edge->getPAGDstNodeID(), tmpDstPts))
538  changed = true;
539 
540  double end = stat->getClk();
541  gepTime += (end - start) / TIMEINTERVAL;
542  return changed;
543 }
544 
545 
553 {
554  double start = stat->getClk();
555  bool changed = false;
556 
557  NodeID dstVar = load->getPAGDstNodeID();
558 
559  const PointsTo& srcPts = getPts(load->getPAGSrcNodeID());
560 
561  // p = *q, the type of p must be a pointer
562  if(load->getPAGDstNode()->isPointer())
563  {
564  for (PointsTo::iterator ptdIt = srcPts.begin(); ptdIt != srcPts.end(); ++ptdIt)
565  {
566  NodeID ptd = *ptdIt;
567 
568  if (pag->isConstantObj(ptd))
569  continue;
570 
571  if (unionPtsFromIn(load, ptd, dstVar))
572  changed = true;
573 
574  if (isFieldInsensitive(ptd))
575  {
578  const NodeBS& allFields = getAllFieldsObjVars(ptd);
579  for (NodeBS::iterator fieldIt = allFields.begin(), fieldEit = allFields.end();
580  fieldIt != fieldEit; ++fieldIt)
581  {
582  if (unionPtsFromIn(load, *fieldIt, dstVar))
583  changed = true;
584  }
585  }
586  }
587  }
588  double end = stat->getClk();
589  loadTime += (end - start) / TIMEINTERVAL;
590  return changed;
591 }
592 
600 {
601 
602  const PointsTo & dstPts = getPts(store->getPAGDstNodeID());
603 
610  if (dstPts.empty())
611  return false;
612 
613  double start = stat->getClk();
614  bool changed = false;
615 
616  // *p = q, the type of q must be a pointer
617  if(getPts(store->getPAGSrcNodeID()).empty() == false && store->getPAGSrcNode()->isPointer())
618  {
619  for (PointsTo::iterator it = dstPts.begin(), eit = dstPts.end(); it != eit; ++it)
620  {
621  NodeID ptd = *it;
622 
623  if (pag->isConstantObj(ptd))
624  continue;
625 
626  if (unionPtsFromTop(store, store->getPAGSrcNodeID(), ptd))
627  changed = true;
628  }
629  }
630 
631  double end = stat->getClk();
632  storeTime += (end - start) / TIMEINTERVAL;
633 
634  double updateStart = stat->getClk();
635  // also merge the DFInSet to DFOutSet.
637  NodeID singleton;
638  bool isSU = isStrongUpdate(store, singleton);
639  if (isSU)
640  {
641  svfgHasSU.set(store->getId());
642  if (strongUpdateOutFromIn(store, singleton))
643  changed = true;
644  }
645  else
646  {
647  svfgHasSU.reset(store->getId());
648  if (weakUpdateOutFromIn(store))
649  changed = true;
650  }
651  double updateEnd = stat->getClk();
652  updateTime += (updateEnd - updateStart) / TIMEINTERVAL;
653 
654  return changed;
655 }
656 
660 bool FlowSensitive::isStrongUpdate(const SVFGNode* node, NodeID& singleton)
661 {
662  bool isSU = false;
663  if (const StoreSVFGNode* store = SVFUtil::dyn_cast<StoreSVFGNode>(node))
664  {
665  const PointsTo& dstCPSet = getPts(store->getPAGDstNodeID());
666  if (dstCPSet.count() == 1)
667  {
669  PointsTo::iterator it = dstCPSet.begin();
670  singleton = *it;
671 
672  // Strong update can be made if this points-to target is not heap, array or field-insensitive.
673  if (!isHeapMemObj(singleton) && !isArrayMemObj(singleton)
674  && pag->getBaseObj(singleton)->isFieldInsensitive() == false
675  && !isLocalVarInRecursiveFun(singleton))
676  {
677  isSU = true;
678  }
679  }
680  }
681  return isSU;
682 }
683 
688 {
689  double start = stat->getClk();
690  CallEdgeMap newEdges;
691  onTheFlyCallGraphSolve(callsites, newEdges);
692 
693  // Bound the new edges by the Andersen's call graph.
694  // TODO: we want this to be an assertion eventually.
695  const CallEdgeMap &andersCallEdgeMap = ander->getIndCallMap();
696  for (typename CallEdgeMap::value_type &csfs : newEdges)
697  {
698  const CallICFGNode *potentialCallSite = csfs.first;
699  FunctionSet &potentialFunctionSet = csfs.second;
700 
701  // Check this callsite even calls anything per Andersen's.
702  typename CallEdgeMap::const_iterator andersFunctionSetIt
703  = andersCallEdgeMap.find(potentialCallSite);
704  if (andersFunctionSetIt == andersCallEdgeMap.end())
705  {
706  potentialFunctionSet.clear();
707  }
708 
709  const FunctionSet &andersFunctionSet = andersFunctionSetIt->second;
710  for (FunctionSet::iterator potentialFunctionIt = potentialFunctionSet.begin();
711  potentialFunctionIt != potentialFunctionSet.end(); )
712  {
713  const SVFFunction *potentialFunction = *potentialFunctionIt;
714  if (andersFunctionSet.find(potentialFunction) == andersFunctionSet.end())
715  {
716  // potentialFunction is not in the Andersen's call graph -- remove it.
717  potentialFunctionIt = potentialFunctionSet.erase(potentialFunctionIt);
718  }
719  else
720  {
721  // potentialFunction is in the Andersen's call graph -- keep it..
722  ++potentialFunctionIt;
723  }
724  }
725  }
726 
727  SVFGEdgeSetTy svfgEdges;
728  connectCallerAndCallee(newEdges, svfgEdges);
729 
730  updateConnectedNodes(svfgEdges);
731 
732  double end = stat->getClk();
733  updateCallGraphTime += (end - start) / TIMEINTERVAL;
734  return (!newEdges.empty());
735 }
736 
741 {
742  CallEdgeMap::const_iterator iter = newEdges.begin();
743  CallEdgeMap::const_iterator eiter = newEdges.end();
744  for (; iter != eiter; iter++)
745  {
746  const CallICFGNode* cs = iter->first;
747  const FunctionSet & functions = iter->second;
748  for (FunctionSet::const_iterator func_iter = functions.begin(); func_iter != functions.end(); func_iter++)
749  {
750  const SVFFunction* func = *func_iter;
751  svfg->connectCallerAndCallee(cs, func, edges);
752  }
753  }
754 }
755 
761 {
762  for (const SVFGEdge* edge : edges)
763  {
764  SVFGNode* dstNode = edge->getDstNode();
765  if (SVFUtil::isa<PHISVFGNode>(dstNode))
766  {
769  pushIntoWorklist(dstNode->getId());
770  }
771  else if (SVFUtil::isa<FormalINSVFGNode, ActualOUTSVFGNode>(dstNode))
772  {
775  bool changed = false;
776 
777  SVFGNode* srcNode = edge->getSrcNode();
778 
779  const NodeBS& pts = SVFUtil::cast<IndirectSVFGEdge>(edge)->getPointsTo();
780  for (NodeBS::iterator ptdIt = pts.begin(), ptdEit = pts.end(); ptdIt != ptdEit; ++ptdIt)
781  {
782  NodeID ptd = *ptdIt;
783 
784  if (propVarPtsAfterCGUpdated(ptd, srcNode, dstNode))
785  changed = true;
786 
787  if (isFieldInsensitive(ptd))
788  {
790  const NodeBS& allFields = getAllFieldsObjVars(ptd);
791  for (NodeBS::iterator fieldIt = allFields.begin(), fieldEit = allFields.end();
792  fieldIt != fieldEit; ++fieldIt)
793  {
794  if (propVarPtsAfterCGUpdated(*fieldIt, srcNode, dstNode))
795  changed = true;
796  }
797  }
798  }
799 
800  if (changed)
801  pushIntoWorklist(dstNode->getId());
802  }
803  }
804 }
805 
806 
811 {
812  if (SVFUtil::isa<StoreSVFGNode>(src))
813  {
814  if (propDFOutToIn(src, var, dst, var))
815  return true;
816  }
817  else
818  {
819  if (propDFInToIn(src, var, dst, var))
820  return true;
821  }
822  return false;
823 }
824 
826 {
827  std::vector<std::pair<unsigned, unsigned>> keys;
828  for (const auto& pair : *pag)
829  keys.emplace_back(pair.first, 1);
830 
831  PointsTo::MappingPtr nodeMapping =
832  std::make_shared<std::vector<NodeID>>(NodeIDAllocator::Clusterer::cluster(ander, keys, candidateMappings, "aux-ander"));
833  PointsTo::MappingPtr reverseNodeMapping =
834  std::make_shared<std::vector<NodeID>>(NodeIDAllocator::Clusterer::getReverseNodeMapping(*nodeMapping));
835 
836  PointsTo::setCurrentBestNodeMapping(nodeMapping, reverseNodeMapping);
837 }
838 
839 void FlowSensitive::plainMap(void) const
840 {
841  assert(Options::NodeAllocStrat() == NodeIDAllocator::Strategy::DENSE
842  && "FS::cluster: plain mapping requires dense allocation strategy.");
843 
844  const size_t numObjects = NodeIDAllocator::get()->getNumObjects();
845  PointsTo::MappingPtr plainMapping = std::make_shared<std::vector<NodeID>>(numObjects);
846  PointsTo::MappingPtr reversePlainMapping = std::make_shared<std::vector<NodeID>>(numObjects);
847  for (NodeID i = 0; i < plainMapping->size(); ++i)
848  {
849  plainMapping->at(i) = i;
850  reversePlainMapping->at(i) = i;
851  }
852 
853  PointsTo::setCurrentBestNodeMapping(plainMapping, reversePlainMapping);
854 }
855 
856 void FlowSensitive::countAliases(Set<std::pair<NodeID, NodeID>> cmp, unsigned *mayAliases, unsigned *noAliases)
857 {
858  for (std::pair<NodeID, NodeID> locPA : cmp)
859  {
860  // loc doesn't make a difference for FSPTA.
861  NodeID p = locPA.second;
862  for (std::pair<NodeID, NodeID> locPB : cmp)
863  {
864  if (locPB == locPA) continue;
865 
866  NodeID q = locPB.second;
867 
868  switch (alias(p, q))
869  {
871  ++(*noAliases);
872  break;
874  ++(*mayAliases);
875  break;
876  default:
877  assert("Not May/NoAlias?");
878  }
879  }
880  }
881 
882 }
#define DBOUT(TYPE, X)
LLVM debug macros, define type of your DBUG model of each pass.
Definition: SVFType.h:484
#define TIMEINTERVAL
Definition: SVFType.h:512
#define DGENERAL
Definition: SVFType.h:490
cJSON * p
Definition: cJSON.cpp:2559
copy
Definition: cJSON.cpp:414
const char *const string
Definition: cJSON.h:172
APOffset getConstantStructFldIdx() const
Get methods.
Definition: AccessPath.h:100
const PAGNode * getParam() const
Return parameter.
Definition: VFGNode.h:907
const PAGNode * getRev() const
Receive parameter at callsite.
Definition: VFGNode.h:1044
static AndersenWaveDiff * createAndersenWaveDiff(SVFIR *_pag)
Create an singleton instance directly instead of invoking llvm pass manager.
Definition: Andersen.h:408
void finalize() override
Finalization of pointer analysis, and normalize points-to information to Bit Vector representation.
void processNode(NodeID nodeId) override
Handle various constraints.
virtual void solveConstraints()
virtual void updateConnectedNodes(const SVFGEdgeSetTy &edges)
Update nodes connected during updating call graph.
static std::unique_ptr< FlowSensitive > fspta
virtual bool propagateFromAPToFP(const ActualParmSVFGNode *ap, const SVFGNode *dst)
virtual bool propagateFromFRToAR(const FormalRetSVFGNode *fr, const SVFGNode *dst)
NodeStack & SCCDetect() override
SCC detection.
bool isStrongUpdate(const SVFGNode *node, NodeID &singleton)
Return TRUE if this is a strong update STORE statement.
virtual void readPtsFromFile(const std::string &filename)
virtual void plainMap(void) const
Sets the global best mapping as a plain mapping, i.e. n -> n.
SVFG::SVFGEdgeSetTy SVFGEdgeSetTy
Definition: FlowSensitive.h:53
void analyze() override
Flow sensitive analysis.
bool propFromSrcToDst(SVFGEdge *edge) override
Propagation.
virtual void cluster(void)
void finalize() override
Finalize analysis.
virtual void countAliases(Set< std::pair< NodeID, NodeID >> cmp, unsigned *mayAliases, unsigned *noAliases)
Fills may/noAliases for the location/pointer pairs in cmp.
bool processSVFGNode(SVFGNode *node)
virtual bool processLoad(const LoadSVFGNode *load)
bool propVarPtsAfterCGUpdated(NodeID var, const SVFGNode *src, const SVFGNode *dst)
virtual bool processPhi(const PHISVFGNode *phi)
virtual bool processStore(const StoreSVFGNode *store)
virtual bool processCopy(const CopySVFGNode *copy)
bool updateCallGraph(const CallSiteToFunPtrMap &callsites) override
Update call graph.
virtual bool processAddr(const AddrSVFGNode *addr)
virtual bool propAlongDirectEdge(const DirectSVFGEdge *edge)
Propagate points-to information along a DIRECT SVFG edge.
void initialize() override
Initialize analysis.
void connectCallerAndCallee(const CallEdgeMap &newEdges, SVFGEdgeSetTy &edges)
Connect nodes in SVFG.
virtual bool processGep(const GepSVFGNode *edge)
virtual bool propVarPtsFromSrcToDst(NodeID var, const SVFGNode *src, const SVFGNode *dst)
Propagate points-to information of a certain variable from src to dst.
virtual bool propAlongIndirectEdge(const IndirectSVFGEdge *edge)
Propagate points-to information along an INDIRECT SVFG edge.
virtual void solveAndwritePtsToFile(const std::string &filename)
const PAGNode * getParam() const
Return parameter.
Definition: VFGNode.h:959
const PAGNode * getRet() const
Return value at callee.
Definition: VFGNode.h:1095
NodeType * getSrcNode() const
Definition: GenericGraph.h:97
NodeType * getDstNode() const
Definition: GenericGraph.h:101
GEdgeSetTy::const_iterator const_iterator
Definition: GenericGraph.h:406
bool isVariantFieldGep() const
Gep statement with a variant field index (pointer arithmetic) for struct field access.
const AccessPath & getAccessPath() const
const NodeBS & getPointsTo() const
Definition: SVFGEdge.h:60
static std::vector< NodeID > cluster(BVDataPTAImpl *pta, const std::vector< std::pair< NodeID, unsigned >> keys, std::vector< std::pair< hclust_fast_methods, std::vector< NodeID >>> &candidates, std::string evalSubtitle="")
static std::vector< NodeID > getReverseNodeMapping(const std::vector< NodeID > &nodeMapping)
static void printStats(std::string title, Map< std::string, std::string > &stats)
static void evaluate(const std::vector< NodeID > &nodeMap, const Map< PointsTo, unsigned > pointsToSets, Map< std::string, std::string > &stats, bool accountForOcc)
Fills in *NumWords statistics in stats..
static NodeIDAllocator * get(void)
Return (singleton) allocator.
NodeID getNumObjects(void) const
Returns the total number of memory objects.
static const Option< bool > PlainMappingFs
Use an explicitly plain mapping with flow-sensitive (not null).
Definition: Options.h:47
static const OptionMap< SVF::NodeIDAllocator::Strategy > NodeAllocStrat
Definition: Options.h:35
static const Option< std::string > ReadAnder
Definition: Options.h:214
static const Option< bool > ClusterAnder
Whether to stage Andersen's with Steensgaard and cluster based on that data.
Definition: Options.h:41
static const Option< u32_t > FsTimeLimit
Time limit for the main phase (i.e., the actual solving) of FS analyses.
Definition: Options.h:72
static const Option< bool > ClusterFs
Whether to cluster FS or VFS with the auxiliary Andersen's.
Definition: Options.h:44
static const Option< std::string > WriteAnder
Definition: Options.h:212
static const Option< bool > DumpVFG
Definition: Options.h:111
OPVers::const_iterator opVerBegin() const
Definition: VFGNode.h:707
const PAGNode * getRes() const
Definition: VFGNode.h:699
OPVers::const_iterator opVerEnd() const
Definition: VFGNode.h:711
virtual Map< DataSet, unsigned > getAllPts(bool liveOnly) const =0
OrderedMap< const CallICFGNode *, FunctionSet > CallEdgeMap
virtual void initialize()
Initialization of a pointer analysis, including building symbol table and SVFIR etc.
Set< const SVFFunction * > FunctionSet
SVFIR::CallSiteToFunPtrMap CallSiteToFunPtrMap
bool empty() const
Returns true if set is empty.
Definition: PointsTo.cpp:98
const_iterator end() const
Definition: PointsTo.h:132
std::shared_ptr< std::vector< NodeID > > MappingPtr
Definition: PointsTo.h:42
static void setCurrentBestNodeMapping(MappingPtr newCurrentBestNodeMapping, MappingPtr newCurrentBestReverseNodeMapping)
Definition: PointsTo.cpp:371
u32_t count() const
Returns number of elements.
Definition: PointsTo.cpp:111
void set(u32_t n)
Inserts n in the set.
Definition: PointsTo.cpp:157
const_iterator begin() const
Definition: PointsTo.h:128
static MappingPtr getCurrentBestNodeMapping()
Definition: PointsTo.cpp:361
NodeID getId() const
Get ID.
Definition: GenericGraph.h:260
virtual bool isPointer() const
Whether it is a pointer.
Definition: SVFVariables.h:106
iterator end() const
unsigned count() const
iterator begin() const
NodeID getPAGDstNodeID() const
Definition: VFGNode.h:157
const PAGEdge * getPAGEdge() const
Definition: VFGNode.h:147
NodeID getPAGSrcNodeID() const
Definition: VFGNode.h:152
PAGNode * getPAGSrcNode() const
Definition: VFGNode.h:162
PAGNode * getPAGDstNode() const
Definition: VFGNode.h:167
virtual NodeStack & SCCDetect()
SCC detection.
Definition: WPAFSSolver.h:67
virtual NodeStack & SCCDetect()
SCC detection.
Definition: WPASolver.h:86
hclust_fast_methods
Definition: fastcluster.h:66
std::string hclustMethodToString(hclust_fast_methods method)
Returns a string representation of a hclust method.
Definition: SVFUtil.cpp:260
void stopAnalysisLimitTimer(bool limitTimerSet)
Definition: SVFUtil.cpp:310
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
bool startAnalysisLimitTimer(unsigned timeLimit)
Definition: SVFUtil.cpp:289
std::ostream & outs()
Overwrite llvm::outs()
Definition: SVFUtil.h:50
for isBitcode
Definition: BasicTypes.h:68
std::stack< NodeID > NodeStack
Definition: GeneralType.h:118
u32_t NodeID
Definition: GeneralType.h:55
@ MayAlias
Definition: SVFType.h:529
@ NoAlias
Definition: SVFType.h:528
std::unordered_map< Key, Value, Hash, KeyEqual, Allocator > Map
Definition: GeneralType.h:101
std::unordered_set< Key, Hash, KeyEqual, Allocator > Set
Definition: GeneralType.h:96