Static Value-Flow Analysis
Loading...
Searching...
No Matches
FlowSensitiveStat.cpp
Go to the documentation of this file.
1//===- FlowSensitiveStat.cpp -- Statistics for flow-sensitive pointer analysis-//
2//
3// SVF: Static Value-Flow Analysis
4//
5// Copyright (C) <2013-2017> <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 * FlowSensitiveStat.cpp
25 *
26 * Created on: 27/11/2013
27 * Author: yesen
28 */
29
30#include "WPA/Andersen.h"
31#include "WPA/WPAStat.h"
32#include "WPA/FlowSensitive.h"
34
35using namespace SVF;
36using namespace SVFUtil;
37
80
85{
86 assert(SVFUtil::isa<FlowSensitive>(fspta) && "not an flow-sensitive pta pass!! what else??");
87 endClk();
88
89 clearStat();
90
91 SVFIR* pag = fspta->getPAG();
92
93 // stat null ptr number
95
96 // stat points-to set information
98
99 // stat address-taken variables' points-to
101
102 u32_t fiObjNumber = 0;
103 u32_t fsObjNumber = 0;
104 Set<SymID> nodeSet;
105 for (SVFIR::const_iterator nodeIt = pag->begin(), nodeEit = pag->end(); nodeIt != nodeEit; nodeIt++)
106 {
107 NodeID nodeId = nodeIt->first;
108 PAGNode* pagNode = nodeIt->second;
109 if(SVFUtil::isa<ObjVar>(pagNode))
110 {
111 const MemObj * memObj = pag->getBaseObj(nodeId);
113 if (nodeSet.insert(baseId).second)
114 {
115 if (memObj->isFieldInsensitive())
116 fiObjNumber++;
117 else
118 fsObjNumber++;
119 }
120 }
121 }
122
123 PTNumStatMap["FIObjNum"] = fiObjNumber;
124 PTNumStatMap["FSObjNum"] = fsObjNumber;
125
126 unsigned numOfCopy = 0;
127 unsigned numOfStore = 0;
130 for (; svfgNodeIt != svfgNodeEit; ++svfgNodeIt)
131 {
132 SVFGNode* svfgNode = svfgNodeIt->second;
133 if (SVFUtil::isa<CopySVFGNode>(svfgNode))
134 numOfCopy++;
135 else if (SVFUtil::isa<StoreSVFGNode>(svfgNode))
136 numOfStore++;
137 }
138
140
141 timeStatMap["TotalTime"] = (endTime - startTime)/TIMEINTERVAL;
142 timeStatMap["SolveTime"] = fspta->solveTime;
143 timeStatMap["SCCTime"] = fspta->sccTime;
144 timeStatMap["ProcessTime"] = fspta->processTime;
145 timeStatMap["PropagationTime"] = fspta->propagationTime;
146 timeStatMap["DirectPropaTime"] = fspta->directPropaTime;
147 timeStatMap["IndirectPropaTime"] = fspta->indirectPropaTime;
148 timeStatMap["Strong/WeakUpdTime"] = fspta->updateTime;
149 timeStatMap["AddrTime"] = fspta->addrTime;
150 timeStatMap["CopyTime"] = fspta->copyTime;
151 timeStatMap["GepTime"] = fspta->gepTime;
152 timeStatMap["LoadTime"] = fspta->loadTime;
153 timeStatMap["StoreTime"] = fspta->storeTime;
154 timeStatMap["UpdateCGTime"] = fspta->updateCallGraphTime;
155 timeStatMap["PhiTime"] = fspta->phiTime;
156
157 PTNumStatMap["TotalPointers"] = pag->getValueNodeNum() + pag->getFieldValNodeNum();
158 PTNumStatMap["TotalObjects"] = pag->getObjectNodeNum() + pag->getFieldObjNodeNum();
159
160 PTNumStatMap["Pointers"] = pag->getValueNodeNum();
161 PTNumStatMap["MemObjects"] = pag->getObjectNodeNum();
162 PTNumStatMap["DummyFieldPtrs"] = pag->getFieldValNodeNum();
163 PTNumStatMap["FieldObjs"] = pag->getFieldObjNodeNum();
164
165 PTNumStatMap["CopysNum"] = numOfCopy;
166 PTNumStatMap["StoresNum"] = numOfStore;
167
168 PTNumStatMap["SolveIterations"] = fspta->numOfIteration;
169
170 PTNumStatMap["IndEdgeSolved"] = fspta->getNumOfResolvedIndCallEdge();
171
172 PTNumStatMap["NullPointer"] = _NumOfNullPtr;
173 PTNumStatMap["PointsToConstPtr"] = _NumOfConstantPtr;
174 PTNumStatMap["PointsToBlkPtr"] = _NumOfBlackholePtr;
175
176 PTNumStatMap["StrongUpdates"] = fspta->svfgHasSU.count();
177
179 PTNumStatMap["SNodesHaveIN"] = _NumOfSVFGNodesHaveInOut[IN];
180 PTNumStatMap["SNodesHaveOUT"] = _NumOfSVFGNodesHaveInOut[OUT];
181
184
187
190
193
194 PTNumStatMap["LD_SNodesHaveIN"] = _NumOfLoadSVFGNodesHaveInOut[IN];
195 PTNumStatMap["LD_SNodesHaveOUT"] = _NumOfLoadSVFGNodesHaveInOut[OUT];
196
197 PTNumStatMap["ST_SNodesHaveIN"] = _NumOfStoreSVFGNodesHaveInOut[IN];
198 PTNumStatMap["ST_SNodesHaveOUT"] = _NumOfStoreSVFGNodesHaveInOut[OUT];
199
200 PTNumStatMap["PHI_SNodesHaveIN"] = _NumOfMSSAPhiSVFGNodesHaveInOut[IN];
201 PTNumStatMap["PHI_SNodesHaveOUT"] = _NumOfMSSAPhiSVFGNodesHaveInOut[OUT];
202
203 /*-----------------------------------------------------*/
204 // SVFIR nodes.
205 PTNumStatMap["VarHaveIN"] = _NumOfVarHaveINOUTPts[IN];
206 PTNumStatMap["VarHaveOUT"] = _NumOfVarHaveINOUTPts[OUT];
207
208 PTNumStatMap["PotentialVarHaveIN"] = _PotentialNumOfVarHaveINOUTPts[IN];
209 PTNumStatMap["PotentialVarHaveOUT"] = _PotentialNumOfVarHaveINOUTPts[OUT];
210
211 PTNumStatMap["VarHaveEmptyIN"] = _NumOfVarHaveEmptyINOUTPts[IN];
212 PTNumStatMap["VarHaveEmptyOUT"] = _NumOfVarHaveEmptyINOUTPts[OUT];
213
216
219
222
225
227 PTNumStatMap["VarHaveOUT_LD"] = _NumOfVarHaveINOUTPtsInLoad[OUT];
228
231
234
235 PTNumStatMap["MaxPtsSize"] = _MaxPtsSize;
236 PTNumStatMap["MaxTopLvlPtsSize"] = _MaxTopLvlPtsSize;
237 PTNumStatMap["MaxINPtsSize"] = _MaxInOutPtsSize[IN];
238 PTNumStatMap["MaxOUTPtsSize"] = _MaxInOutPtsSize[OUT];
239
240 timeStatMap["AvgPtsSize"] = _AvgPtsSize;
241 timeStatMap["AvgTopLvlPtsSize"] = _AvgTopLvlPtsSize;
242
243 PTNumStatMap["NumOfAddrTakenVar"] = _NumOfAddrTakeVar;
244 timeStatMap["AvgAddrTakenVarPts"] = (_NumOfAddrTakeVar == 0) ?
246 PTNumStatMap["MaxAddrTakenVarPts"] = _MaxAddrTakenVarPts;
247
248 timeStatMap["AvgINPtsSize"] = _AvgInOutPtsSize[IN];
249 timeStatMap["AvgOUTPtsSize"] = _AvgInOutPtsSize[OUT];
250
251 PTNumStatMap["ProcessedAddr"] = fspta->numOfProcessedAddr;
252 PTNumStatMap["ProcessedCopy"] = fspta->numOfProcessedCopy;
253 PTNumStatMap["ProcessedGep"] = fspta->numOfProcessedGep;
254 PTNumStatMap["ProcessedLoad"] = fspta->numOfProcessedLoad;
255 PTNumStatMap["ProcessedStore"] = fspta->numOfProcessedStore;
256 PTNumStatMap["ProcessedPhi"] = fspta->numOfProcessedPhi;
257 PTNumStatMap["ProcessedAParam"] = fspta->numOfProcessedActualParam;
258 PTNumStatMap["ProcessedFRet"] = fspta->numOfProcessedFormalRet;
259 PTNumStatMap["ProcessedMSSANode"] = fspta->numOfProcessedMSSANode;
260
261 PTNumStatMap["NumOfNodesInSCC"] = fspta->numOfNodesInSCC;
262 PTNumStatMap["MaxSCCSize"] = fspta->maxSCCSize;
263 PTNumStatMap["NumOfSCC"] = fspta->numOfSCC;
264 timeStatMap["AverageSCCSize"] = (fspta->numOfSCC == 0) ? 0 :
266
267 PTAStat::printStat("Flow-Sensitive Pointer Analysis Statistics");
268}
269
271{
272 _NumOfNullPtr = 0;
273 for (SVFIR::iterator iter = fspta->getPAG()->begin(), eiter = fspta->getPAG()->end();
274 iter != eiter; ++iter)
275 {
276 NodeID pagNodeId = iter->first;
277 PAGNode* pagNode = iter->second;
280 if (inComingStore.empty()==false || outGoingLoad.empty()==false)
281 {
283 const PointsTo& pts = fspta->getPts(pagNodeId);
285 {
287 }
289 {
291 }
292 if(pts.empty())
293 {
294 std::string str;
295 std::stringstream rawstr(str);
296 if (!SVFUtil::isa<DummyValVar>(pagNode) && !SVFUtil::isa<DummyObjVar>(pagNode))
297 {
298 // if a pointer is in dead function, we do not care
299 if(pagNode->getValue()->ptrInUncalledFunction() == false)
300 {
302 rawstr << "##Null Pointer : (NodeID " << pagNode->getId()
303 << ") PtrName:" << pagNode->getValue()->getName();
304 writeWrnMsg(rawstr.str());
305 }
306 }
307 else
308 {
310 rawstr << "##Null Pointer : (NodeID " << pagNode->getId();
311 writeWrnMsg(rawstr.str());
312 }
313 }
314 }
315 }
316}
317
322{
323 // TODO: needs to be made to work for persistent.
324 if (SVFUtil::isa<FlowSensitive::MutDFPTDataTy>(fspta->getPTDataTy()))
325 {
326 // stat of IN set
328 // stat of OUT set
330 }
331
335 for (SVFIR::iterator iter = fspta->getPAG()->begin(), eiter = fspta->getPAG()->end();
336 iter != eiter; ++iter)
337 {
338 NodeID node = iter->first;
339 if (fspta->getPAG()->isValidTopLevelPtr(iter->second) == false)
340 continue;
341 u32_t size = fspta->getPts(node).count();
342
344 topTopLvlPtsSize+=size;
345
346 if(size > _MaxPtsSize) _MaxPtsSize = size;
347
348 if (size > _MaxTopLvlPtsSize) _MaxTopLvlPtsSize = size;
349 }
350
353
356 if (totalPointer != 0)
358}
359
361{
362 // Get number of nodes which have IN/OUT set
363 _NumOfSVFGNodesHaveInOut[inOrOut] = data.size();
364
366 DFInOutMap::const_iterator it = data.begin();
367 DFInOutMap::const_iterator eit = data.end();
368 for (; it != eit; ++it)
369 {
370 const SVFGNode* node = fspta->svfg->getSVFGNode(it->first);
371
372 // Count number of SVFG nodes have IN/OUT set.
373 if (SVFUtil::isa<FormalINSVFGNode>(node))
375 else if (SVFUtil::isa<FormalOUTSVFGNode>(node))
377 else if (SVFUtil::isa<ActualINSVFGNode>(node))
379 else if (SVFUtil::isa<ActualOUTSVFGNode>(node))
381 else if (SVFUtil::isa<LoadSVFGNode>(node))
383 else if (SVFUtil::isa<StoreSVFGNode>(node))
385 else if (SVFUtil::isa<MSSAPHISVFGNode>(node))
387 else
388 assert(false && "unexpected node have IN/OUT set");
389
390 /*-----------------------------------------------------*/
391
392 // Count SVFIR nodes and their points-to set size.
393 const PtsMap& cptsMap = it->second;
394 PtsMap::const_iterator ptsIt = cptsMap.begin();
395 PtsMap::const_iterator ptsEit = cptsMap.end();
396 for (; ptsIt != ptsEit; ++ptsIt)
397 {
398 if (ptsIt->second.empty())
399 {
401 continue;
402 }
403
404 u32_t ptsNum = ptsIt->second.count();
405
406 // Only node with non-empty points-to set are counted.
408
409 if (SVFUtil::isa<FormalINSVFGNode>(node))
411 else if (SVFUtil::isa<FormalOUTSVFGNode>(node))
413 else if (SVFUtil::isa<ActualINSVFGNode>(node))
415 else if (SVFUtil::isa<ActualOUTSVFGNode>(node))
417 else if (SVFUtil::isa<LoadSVFGNode>(node))
419 else if (SVFUtil::isa<StoreSVFGNode>(node))
421 else if (SVFUtil::isa<MSSAPHISVFGNode>(node))
423 else
424 assert(false && "unexpected node have IN/OUT set");
425
427
430
432 }
433 }
434
437
439
440 // How many IN/OUT PTSs could we have *potentially* had?
441 // l'-o->l, l''-o->l, ..., means there is a possibility of 1 IN PTS.
442 // *p = q && { o } in pts_ander(p) means there is a possibility of 1 OUT PTS.
443 // For OUTs at stores, we must also account for WU/SUs.
444 const SVFG *svfg = fspta->svfg;
445 for (SVFG::const_iterator it = svfg->begin(); it != svfg->end(); ++it)
446 {
447 const SVFGNode *sn = it->second;
448
449 // Unique objects coming into s.
451 for (const SVFGEdge *e : sn->getInEdges())
452 {
453 const IndirectSVFGEdge *ie = SVFUtil::dyn_cast<IndirectSVFGEdge>(e);
454 if (!ie) continue;
455 for (NodeID o : ie->getPointsTo()) incomingObjects.set(o);
456 }
457
459
460 if (const StoreSVFGNode *store = SVFUtil::dyn_cast<StoreSVFGNode>(sn))
461 {
462 NodeID p = store->getPAGDstNodeID();
463 // Reuse incomingObjects; what's already in there will be propagated forwarded
464 // as a WU/SU, and what's not (first defined at the store), will be added.
465 for (NodeID o : fspta->ander->getPts(p)) incomingObjects.set(o);
466
468 }
469 }
470}
471
476{
477 SVFG::SVFGNodeIDToNodeMapTy::const_iterator it = fspta->svfg->begin();
478 SVFG::SVFGNodeIDToNodeMapTy::const_iterator eit = fspta->svfg->end();
479 for (; it != eit; ++it)
480 {
481 const SVFGNode* node = it->second;
482 if (const StoreSVFGNode* store = SVFUtil::dyn_cast<StoreSVFGNode>(node))
483 {
484 calculateAddrVarPts(store->getPAGDstNodeID(), store);
485 }
486 }
487}
488
493{
494 const PointsTo& pts = fspta->getPts(pointer);
496 PointsTo::iterator ptsIt = pts.begin();
498 for (; ptsIt != ptsEit; ++ptsIt)
499 {
500 const NodeID ptd = *ptsIt;
501
502 const PointsTo& cpts = fspta->getDFOutPtsSet(svfg_node, ptd);
504 if (cpts.count() > _MaxAddrTakenVarPts)
505 _MaxAddrTakenVarPts = cpts.count();
506 }
507}
508
509
#define TIMEINTERVAL
Definition SVFType.h:512
cJSON * p
Definition cJSON.cpp:2559
virtual const PointsTo & getPts(NodeID id)
Operation of points-to set.
Definition Andersen.h:239
const PointsTo & getPts(NodeID id) override
PTDataTy * getPTDataTy() const
Get points-to data structure.
void calculateAddrVarPts(NodeID pointer, const SVFGNode *node)
u32_t _NumOfActualInSVFGNodesHaveInOut[2]
Definition WPAStat.h:131
double _AvgPtsSize
average points-to set size.
Definition WPAStat.h:156
double _AvgAddrTakenVarPtsSize
average points-to set size of addr-taken variables.
Definition WPAStat.h:159
u32_t _PotentialNumOfVarHaveINOUTPts[2]
Definition WPAStat.h:147
u32_t _NumOfVarHaveINOUTPtsInFormalOut[2]
Definition WPAStat.h:141
FlowSensitive::PtsMap PtsMap
Definition WPAStat.h:89
u32_t _NumOfFormalOutSVFGNodesHaveInOut[2]
Definition WPAStat.h:130
u32_t _NumOfVarHaveEmptyINOUTPts[2]
Definition WPAStat.h:139
u32_t _NumOfVarHaveINOUTPtsInStore[2]
Definition WPAStat.h:145
u32_t _NumOfFormalInSVFGNodesHaveInOut[2]
Definition WPAStat.h:129
double _AvgTopLvlPtsSize
average points-to set size in top-level pointers.
Definition WPAStat.h:157
u32_t _NumOfActualOutSVFGNodesHaveInOut[2]
Definition WPAStat.h:132
u32_t _NumOfVarHaveINOUTPtsInActualIn[2]
Definition WPAStat.h:142
FlowSensitive::DFInOutMap DFInOutMap
Definition WPAStat.h:88
u32_t _NumOfMSSAPhiSVFGNodesHaveInOut[2]
Definition WPAStat.h:135
u32_t _MaxPtsSize
sizes of points-to set
Definition WPAStat.h:150
u32_t _MaxAddrTakenVarPts
max points-to set size of addr-taken variables.
Definition WPAStat.h:161
void statInOutPtsSize(const DFInOutMap &data, ENUM_INOUT inOrOut)
u32_t _TotalPtsSize
total points-to set size.
Definition WPAStat.h:154
u32_t _NumOfVarHaveINOUTPtsInMSSAPhi[2]
Definition WPAStat.h:146
u32_t _NumOfSVFGNodesHaveInOut[2]
number of SVFG nodes which have IN/OUT set.
Definition WPAStat.h:128
u32_t _NumOfVarHaveINOUTPtsInLoad[2]
Definition WPAStat.h:144
u32_t _MaxInOutPtsSize[2]
max points-to set size in IN/OUT set.
Definition WPAStat.h:152
u32_t _NumOfVarHaveINOUTPts[2]
number of pag nodes which have points-to set in IN/OUT set.
Definition WPAStat.h:138
u32_t _NumOfLoadSVFGNodesHaveInOut[2]
Definition WPAStat.h:133
u32_t _NumOfVarHaveINOUTPtsInActualOut[2]
Definition WPAStat.h:143
u32_t _NumOfVarHaveINOUTPtsInFormalIn[2]
Definition WPAStat.h:140
u32_t _NumOfStoreSVFGNodesHaveInOut[2]
Definition WPAStat.h:134
u32_t _NumOfAddrTakeVar
number of occurrences of addr-taken variables in load/store.
Definition WPAStat.h:162
u32_t _MaxTopLvlPtsSize
max points-to set size in top-level pointers.
Definition WPAStat.h:151
double _AvgInOutPtsSize[2]
average points-to set size in IN set.
Definition WPAStat.h:158
FlowSensitive * fspta
Definition WPAStat.h:91
u32_t numOfProcessedLoad
Number of processed Phi node.
u32_t numOfProcessedCopy
Number of processed Addr node.
double gepTime
time of handling gep edges
double indirectPropaTime
time of points-to propagation of top-level pointers
double addrTime
time of handling address edges
const DFInOutMap & getDFOutputMap() const
double solveTime
time of solve.
const DFInOutMap & getDFInputMap() const
AndersenWaveDiff * ander
u32_t numOfProcessedStore
Number of processed Load node.
const PointsTo & getDFOutPtsSet(const SVFGNode *stmt, const NodeID node)
double storeTime
time of store edges
double copyTime
time of handling copy edges
u32_t numOfProcessedGep
Number of processed Copy node.
u32_t maxSCCSize
Number of processed mssa node.
double loadTime
time of load edges
u32_t numOfProcessedActualParam
Number of processed Store node.
u32_t numOfProcessedPhi
Number of processed Gep node.
double propagationTime
time of points-to propagation.
u32_t numOfProcessedFormalRet
Number of processed actual param node.
double directPropaTime
time of points-to propagation of address-taken objects
double processTime
time of processNode.
u32_t numOfProcessedAddr
Statistics.
double phiTime
time of phi nodes.
double sccTime
time of SCC detection.
double updateTime
time of strong/weak updates.
u32_t numOfProcessedMSSANode
Number of processed formal ret node.
double updateCallGraphTime
time of updating call graph
iterator begin()
Iterators.
IDToNodeMapTy::const_iterator const_iterator
IDToNodeMapTy::iterator iterator
Node Iterators.
u32_t getValueNodeNum() const
Definition IRGraph.h:186
u32_t getObjectNodeNum() const
Definition IRGraph.h:190
SymID getId() const
Get the memory object id.
void performStat() override
Definition PTAStat.cpp:52
bool containBlackHoleNode(const PointsTo &pts)
Determine whether a points-to contains a black hole or constant node.
SVFIR * getPAG() const
u32_t getNumOfResolvedIndCallEdge() const
Return number of resolved indirect call edges.
bool containConstantNode(const PointsTo &pts)
u32_t count() const
Returns number of elements.
Definition PointsTo.cpp:111
SVFGNode * getSVFGNode(NodeID id) const
Get a SVFG node.
Definition SVFG.h:150
u32_t getFieldObjNodeNum() const
Definition SVFIR.h:339
bool isValidTopLevelPtr(const SVFVar *node)
Definition SVFIR.cpp:685
const MemObj * getBaseObj(NodeID id) const
Definition SVFIR.h:481
u32_t getFieldValNodeNum() const
Node and edge statistics.
Definition SVFIR.h:335
NUMStatMap PTNumStatMap
Definition SVFStat.h:77
virtual void printStat(std::string str="")
Definition SVFStat.cpp:67
virtual void endClk()
Definition SVFStat.h:63
TIMEStatMap timeStatMap
Definition SVFStat.h:78
double endTime
Definition SVFStat.h:81
double startTime
Definition SVFStat.h:80
GenericNode< SVFVar, SVFStmt >::GEdgeSetTy SVFStmtSetTy
SVFStmt::SVFStmtSetTy & getIncomingEdges(SVFStmt::PEDGEK kind)
Get incoming SVFIR statements (edges)
unsigned count() const
u32_t numOfIteration
num of iterations during constraint solving
Definition WPASolver.h:200
void writeWrnMsg(const std::string &msg)
Writes a message run through wrnMsg.
Definition SVFUtil.cpp:67
for isBitcode
Definition BasicTypes.h:68
u32_t NodeID
Definition GeneralType.h:55
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74
unsigned SymID
Definition GeneralType.h:57
unsigned u32_t
Definition GeneralType.h:46