Static Value-Flow Analysis
Loading...
Searching...
No Matches
ContextDDA.cpp
Go to the documentation of this file.
1//===- ContextDDA.cpp -- Context-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 * ContextDDA.cpp
25 *
26 * Created on: Aug 17, 2014
27 * Author: Yulei Sui
28 */
29
30#include "Util/Options.h"
31#include "DDA/ContextDDA.h"
32#include "DDA/FlowDDA.h"
33#include "DDA/DDAClient.h"
35
36using namespace SVF;
37using namespace SVFUtil;
38
48
53{
54 if(flowDDA)
55 delete flowDDA;
56 flowDDA = nullptr;
57}
58
71
76{
77
78 resetQuery();
80
81 NodeID id = var.get_id();
82 PAGNode* node = getPAG()->getGNode(id);
84
85 // start DDA analysis
86 DOTIMESTAT(double start = DDAStat::getClk(true));
87 const CxtPtSet& cpts = findPT(dpm);
90
91 if(isOutOfBudgetQuery() == false)
92 unionPts(var,cpts);
93 else
95
96 if (this->printStat())
99 return this->getPts(var);
100}
101
106{
107 ContextCond cxt;
108 CxtVar var(cxt, id);
110}
111
116{
117
118 DBOUT(DGENERAL,outs() << "~~~Out of budget query, downgrade to flow sensitive analysis \n");
119 flowDDA->computeDDAPts(dpm.getCurNodeID());
120 const PointsTo& flowPts = flowDDA->getPts(dpm.getCurNodeID());
122 for(PointsTo::iterator it = flowPts.begin(), eit = flowPts.end(); it!=eit; ++it)
123 {
124 ContextCond cxt;
125 CxtVar var(cxt, *it);
126 cxtPts.set(var);
127 }
129 unionPts(dpm.getCondVar(),cxtPts);
131}
132
137{
138 if(singleton)
139 return true;
140
141 int i = cxt1.cxtSize() - 1;
142 int j = cxt2.cxtSize() - 1;
143 for(; i >= 0 && j>=0; i--, j--)
144 {
145 if(cxt1[i] != cxt2[j])
146 return false;
147 }
148 return true;
149}
150
155{
157 for (CxtPtSet::iterator piter = srcPts.begin(); piter != srcPts.end(); ++piter)
158 {
159
160 CxtVar ptd = *piter;
161 if (isBlkObjOrConstantObj(ptd.get_id()))
162 tmpDstPts.set(ptd);
163 else
164 {
165 const GepStmt* gepStmt = SVFUtil::cast<GepStmt>(gep->getPAGEdge());
166 if (gepStmt->isVariantFieldGep())
167 {
168 setObjFieldInsensitive(ptd.get_id());
169 CxtVar var(ptd.get_cond(),getFIObjVar(ptd.get_id()));
170 tmpDstPts.set(var);
171 }
172 else
173 {
174 CxtVar var(ptd.get_cond(),getGepObjVar(ptd.get_id(),
175 gepStmt->getAccessPath().getConstantStructFldIdx()));
176 tmpDstPts.set(var);
177 }
178 }
179 }
180
181 DBOUT(DDDA, outs() << "\t return created gep objs ");
182 DBOUT(DDDA, outs() << srcPts.toString());
183 DBOUT(DDDA, outs() << " --> ");
184 DBOUT(DDDA, outs() << tmpDstPts.toString());
185 DBOUT(DDDA, outs() << "\n");
186 return tmpDstPts;
187}
188
190{
191 if(getPAG()->isIndirectCallSites(cs))
192 {
193 NodeID id = getPAG()->getFunPtr(cs);
194 PAGNode* node = getPAG()->getGNode(id);
195 CxtVar funptrVar(dpm.getCondVar().get_cond(), id);
198 if(pts.test(getPAG()->getObjectNode(callee)))
199 return true;
200 else
201 return false;
202 }
203 return true;
204}
205
211{
212
214 if (const CallDirSVFGEdge* callEdge = SVFUtil::dyn_cast<CallDirSVFGEdge>(edge))
215 svfg_csId = callEdge->getCallSiteId();
216 else
217 svfg_csId = SVFUtil::cast<CallIndSVFGEdge>(edge)->getCallSiteId();
218
220 const SVFFunction* callee = edge->getDstNode()->getFun();
221
222 if(getCallGraph()->hasCallSiteID(cbn,callee))
223 {
225 }
226
227 return 0;
228}
229
235{
236
238 if (const RetDirSVFGEdge* retEdge = SVFUtil::dyn_cast<RetDirSVFGEdge>(edge))
239 svfg_csId = retEdge->getCallSiteId();
240 else
241 svfg_csId = SVFUtil::cast<RetIndSVFGEdge>(edge)->getCallSiteId();
242
244 const SVFFunction* callee = edge->getSrcNode()->getFun();
245
246 if(getCallGraph()->hasCallSiteID(cbn,callee))
247 {
249 }
250
251 return 0;
252}
253
254
257{
258 _client->handleStatement(edge->getSrcNode(), dpm.getCurNodeID());
259
260 if (edge->isCallVFGEdge())
261 {
263 if(CallSiteID csId = getCSIDAtCall(dpm,edge))
264 {
265
266 if(isEdgeInRecursion(csId))
267 {
268 DBOUT(DDDA,outs() << "\t\t call edge " << getCallGraph()->getCallerOfCallSite(csId)->getName() <<
269 "=>" << getCallGraph()->getCalleeOfCallSite(csId)->getName() << "in recursion \n");
271 }
272 else
273 {
274 if (dpm.matchContext(csId) == false)
275 {
276 DBOUT(DDDA, outs() << "\t\t context not match, edge "
277 << edge->getDstID() << " --| " << edge->getSrcID() << " \t");
278 DBOUT(DDDA, dumpContexts(dpm.getCond()));
279 return false;
280 }
281
282 DBOUT(DDDA, outs() << "\t\t match contexts ");
283 DBOUT(DDDA, dumpContexts(dpm.getCond()));
284 }
285 }
286 }
287
288 else if (edge->isRetVFGEdge())
289 {
291 if(CallSiteID csId = getCSIDAtRet(dpm,edge))
292 {
293
294 if(isEdgeInRecursion(csId))
295 {
296 DBOUT(DDDA,outs() << "\t\t return edge " << getCallGraph()->getCalleeOfCallSite(csId)->getName() <<
297 "=>" << getCallGraph()->getCallerOfCallSite(csId)->getName() << "in recursion \n");
299 }
300 else
301 {
304 if (dpm.getCond().containCallStr(csId))
305 {
306 outOfBudgetQuery = true;
307 SVFUtil::writeWrnMsg("Call site ID is contained in call string. Is this a recursion?");
308 return false;
309 }
310 else
311 {
312 assert(dpm.getCond().containCallStr(csId) ==false && "contain visited call string ??");
313 if(dpm.pushContext(csId))
314 {
315 DBOUT(DDDA, outs() << "\t\t push context ");
316 DBOUT(DDDA, dumpContexts(dpm.getCond()));
317 }
318 else
319 {
320 DBOUT(DDDA, outs() << "\t\t context is full ");
321 DBOUT(DDDA, dumpContexts(dpm.getCond()));
322 }
323 }
324 }
325 }
326 }
327
328 return true;
329}
330
331
336{
337 const MemObj* mem = _pag->getObject(getPtrNodeID(var));
338 assert(mem && "memory object is null??");
340 assert(baseVar && "base object is null??");
341 if (SVFUtil::isa<HeapObjVar, DummyObjVar>(baseVar))
342 {
343 if (!mem->getValue())
344 {
346 GepObjVar* gepobj = SVFUtil::dyn_cast<GepObjVar>(pnode);
347 if (gepobj != nullptr)
348 {
349 assert(SVFUtil::isa<DummyObjVar>(_pag->getGNode(gepobj->getBaseNode()))
350 && "empty refVal in a gep object whose base is a non-dummy object");
351 }
352 else
353 {
354 assert((SVFUtil::isa<DummyObjVar, DummyValVar>(pnode))
355 && "empty refVal in non-dummy object");
356 }
357 return true;
358 }
359 else if(const SVFBaseNode* gNode = mem->getGNode())
360 {
361 if (const auto& node =
362 SVFUtil::dyn_cast<ICFGNode>(gNode))
363 {
364 const SVFFunction* svfFun = node->getFun();
366 return true;
367 if(var.get_cond().isConcreteCxt() == false)
368 return true;
369 if(_pag->getICFG()->isInLoop(node))
370 return true;
371 }
372 }
373 }
374 return false;
375}
#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
const PointsTo & getPts(NodeID id) override
virtual bool unionPts(CVar id, const CPtSet &target)
virtual PointsTo getBVPointsTo(const CPtSet &cpts) const
Given a conditional pts return its bit vector points-to.
virtual const CPtSet & getPts(CVar id)
OrderedSet< Element >::iterator iterator
virtual bool isHeapCondMemObj(const CxtVar &var, const StoreSVFGNode *store) override
bool testIndCallReachability(CxtLocDPItem &dpm, const SVFFunction *callee, const CallICFGNode *cs)
refine indirect call edge
void handleOutOfBudgetDpm(const CxtLocDPItem &dpm)
Handle out-of-budget dpm.
virtual void popRecursiveCallSites(CxtLocDPItem &dpm)
Pop recursive callsites.
Definition ContextDDA.h:123
FlowDDA * flowDDA
downgrade to flowDDA if out-of-budget
Definition ContextDDA.h:224
CallSiteID getCSIDAtCall(CxtLocDPItem &dpm, const SVFGEdge *edge)
get callsite id from call, return 0 if it is a spurious call edge
virtual void computeDDAPts(NodeID id) override
Compute points-to set for an unconditional pointer.
virtual bool isEdgeInRecursion(CallSiteID csId)
Whether call/return inside recursion.
Definition ContextDDA.h:134
virtual bool isCondCompatible(const ContextCond &cxt1, const ContextCond &cxt2, bool singleton) const override
virtual ~ContextDDA()
Destructor.
virtual NodeID getPtrNodeID(const CxtVar &var) const override
Override parent method.
Definition ContextDDA.h:100
CallSiteID getCSIDAtRet(CxtLocDPItem &dpm, const SVFGEdge *edge)
get callsite id from return, return 0 if it is a spurious return edge
virtual bool handleBKCondition(CxtLocDPItem &dpm, const SVFGEdge *edge) override
Handle condition for context or path analysis (backward analysis)
virtual void dumpContexts(const ContextCond &cxts)
dump context call strings
Definition ContextDDA.h:212
ContextDDA(SVFIR *_pag, DDAClient *client)
Constructor.
virtual void initialize() override
Initialization of the analysis.
DDAClient * _client
DDA client.
Definition ContextDDA.h:225
virtual CxtPtSet processGepPts(const GepSVFGNode *gep, const CxtPtSet &srcPts) override
processGep node
virtual void handleStatement(const SVFGNode *, NodeID)
Call back used by DDAVFSolver.
Definition DDAClient.h:77
double _AnaTimePerQuery
Definition DDAStat.h:61
double _TotalTimeOfQueries
Definition DDAStat.h:63
virtual void updateCachedPointsTo(const CxtLocDPItem &dpm, const CxtPtSet &pts)
AndersenWaveDiff * _ander
Andersen's analysis.
const SVFGNode * getDefSVFGNode(const PAGNode *pagNode) const
GetDefinition SVFG.
virtual const CxtPtSet & findPT(const CxtLocDPItem &dpm)
Compute points-to.
void setCallGraphSCC(CallGraphSCC *scc)
Set callgraphSCC.
virtual CxtLocDPItem getDPIm(const CxtVar &var, const SVFGNode *loc) const
Given CVar and location (SVFGNode) return a new DPItem.
Definition DDAVFSolver.h:96
void addOutOfBudgetDpm(const CxtLocDPItem &dpm)
virtual void buildSVFG(SVFIR *pag)
Build SVFG.
DDAStat * setDDAStat(DDAStat *s)
Set DDAStat.
void setCallGraph(PTACallGraph *cg)
Set callgraph.
bool outOfBudgetQuery
Whether the current query is out of step limits.
virtual void resetQuery()
Reset visited map for next points-to query.
static void setMaxBudget(u32_t max)
set max step budge per query
Definition DPItem.h:86
void computeDDAPts(NodeID id) override
Compute points-to set for all top variable.
Definition FlowDDA.cpp:43
virtual void initialize() override
Initialization of the analysis.
Definition FlowDDA.h:86
NodeType * getGNode(NodeID id) const
Get a node.
bool isInLoop(const ICFGNode *node)
Whether node is in a loop.
Definition ICFG.h:117
const SVFBaseNode * getGNode() const
Get the reference value to this object.
const SVFValue * getValue() const
Get the reference value to this object.
static const Option< u32_t > CxtBudget
Definition Options.h:81
CallSiteID getCallSiteID(const CallICFGNode *cs, const SVFFunction *callee) const
Get CallSiteID.
virtual void initialize()
Initialization of a pointer analysis, including building symbol table and SVFIR etc.
virtual bool isBlkObjOrConstantObj(NodeID ptd) const
bool printStat()
Whether print statistics.
PTAStat * stat
Statistics.
NodeID getFIObjVar(NodeID id)
SVFIR * getPAG() const
PTACallGraph * getCallGraph() const
Return call graph.
bool isInRecursion(const SVFFunction *fun) const
NodeID getGepObjVar(NodeID id, const APOffset &ap)
void setObjFieldInsensitive(NodeID id)
static SVFIR * pag
SVFIR.
CallGraphSCC * getCallGraphSCC() const
Return call graph SCC.
NodeID getFunPtr(const CallICFGNode *cs) const
Definition SVFIR.h:355
const BaseObjVar * getBaseObject(NodeID id) const
Definition SVFIR.h:405
ICFG * getICFG() const
Definition SVFIR.h:172
const MemObj * getObject(NodeID id) const
Definition SVFIR.h:396
virtual void printStatPerQuery(NodeID, const PointsTo &)
Definition SVFStat.h:89
virtual void performStatPerQuery(NodeID)
Definition SVFStat.h:87
static double getClk(bool mark=false)
Definition SVFStat.cpp:48
const CallICFGNode * getCallSite(CallSiteID id) const
Definition VFG.h:182
void writeWrnMsg(const std::string &msg)
Writes a message run through wrnMsg.
Definition SVFUtil.cpp:67
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
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74