Static Value-Flow Analysis
Loading...
Searching...
No Matches
DDAVFSolver.h
Go to the documentation of this file.
1//===- DDAVFSolver.h -- Demand-driven analysis value-flow solver------------//
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 * DDAVFSolver.h
25 *
26 * Created on: Jul 3, 2014
27 * Author: Yulei Sui
28 */
29
30#ifndef VALUEFLOWDDA_H_
31#define VALUEFLOWDDA_H_
32
33#include <algorithm>
34
35#include "DDA/DDAStat.h"
36#include "Graphs/SCC.h"
37#include "MSSA/SVFGBuilder.h"
39#include "WPA/Andersen.h"
40#include "Util/GeneralType.h"
41
42namespace SVF
43{
44
48template<class CVar, class CPtSet, class DPIm>
50{
51 friend class DDAStat;
52public:
65
67 DDAVFSolver(): outOfBudgetQuery(false),_pag(nullptr),_svfg(nullptr),_ander(nullptr),_callGraph(nullptr), _callGraphSCC(nullptr), _svfgSCC(nullptr), ddaStat(nullptr)
68 {
69 }
70
71 virtual ~DDAVFSolver()
72 {
73 if(_ander != nullptr)
74 {
75 // AndersenWaveDiff::releaseAndersenWaveDiff();
76 _ander = nullptr;
77 }
78
79 if (_svfg != nullptr)
80 {
81 // DDASVFGBuilder::releaseDDASVFG();
82 _svfg = nullptr;
83 }
84
85 if (_svfgSCC != nullptr)
86 delete _svfgSCC;
87 _svfgSCC = nullptr;
88
89 _callGraph = nullptr;
90 _callGraphSCC = nullptr;
91 }
92
94 {
95 return candidateQueries;
96 }
97
98 virtual inline DPIm getDPIm(const CVar& var, const SVFGNode* loc) const
99 {
100 DPIm dpm(var,loc);
101 return dpm;
102 }
103
104 virtual bool unionDDAPts(CPtSet& pts, const CPtSet& targetPts)
105 {
106 return (pts |= targetPts);
107 }
108
109 virtual bool unionDDAPts(DPIm dpm, const CPtSet& targetPts)
110 {
111 CPtSet& pts = isTopLevelPtrStmt(dpm.getLoc()) ? dpmToTLCPtSetMap[dpm] : dpmToADCPtSetMap[dpm];
112 return pts |= targetPts;
113 }
114
115 virtual void addDDAPts(CPtSet& pts, const CVar& var)
116 {
117 pts.set(var);
118 }
119
120 inline SVFG* getSVFG() const
121 {
122 return _svfg;
123 }
124
125 inline SVFGSCC* getSVFGSCC() const
126 {
127 return _svfgSCC;
128 }
129 // Dump cptsSet
130 inline void dumpCPtSet(const CPtSet& cpts) const
131 {
132 SVFUtil::outs() << "{";
133 for(typename CPtSet::iterator it = cpts.begin(), eit = cpts.end(); it!=eit; ++it)
134 {
135 SVFUtil::outs() << (*it) << " ";
136 }
137 SVFUtil::outs() << "}\n";
138 }
139
140 virtual const CPtSet& findPT(const DPIm& dpm)
141 {
142
143 if(isbkVisited(dpm))
144 {
145 const CPtSet& cpts = getCachedPointsTo(dpm);
146 DBOUT(DDDA, SVFUtil::outs() << "\t already backward visited dpm: ");
147 DBOUT(DDDA, dpm.dump());
148 DBOUT(DDDA, SVFUtil::outs() << "\t return points-to: ");
149 DBOUT(DDDA, dumpCPtSet(cpts));
150 return cpts;
151 }
152
153 DBOUT(DDDA, SVFUtil::outs() << "\t backward visit dpm: ");
154 DBOUT(DDDA, dpm.dump());
155 markbkVisited(dpm);
156 addDpmToLoc(dpm);
157
158 if(testOutOfBudget(dpm) == false)
159 {
160
161 CPtSet pts;
162 handleSingleStatement(dpm, pts);
163
165 updateCachedPointsTo(dpm, pts);
166 }
167 return getCachedPointsTo(dpm);
168 }
169
170protected:
172 virtual void handleSingleStatement(const DPIm& dpm, CPtSet& pts)
173 {
175 resolveFunPtr(dpm);
176
177 const SVFGNode* node = dpm.getLoc();
179 {
181 }
185 {
186 backtraceAlongDirectVF(pts,dpm);
187 }
188 else if(SVFUtil::isa<GepSVFGNode>(node))
189 {
190 CPtSet gepPts;
191 backtraceAlongDirectVF(gepPts,dpm);
193 }
194 else if(const LoadSVFGNode* load = SVFUtil::dyn_cast<LoadSVFGNode>(node))
195 {
196 if(load->getDstNode()->isPointer() == false)
197 return;
198
199 CPtSet loadpts;
200 startNewPTCompFromLoadSrc(loadpts,dpm);
201 for(typename CPtSet::iterator it = loadpts.begin(), eit = loadpts.end(); it!=eit; ++it)
202 {
204 }
205 }
206 else if(const StoreSVFGNode* store = SVFUtil::dyn_cast<StoreSVFGNode>(node))
207 {
208 if(store->getSrcNode()->isPointer() == false)
209 return;
210
211 if(isMustAlias(getLoadDpm(dpm),dpm))
212 {
213 DBOUT(DDDA, SVFUtil::outs() << "+++must alias for load and store:");
214 DBOUT(DDDA, getLoadDpm(dpm).dump());
215 DBOUT(DDDA, dpm.dump());
216 DBOUT(DDDA, SVFUtil::outs() << "+++\n");
217 DOSTAT(ddaStat->_NumOfMustAliases++);
218 backtraceToStoreSrc(pts,dpm);
219 }
220 else
221 {
222 CPtSet storepts;
223 startNewPTCompFromStoreDst(storepts,dpm);
224 for(typename CPtSet::iterator it = storepts.begin(), eit = storepts.end(); it!=eit; ++it)
225 {
226 if(propagateViaObj(*it,getLoadCVar(dpm)))
227 {
228 backtraceToStoreSrc(pts,getDPImWithOldCond(dpm,*it,store));
229
230 if(isStrongUpdate(storepts,store))
231 {
232 DBOUT(DDDA, SVFUtil::outs() << "backward strong update for obj " << dpm.getCurNodeID() << "\n");
233 DOSTAT(addSUStat(dpm,store);)
234 }
235 else
236 {
237 DOSTAT(rmSUStat(dpm,store);)
239 }
240 }
241 else
242 {
244 }
245 }
246 }
247 }
248 else if(SVFUtil::isa<MRSVFGNode>(node))
249 {
251 }
252 else
253 assert(false && "unexpected kind of SVFG nodes");
254 }
255
257 void reCompute(const DPIm& dpm)
258 {
260 SVFGEdgeSet newIndirectEdges;
261 if(_pag->isFunPtr(dpm.getCurNodeID()))
262 {
263 const CallSiteSet& csSet = _pag->getIndCallSites(dpm.getCurNodeID());
264 for(CallSiteSet::const_iterator it = csSet.begin(), eit = csSet.end(); it!=eit; ++it)
265 updateCallGraphAndSVFG(dpm, (*it),newIndirectEdges);
266 }
268 if(!newIndirectEdges.empty())
269 _callGraphSCC->find();
270 reComputeForEdges(dpm,newIndirectEdges,true);
271
273 SVFGEdgeSet edgeSet(dpm.getLoc()->getOutEdges());
274 reComputeForEdges(dpm,edgeSet,false);
275 }
276
278 void reComputeForEdges(const DPIm& dpm, const SVFGEdgeSet& edgeSet, bool indirectCall = false)
279 {
280 for (SVFGNode::const_iterator it = edgeSet.begin(), eit = edgeSet.end(); it != eit; ++it)
281 {
282 const SVFGEdge* edge = *it;
283 const SVFGNode* dst = edge->getDstNode();
284 typename LocToDPMVecMap::const_iterator locIt = getLocToDPMVecMap().find(dst->getId());
286 if (locIt == getLocToDPMVecMap().end())
287 continue;
288 DPTItemSet dpmSet(locIt->second.begin(), locIt->second.end());
289 for(typename DPTItemSet::const_iterator it = dpmSet.begin(),eit = dpmSet.end(); it!=eit; ++it)
290 {
291 const DPIm& dstDpm = *it;
292 if(!indirectCall && SVFUtil::isa<IndirectSVFGEdge>(edge) && !SVFUtil::isa<LoadSVFGNode>(edge->getDstNode()))
293 {
294 if(dstDpm.getCurNodeID() == dpm.getCurNodeID())
295 {
296 DBOUT(DDDA,SVFUtil::outs() << "\t Recompute, forward from :");
297 DBOUT(DDDA, dpm.dump());
298 DOSTAT(ddaStat->_NumOfStepInCycle++);
299 clearbkVisited(dstDpm);
300 findPT(dstDpm);
301 }
302 }
303 else
304 {
305 if(indirectCall)
306 DBOUT(DDDA,SVFUtil::outs() << "\t Recompute for indirect call from :");
307 else
308 DBOUT(DDDA,SVFUtil::outs() << "\t Recompute forward from :");
309 DBOUT(DDDA, dpm.dump());
310 DOSTAT(ddaStat->_NumOfStepInCycle++);
311 clearbkVisited(dstDpm);
312 findPT(dstDpm);
313 }
314 }
315 }
316 }
317
319 virtual inline void buildSVFG(SVFIR* pag)
320 {
322 _svfg = svfgBuilder.buildPTROnlySVFG(_ander);
323 _pag = _svfg->getPAG();
324 }
325
326 virtual inline void resetQuery()
327 {
330
331 locToDpmSetMap.clear();
332 dpmToloadDpmMap.clear();
333 loadToPTCVarMap.clear();
334 outOfBudgetQuery = false;
335 ddaStat->_NumOfStep = 0;
336 }
337
338 inline void OOBResetVisited()
339 {
340 for(typename LocToDPMVecMap::const_iterator it = locToDpmSetMap.begin(),eit = locToDpmSetMap.end(); it!=eit; ++it)
341 {
342 DPTItemSet dpmSet(it->second.begin(), it->second.end());
343 for(typename DPTItemSet::const_iterator dit = dpmSet.begin(),deit=dpmSet.end(); dit!=deit; ++dit)
344 if(isOutOfBudgetDpm(*dit)==false)
345 clearbkVisited(*dit);
346 }
347 }
348
349 inline const SVFGNode* getDefSVFGNode(const ValVar* valVar) const
350 {
351 return getSVFG()->getDefSVFGNode(valVar);
352 }
353
354 void backtraceAlongIndirectVF(CPtSet& pts, const DPIm& oldDpm)
355 {
356 const SVFGNode* node = oldDpm.getLoc();
357 NodeID obj = oldDpm.getCurNodeID();
358 if (_pag->isConstantObj(obj))
359 return;
360 const SVFGEdgeSet edgeSet(node->getInEdges());
361 for (SVFGNode::const_iterator it = edgeSet.begin(), eit = edgeSet.end(); it != eit; ++it)
362 {
363 if(const IndirectSVFGEdge* indirEdge = SVFUtil::dyn_cast<IndirectSVFGEdge>(*it))
364 {
365 const NodeBS& guard = indirEdge->getPointsTo();
366 if(guard.test(obj))
367 {
368 DBOUT(DDDA, SVFUtil::outs() << "\t\t==backtrace indirectVF svfgNode " <<
369 indirEdge->getDstID() << " --> " << indirEdge->getSrcID() << "\n");
370 backwardPropDpm(pts,oldDpm.getCurNodeID(),oldDpm,indirEdge);
371 }
372 }
373 }
374 }
375
376 void backtraceAlongDirectVF(CPtSet& pts, const DPIm& oldDpm)
377 {
378 const SVFGNode* node = oldDpm.getLoc();
379 const SVFGEdgeSet edgeSet(node->getInEdges());
380 for (SVFGNode::const_iterator it = edgeSet.begin(), eit = edgeSet.end(); it != eit; ++it)
381 {
382 if(const DirectSVFGEdge* dirEdge = SVFUtil::dyn_cast<DirectSVFGEdge>(*it))
383 {
384 DBOUT(DDDA, SVFUtil::outs() << "\t\t==backtrace directVF svfgNode " <<
385 dirEdge->getDstID() << " --> " << dirEdge->getSrcID() << "\n");
386 const SVFGNode* srcNode = dirEdge->getSrcNode();
387 backwardPropDpm(pts,getSVFG()->getLHSTopLevPtr(srcNode)->getId(),oldDpm,dirEdge);
388 }
389 }
390 }
391
394 inline void startNewPTCompFromLoadSrc(CPtSet& pts, const DPIm& oldDpm)
395 {
396 const LoadSVFGNode* load = SVFUtil::cast<LoadSVFGNode>(oldDpm.getLoc());
397 const SVFGNode* loadSrc = getDefSVFGNode(load->getSrcNode());
398 DBOUT(DDDA, SVFUtil::outs() << "!##start new computation from loadSrc svfgNode " <<
399 load->getId() << " --> " << loadSrc->getId() << "\n");
400 const SVFGEdge* edge = getSVFG()->getIntraVFGEdge(loadSrc,load,SVFGEdge::IntraDirectVF);
401 assert(edge && "Edge not found!!");
402 backwardPropDpm(pts,load->getSrcNodeID(),oldDpm,edge);
403
404 }
405 inline void startNewPTCompFromStoreDst(CPtSet& pts, const DPIm& oldDpm)
406 {
407 const StoreSVFGNode* store = SVFUtil::cast<StoreSVFGNode>(oldDpm.getLoc());
408 const SVFGNode* storeDst = getDefSVFGNode(store->getDstNode());
409 DBOUT(DDDA, SVFUtil::outs() << "!##start new computation from storeDst svfgNode " <<
410 store->getId() << " --> " << storeDst->getId() << "\n");
411 const SVFGEdge* edge = getSVFG()->getIntraVFGEdge(storeDst,store,SVFGEdge::IntraDirectVF);
412 assert(edge && "Edge not found!!");
413 backwardPropDpm(pts,store->getDstNodeID(),oldDpm,edge);
414 }
415 inline void backtraceToStoreSrc(CPtSet& pts, const DPIm& oldDpm)
416 {
417 const StoreSVFGNode* store = SVFUtil::cast<StoreSVFGNode>(oldDpm.getLoc());
418 const SVFGNode* storeSrc = getDefSVFGNode(store->getSrcNode());
419 DBOUT(DDDA, SVFUtil::outs() << "++backtrace to storeSrc from svfgNode " << getLoadDpm(oldDpm).getLoc()->getId() << " to "<<
420 store->getId() << " to " << storeSrc->getId() <<"\n");
421 const SVFGEdge* edge = getSVFG()->getIntraVFGEdge(storeSrc,store,SVFGEdge::IntraDirectVF);
422 assert(edge && "Edge not found!!");
423 backwardPropDpm(pts,store->getSrcNodeID(),oldDpm,edge);
424 }
425
426
428 virtual void backwardPropDpm(CPtSet& pts, NodeID ptr,const DPIm& oldDpm,const SVFGEdge* edge)
429 {
430 DPIm dpm(oldDpm);
431 dpm.setLocVar(edge->getSrcNode(),ptr);
432 DOTIMESTAT(double start = DDAStat::getClk(true));
434 if(handleBKCondition(dpm,edge)==false)
435 {
436 DOTIMESTAT(ddaStat->_TotalTimeOfBKCondition += DDAStat::getClk(true) - start);
437 DBOUT(DDDA, SVFUtil::outs() << "\t!!! infeasible path svfgNode: " << edge->getDstID() << " --| " << edge->getSrcID() << "\n");
438 DOSTAT(ddaStat->_NumOfInfeasiblePath++);
439 return;
440 }
441
444 addLoadDpmAndCVar(dpm,getLoadDpm(oldDpm),getLoadCVar(oldDpm));
445
446 DOSTAT(ddaStat->_NumOfDPM++);
448 unionDDAPts(pts,findPT(dpm));
449 }
450
451 virtual bool isMustAlias(const DPIm&, const DPIm&)
452 {
453 return false;
454 }
455
456 virtual bool isStrongUpdate(const CPtSet& dstCPSet, const StoreSVFGNode* store)
457 {
458 if (dstCPSet.count() == 1)
459 {
461 typename CPtSet::iterator it = dstCPSet.begin();
462 const CVar& var = *it;
463 // Strong update can be made if this points-to target is not heap, array or field-insensitive.
464 if (!isHeapCondMemObj(var,store) && !isArrayCondMemObj(var)
466 {
467 return true;
468 }
469 }
470 return false;
471 }
472
473 virtual inline bool isLocalCVarInRecursion(const CVar& var) const
474 {
475 NodeID id = getPtrNodeID(var);
476 const BaseObjVar* baseObj = _pag->getBaseObject(id);
477 assert(baseObj && "base object is null??");
478 if(SVFUtil::isa<StackObjVar>(baseObj))
479 {
480 if(const FunObjVar* svffun = _pag->getSVFVar(id)->getFunction())
481 {
482 return _callGraphSCC->isInCycle(_callGraph->getCallGraphNode(svffun)->getId());
483 }
484 }
485 return false;
486 }
487
489 virtual inline bool propagateViaObj(const CVar& storeObj, const CVar& loadObj)
490 {
491 return getPtrNodeID(storeObj) == getPtrNodeID(loadObj);
492 }
493
494 void resolveFunPtr(const DPIm& dpm)
495 {
496 if(const CallICFGNode* cbn= getSVFG()->isCallSiteRetSVFGNode(dpm.getLoc()))
497 {
498 if(_pag->isIndirectCallSites(cbn))
499 {
500 NodeID funPtr = _pag->getFunPtr(cbn);
501 DPIm funPtrDpm(dpm);
502 funPtrDpm.setLocVar(getSVFG()->getDefSVFGNode(_pag->getValVar(funPtr)),funPtr);
503 findPT(funPtrDpm);
504 }
505 }
506 else if(const FunObjVar* fun = getSVFG()->isFunEntrySVFGNode(dpm.getLoc()))
507 {
508 CallInstSet csSet;
510 _ander->getCallGraph()->getIndCallSitesInvokingCallee(fun,csSet);
511 for(CallInstSet::const_iterator it = csSet.begin(), eit = csSet.end(); it!=eit; ++it)
512 {
513 NodeID funPtr = _pag->getFunPtr(*it);
514 DPIm funPtrDpm(dpm);
515 funPtrDpm.setLocVar(getSVFG()->getDefSVFGNode(_pag->getValVar(funPtr)),funPtr);
516 findPT(funPtrDpm);
517 }
518 }
519 }
520
521
522
523 virtual NodeID getPtrNodeID(const CVar& var) const = 0;
525 virtual CPtSet processGepPts(const GepSVFGNode* gep, const CPtSet& srcPts) = 0;
527 virtual void handleAddr(CPtSet& pts,const DPIm& dpm,const AddrSVFGNode* addr) = 0;
529 virtual CPtSet getConservativeCPts(const DPIm& dpm) = 0;
531 virtual inline bool handleBKCondition(DPIm&, const SVFGEdge*)
532 {
533 return true;
534 }
535
536 virtual inline void updateCallGraphAndSVFG(const DPIm&, const CallICFGNode*, SVFGEdgeSet&) {}
538
540
541 inline void markbkVisited(const DPIm& dpm)
542 {
543 backwardVisited.insert(dpm);
544 }
545 inline bool isbkVisited(const DPIm& dpm)
546 {
547 return backwardVisited.find(dpm)!=backwardVisited.end();
548 }
549 inline void clearbkVisited(const DPIm& dpm)
550 {
551 assert(backwardVisited.find(dpm)!=backwardVisited.end() && "dpm not found!");
552 backwardVisited.erase(dpm);
553 }
554
555
557
558 virtual inline const CPtSet& getCachedPointsTo(const DPIm& dpm)
559 {
560 if (isTopLevelPtrStmt(dpm.getLoc()))
561 return getCachedTLPointsTo(dpm);
562 else
563 return getCachedADPointsTo(dpm);
564 }
565 virtual inline void updateCachedPointsTo(const DPIm& dpm, const CPtSet& pts)
566 {
567 if (unionDDAPts(dpm, pts))
568 {
569 DOSTAT(double start = DDAStat::getClk(true));
570 reCompute(dpm);
571 DOSTAT(ddaStat->_AnaTimeCyclePerQuery += DDAStat::getClk(true) - start);
572 }
573 }
574 virtual inline const CPtSet& getCachedTLPointsTo(const DPIm& dpm)
575 {
576 return dpmToTLCPtSetMap[dpm];
577 }
578 virtual inline const CPtSet& getCachedADPointsTo(const DPIm& dpm)
579 {
580 return dpmToADCPtSetMap[dpm];
581 }
582
583
585 inline bool isTopLevelPtrStmt(const SVFGNode* stmt)
586 {
588 }
589
590 virtual inline DPIm getDPImWithOldCond(const DPIm& oldDpm,const CVar& var, const SVFGNode* loc)
591 {
592 DPIm dpm(oldDpm);
593 dpm.setLocVar(loc,getPtrNodeID(var));
594
596 addLoadDpmAndCVar(dpm,getLoadDpm(oldDpm),var);
597
599 addLoadDpmAndCVar(dpm,oldDpm,var);
600
601 DOSTAT(ddaStat->_NumOfDPM++);
602 return dpm;
603 }
604
605 inline void SVFGSCCDetection()
606 {
607 if(_svfgSCC==nullptr)
608 {
609 _svfgSCC = new SVFGSCC(getSVFG());
610 }
611 _svfgSCC->find();
612 }
613
615 {
616 return _svfgSCC->repNode(id);
617 }
618
619 inline bool isSVFGNodeInCycle(const SVFGNode* node)
620 {
621 return _svfgSCC->isInCycle(node->getId());
622 }
623
624 inline bool edgeInSVFGSCC(const SVFGEdge* edge)
625 {
626 return (getSVFGSCCRepNode(edge->getSrcID()) == getSVFGSCCRepNode(edge->getDstID()));
627 }
628
629 inline void setCallGraph (CallGraph* cg)
630 {
631 _callGraph = cg;
632 }
633
634 inline void setCallGraphSCC (CallGraphSCC* scc)
635 {
636 _callGraphSCC = scc;
637 }
638
639
640 virtual inline bool isHeapCondMemObj(const CVar& var, const StoreSVFGNode*)
641 {
642 const BaseObjVar* pVar = _pag->getBaseObject(getPtrNodeID(var));
643 return pVar && SVFUtil::isa<HeapObjVar, DummyObjVar>(pVar);
644 }
645
646 inline bool isArrayCondMemObj(const CVar& var) const
647 {
648 const BaseObjVar* obj = _pag->getBaseObject(getPtrNodeID(var));
649 assert(obj && "base object is null??");
650 return obj->isArray();
651 }
652 inline bool isFieldInsenCondMemObj(const CVar& var) const
653 {
654 const BaseObjVar* baseObj = _pag->getBaseObject(getPtrNodeID(var));
655 return baseObj->isFieldInsensitive();
656 }
657
658private:
660
661 inline const LocToDPMVecMap& getLocToDPMVecMap() const
662 {
663 return locToDpmSetMap;
664 }
665 inline const DPTItemSet& getDpmSetAtLoc(const SVFGNode* loc)
666 {
667 return locToDpmSetMap[loc->getId()];
668 }
669 inline void addDpmToLoc(const DPIm& dpm)
670 {
671 locToDpmSetMap[dpm.getLoc()->getId()].insert(dpm);
672 }
673 inline void removeDpmFromLoc(const DPIm& dpm)
674 {
675 assert(dpm == locToDpmSetMap[dpm.getLoc()].back() && "dpm not match with the end of vector");
676 locToDpmSetMap[dpm.getLoc()->getId()].erase(dpm);
677 }
678
679protected:
681
682 inline void addLoadDpmAndCVar(const DPIm& dpm,const DPIm& loadDpm,const CVar& loadVar)
683 {
684 addLoadCVar(dpm,loadVar);
685 addLoadDpm(dpm,loadDpm);
686 }
687
688 inline void addLoadDpm(const DPIm& dpm,const DPIm& loadDpm)
689 {
690 typename DPMToDPMMap::iterator it = dpmToloadDpmMap.find(dpm);
691 if(it!=dpmToloadDpmMap.end())
692 it->second = loadDpm;
693 else
694 dpmToloadDpmMap.insert(std::make_pair(dpm,loadDpm));
695 }
696 inline const DPIm& getLoadDpm(const DPIm& dpm) const
697 {
698 typename DPMToDPMMap::const_iterator it = dpmToloadDpmMap.find(dpm);
699 assert(it!=dpmToloadDpmMap.end() && "not found??");
700 return it->second;
701 }
702 inline void addLoadCVar(const DPIm& dpm, const CVar& loadVar)
703 {
704 typename DPMToCVarMap::iterator it = loadToPTCVarMap.find(dpm);
705 if(it!=loadToPTCVarMap.end())
706 it->second = loadVar;
707 else
708 loadToPTCVarMap.insert(std::make_pair(dpm,loadVar));
709 }
710 inline const CVar& getLoadCVar(const DPIm& dpm) const
711 {
712 typename DPMToCVarMap::const_iterator it = loadToPTCVarMap.find(dpm);
713 assert(it!=loadToPTCVarMap.end() && "not found??");
714 return it->second;
715 }
716
717
719 {
720 return _ander;
721 }
722
723
724
725 inline void handleOutOfBudgetDpm(const DPIm& dpm) {}
726 inline bool testOutOfBudget(const DPIm& dpm)
727 {
728 if(outOfBudgetQuery) return true;
729 if(++ddaStat->_NumOfStep > DPIm::getMaxBudget())
730 outOfBudgetQuery = true;
731 return isOutOfBudgetDpm(dpm) || outOfBudgetQuery;
732 }
733 inline bool isOutOfBudgetQuery() const
734 {
735 return outOfBudgetQuery;
736 }
737 inline void addOutOfBudgetDpm(const DPIm& dpm)
738 {
739 outOfBudgetDpms.insert(dpm);
740 }
741 inline bool isOutOfBudgetDpm(const DPIm& dpm) const
742 {
743 return outOfBudgetDpms.find(dpm) != outOfBudgetDpms.end();
744 }
745
746
749 {
750 ddaStat = s;
751 return ddaStat;
752 }
753
754 inline void addSUStat(const DPIm& dpm, const SVFGNode* node)
755 {
756 if (storeToDPMs[node].insert(dpm).second)
757 {
758 ddaStat->_NumOfStrongUpdates++;
759 ddaStat->_StrongUpdateStores.set(node->getId());
760 }
761 }
762
763 inline void rmSUStat(const DPIm& dpm, const SVFGNode* node)
764 {
765 DPTItemSet& dpmSet = storeToDPMs[node];
766 if (dpmSet.erase(dpm))
767 {
768 ddaStat->_NumOfStrongUpdates--;
769 if(dpmSet.empty())
770 ddaStat->_StrongUpdateStores.reset(node->getId());
771 }
772 }
773
792};
793
794} // End namespace SVF
795
796#endif /* VALUEFLOWDDA_H_ */
#define DBOUT(TYPE, X)
LLVM debug macros, define type of your DBUG model of each pass.
Definition SVFType.h:576
#define DDDA
Definition SVFType.h:588
#define DOSTAT(X)
Definition SVFType.h:577
#define DOTIMESTAT(X)
Definition SVFType.h:578
#define false
Definition cJSON.cpp:70
static AndersenWaveDiff * createAndersenWaveDiff(SVFIR *_pag)
Create an singleton instance directly instead of invoking llvm pass manager.
Definition Andersen.h:430
bool isArray() const
bool isFieldInsensitive() const
Return true if its field limit is 0.
Set< const CallICFGNode * > CallInstSet
Definition CallGraph.h:55
void removeDpmFromLoc(const DPIm &dpm)
bool edgeInSVFGSCC(const SVFGEdge *edge)
Return TRUE if this edge is inside a SVFG SCC, i.e., src node and dst node are in the same SCC on the...
void backtraceAlongIndirectVF(CPtSet &pts, const DPIm &oldDpm)
Backward traverse along indirect value flows.
OrderedSet< DPIm > DPTItemSet
Definition DDAVFSolver.h:57
virtual const CPtSet & getCachedADPointsTo(const DPIm &dpm)
bool isOutOfBudgetDpm(const DPIm &dpm) const
SVFIR::CallSiteSet CallSiteSet
Definition DDAVFSolver.h:56
SVFGBuilder svfgBuilder
SVFG Builder.
NodeID getSVFGSCCRepNode(NodeID id)
Get SCC rep node of a SVFG node.
void addLoadDpmAndCVar(const DPIm &dpm, const DPIm &loadDpm, const CVar &loadVar)
LoadDpm for must-alias analysis.
const CVar & getLoadCVar(const DPIm &dpm) const
virtual bool isLocalCVarInRecursion(const CVar &var) const
Whether a local variable is in function recursions.
virtual ~DDAVFSolver()
Destructor.
Definition DDAVFSolver.h:71
virtual void updateCachedPointsTo(const DPIm &dpm, const CPtSet &pts)
DPImToCPtSetMap dpmToADCPtSetMap
points-to caching map for address-taken vars
OrderedMap< DPIm, DPIm > DPMToDPMMap
Definition DDAVFSolver.h:60
DPImToCPtSetMap dpmToTLCPtSetMap
points-to caching map for top-level vars
virtual bool isMustAlias(const DPIm &, const DPIm &)
whether load and store are aliased
bool isFieldInsenCondMemObj(const CVar &var) const
virtual CPtSet getConservativeCPts(const DPIm &dpm)=0
Get conservative points-to results when the query is out of budget.
SCCDetection< CallGraph * > CallGraphSCC
Definition DDAVFSolver.h:54
virtual NodeID getPtrNodeID(const CVar &var) const =0
Methods to be implemented in child class.
bool testOutOfBudget(const DPIm &dpm)
void addLoadDpm(const DPIm &dpm, const DPIm &loadDpm)
Note that simply use "dpmToloadDpmMap[dpm]=loadDpm", requires DPIm have a default constructor.
AndersenWaveDiff * getAndersenAnalysis() const
Return Andersen's analysis.
CallGraphSCC * _callGraphSCC
SCC for PTACallGraph.
SCCDetection< SVFG * > SVFGSCC
Definition DDAVFSolver.h:53
const LocToDPMVecMap & getLocToDPMVecMap() const
Map a SVFGNode to its dpms for handling value-flow cycles.
SVFGSCC * _svfgSCC
SCC for SVFG.
SVFIR * _pag
SVFIR.
virtual void addDDAPts(CPtSet &pts, const CVar &var)
Add pts.
virtual bool handleBKCondition(DPIm &, const SVFGEdge *)
Handle condition for context or path analysis (backward analysis).
virtual void updateCallGraphAndSVFG(const DPIm &, const CallICFGNode *, SVFGEdgeSet &)
Update call graph.
DPTItemSet backwardVisited
visited map during backward traversing
virtual bool isHeapCondMemObj(const CVar &var, const StoreSVFGNode *)
Check heap and array object.
SVFGEdge::SVFGEdgeSetTy SVFGEdgeSet
Definition DDAVFSolver.h:63
DPMToCVarMap loadToPTCVarMap
map a load dpm to its cvar pointed by its pointer operand
void markbkVisited(const DPIm &dpm)
Visited flags to avoid cycles.
SVFG * _svfg
SVFG.
void addLoadCVar(const DPIm &dpm, const CVar &loadVar)
bool isOutOfBudgetQuery() const
void backtraceAlongDirectVF(CPtSet &pts, const DPIm &oldDpm)
Backward traverse along direct value flows.
bool isTopLevelPtrStmt(const SVFGNode *stmt)
Whether this is a top-level pointer statement.
void rmSUStat(const DPIm &dpm, const SVFGNode *node)
remove strong updates num if the dpm goes to weak updates branch
DDAVFSolver()
Constructor.
Definition DDAVFSolver.h:67
NodeBS & getCandidateQueries()
Return candidate pointers for DDA.
Definition DDAVFSolver.h:93
OrderedMap< DPIm, CPtSet > DPImToCPtSetMap
Definition DDAVFSolver.h:58
void reCompute(const DPIm &dpm)
recompute points-to for value-flow cycles and indirect calls
void handleOutOfBudgetDpm(const DPIm &dpm)
handle out-of-budget queries
virtual bool isStrongUpdate(const CPtSet &dstCPSet, const StoreSVFGNode *store)
Return TRUE if this is a strong update STORE statement.
virtual bool unionDDAPts(CPtSet &pts, const CPtSet &targetPts)
Union pts.
virtual void handleSingleStatement(const DPIm &dpm, CPtSet &pts)
Handle single statement.
bool isbkVisited(const DPIm &dpm)
bool isArrayCondMemObj(const CVar &var) const
DPMToDPMMap dpmToloadDpmMap
dpms at loads for may/must-alias analysis with stores
void setCallGraph(CallGraph *cg)
Set callgraph.
AndersenWaveDiff * _ander
Andersen's analysis.
void dumpCPtSet(const CPtSet &cpts) const
LocToDPMVecMap locToDpmSetMap
map location to its dpms
void clearbkVisited(const DPIm &dpm)
OrderedMap< NodeID, DPTItemSet > LocToDPMVecMap
Definition DDAVFSolver.h:61
DPTItemSet outOfBudgetDpms
out of budget dpm set
virtual CPtSet processGepPts(const GepSVFGNode *gep, const CPtSet &srcPts)=0
ProcessGep node to generate field object nodes of a struct.
CallGraph * _callGraph
PTACallGraph.
void OOBResetVisited()
Reset visited map if the current query is out-of-budget.
void SVFGSCCDetection()
SVFG SCC detection.
virtual const CPtSet & findPT(const DPIm &dpm)
Compute points-to.
void setCallGraphSCC(CallGraphSCC *scc)
Set callgraphSCC.
const SVFGNode * getDefSVFGNode(const ValVar *valVar) const
GetDefinition SVFG.
SVFG * getSVFG() const
Return SVFG.
const DPTItemSet & getDpmSetAtLoc(const SVFGNode *loc)
virtual DPIm getDPImWithOldCond(const DPIm &oldDpm, const CVar &var, const SVFGNode *loc)
Return dpm with old context and path conditions.
OrderedMap< const SVFGNode *, DPTItemSet > StoreToPMSetMap
Definition DDAVFSolver.h:64
void startNewPTCompFromLoadSrc(CPtSet &pts, const DPIm &oldDpm)
void reComputeForEdges(const DPIm &dpm, const SVFGEdgeSet &edgeSet, bool indirectCall=false)
Traverse along out edges to find all nodes which may be affected by locDPM.
virtual bool propagateViaObj(const CVar &storeObj, const CVar &loadObj)
If the points-to contain the object obj, we could move forward along indirect value-flow edge.
virtual void handleAddr(CPtSet &pts, const DPIm &dpm, const AddrSVFGNode *addr)=0
Handle AddrSVFGNode to add proper points-to.
virtual DPIm getDPIm(const CVar &var, const SVFGNode *loc) const
Given CVar and location (SVFGNode) return a new DPItem.
Definition DDAVFSolver.h:98
void backtraceToStoreSrc(CPtSet &pts, const DPIm &oldDpm)
bool isSVFGNodeInCycle(const SVFGNode *node)
Return whether this SVFGNode is in cycle.
SVFGSCC * getSVFGSCC() const
Return SVFGSCC.
NodeBS candidateQueries
candidate pointers;
void addOutOfBudgetDpm(const DPIm &dpm)
DDAStat * ddaStat
DDA stat.
virtual bool unionDDAPts(DPIm dpm, const CPtSet &targetPts)
Union pts.
void addSUStat(const DPIm &dpm, const SVFGNode *node)
stat strong updates num
virtual const CPtSet & getCachedPointsTo(const DPIm &dpm)
Points-to Caching for top-level pointers and address-taken objects.
OrderedSet< const SVFGEdge * > ConstSVFGEdgeSet
Definition DDAVFSolver.h:62
OrderedMap< DPIm, CVar > DPMToCVarMap
Definition DDAVFSolver.h:59
virtual void buildSVFG(SVFIR *pag)
Build SVFG.
const DPIm & getLoadDpm(const DPIm &dpm) const
virtual const CPtSet & getCachedTLPointsTo(const DPIm &dpm)
StoreToPMSetMap storeToDPMs
map store to set of DPM which have been stong updated there
virtual void backwardPropDpm(CPtSet &pts, NodeID ptr, const DPIm &oldDpm, const SVFGEdge *edge)
dpm transit during backward tracing
void addDpmToLoc(const DPIm &dpm)
DDAStat * setDDAStat(DDAStat *s)
Set DDAStat.
CallGraphEdge::CallInstSet CallInstSet
Definition DDAVFSolver.h:55
friend class DDAStat
Definition DDAVFSolver.h:51
void resolveFunPtr(const DPIm &dpm)
resolve function pointer
bool outOfBudgetQuery
Whether the current query is out of step limits.
virtual void resetQuery()
Reset visited map for next points-to query.
void startNewPTCompFromStoreDst(CPtSet &pts, const DPIm &oldDpm)
NodeType * getSrcNode() const
NodeType * getDstNode() const
NodeID getDstID() const
NodeID getSrcID() const
get methods of the components
const GEdgeSetTy & getInEdges() const
const ValVar * getSrcNode() const
Definition VFGNode.h:213
const SVFGNode * getDefSVFGNode(const ValVar *valVar) const
Given a valVar, return its definition site.
Definition SVFG.h:171
Set< const CallICFGNode * > CallSiteSet
Definition SVFIR.h:55
static double getClk(bool mark=false)
Definition SVFStat.cpp:52
NodeID getId() const
Get ID.
Definition SVFValue.h:158
bool test(unsigned Idx) const
NodeID getSrcNodeID() const
Definition VFGNode.h:152
NodeID getDstNodeID() const
Definition VFGNode.h:157
const ValVar * getDstNode() const
Definition VFGNode.h:278
const ValVar * getSrcNode() const
Definition VFGNode.h:274
@ IntraDirectVF
Definition VFGEdge.h:53
VFGEdgeSetTy SVFGEdgeSetTy
Definition VFGEdge.h:118
VFGEdge::VFGEdgeSetTy::const_iterator const_iterator
Definition VFGNode.h:55
VFGEdge * getIntraVFGEdge(const VFGNode *src, const VFGNode *dst, VFGEdge::VFGEdgeK kind)
Get a SVFG edge according to src and dst.
Definition VFG.cpp:908
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
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
std::map< Key, Value, Compare, Allocator > OrderedMap
Definition GeneralType.h:64
ActualParmVFGNode ActualParmSVFGNode
Definition SVFG.h:44
LoadVFGNode LoadSVFGNode
Definition SVFG.h:54
u32_t NodeID
Definition GeneralType.h:76
std::set< Key, Compare, Allocator > OrderedSet
Definition GeneralType.h:60
StoreVFGNode StoreSVFGNode
Definition SVFG.h:53
VFGNode SVFGNode
Definition SVFG.h:43
GepVFGNode GepSVFGNode
Definition SVFG.h:55
PHIVFGNode PHISVFGNode
Definition SVFG.h:56
ActualRetVFGNode ActualRetSVFGNode
Definition SVFG.h:45
AddrVFGNode AddrSVFGNode
Definition SVFG.h:51
VFGEdge SVFGEdge
Definition SVFG.h:42
SparseBitVector NodeBS
Definition GeneralType.h:82
void dump(const SparseBitVector< ElementSize > &LHS, std::ostream &out)
CopyVFGNode CopySVFGNode
Definition SVFG.h:52
FormalParmVFGNode FormalParmSVFGNode
Definition SVFG.h:46
FormalRetVFGNode FormalRetSVFGNode
Definition SVFG.h:47
NullPtrVFGNode NullPtrSVFGNode
Definition SVFG.h:49