Static Value-Flow Analysis
DDAClient.cpp
Go to the documentation of this file.
1 //===- DDAClient.cpp -- Clients of 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  * @file: DDAClient.cpp
25  * @author: yesen
26  * @date: 16 Feb 2015
27  *
28  * LICENSE
29  *
30  */
31 
32 
33 #include "Util/Options.h"
34 #include "Util/SVFUtil.h"
35 #include "MemoryModel/PointsTo.h"
36 
37 #include "DDA/DDAClient.h"
38 #include "DDA/FlowDDA.h"
39 #include <iostream>
40 #include <iomanip> // for std::setw
41 
42 using namespace SVF;
43 using namespace SVFUtil;
44 
45 
47 {
48 
49  DDAStat* stat = static_cast<DDAStat*>(pta->getStat());
50  u32_t vmrss = 0;
51  u32_t vmsize = 0;
52  SVFUtil::getMemoryUsageKB(&vmrss, &vmsize);
53  stat->setMemUsageBefore(vmrss, vmsize);
54 
55  collectCandidateQueries(pta->getPAG());
56 
57  u32_t count = 0;
58  for (OrderedNodeSet::iterator nIter = candidateQueries.begin();
59  nIter != candidateQueries.end(); ++nIter,++count)
60  {
61  PAGNode* node = pta->getPAG()->getGNode(*nIter);
62  if(pta->getPAG()->isValidTopLevelPtr(node))
63  {
64  DBOUT(DGENERAL,outs() << "\n@@Computing PointsTo for :" << node->getId() <<
65  " [" << count + 1<< "/" << candidateQueries.size() << "]" << " \n");
66  DBOUT(DDDA,outs() << "\n@@Computing PointsTo for :" << node->getId() <<
67  " [" << count + 1<< "/" << candidateQueries.size() << "]" << " \n");
68  setCurrentQueryPtr(node->getId());
69  pta->computeDDAPts(node->getId());
70  }
71  }
72 
73  vmrss = vmsize = 0;
74  SVFUtil::getMemoryUsageKB(&vmrss, &vmsize);
75  stat->setMemUsageAfter(vmrss, vmsize);
76 }
77 
79 {
80  setPAG(p);
81  for(SVFIR::CallSiteToFunPtrMap::const_iterator it = pag->getIndirectCallsites().begin(),
82  eit = pag->getIndirectCallsites().end(); it!=eit; ++it)
83  {
84  if (it->first->isVirtualCall())
85  {
86  const SVFVar* vtblPtr = it->first->getVtablePtr();
87  assert(vtblPtr != nullptr && "not a vtable pointer?");
88  NodeID vtblId = vtblPtr->getId();
89  addCandidate(vtblId);
90  vtableToCallSiteMap[vtblId] = it->first;
91  }
92  else
93  {
94  addCandidate(it->second);
95  }
96  }
97  return candidateQueries;
98 }
99 
101 {
102 
104  u32_t totalCallsites = 0;
105  u32_t morePreciseCallsites = 0;
106  u32_t zeroTargetCallsites = 0;
107  u32_t oneTargetCallsites = 0;
108  u32_t twoTargetCallsites = 0;
109  u32_t moreThanTwoCallsites = 0;
110 
111  for (VTablePtrToCallSiteMap::iterator nIter = vtableToCallSiteMap.begin();
112  nIter != vtableToCallSiteMap.end(); ++nIter)
113  {
114  NodeID vtptr = nIter->first;
115  const PointsTo& ddaPts = pta->getPts(vtptr);
116  const PointsTo& anderPts = ander->getPts(vtptr);
117 
118  PTACallGraph* callgraph = ander->getCallGraph();
119  const CallICFGNode* cbn = nIter->second;
120 
121  if(!callgraph->hasIndCSCallees(cbn))
122  {
123  //outs() << "virtual callsite has no callee" << *(nIter->second.getInstruction()) << "\n";
124  continue;
125  }
126 
127  const PTACallGraph::FunctionSet& callees = callgraph->getIndCSCallees(cbn);
128  totalCallsites++;
129  if(callees.size() == 0)
130  zeroTargetCallsites++;
131  else if(callees.size() == 1)
132  oneTargetCallsites++;
133  else if(callees.size() == 2)
134  twoTargetCallsites++;
135  else
136  moreThanTwoCallsites++;
137 
138  if(ddaPts.count() >= anderPts.count() || ddaPts.empty())
139  continue;
140 
141  Set<const SVFFunction*> ander_vfns;
142  Set<const SVFFunction*> dda_vfns;
143  ander->getVFnsFromPts(cbn,anderPts, ander_vfns);
144  pta->getVFnsFromPts(cbn,ddaPts, dda_vfns);
145 
146  ++morePreciseCallsites;
147  outs() << "============more precise callsite =================\n";
148  outs() << (nIter->second)->toString() << "\n";
149  outs() << (nIter->second)->getSourceLoc() << "\n";
150  outs() << "\n";
151  outs() << "------ander pts or vtable num---(" << anderPts.count() << ")--\n";
152  outs() << "------DDA vfn num---(" << ander_vfns.size() << ")--\n";
153  //ander->dumpPts(vtptr, anderPts);
154  outs() << "------DDA pts or vtable num---(" << ddaPts.count() << ")--\n";
155  outs() << "------DDA vfn num---(" << dda_vfns.size() << ")--\n";
156  //pta->dumpPts(vtptr, ddaPts);
157  outs() << "-------------------------\n";
158  outs() << "\n";
159  outs() << "=================================================\n";
160  }
161 
162  outs() << "=================================================\n";
163  outs() << "Total virtual callsites: " << vtableToCallSiteMap.size() << "\n";
164  outs() << "Total analyzed virtual callsites: " << totalCallsites << "\n";
165  outs() << "Indirect call map size: " << ander->getCallGraph()->getIndCallMap().size() << "\n";
166  outs() << "Precise callsites: " << morePreciseCallsites << "\n";
167  outs() << "Zero target callsites: " << zeroTargetCallsites << "\n";
168  outs() << "One target callsites: " << oneTargetCallsites << "\n";
169  outs() << "Two target callsites: " << twoTargetCallsites << "\n";
170  outs() << "More than two target callsites: " << moreThanTwoCallsites << "\n";
171  outs() << "=================================================\n";
172 }
173 
174 
177 {
178  setPAG(pag);
180  for (SVFStmt::SVFStmtSetTy::iterator iter = loads.begin(), eiter =
181  loads.end(); iter != eiter; ++iter)
182  {
183  PAGNode* loadsrc = (*iter)->getSrcNode();
184  loadSrcNodes.insert(loadsrc);
185  addCandidate(loadsrc->getId());
186  }
187 
189  for (SVFStmt::SVFStmtSetTy::iterator iter = stores.begin(), eiter =
190  stores.end(); iter != eiter; ++iter)
191  {
192  PAGNode* storedst = (*iter)->getDstNode();
193  storeDstNodes.insert(storedst);
194  addCandidate(storedst->getId());
195  }
197  for (SVFStmt::SVFStmtSetTy::iterator iter = geps.begin(), eiter =
198  geps.end(); iter != eiter; ++iter)
199  {
200  PAGNode* gepsrc = (*iter)->getSrcNode();
201  gepSrcNodes.insert(gepsrc);
202  addCandidate(gepsrc->getId());
203  }
204  return candidateQueries;
205 }
206 
208 {
209 
210  for(PAGNodeSet::const_iterator lit = loadSrcNodes.begin(); lit!=loadSrcNodes.end(); lit++)
211  {
212  for(PAGNodeSet::const_iterator sit = storeDstNodes.begin(); sit!=storeDstNodes.end(); sit++)
213  {
214  const PAGNode* node1 = *lit;
215  const PAGNode* node2 = *sit;
216  if(node1->hasValue() && node2->hasValue())
217  {
218  AliasResult result = pta->alias(node1->getId(),node2->getId());
219 
220  outs() << "\n=================================================\n";
221  outs() << "Alias Query for (" << node1->getValue()->toString() << ",";
222  outs() << node2->getValue()->toString() << ") \n";
223  outs() << "[NodeID:" << node1->getId() << ", NodeID:" << node2->getId() << " " << result << "]\n";
224  outs() << "=================================================\n";
225 
226  }
227  }
228  }
229 }
230 
#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
cJSON * p
Definition: cJSON.cpp:2559
int count
Definition: cJSON.h:216
virtual OrderedNodeSet & collectCandidateQueries(SVFIR *pag)
Only collect function pointers as query candidates.
Definition: DDAClient.cpp:176
virtual void performStat(PointerAnalysis *pta)
Definition: DDAClient.cpp:207
static AndersenWaveDiff * createAndersenWaveDiff(SVFIR *_pag)
Create an singleton instance directly instead of invoking llvm pass manager.
Definition: Andersen.h:408
virtual const PointsTo & getPts(NodeID id)
Operation of points-to set.
Definition: Andersen.h:239
virtual void answerQueries(PointerAnalysis *pta)
Definition: DDAClient.cpp:46
virtual OrderedNodeSet & collectCandidateQueries(SVFIR *p)
Only collect function pointers as query candidates.
Definition: DDAClient.cpp:78
virtual void performStat(PointerAnalysis *pta)
Definition: DDAClient.cpp:100
NodeType * getGNode(NodeID id) const
Get a node.
Definition: GenericGraph.h:653
Set< const SVFFunction * > FunctionSet
Definition: PTACallGraph.h:251
bool hasIndCSCallees(const CallICFGNode *cs) const
Definition: PTACallGraph.h:308
const FunctionSet & getIndCSCallees(const CallICFGNode *cs) const
Definition: PTACallGraph.h:312
CallEdgeMap & getIndCallMap()
Get callees from an indirect callsite.
Definition: PTACallGraph.h:304
void setMemUsageBefore(u32_t vmrss, u32_t vmsize)
Definition: PTAStat.h:56
void setMemUsageAfter(u32_t vmrss, u32_t vmsize)
Definition: PTAStat.h:62
void getVFnsFromPts(const CallICFGNode *cs, const PointsTo &target, VFunSet &vfns)
virtual void computeDDAPts(NodeID)
Compute points-to results on-demand, overridden by derived classes.
PTAStat * getStat() const
Get PTA stat.
SVFIR * getPAG() const
virtual const PointsTo & getPts(NodeID ptr)=0
Get points-to targets of a pointer. It needs to be implemented in child class.
PTACallGraph * getCallGraph() const
Return call graph.
virtual AliasResult alias(const SVFValue *V1, const SVFValue *V2)=0
Interface exposed to users of our pointer analysis, given Value infos.
bool empty() const
Returns true if set is empty.
Definition: PointsTo.cpp:98
u32_t count() const
Returns number of elements.
Definition: PointsTo.cpp:111
NodeID getId() const
Get ID.
Definition: GenericGraph.h:260
bool isValidTopLevelPtr(const SVFVar *node)
Definition: SVFIR.cpp:673
SVFStmt::SVFStmtSetTy & getSVFStmtSet(SVFStmt::PEDGEK kind)
Get/set methods to get SVFStmts based on their kinds and ICFGNodes.
Definition: SVFIR.h:201
GenericNode< SVFVar, SVFStmt >::GEdgeSetTy SVFStmtSetTy
std::string toString() const
Needs to be implemented by a SVF front end.
Definition: LLVMUtil.cpp:663
bool hasValue() const
Definition: SVFVariables.h:101
const SVFValue * getValue() const
Get/has methods of the components.
Definition: SVFVariables.h:83
const std::string getSourceLoc(const Value *val)
Definition: LLVMUtil.cpp:430
bool getMemoryUsageKB(u32_t *vmrss_kb, u32_t *vmsize_kb)
Get memory usage from system file. Return TRUE if succeed.
Definition: SVFUtil.cpp:177
std::ostream & outs()
Overwrite llvm::outs()
Definition: SVFUtil.h:50
for isBitcode
Definition: BasicTypes.h:68
OrderedSet< NodeID > OrderedNodeSet
Definition: GeneralType.h:112
u32_t NodeID
Definition: GeneralType.h:55
AliasResult
Definition: SVFType.h:527
unsigned u32_t
Definition: GeneralType.h:46
std::unordered_set< Key, Hash, KeyEqual, Allocator > Set
Definition: GeneralType.h:96