Static Value-Flow Analysis
FlowDDA.cpp
Go to the documentation of this file.
1 //===- FlowDDA.cpp -- Flow-sensitive demand-driven analysis -------------//
2 //
3 // SVF: Static Value-Flow Analysis
4 //
5 // Copyright (C) <2013-> <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  * FlowDDA.cpp
25  *
26  * Created on: Jun 30, 2014
27  * Author: Yulei Sui, Sen Ye
28  */
29 
30 #include "Util/Options.h"
31 #include "DDA/FlowDDA.h"
32 #include "DDA/DDAClient.h"
33 #include "MemoryModel/PointsTo.h"
34 
35 using namespace std;
36 using namespace SVF;
37 using namespace SVFUtil;
38 
39 
43 void FlowDDA::computeDDAPts(NodeID id)
44 {
45  resetQuery();
46  LocDPItem::setMaxBudget(Options::FlowBudget());
47 
48  PAGNode* node = getPAG()->getGNode(id);
49  LocDPItem dpm = getDPIm(node->getId(),getDefSVFGNode(node));
50 
52  DOTIMESTAT(double start = DDAStat::getClk(true));
53  const PointsTo& pts = findPT(dpm);
54  DOTIMESTAT(ddaStat->_AnaTimePerQuery = DDAStat::getClk(true) - start);
55  DOTIMESTAT(ddaStat->_TotalTimeOfQueries += ddaStat->_AnaTimePerQuery);
56 
57  if(isOutOfBudgetQuery() == false)
58  unionPts(node->getId(),pts);
59  else
60  handleOutOfBudgetDpm(dpm);
61 
62  if(this->printStat())
63  DOSTAT(stat->performStatPerQuery(node->getId()));
64 
65  DBOUT(DGENERAL,stat->printStatPerQuery(id,getPts(id)));
66 }
67 
68 
72 void FlowDDA::handleOutOfBudgetDpm(const LocDPItem& dpm)
73 {
74  DBOUT(DGENERAL,outs() << "~~~Out of budget query, downgrade to andersen analysis \n");
75  const PointsTo& anderPts = getAndersenAnalysis()->getPts(dpm.getCurNodeID());
76  updateCachedPointsTo(dpm,anderPts);
77  unionPts(dpm.getCurNodeID(),anderPts);
78  addOutOfBudgetDpm(dpm);
79 }
80 
81 bool FlowDDA::testIndCallReachability(LocDPItem&, const SVFFunction* callee, CallSiteID csId)
82 {
83 
84  const CallICFGNode* cbn = getSVFG()->getCallSite(csId);
85 
86  if(getPAG()->isIndirectCallSites(cbn))
87  {
88  if(getCallGraph()->hasIndCSCallees(cbn))
89  {
90  const FunctionSet& funset = getCallGraph()->getIndCSCallees(cbn);
91  if(funset.find(callee)!=funset.end())
92  return true;
93  }
94 
95  return false;
96  }
97  else // if this is an direct call
98  return true;
99 
100 }
101 
102 bool FlowDDA::handleBKCondition(LocDPItem& dpm, const SVFGEdge* edge)
103 {
104  _client->handleStatement(edge->getSrcNode(), dpm.getCurNodeID());
105 // CallSiteID csId = 0;
106 //
107 // if (edge->isCallVFGEdge()) {
108 // /// we don't handle context in recursions, they treated as assignments
109 // if (const CallDirSVFGEdge* callEdge = SVFUtil::dyn_cast<CallDirSVFGEdge>(edge))
110 // csId = callEdge->getCallSiteId();
111 // else
112 // csId = SVFUtil::cast<CallIndSVFGEdge>(edge)->getCallSiteId();
113 //
114 // const SVFFunction* callee = edge->getDstNode()->getBB()->getParent();
115 // if(testIndCallReachability(dpm,callee,csId)==false){
116 // return false;
117 // }
118 //
119 // }
120 //
121 // else if (edge->isRetVFGEdge()) {
122 // /// we don't handle context in recursions, they treated as assignments
123 // if (const RetDirSVFGEdge* retEdge = SVFUtil::dyn_cast<RetDirSVFGEdge>(edge))
124 // csId = retEdge->getCallSiteId();
125 // else
126 // csId = SVFUtil::cast<RetIndSVFGEdge>(edge)->getCallSiteId();
127 //
128 // const SVFFunction* callee = edge->getSrcNode()->getBB()->getParent();
129 // if(testIndCallReachability(dpm,callee,csId)==false){
130 // return false;
131 // }
132 //
133 // }
134 
135  return true;
136 }
137 
141 PointsTo FlowDDA::processGepPts(const GepSVFGNode* gep, const PointsTo& srcPts)
142 {
143  PointsTo tmpDstPts;
144  for (PointsTo::iterator piter = srcPts.begin(); piter != srcPts.end(); ++piter)
145  {
146  NodeID ptd = *piter;
147  if (isBlkObjOrConstantObj(ptd))
148  tmpDstPts.set(ptd);
149  else
150  {
151  const GepStmt* gepStmt = SVFUtil::cast<GepStmt>(gep->getPAGEdge());
152  if (gepStmt->isVariantFieldGep())
153  {
154  setObjFieldInsensitive(ptd);
155  tmpDstPts.set(getFIObjVar(ptd));
156  }
157  else
158  {
159  NodeID fieldSrcPtdNode = getGepObjVar(ptd, gepStmt->getAccessPath().getConstantStructFldIdx());
160  tmpDstPts.set(fieldSrcPtdNode);
161  }
162  }
163  }
164  DBOUT(DDDA, outs() << "\t return created gep objs {");
165  DBOUT(DDDA, SVFUtil::dumpSet(srcPts));
166  DBOUT(DDDA, outs() << "} --> {");
167  DBOUT(DDDA, SVFUtil::dumpSet(tmpDstPts));
168  DBOUT(DDDA, outs() << "}\n");
169  return tmpDstPts;
170 }
171 
177 bool FlowDDA::isHeapCondMemObj(const NodeID& var, const StoreSVFGNode*)
178 {
179  const MemObj* mem = _pag->getObject(getPtrNodeID(var));
180  assert(mem && "memory object is null??");
181  if(mem->isHeap())
182  {
183 // if(const Instruction* mallocSite = SVFUtil::dyn_cast<Instruction>(mem->getValue())) {
184 // const SVFFunction* fun = mallocSite->getParent()->getParent();
185 // const SVFFunction* curFun = store->getBB() ? store->getBB()->getParent() : nullptr;
186 // if(fun!=curFun)
187 // return true;
188 // if(_callGraphSCC->isInCycle(_callGraph->getCallGraphNode(fun)->getId()))
189 // return true;
190 // if(_pag->getICFG()->isInLoop(mallocSite))
191 // return true;
192 //
193 // return false;
194 // }
195  return true;
196  }
197  return false;
198 }
#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
#define DDDA
Definition: SVFType.h:496
#define DOSTAT(X)
Definition: SVFType.h:485
#define DOTIMESTAT(X)
Definition: SVFType.h:486
APOffset getConstantStructFldIdx() const
Get methods.
Definition: AccessPath.h:100
NodeID getCurNodeID() const
Definition: DPItem.h:77
BVDataPTAImpl::FunctionSet FunctionSet
Definition: FlowDDA.h:59
NodeType * getSrcNode() const
Definition: GenericGraph.h:97
bool isVariantFieldGep() const
Gep statement with a variant field index (pointer arithmetic) for struct field access.
const AccessPath & getAccessPath() const
bool isHeap() const
const_iterator end() const
Definition: PointsTo.h:132
void set(u32_t n)
Inserts n in the set.
Definition: PointsTo.cpp:157
const_iterator begin() const
Definition: PointsTo.h:128
NodeID getId() const
Get ID.
Definition: GenericGraph.h:260
const PAGEdge * getPAGEdge() const
Definition: VFGNode.h:147
void dumpSet(NodeBS To, OutStream &O=SVFUtil::outs())
Dump sparse bitvector set.
Definition: SVFUtil.cpp:147
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