Static Value-Flow Analysis
AndersenStat.cpp
Go to the documentation of this file.
1 //===- AndersenStat.cpp -- Statistics of Andersen's 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  * AndersenStat.cpp
25  *
26  * Created on: Oct 12, 2013
27  * Author: Yulei Sui
28  */
29 
31 #include "WPA/WPAStat.h"
32 #include "WPA/Andersen.h"
33 
34 using namespace SVF;
35 using namespace SVFUtil;
36 using namespace std;
37 
43 
44 const char* AndersenStat::CollapseTime = "CollapseTime";
45 
50 {
51  _NumOfNullPtr = 0;
54  startClk();
55 }
56 
61 {
62  _NumOfCycles = 0;
63  _NumOfPWCCycles = 0;
65  NodeSet repNodes;
66  repNodes.clear();
67  for(ConstraintGraph::iterator it = consCG->begin(), eit = consCG->end(); it!=eit; ++it)
68  {
69  // sub nodes have been removed from the constraint graph, only rep nodes are left.
70  NodeID repNode = consCG->sccRepNode(it->first);
71  NodeBS& subNodes = consCG->sccSubNodes(repNode);
72  NodeBS clone = subNodes;
73  for (NodeBS::iterator it = subNodes.begin(), eit = subNodes.end(); it != eit; ++it)
74  {
75  NodeID nodeId = *it;
76  PAGNode* pagNode = pta->getPAG()->getGNode(nodeId);
77  if (SVFUtil::isa<ObjVar>(pagNode) && pta->isFieldInsensitive(nodeId))
78  {
79  NodeID baseId = consCG->getBaseObjVar(nodeId);
80  clone.reset(nodeId);
81  clone.set(baseId);
82  }
83  }
84  u32_t num = clone.count();
85  if (num > 1)
86  {
87  if(repNodes.insert(repNode).second)
88  {
89  _NumOfNodesInCycles += num;
90  if(consCG->isPWCNode(repNode))
91  _NumOfPWCCycles ++;
92  }
93  if( num > _MaxNumOfNodesInSCC)
94  _MaxNumOfNodesInSCC = num;
95  }
96  }
97  _NumOfCycles += repNodes.size();
98 }
99 
101 {
102 
103 
105 
106  u32_t numOfCopys = 0;
107  u32_t numOfGeps = 0;
108  // collect copy and gep edges
109  for(ConstraintEdge::ConstraintEdgeSetTy::iterator it = consCG->getDirectCGEdges().begin(),
110  eit = consCG->getDirectCGEdges().end(); it!=eit; ++it)
111  {
112  if(SVFUtil::isa<CopyCGEdge>(*it))
113  numOfCopys++;
114  else if(SVFUtil::isa<GepCGEdge>(*it))
115  numOfGeps++;
116  else
117  assert(false && "what else!!");
118  }
119 
120  u32_t totalNodeNumber = 0;
121  u32_t cgNodeNumber = 0;
122  u32_t objNodeNumber = 0;
123  u32_t addrtotalIn = 0;
124  u32_t addrmaxIn = 0;
125  u32_t addrmaxOut = 0;
126  u32_t copytotalIn = 0;
127  u32_t copymaxIn = 0;
128  u32_t copymaxOut = 0;
129  u32_t loadtotalIn = 0;
130  u32_t loadmaxIn = 0;
131  u32_t loadmaxOut = 0;
132  u32_t storetotalIn = 0;
133  u32_t storemaxIn = 0;
134  u32_t storemaxOut = 0;
135 
136 
137  for (ConstraintGraph::ConstraintNodeIDToNodeMapTy::iterator nodeIt = consCG->begin(), nodeEit = consCG->end();
138  nodeIt != nodeEit; nodeIt++)
139  {
140  totalNodeNumber++;
141  if(nodeIt->second->getInEdges().empty() && nodeIt->second->getOutEdges().empty())
142  continue;
143  cgNodeNumber++;
144  if(SVFUtil::isa<ObjVar>(pta->getPAG()->getGNode(nodeIt->first)))
145  objNodeNumber++;
146 
147  u32_t nCopyIn = nodeIt->second->getDirectInEdges().size();
148  if(nCopyIn > copymaxIn)
149  copymaxIn = nCopyIn;
150  copytotalIn +=nCopyIn;
151  u32_t nCopyOut = nodeIt->second->getDirectOutEdges().size();
152  if(nCopyOut > copymaxOut)
153  copymaxOut = nCopyOut;
154  u32_t nLoadIn = nodeIt->second->getLoadInEdges().size();
155  if(nLoadIn > loadmaxIn)
156  loadmaxIn = nLoadIn;
157  loadtotalIn +=nLoadIn;
158  u32_t nLoadOut = nodeIt->second->getLoadOutEdges().size();
159  if(nLoadOut > loadmaxOut)
160  loadmaxOut = nLoadOut;
161  u32_t nStoreIn = nodeIt->second->getStoreInEdges().size();
162  if(nStoreIn > storemaxIn)
163  storemaxIn = nStoreIn;
164  storetotalIn +=nStoreIn;
165  u32_t nStoreOut = nodeIt->second->getStoreOutEdges().size();
166  if(nStoreOut > storemaxOut)
167  storemaxOut = nStoreOut;
168  u32_t nAddrIn = nodeIt->second->getAddrInEdges().size();
169  if(nAddrIn > addrmaxIn)
170  addrmaxIn = nAddrIn;
171  addrtotalIn +=nAddrIn;
172  u32_t nAddrOut = nodeIt->second->getAddrOutEdges().size();
173  if(nAddrOut > addrmaxOut)
174  addrmaxOut = nAddrOut;
175  }
176  double storeavgIn = (double)storetotalIn/cgNodeNumber;
177  double loadavgIn = (double)loadtotalIn/cgNodeNumber;
178  double copyavgIn = (double)copytotalIn/cgNodeNumber;
179  double addravgIn = (double)addrtotalIn/cgNodeNumber;
180  double avgIn = (double)(addrtotalIn + copytotalIn + loadtotalIn + storetotalIn)/cgNodeNumber;
181 
182 
183  PTNumStatMap["NumOfCGNode"] = totalNodeNumber;
184  PTNumStatMap["NumOfValidNode"] = cgNodeNumber;
185  PTNumStatMap["NumOfValidObjNode"] = objNodeNumber;
186  PTNumStatMap["NumOfCGEdge"] = consCG->getLoadCGEdges().size() + consCG->getStoreCGEdges().size()
187  + numOfCopys + numOfGeps;
188  PTNumStatMap["NumOfAddrs"] = consCG->getAddrCGEdges().size();
189  PTNumStatMap["NumOfCopys"] = numOfCopys;
190  PTNumStatMap["NumOfGeps"] = numOfGeps;
191  PTNumStatMap["NumOfLoads"] = consCG->getLoadCGEdges().size();
192  PTNumStatMap["NumOfStores"] = consCG->getStoreCGEdges().size();
193  PTNumStatMap["MaxInCopyEdge"] = copymaxIn;
194  PTNumStatMap["MaxOutCopyEdge"] = copymaxOut;
195  PTNumStatMap["MaxInLoadEdge"] = loadmaxIn;
196  PTNumStatMap["MaxOutLoadEdge"] = loadmaxOut;
197  PTNumStatMap["MaxInStoreEdge"] = storemaxIn;
198  PTNumStatMap["MaxOutStoreEdge"] = storemaxOut;
199  PTNumStatMap["MaxInAddrEdge"] = addrmaxIn;
200  PTNumStatMap["MaxOutAddrEdge"] = addrmaxOut;
201  timeStatMap["AvgIn/OutStoreEdge"] = storeavgIn;
202  timeStatMap["AvgIn/OutCopyEdge"] = copyavgIn;
203  timeStatMap["AvgIn/OutLoadEdge"] = loadavgIn;
204  timeStatMap["AvgIn/OutAddrEdge"] = addravgIn;
205  timeStatMap["AvgIn/OutEdge"] = avgIn;
206 }
211 {
212 
213  _NumOfNullPtr = 0;
214  for (SVFIR::iterator iter = pta->getPAG()->begin(), eiter = pta->getPAG()->end();
215  iter != eiter; ++iter)
216  {
217  NodeID pagNodeId = iter->first;
218  PAGNode* pagNode = iter->second;
219  if (SVFUtil::isa<ValVar>(pagNode) == false)
220  continue;
221  SVFStmt::SVFStmtSetTy& inComingStore = pagNode->getIncomingEdges(SVFStmt::Store);
222  SVFStmt::SVFStmtSetTy& outGoingLoad = pagNode->getOutgoingEdges(SVFStmt::Load);
223  if (inComingStore.empty()==false || outGoingLoad.empty()==false)
224  {
226  const PointsTo& pts = pta->getPts(pagNodeId);
227  if (pta->containBlackHoleNode(pts))
229 
230  if (pta->containConstantNode(pts))
232 
233  if(pts.empty())
234  {
235  std::string str;
236  std::stringstream rawstr(str);
237  if (!SVFUtil::isa<DummyValVar>(pagNode) && !SVFUtil::isa<DummyObjVar>(pagNode) )
238  {
239  // if a pointer is in dead function, we do not care
240  if(pagNode->getValue()->ptrInUncalledFunction() == false)
241  {
242  _NumOfNullPtr++;
243  rawstr << "##Null Pointer : (NodeID " << pagNode->getId()
244  << ") PtrName:" << pagNode->getValue()->getName();
245  writeWrnMsg(rawstr.str());
246  //pagNode->getValue()->dump();
247  }
248  }
249  else
250  {
251  _NumOfNullPtr++;
252  rawstr << "##Null Pointer : (NodeID " << pagNode->getId() << ")";
253  writeWrnMsg(rawstr.str());
254  }
255  }
256  }
257  }
258 
259 }
260 
265 {
266 
267  assert(SVFUtil::isa<AndersenBase>(pta) && "not an andersen pta pass!! what else??");
268  endClk();
269 
270  SVFIR* pag = pta->getPAG();
272 
273  // collect constraint graph cycles
274  collectCycleInfo(consCG);
275 
276  // stat null ptr number
277  statNullPtr();
278 
279  u32_t totalPointers = 0;
280  u32_t totalTopLevPointers = 0;
281  u32_t totalPtsSize = 0;
282  u32_t totalTopLevPtsSize = 0;
283  for (SVFIR::iterator iter = pta->getPAG()->begin(), eiter = pta->getPAG()->end();
284  iter != eiter; ++iter)
285  {
286  NodeID node = iter->first;
287  const PointsTo& pts = pta->getPts(node);
288  u32_t size = pts.count();
289  totalPointers++;
290  totalPtsSize+=size;
291 
292  if(pta->getPAG()->isValidTopLevelPtr(pta->getPAG()->getGNode(node)))
293  {
294  totalTopLevPointers++;
295  totalTopLevPtsSize+=size;
296  }
297 
298  if(size > _MaxPtsSize )
299  _MaxPtsSize = size;
300  }
301 
302 
304 
306 
307  timeStatMap["TotalTime"] = (endTime - startTime)/TIMEINTERVAL;
308  timeStatMap["SCCDetectTime"] = Andersen::timeOfSCCDetection;
309  timeStatMap["SCCMergeTime"] = Andersen::timeOfSCCMerges;
311 
315 
316  PTNumStatMap["TotalPointers"] = pag->getValueNodeNum() + pag->getFieldValNodeNum();
317  PTNumStatMap["TotalObjects"] = pag->getObjectNodeNum() + pag->getFieldObjNodeNum();
318 
319 
320  PTNumStatMap["AddrProcessed"] = Andersen::numOfProcessedAddr;
321  PTNumStatMap["CopyProcessed"] = Andersen::numOfProcessedCopy;
322  PTNumStatMap["GepProcessed"] = Andersen::numOfProcessedGep;
323  PTNumStatMap["LoadProcessed"] = Andersen::numOfProcessedLoad;
324  PTNumStatMap["StoreProcessed"] = Andersen::numOfProcessedStore;
325 
326  PTNumStatMap["NumOfSFRs"] = Andersen::numOfSfrs;
327  PTNumStatMap["NumOfFieldExpand"] = Andersen::numOfFieldExpand;
328 
329  PTNumStatMap["Pointers"] = pag->getValueNodeNum();
330  PTNumStatMap["MemObjects"] = pag->getObjectNodeNum();
331  PTNumStatMap["DummyFieldPtrs"] = pag->getFieldValNodeNum();
332  PTNumStatMap["FieldObjs"] = pag->getFieldObjNodeNum();
333 
334  timeStatMap["AvgPtsSetSize"] = (double)totalPtsSize/totalPointers;;
335  timeStatMap["AvgTopLvlPtsSize"] = (double)totalTopLevPtsSize/totalTopLevPointers;;
336 
337  PTNumStatMap["MaxPtsSetSize"] = _MaxPtsSize;
338 
339  PTNumStatMap["SolveIterations"] = pta->numOfIteration;
340 
341  PTNumStatMap["IndCallSites"] = consCG->getIndirectCallsites().size();
342  PTNumStatMap["IndEdgeSolved"] = pta->getNumOfResolvedIndCallEdge();
343 
344  PTNumStatMap["NumOfSCCDetect"] = Andersen::numOfSCCDetection;
345  PTNumStatMap["TotalCycleNum"] = _NumOfCycles;
346  PTNumStatMap["TotalPWCCycleNum"] = _NumOfPWCCycles;
347  PTNumStatMap["NodesInCycles"] = _NumOfNodesInCycles;
348  PTNumStatMap["MaxNodesInSCC"] = _MaxNumOfNodesInSCC;
349  PTNumStatMap["NullPointer"] = _NumOfNullPtr;
350  PTNumStatMap["PointsToConstPtr"] = _NumOfConstantPtr;
351  PTNumStatMap["PointsToBlkPtr"] = _NumOfBlackholePtr;
352 
353  PTAStat::printStat("Andersen Pointer Analysis Stats");
354 }
355 
unsigned u32_t
Definition: CommandLine.h:18
#define TIMEINTERVAL
Definition: SVFType.h:512
cJSON * p
Definition: cJSON.cpp:2559
const char *const string
Definition: cJSON.h:172
static double timeOfSCCMerges
Definition: Andersen.h:167
static u32_t numOfProcessedCopy
Number of processed Addr edge.
Definition: Andersen.h:158
static u32_t numOfSCCDetection
Definition: Andersen.h:165
static u32_t numOfSfrs
Number of processed Store edge.
Definition: Andersen.h:162
static double timeOfUpdateCallGraph
Definition: Andersen.h:173
static u32_t numOfProcessedStore
Number of processed Load edge.
Definition: Andersen.h:161
static u32_t numOfProcessedAddr
Statistics.
Definition: Andersen.h:157
static u32_t numOfProcessedLoad
Number of processed Gep edge.
Definition: Andersen.h:160
static double timeOfSCCDetection
Definition: Andersen.h:166
static u32_t numOfFieldExpand
Definition: Andersen.h:163
static double timeOfProcessLoadStore
Definition: Andersen.h:172
static u32_t numOfProcessedGep
Number of processed Copy edge.
Definition: Andersen.h:159
static double timeOfProcessCopyGep
Definition: Andersen.h:171
ConstraintGraph * getConstraintGraph()
Get constraint graph.
Definition: Andersen.h:122
static double timeOfCollapse
Definition: Andersen.h:168
AndersenStat(AndersenBase *p)
u32_t _NumOfBlackholePtr
Definition: WPAStat.h:64
u32_t _NumOfNullPtr
Definition: WPAStat.h:62
static const char * CollapseTime
Definition: WPAStat.h:55
virtual void performStat()
static u32_t _NumOfCycles
Definition: WPAStat.h:58
static u32_t _MaxPtsSize
Definition: WPAStat.h:57
AndersenBase * pta
Definition: WPAStat.h:52
static u32_t _NumOfNodesInCycles
Definition: WPAStat.h:60
u32_t _NumOfConstantPtr
Definition: WPAStat.h:63
static u32_t _MaxNumOfNodesInSCC
Definition: WPAStat.h:61
void collectCycleInfo(ConstraintGraph *consCG)
static u32_t _NumOfPWCCycles
Definition: WPAStat.h:59
const PointsTo & getPts(NodeID id) override
NodeID sccRepNode(NodeID id) const
SCC rep/sub nodes methods.
Definition: ConsG.h:235
const SVFIR::CallSiteToFunPtrMap & getIndirectCallsites() const
Wrappers for invoking SVFIR methods.
Definition: ConsG.h:304
ConstraintEdge::ConstraintEdgeSetTy & getStoreCGEdges()
Get Store edges.
Definition: ConsG.h:211
NodeID getBaseObjVar(NodeID id)
Definition: ConsG.h:320
bool isPWCNode(NodeID nodeId)
Check/Set PWC (positive weight cycle) flag.
Definition: ConsG.h:350
ConstraintEdge::ConstraintEdgeSetTy & getDirectCGEdges()
Get Copy/call/ret/gep edges.
Definition: ConsG.h:201
ConstraintEdge::ConstraintEdgeSetTy & getAddrCGEdges()
Get SVFIR edge.
Definition: ConsG.h:196
NodeBS & sccSubNodes(NodeID id)
Definition: ConsG.h:243
ConstraintEdge::ConstraintEdgeSetTy & getLoadCGEdges()
Get Load edges.
Definition: ConsG.h:206
iterator begin()
Iterators.
Definition: GenericGraph.h:627
NodeType * getGNode(NodeID id) const
Get a node.
Definition: GenericGraph.h:653
IDToNodeMapTy::iterator iterator
Node Iterators.
Definition: GenericGraph.h:606
u32_t getValueNodeNum() const
Definition: IRGraph.h:186
u32_t getObjectNodeNum() const
Definition: IRGraph.h:190
void performStat() override
Definition: PTAStat.cpp:52
bool isFieldInsensitive(NodeID id) const
SVFIR * getPAG() const
bool containBlackHoleNode(const PointsTo &pts)
Determine whether a points-to contains a black hole or constant node.
u32_t getNumOfResolvedIndCallEdge() const
Return number of resolved indirect call edges.
bool containConstantNode(const PointsTo &pts)
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
u32_t getFieldObjNodeNum() const
Definition: SVFIR.h:338
bool isValidTopLevelPtr(const SVFVar *node)
Definition: SVFIR.cpp:673
u32_t getFieldValNodeNum() const
Node and edge statistics.
Definition: SVFIR.h:334
NUMStatMap PTNumStatMap
Definition: SVFStat.h:77
virtual void printStat(std::string str="")
Definition: SVFStat.cpp:66
virtual void endClk()
Definition: SVFStat.h:63
TIMEStatMap timeStatMap
Definition: SVFStat.h:78
virtual void startClk()
Definition: SVFStat.h:58
double endTime
Definition: SVFStat.h:81
double startTime
Definition: SVFStat.h:80
GenericNode< SVFVar, SVFStmt >::GEdgeSetTy SVFStmtSetTy
const std::string & getName() const
Definition: SVFValue.h:243
bool ptrInUncalledFunction() const
Definition: SVFValue.h:264
SVFStmt::SVFStmtSetTy & getIncomingEdges(SVFStmt::PEDGEK kind)
Get incoming SVFIR statements (edges)
Definition: SVFVariables.h:137
SVFStmt::SVFStmtSetTy & getOutgoingEdges(SVFStmt::PEDGEK kind)
Get outgoing SVFIR statements (edges)
Definition: SVFVariables.h:142
const SVFValue * getValue() const
Get/has methods of the components.
Definition: SVFVariables.h:83
iterator end() const
void set(unsigned Idx)
unsigned count() const
iterator begin() const
void reset(unsigned Idx)
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:66
for isBitcode
Definition: BasicTypes.h:68
Set< NodeID > NodeSet
Definition: GeneralType.h:113
u32_t NodeID
Definition: GeneralType.h:55
unsigned u32_t
Definition: GeneralType.h:46