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 const ValVar* node = getPAG()->getValVar(id);
83 CxtLocDPItem dpm = getDPIm(var, getDefSVFGNode(node));
84
85 // start DDA analysis
86 DOTIMESTAT(double start = DDAStat::getClk(true));
87 const CxtPtSet& cpts = findPT(dpm);
88 DOTIMESTAT(ddaStat->_AnaTimePerQuery = DDAStat::getClk(true) - start);
89 DOTIMESTAT(ddaStat->_TotalTimeOfQueries += ddaStat->_AnaTimePerQuery);
90
91 if(isOutOfBudgetQuery() == false)
92 unionPts(var,cpts);
93 else
95
96 if (this->printStat())
97 DOSTAT(stat->performStatPerQuery(id));
98 DBOUT(DGENERAL, stat->printStatPerQuery(id,getBVPointsTo(getPts(var))));
99 return this->getPts(var);
100}
101
106{
107 ContextCond cxt;
108 CxtVar var(cxt, id);
109 computeDDAPts(var);
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());
121 CxtPtSet cxtPts;
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 }
128 updateCachedPointsTo(dpm,cxtPts);
129 unionPts(dpm.getCondVar(),cxtPts);
131}
132
136bool ContextDDA::isCondCompatible(const ContextCond& cxt1, const ContextCond& cxt2, bool singleton) const
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{
156 CxtPtSet tmpDstPts;
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->getSVFStmt());
166 if (gepStmt->isVariantFieldGep())
167 {
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(),
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 const ValVar* node = getPAG()->getValVar(id);
195 CxtVar funptrVar(dpm.getCondVar().get_cond(), id);
196 CxtLocDPItem funptrDpm = getDPIm(funptrVar,getDefSVFGNode(node));
197 PointsTo pts = getBVPointsTo(findPT(funptrDpm));
198 if(pts.test(callee->getId()))
199 return true;
200 else
201 return false;
202 }
203 return true;
204}
205
211{
212
213 CallSiteID svfg_csId = 0;
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
219 const CallICFGNode* cbn = getSVFG()->getCallSite(svfg_csId);
220 const FunObjVar* callee = edge->getDstNode()->getFun();
221
222 if(getCallGraph()->hasCallSiteID(cbn,callee))
223 {
224 return getCallGraph()->getCallSiteID(cbn,callee);
225 }
226
227 return 0;
228}
229
235{
236
237 CallSiteID svfg_csId = 0;
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
243 const CallICFGNode* cbn = getSVFG()->getCallSite(svfg_csId);
244 const FunObjVar* callee = edge->getSrcNode()->getFun();
245
246 if(getCallGraph()->hasCallSiteID(cbn,callee))
247 {
248 return getCallGraph()->getCallSiteID(cbn,callee);
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");
279 return false;
280 }
281
282 DBOUT(DDDA, outs() << "\t\t match contexts ");
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 ");
317 }
318 else
319 {
320 DBOUT(DDDA, outs() << "\t\t context is full ");
322 }
323 }
324 }
325 }
326 }
327
328 return true;
329}
330
331
336{
337 const BaseObjVar* obj = _pag->getBaseObject(getPtrNodeID(var));
338 assert(obj && "base object is null??");
339 const BaseObjVar* baseVar = _pag->getBaseObject(getPtrNodeID(var));
340 assert(baseVar && "base object is null??");
342 {
343 if (isa<DummyObjVar>(baseVar))
344 {
345 const SVFVar* pnode = _pag->getSVFVar(getPtrNodeID(var));
346 const GepObjVar* gepobj = SVFUtil::dyn_cast<GepObjVar>(pnode);
347 if (gepobj != nullptr)
348 {
349 assert(SVFUtil::isa<DummyObjVar>(_pag->getSVFVar(gepobj->getBaseNode()))
350 && "empty refVal in a gep object whose base is a non-dummy object");
351 }
352 else
353 {
355 && "empty refVal in non-dummy object");
356 }
357 return true;
358 }
359 else if(const ICFGNode* node = obj->getICFGNode())
360 {
361 const FunObjVar* svfFun = node->getFun();
362 if(_ander->isInRecursion(svfFun))
363 return true;
364 if(var.get_cond().isConcreteCxt() == false)
365 return true;
366 if(_pag->getICFG()->isInLoop(node))
367 return true;
368 }
369 }
370 return false;
371}
#define DBOUT(TYPE, X)
LLVM debug macros, define type of your DBUG model of each pass.
Definition SVFType.h:576
#define DGENERAL
Definition SVFType.h:582
#define DDDA
Definition SVFType.h:588
#define DOSTAT(X)
Definition SVFType.h:577
#define DOTIMESTAT(X)
Definition SVFType.h:578
APOffset getConstantStructFldIdx() const
Get methods.
Definition AccessPath.h:102
NodeID getId() const
Get the memory object id.
const ICFGNode * getICFGNode() const
Get the ICFGNode related to the creation of this object.
CallSiteID getCallSiteID(const CallICFGNode *cs, const FunObjVar *callee) const
Get CallSiteID.
Definition CallGraph.h:389
virtual bool unionPts(CVar id, const CPtSet &target)
CondPTAImpl(SVFIR *pag, PTATY type)
virtual PointsTo getBVPointsTo(const CPtSet &cpts) const
virtual const CPtSet & getPts(CVar id)
std::string toString() const
OrderedSet< CxtVar >::iterator iterator
iterator begin()
Iterators.
void set(const Element &var)
Add the element into set.
NodeID get_id() const
const Cond & get_cond() const
u32_t cxtSize() const
Get context size.
Definition DPItem.h:261
bool containCallStr(NodeID cxt) const
Whether contains callstring cxt.
Definition DPItem.h:256
bool isConcreteCxt() const
Whether it is an concrete context.
Definition DPItem.h:246
virtual bool isHeapCondMemObj(const CxtVar &var, const StoreSVFGNode *store) override
void handleOutOfBudgetDpm(const CxtLocDPItem &dpm)
Handle out-of-budget dpm.
virtual void popRecursiveCallSites(CxtLocDPItem &dpm)
Pop recursive callsites.
Definition ContextDDA.h:124
FlowDDA * flowDDA
downgrade to flowDDA if out-of-budget
Definition ContextDDA.h:225
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:135
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:101
CallSiteID getCSIDAtRet(CxtLocDPItem &dpm, const SVFGEdge *edge)
get callsite id from return, return 0 if it is a spurious return edge
bool testIndCallReachability(CxtLocDPItem &dpm, const FunObjVar *callee, const CallICFGNode *cs)
refine indirect call 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:213
ContextDDA(SVFIR *_pag, DDAClient *client)
Constructor.
virtual void initialize() override
Initialization of the analysis.
DDAClient * _client
DDA client.
Definition ContextDDA.h:226
virtual CxtPtSet processGepPts(const GepSVFGNode *gep, const CxtPtSet &srcPts) override
processGep node
bool matchContext(NodeID cxt)
Match context.
Definition DPItem.h:431
bool pushContext(NodeID cxt)
Push context.
Definition DPItem.h:425
CxtVar getCondVar() const
Get context var.
Definition DPItem.h:409
const ContextCond & getCond() const
Get context.
Definition DPItem.h:415
virtual void updateCachedPointsTo(const CxtLocDPItem &dpm, const CxtPtSet &pts)
virtual const CxtPtSet & findPT(const CxtLocDPItem &dpm)
const SVFGNode * getDefSVFGNode(const ValVar *valVar) const
virtual CxtLocDPItem getDPIm(const CxtVar &var, const SVFGNode *loc) const
Definition DDAVFSolver.h:98
void addOutOfBudgetDpm(const CxtLocDPItem &dpm)
NodeID getCurNodeID() const
Definition DPItem.h:78
static void setMaxBudget(u32_t max)
set max step budge per query
Definition DPItem.h:87
NodeType * getSrcNode() const
NodeType * getDstNode() const
NodeID getDstID() const
NodeID getSrcID() const
get methods of the components
NodeID getBaseNode(void) const
Return the base object from which this GEP node came from.
bool isVariantFieldGep() const
Gep statement with a variant field index (pointer arithmetic) for struct field access.
const AccessPath & getAccessPath() const
static const Option< u32_t > CxtBudget
Definition Options.h:77
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
CallGraph * getCallGraph() const
Return call graph.
NodeID getGepObjVar(NodeID id, const APOffset &ap)
void setObjFieldInsensitive(NodeID id)
static SVFIR * pag
SVFIR.
CallGraphSCC * getCallGraphSCC() const
Return call graph SCC.
const_iterator end() const
Definition PointsTo.h:133
const_iterator iterator
Definition PointsTo.h:41
const_iterator begin() const
Definition PointsTo.h:129
bool test(u32_t n) const
Returns true if n is in this set.
Definition PointsTo.cpp:143
NodeID getFunPtr(const CallICFGNode *cs) const
Definition SVFIR.h:458
const ValVar * getValVar(NodeID id) const
Definition SVFIR.h:140
static double getClk(bool mark=false)
Definition SVFStat.cpp:52
const SVFStmt * getSVFStmt() const
Definition VFGNode.h:147
bool isRetVFGEdge() const
Definition VFGEdge.h:88
bool isCallVFGEdge() const
Definition VFGEdge.h:84
virtual const FunObjVar * getFun() const
Get the function of this SVFGNode.
Definition VFGNode.h:79
const CallICFGNode * getCallSite(CallSiteID id) const
Definition VFG.h:182
std::enable_if_t<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type > cast(const Y &Val)
Definition Casting.h:360
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:88
std::ostream & outs()
Overwrite llvm::outs().
Definition SVFUtil.h:58
LLVM_NODISCARD std::enable_if_t<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type > dyn_cast(const Y &Val)
Definition Casting.h:405
for isBitcode
Definition BasicTypes.h:70
unsigned CallSiteID
Definition GeneralType.h:78
PTATY
Pointer analysis type list.
Definition PTATY.h:9
@ Cxt_DDA
context sensitive DDA
Definition PTATY.h:32
u32_t NodeID
Definition GeneralType.h:76
StoreVFGNode StoreSVFGNode
Definition SVFG.h:53
GepVFGNode GepSVFGNode
Definition SVFG.h:55
VFGEdge SVFGEdge
Definition SVFG.h:42
CxtStmtDPItem< SVFGNode > CxtLocDPItem
Definition ContextDDA.h:50
CondVar< ContextCond > CxtVar
Definition DPItem.h:386
CondStdSet< CxtVar > CxtPtSet
Definition DPItem.h:387