Static Value-Flow Analysis
SVFStat.cpp
Go to the documentation of this file.
1 //===- SVFStat.cpp -- Base class for statistics---------------------------------//
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  * SVFStat.cpp
25  *
26  * Created on: Sep 1, 2022
27  * Author: Xiao Cheng
28  */
29 
30 #include "Util/Options.h"
31 #include "Util/SVFStat.h"
32 
33 using namespace SVF;
34 using namespace std;
35 
39 bool SVFStat::printGeneralStats = true;
40 
41 SVFStat::SVFStat() : startTime(0), endTime(0)
42 {
43  assert((Options::ClockType() == ClockType::Wall || Options::ClockType() == ClockType::CPU)
44  && "PTAStat: unknown clock type!");
45 }
46 
47 double SVFStat::getClk(bool mark)
48 {
49  if (Options::MarkedClocksOnly() && !mark) return 0.0;
50 
51  if (Options::ClockType() == ClockType::Wall)
52  {
53  struct timespec time;
54  clock_gettime(CLOCK_MONOTONIC, &time);
55  return (double)(time.tv_nsec + time.tv_sec * 1000000000) / 1000000.0;
56  }
57  else if (Options::ClockType() == ClockType::CPU)
58  {
59  return CLOCK_IN_MS();
60  }
61 
62  assert(false && "PTAStat::getClk: unknown clock type");
63  abort();
64 }
65 
66 void SVFStat::printStat(string statname)
67 {
68 
69  std::string moduleName(SVFIR::getPAG()->getModule()->getModuleIdentifier());
70  std::vector<std::string> names = SVFUtil::split(moduleName,'/');
71  if (names.size() > 1)
72  {
73  moduleName = names[names.size() - 1];
74  }
75 
76  SVFUtil::outs() << "\n*********" << statname << "***************\n";
77  SVFUtil::outs() << "################ (program : " << moduleName << ")###############\n";
78  SVFUtil::outs().flags(std::ios::left);
79  unsigned field_width = 20;
80 
81  for(NUMStatMap::iterator it = generalNumMap.begin(), eit = generalNumMap.end(); it!=eit; ++it)
82  {
83  // format out put with width 20 space
84  std::cout << std::setw(field_width) << it->first << it->second << "\n";
85  }
86 
87  if(!timeStatMap.empty())
88  SVFUtil::outs() << "----------------Time and memory stats--------------------\n";
89  for(TIMEStatMap::iterator it = timeStatMap.begin(), eit = timeStatMap.end(); it!=eit; ++it)
90  {
91  // format out put with width 20 space
92  SVFUtil::outs() << std::setw(field_width) << it->first << it->second << "\n";
93  }
94 
95  if(!PTNumStatMap.empty())
96  SVFUtil::outs() << "----------------Numbers stats----------------------------\n";
97  for(NUMStatMap::iterator it = PTNumStatMap.begin(), eit = PTNumStatMap.end(); it!=eit; ++it)
98  {
99  // format out put with width 20 space
100  SVFUtil::outs() << std::setw(field_width) << it->first << it->second << "\n";
101  }
102  SVFUtil::outs() << "#######################################################" << std::endl;
103  SVFUtil::outs().flush();
104  generalNumMap.clear();
105  PTNumStatMap.clear();
106  timeStatMap.clear();
107 }
108 
110 {
111 
113  if(printGeneralStats == false)
114  return;
115 
116  SVFIR* pag = SVFIR::getPAG();
117  u32_t numOfFunction = 0;
118  u32_t numOfGlobal = 0;
119  u32_t numOfStack = 0;
120  u32_t numOfHeap = 0;
121  u32_t numOfHasVarArray = 0;
122  u32_t numOfHasVarStruct = 0;
123  u32_t numOfHasConstArray = 0;
124  u32_t numOfHasConstStruct = 0;
125  u32_t numOfScalar = 0;
126  u32_t numOfConstant = 0;
127  u32_t fiObjNumber = 0;
128  u32_t fsObjNumber = 0;
129  Set<SymID> memObjSet;
130  for(SVFIR::iterator it = pag->begin(), eit = pag->end(); it!=eit; ++it)
131  {
132  PAGNode* node = it->second;
133  if(ObjVar* obj = SVFUtil::dyn_cast<ObjVar>(node))
134  {
135  const MemObj* mem = obj->getMemObj();
136  if (memObjSet.insert(mem->getId()).second == false)
137  continue;
138  if(mem->isBlackHoleObj())
139  continue;
140  if(mem->isFunction())
141  numOfFunction++;
142  if(mem->isGlobalObj())
143  numOfGlobal++;
144  if(mem->isStack())
145  numOfStack++;
146  if(mem->isHeap())
147  numOfHeap++;
148  if(mem->isVarArray())
149  numOfHasVarArray++;
150  if(mem->isVarStruct())
151  numOfHasVarStruct++;
152  if(mem->isConstantArray())
153  numOfHasConstArray++;
154  if(mem->isConstantStruct())
155  numOfHasConstStruct++;
156  if(mem->getType()->isPointerTy() == false)
157  numOfScalar++;
158  if(mem->isConstDataOrConstGlobal())
159  numOfConstant++;
160 
161  if (mem->isFieldInsensitive())
162  fiObjNumber++;
163  else
164  fsObjNumber++;
165  }
166  }
167 
168 
169 
170  generalNumMap["TotalPointers"] = pag->getValueNodeNum() + pag->getFieldValNodeNum();
171  generalNumMap["TotalObjects"] = pag->getObjectNodeNum();
172  generalNumMap["TotalFieldObjects"] = pag->getFieldObjNodeNum();
174  generalNumMap["TotalSVFStmts"] = pag->getPAGEdgeNum();
175  generalNumMap["TotalPTASVFStmts"] = pag->getPTAPAGEdgeNum();
176  generalNumMap["FIObjNum"] = fiObjNumber;
177  generalNumMap["FSObjNum"] = fsObjNumber;
178 
179  generalNumMap["AddrsNum"] = pag->getSVFStmtSet(SVFStmt::Addr).size();
180  generalNumMap["LoadsNum"] = pag->getSVFStmtSet(SVFStmt::Load).size();
181  generalNumMap["StoresNum"] = pag->getSVFStmtSet(SVFStmt::Store).size();
182  generalNumMap["CopysNum"] = pag->getSVFStmtSet(SVFStmt::Copy).size();
183  generalNumMap["GepsNum"] = pag->getSVFStmtSet(SVFStmt::Gep).size();
184  generalNumMap["CallsNum"] = pag->getSVFStmtSet(SVFStmt::Call).size();
185  generalNumMap["ReturnsNum"] = pag->getSVFStmtSet(SVFStmt::Ret).size();
186 
187  generalNumMap["FunctionObjs"] = numOfFunction;
188  generalNumMap["GlobalObjs"] = numOfGlobal;
189  generalNumMap["HeapObjs"] = numOfHeap;
190  generalNumMap["StackObjs"] = numOfStack;
191 
192  generalNumMap["VarStructObj"] = numOfHasVarStruct;
193  generalNumMap["VarArrayObj"] = numOfHasVarArray;
194  generalNumMap["ConstStructObj"] = numOfHasConstStruct;
195  generalNumMap["ConstArrayObj"] = numOfHasConstArray;
196  generalNumMap["NonPtrObj"] = numOfScalar;
197  generalNumMap["ConstantObj"] = numOfConstant;
198 
199  generalNumMap["IndCallSites"] = pag->getIndirectCallsites().size();
200  generalNumMap["TotalCallSite"] = pag->getCallSiteSet().size();
201 
203  timeStatMap["SymbolTableTime"] = SVFStat::timeOfBuildingSymbolTable;
205 
206  // REFACTOR-TODO bitcastInstStat();
207  branchStat();
208 
209  printStat("General Stats");
210 
211  printGeneralStats = false;
212 }
213 
214 
216 {
217  u32_t numOfBB_2Succ = 0;
218  u32_t numOfBB_3Succ = 0;
219  PTACallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph();
220  for (const auto& item: *svfirCallGraph)
221  {
222  const SVFFunction* func = item.second->getFunction();
223  for (SVFFunction::const_iterator bbIt = func->begin(), bbEit = func->end();
224  bbIt != bbEit; ++bbIt)
225  {
226  const SVFBasicBlock* bb = *bbIt;
227  u32_t numOfSucc = bb->getNumSuccessors();
228  if (numOfSucc == 2)
229  numOfBB_2Succ++;
230  else if (numOfSucc > 2)
231  numOfBB_3Succ++;
232  }
233  }
234 
235  generalNumMap["BBWith2Succ"] = numOfBB_2Succ;
236  generalNumMap["BBWith3Succ"] = numOfBB_3Succ;
237 }
238 
239 /* REFACTOR-TODO
240 void PTAStat::bitcastInstStat()
241 {
242  SVFModule* module = pta->getModule();
243  u32_t numberOfBitCast = 0;
244  for (SVFModule::llvm_const_iterator funIter = module->llvmFunBegin(), funEiter = module->llvmFunEnd();
245  funIter != funEiter; ++funIter)
246  {
247  const Function* func = *funIter;
248  for (Function::const_iterator bbIt = func->begin(), bbEit = func->end();
249  bbIt != bbEit; ++bbIt)
250  {
251  const BasicBlock& bb = *bbIt;
252  for (BasicBlock::const_iterator instIt = bb.begin(), instEit = bb.end();
253  instIt != instEit; ++instIt)
254  {
255  const Instruction& inst = *instIt;
256  if (const BitCastInst* bitcast = SVFUtil::dyn_cast<BitCastInst>(&inst))
257  {
258  if (SVFUtil::isa<PointerType>(bitcast->getSrcTy()))
259  numberOfBitCast++;
260  }
261  }
262  }
263  }
264 
265  generalNumMap["BitCastNumber"] = numberOfBitCast;
266 }
267 */
#define CLOCK_IN_MS()
Definition: SVFType.h:513
cJSON * item
Definition: cJSON.h:222
const char *const string
Definition: cJSON.h:172
iterator begin()
Iterators.
Definition: GenericGraph.h:627
IDToNodeMapTy::iterator iterator
Node Iterators.
Definition: GenericGraph.h:606
u32_t getValueNodeNum() const
Definition: IRGraph.h:186
u32_t getPTAPAGEdgeNum() const
Definition: IRGraph.h:211
u32_t getPAGEdgeNum() const
Definition: IRGraph.h:207
u32_t getObjectNodeNum() const
Definition: IRGraph.h:190
bool isConstantStruct() const
const SVFType * getType() const
Get obj type.
bool isConstDataOrConstGlobal() const
SymID getId() const
Get the memory object id.
bool isGlobalObj() const
bool isFieldInsensitive() const
Return true if its field limit is 0.
bool isVarArray() const
bool isBlackHoleObj() const
Whether it is a black hole object.
bool isConstantArray() const
bool isHeap() const
bool isVarStruct() const
bool isFunction() const
object attributes methods
bool isStack() const
static const OptionMap< enum PTAStat::ClockType > ClockType
Definition: Options.h:24
static const Option< bool > MarkedClocksOnly
Definition: Options.h:31
u32_t getNumSuccessors() const
Definition: SVFValue.h:615
const_iterator end() const
Definition: SVFValue.h:440
const_iterator begin() const
Definition: SVFValue.h:435
std::vector< const SVFBasicBlock * >::const_iterator const_iterator
Definition: SVFValue.h:305
PTACallGraph * getCallGraph()
Definition: SVFIR.h:192
const CallSiteToFunPtrMap & getIndirectCallsites() const
Add/get indirect callsites.
Definition: SVFIR.h:350
static SVFIR * getPAG(bool buildFromFile=false)
Singleton design here to make sure we only have one instance during any analysis.
Definition: SVFIR.h:115
u32_t getFieldObjNodeNum() const
Definition: SVFIR.h:338
u32_t getFieldValNodeNum() const
Node and edge statistics.
Definition: SVFIR.h:334
const CallSiteSet & getCallSiteSet() const
Get all callsites.
Definition: SVFIR.h:254
SVFStmt::SVFStmtSetTy & getSVFStmtSet(SVFStmt::PEDGEK kind)
Get/set methods to get SVFStmts based on their kinds and ICFGNodes.
Definition: SVFIR.h:201
NUMStatMap generalNumMap
Definition: SVFStat.h:76
NUMStatMap PTNumStatMap
Definition: SVFStat.h:77
virtual void printStat(std::string str="")
Definition: SVFStat.cpp:66
void branchStat()
Definition: SVFStat.cpp:215
static bool printGeneralStats
SVF's general statistics are only printed once even if you run multiple anayses.
Definition: SVFStat.h:74
std::string moduleName
Definition: SVFStat.h:99
TIMEStatMap timeStatMap
Definition: SVFStat.h:78
virtual void performStat()=0
Definition: SVFStat.cpp:109
static double timeOfBuildingLLVMModule
Definition: SVFStat.h:93
static double getClk(bool mark=false)
Definition: SVFStat.cpp:47
static double timeOfBuildingSymbolTable
Definition: SVFStat.h:94
static double timeOfBuildingSVFIR
Definition: SVFStat.h:95
bool isPointerTy() const
Definition: SVFType.h:249
static SymbolTableInfo * SymbolInfo()
Singleton design here to make sure we only have one instance during any analysis.
u32_t getMaxStructSize() const
std::vector< std::string > split(const std::string &s, char separator)
Split into two substrings around the first occurrence of a separator string.
Definition: SVFUtil.h:203
std::ostream & outs()
Overwrite llvm::outs()
Definition: SVFUtil.h:50
for isBitcode
Definition: BasicTypes.h:68
unsigned u32_t
Definition: GeneralType.h:46
std::unordered_set< Key, Hash, KeyEqual, Allocator > Set
Definition: GeneralType.h:96