Static Value-Flow Analysis
SVFUtil.cpp
Go to the documentation of this file.
1 //===- AnalysisUtil.cpp -- Helper functions for 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  * AnalysisUtil.cpp
25  *
26  * Created on: Apr 11, 2013
27  * Author: Yulei Sui
28  */
29 
30 #include "Util/Options.h"
31 #include "Util/SVFUtil.h"
32 #include "MemoryModel/PointsTo.h"
33 
34 #include <sys/resource.h>
35 
36 using namespace SVF;
37 
39 #define KNRM "\x1B[1;0m"
40 #define KRED "\x1B[1;31m"
41 #define KGRN "\x1B[1;32m"
42 #define KYEL "\x1B[1;33m"
43 #define KBLU "\x1B[1;34m"
44 #define KPUR "\x1B[1;35m"
45 #define KCYA "\x1B[1;36m"
46 #define KWHT "\x1B[1;37m"
47 
48 
49 
54 {
55  return KGRN + msg + KNRM;
56 }
57 
62 {
63  return KYEL + msg + KNRM;
64 }
65 
67 {
69  return;
70  outs() << wrnMsg(msg) << "\n";
71 }
72 
77 {
78  return KRED + msg + KNRM;
79 }
80 
82 {
83  return KYEL + msg + KNRM;
84 }
85 
87 {
88  return KPUR + msg + KNRM;
89 }
90 
92 {
93  return KCYA + msg + KNRM;
94 }
95 
100 {
101  return KBLU + msg + KNRM;
102 }
103 
107 void SVFUtil::dumpPointsToSet(unsigned node, NodeBS bs)
108 {
109  outs() << "node " << node << " points-to: {";
110  dumpSet(bs);
111  outs() << "}\n";
112 }
113 
114 // For use from the debugger.
116 {
117  outs() << "{";
118  dumpSet(bs);
119  outs() << "}\n";
120 }
121 
123 {
124  outs() << "{";
125  for (PointsToList::const_iterator ii = ptl.begin(), ie = ptl.end();
126  ii != ie; ii++)
127  {
128  auto bs = *ii;
129  dumpSet(bs);
130  }
131  outs() << "}\n";
132 }
133 
137 void SVFUtil::dumpAliasSet(unsigned node, NodeBS bs)
138 {
139  outs() << "node " << node << " alias set: {";
140  dumpSet(bs);
141  outs() << "}\n";
142 }
143 
148 {
149  for (NodeBS::iterator ii = bs.begin(), ie = bs.end();
150  ii != ie; ii++)
151  {
152  O << " " << *ii << " ";
153  }
154 }
155 
157 {
158  for (NodeID n : pt)
159  {
160  o << " " << n << " ";
161  }
162 }
163 
168 {
169  u32_t vmrss, vmsize;
170  if (getMemoryUsageKB(&vmrss, &vmsize))
171  O << infor << "\tVmRSS: " << vmrss << "\tVmSize: " << vmsize << "\n";
172 }
173 
177 bool SVFUtil::getMemoryUsageKB(u32_t* vmrss_kb, u32_t* vmsize_kb)
178 {
179  /* Get the current process' status file from the proc filesystem */
180  char buffer[8192];
181  FILE* procfile = fopen("/proc/self/status", "r");
182  if(procfile)
183  {
184  u32_t result = fread(buffer, sizeof(char), 8192, procfile);
185  if (result == 0)
186  {
187  fputs ("Reading error\n",stderr);
188  }
189  }
190  else
191  {
192  SVFUtil::writeWrnMsg(" /proc/self/status file not exit!");
193  return false;
194  }
195  fclose(procfile);
196 
197  /* Look through proc status contents line by line */
198  char delims[] = "\n";
199  char* line = strtok(buffer, delims);
200 
201  bool found_vmrss = false;
202  bool found_vmsize = false;
203 
204  while (line != nullptr && (found_vmrss == false || found_vmsize == false))
205  {
206  if (strstr(line, "VmRSS:") != nullptr)
207  {
208  sscanf(line, "%*s %u", vmrss_kb);
209  found_vmrss = true;
210  }
211 
212  if (strstr(line, "VmSize:") != nullptr)
213  {
214  sscanf(line, "%*s %u", vmsize_kb);
215  found_vmsize = true;
216  }
217 
218  line = strtok(nullptr, delims);
219  }
220 
221  return (found_vmrss && found_vmsize);
222 }
223 
228 {
229  const rlim_t kStackSize = 256L * 1024L * 1024L; // min stack size = 256 Mb
230  struct rlimit rl;
231  int result = getrlimit(RLIMIT_STACK, &rl);
232  if (result == 0)
233  {
234  if (rl.rlim_cur < kStackSize)
235  {
236  rl.rlim_cur = kStackSize;
237  result = setrlimit(RLIMIT_STACK, &rl);
238  if (result != 0)
239  writeWrnMsg("setrlimit returned result !=0 \n");
240  }
241  }
242 }
243 
248 {
249  if (const SVFCallInst* call = SVFUtil::dyn_cast<SVFCallInst>(inst))
250  {
251  const SVFFunction* func = call->getCalledFunction();
252  if (func && func->isIntrinsic())
253  {
254  return true;
255  }
256  }
257  return false;
258 }
259 
261 {
262  switch (method)
263  {
265  return "single";
267  return "complete";
269  return "average";
271  return "median";
273  return "svf-best";
274  default:
275  assert(false && "SVFUtil::hclustMethodToString: unknown method");
276  abort();
277  }
278 }
279 
281 {
282  SVFUtil::outs().flush();
283  // TODO: output does not indicate which time limit is reached.
284  // This can be better in the future.
285  SVFUtil::outs() << "WPA: time limit reached\n";
286  exit(101);
287 }
288 
289 bool SVFUtil::startAnalysisLimitTimer(unsigned timeLimit)
290 {
291  if (timeLimit == 0) return false;
292 
293  // If an alarm is already set, don't set another. That means this analysis
294  // is part of another which has a time limit.
295  unsigned remainingSeconds = alarm(0);
296  if (remainingSeconds != 0)
297  {
298  // Continue the previous alarm and move on.
299  alarm(remainingSeconds);
300  return false;
301  }
302 
303  signal(SIGALRM, &timeLimitReached);
304  alarm(timeLimit);
305  return true;
306 }
307 
310 void SVFUtil::stopAnalysisLimitTimer(bool limitTimerSet)
311 {
312  if (limitTimerSet) alarm(0);
313 }
314 
320 bool SVFUtil::matchArgs(const CallICFGNode* call, const SVFFunction* callee)
321 {
322  if (callee->isVarArg() || ThreadAPI::getThreadAPI()->isTDFork(call))
323  return call->arg_size() >= callee->arg_size();
324  else
325  return call->arg_size() == callee->arg_size();
326 }
327 
328 bool SVFUtil::isCallSite(const ICFGNode* inst)
329 {
330  return SVFUtil::isa<CallICFGNode>(inst);
331 }
332 
334 {
335  if (const CallICFGNode* call = SVFUtil::dyn_cast<CallICFGNode>(inst))
336  {
337  const SVFFunction* func = call->getCalledFunction();
338  if (func && func->isIntrinsic())
339  {
340  return true;
341  }
342  }
343  return false;
344 }
345 
347 {
348  return isExtCall(cs->getCalledFunction());
349 }
350 
352 {
354 }
355 
356 
358 {
360 }
361 
362 
363 bool SVFUtil::isExtCall(const ICFGNode* node)
364 {
365  if(!isCallSite(node)) return false;
366  return isExtCall(cast<CallICFGNode>(node)->getCalledFunction());
367 }
368 
370 {
371  if(!isCallSite(cs)) return false;
372  return isHeapAllocExtCallViaRet(cast<CallICFGNode>(cs)) || isHeapAllocExtCallViaArg(cast<CallICFGNode>(cs));
373 }
374 
376 {
377  bool isPtrTy = cs->getType()->isPointerTy();
378  return isPtrTy && isHeapAllocExtFunViaRet(cs->getCalledFunction());
379 }
380 
382 {
383  bool isPtrTy = cs->getType()->isPointerTy();
384  return isPtrTy && isReallocExtFun(cs->getCalledFunction());
385 }
386 
387 
389 {
390  if (const auto& intraNode = dyn_cast<IntraICFGNode>(node))
391  return intraNode->isRetInst();
392  else
393  return false;
394 }
395 
397 {
399 }
400 
403 {
404  PTACallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph();
405  for (const auto& item: *svfirCallGraph)
406  {
407  const PTACallGraphNode*fun = item.second;
408  if (fun->getName()==funName)
409  return fun->getFunction();
410  }
411  return nullptr;
412 }
413 
416 {
417  PTACallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph();
418  for (const auto& item: *svfirCallGraph)
419  {
420  const PTACallGraphNode*fun = item.second;
421  if (isProgEntryFunction(fun->getFunction()))
422  return (fun->getFunction());
423  }
424  return nullptr;
425 }
#define KNRM
Color for output format.
Definition: SVFUtil.cpp:39
#define KPUR
Definition: SVFUtil.cpp:44
#define KBLU
Definition: SVFUtil.cpp:43
#define KRED
Definition: SVFUtil.cpp:40
#define KYEL
Definition: SVFUtil.cpp:42
#define KGRN
Definition: SVFUtil.cpp:41
#define KCYA
Definition: SVFUtil.cpp:45
cJSON * n
Definition: cJSON.cpp:2558
char * buffer
Definition: cJSON.h:163
cJSON * item
Definition: cJSON.h:222
const char *const string
Definition: cJSON.h:172
const SVFFunction * getCalledFunction() const
Definition: ICFGNode.h:518
u32_t arg_size() const
Definition: ICFGNode.h:505
static const Option< bool > DisableWarn
Definition: Options.h:205
const std::string & getName() const
Definition: PTACallGraph.h:192
const SVFFunction * getFunction() const
Get function of this call node.
Definition: PTACallGraph.h:198
virtual const SVFType * getType() const
Definition: GenericGraph.h:271
bool isIntrinsic() const
Definition: SVFValue.h:371
u32_t arg_size() const
Definition: SVFValue.cpp:170
bool isVarArg() const
Definition: SVFValue.cpp:181
PTACallGraph * getCallGraph()
Definition: SVFIR.h:192
static SVFIR * getPAG(bool buildFromFile=false)
Singleton design here to make sure we only have one instance during any analysis.
Definition: SVFIR.h:115
bool isPointerTy() const
Definition: SVFType.h:249
iterator end() const
iterator begin() const
bool isTDFork(const CallICFGNode *inst) const
Return true if this call create a new thread.
Definition: ThreadAPI.cpp:133
static ThreadAPI * getThreadAPI()
Return a static reference.
Definition: ThreadAPI.h:105
char * strstr(const char *haystack, const char *needle)
Definition: extapi.c:821
char * strtok(char *str, const char *delim)
Definition: extapi.c:463
hclust_fast_methods
Definition: fastcluster.h:66
@ HCLUST_METHOD_AVERAGE
Definition: fastcluster.h:72
@ HCLUST_METHOD_COMPLETE
Definition: fastcluster.h:70
@ HCLUST_METHOD_SVF_BEST
Definition: fastcluster.h:76
@ HCLUST_METHOD_MEDIAN
Definition: fastcluster.h:74
@ HCLUST_METHOD_SINGLE
Definition: fastcluster.h:68
bool isHeapAllocExtCallViaRet(const Instruction *inst)
Definition: LLVMUtil.cpp:618
bool isCallSite(const Instruction *inst)
Whether an instruction is a call or invoke instruction.
Definition: LLVMUtil.h:45
bool isHeapAllocExtCallViaArg(const Instruction *inst)
Definition: LLVMUtil.cpp:634
bool isProgEntryFunction(const Function *fun)
Check whether a function is an entry function (i.e., main)
Definition: LLVMUtil.h:79
bool isReallocExtCall(const CallICFGNode *cs)
Definition: SVFUtil.cpp:381
std::string sucMsg(const std::string &msg)
Returns successful message by converting a string into green string output.
Definition: SVFUtil.cpp:53
void increaseStackSize()
Increase the stack size limit.
Definition: SVFUtil.cpp:227
std::string bugMsg1(const std::string &msg)
Definition: SVFUtil.cpp:81
std::string hclustMethodToString(hclust_fast_methods method)
Returns a string representation of a hclust method.
Definition: SVFUtil.cpp:260
void stopAnalysisLimitTimer(bool limitTimerSet)
Definition: SVFUtil.cpp:310
bool isHeapAllocExtFunViaRet(const SVFFunction *fun)
Return true if the call is a heap allocator/reallocator.
Definition: SVFUtil.h:296
bool isExtCall(const SVFFunction *fun)
Definition: SVFUtil.h:278
std::string pasMsg(const std::string &msg)
Print each pass/phase message by converting a string into blue string output.
Definition: SVFUtil.cpp:99
OrderedSet< PointsTo, equalPointsTo > PointsToList
Definition: SVFUtil.h:166
void dumpAliasSet(unsigned node, NodeBS To)
Dump alias set.
Definition: SVFUtil.cpp:137
bool getMemoryUsageKB(u32_t *vmrss_kb, u32_t *vmsize_kb)
Get memory usage from system file. Return TRUE if succeed.
Definition: SVFUtil.cpp:177
void reportMemoryUsageKB(const std::string &infor, OutStream &O=SVFUtil::outs())
Print memory usage in KB.
Definition: SVFUtil.cpp:167
bool startAnalysisLimitTimer(unsigned timeLimit)
Definition: SVFUtil.cpp:289
std::string errMsg(const std::string &msg)
Print error message by converting a string into red string output.
Definition: SVFUtil.cpp:76
std::string bugMsg3(const std::string &msg)
Definition: SVFUtil.cpp:91
bool isHeapAllocExtCallViaArg(const CallICFGNode *cs)
Definition: SVFUtil.cpp:351
bool isHeapAllocExtCall(const ICFGNode *cs)
Definition: SVFUtil.cpp:369
u32_t getHeapAllocHoldingArgPosition(const SVFFunction *fun)
Get the position of argument that holds an allocated heap object.
Definition: SVFUtil.h:309
bool isCallSite(const SVFValue *val)
Whether an instruction is a call or invoke instruction.
Definition: SVFUtil.h:175
bool isReallocExtFun(const SVFFunction *fun)
Return true if the call is a heap reallocator.
Definition: SVFUtil.h:317
void writeWrnMsg(const std::string &msg)
Writes a message run through wrnMsg.
Definition: SVFUtil.cpp:66
void dumpSparseSet(const NodeBS &To)
Definition: SVFUtil.cpp:115
bool isHeapAllocExtFunViaArg(const SVFFunction *fun)
Definition: SVFUtil.h:302
bool isIntrinsicInst(const SVFInstruction *inst)
Return true if it is an llvm intrinsic instruction.
Definition: SVFUtil.cpp:247
void dumpPointsToSet(unsigned node, NodeBS To)
Dump points-to set.
Definition: SVFUtil.cpp:107
std::string bugMsg2(const std::string &msg)
Definition: SVFUtil.cpp:86
bool isProgExitCall(const CallICFGNode *cs)
Definition: SVFUtil.cpp:396
std::string wrnMsg(const std::string &msg)
Returns warning message by converting a string into yellow string output.
Definition: SVFUtil.cpp:61
bool isRetInstNode(const ICFGNode *node)
Definition: SVFUtil.cpp:388
bool matchArgs(const CallICFGNode *cs, const SVFFunction *callee)
Definition: SVFUtil.cpp:320
void timeLimitReached(int signum)
Function to call when alarm for time limit hits.
Definition: SVFUtil.cpp:280
const SVFFunction * getProgFunction(const std::string &funName)
Get program entry function from function name.
Definition: SVFUtil.cpp:402
bool isHeapAllocExtCallViaRet(const CallICFGNode *cs)
interfaces to be used externally
Definition: SVFUtil.cpp:375
void dumpSet(NodeBS To, OutStream &O=SVFUtil::outs())
Dump sparse bitvector set.
Definition: SVFUtil.cpp:147
bool isProgExitFunction(const SVFFunction *fun)
Return true if this is a program exit function call.
Definition: SVFUtil.h:338
std::ostream & outs()
Overwrite llvm::outs()
Definition: SVFUtil.h:50
const SVFFunction * getProgEntryFunction()
Get program entry function.
Definition: SVFUtil.cpp:415
void dumpPointsToList(const PointsToList &ptl)
Definition: SVFUtil.cpp:122
for isBitcode
Definition: BasicTypes.h:68
u32_t NodeID
Definition: GeneralType.h:55
std::ostream OutStream
Definition: GeneralType.h:45
unsigned u32_t
Definition: GeneralType.h:46