SVF
PathCondAllocator.cpp
Go to the documentation of this file.
1 //===- PathAllocator.cpp -- Path condition 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 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 General Public License for more details.
17 
18 // You should have received a copy of the GNU General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 //
21 //===----------------------------------------------------------------------===//
22 
23 
24 /*
25  * PathAllocator.cpp
26  *
27  * Created on: Apr 3, 2014
28  * Author: Yulei Sui
29  */
30 
31 #include "Util/Options.h"
32 #include "SVF-FE/LLVMUtil.h"
33 #include "Util/PathCondAllocator.h"
34 #include "Util/DPItem.h"
35 #include <limits.h>
36 
37 using namespace SVF;
38 using namespace SVFUtil;
39 
40 u64_t DPItem::maximumBudget = ULONG_MAX - 1;
45 
48 
53 {
54  DBOUT(DGENERAL,outs() << pasMsg("path condition allocation starts\n"));
55 
56  for (SVFModule::const_iterator fit = M->begin(); fit != M->end(); ++fit)
57  {
58  const SVFFunction * func = *fit;
59  if (!SVFUtil::isExtCall(func))
60  {
61  // Allocate conditions for a program.
62  for (Function::const_iterator bit = func->getLLVMFun()->begin(), ebit = func->getLLVMFun()->end(); bit != ebit; ++bit)
63  {
64  const BasicBlock & bb = *bit;
65  collectBBCallingProgExit(bb);
66  allocateForBB(bb);
67  }
68  }
69  }
70 
72  printPathCond();
73 
74  DBOUT(DGENERAL,outs() << pasMsg("path condition allocation ends\n"));
75 }
76 
81 {
82 
83  u32_t succ_number = getBBSuccessorNum(&bb);
84 
85  // if successor number greater than 1, allocate new decision variable for successors
86  if(succ_number > 1)
87  {
88 
89  //allocate log2(num_succ) decision variables
90  double num = log(succ_number)/log(2);
91  u32_t bit_num = (u32_t)ceil(num);
92  u32_t succ_index = 0;
93  std::vector<Condition*> condVec;
94  for(u32_t i = 0 ; i < bit_num; i++)
95  {
96  condVec.push_back(newCond(bb.getTerminator()));
97  }
98 
99  // iterate each successor
100  for (succ_const_iterator succ_it = succ_begin(&bb);
101  succ_it != succ_end(&bb);
102  succ_it++, succ_index++)
103  {
104 
105  const BasicBlock* succ = *succ_it;
106 
107  Condition* path_cond = getTrueCond();
108 
110 
111  // for each successor decide its bit representation
112  // decide whether each bit of succ_index is 1 or 0, if (three successor) succ_index is 000 then use C1^C2^C3
113  // if 001 use C1^C2^negC3
114  for(u32_t j = 0 ; j < bit_num; j++)
115  {
116  //test each bit of this successor's index (binary representation)
117  u32_t tool = 0x01 << j;
118  if(tool & succ_index)
119  {
120  path_cond = condAnd(path_cond, condVec.at(j));
121  }
122  else
123  {
124  path_cond = condAnd(path_cond, (condNeg(condVec.at(j))));
125  }
126  }
127  setBranchCond(&bb,succ,path_cond);
128  }
129 
130  }
131 }
132 
137 {
138  u32_t pos = getBBSuccessorPos(bb,succ);
139  if(getBBSuccessorNum(bb) == 1)
140  return getTrueCond();
141  else
142  {
143  BBCondMap::const_iterator it = bbConds.find(bb);
144  assert(it!=bbConds.end() && "basic block does not have branch and conditions??");
145  CondPosMap::const_iterator cit = it->second.find(pos);
146  assert(cit!=it->second.end() && "no condition on the branch??");
147  return cit->second;
148  }
149 }
150 
155 {
157  assert(getBBSuccessorNum(bb) > 1 && "not more than one successor??");
158  u32_t pos = getBBSuccessorPos(bb,succ);
159  CondPosMap& condPosMap = bbConds[bb];
160 
163  //assert(condPosMap.find(pos) == condPosMap.end() && "this branch has already been set ");
164 
165  condPosMap[pos] = cond;
166 }
167 
172 {
173 
174  const BasicBlock* succ1 = brInst->getSuccessor(0);
175 
176  if(isTestNullExpr(brInst->getCondition(),val))
177  {
178  // succ is then branch
179  if(succ1 == succ)
180  return getFalseCond();
181  // succ is else branch
182  else
183  return getTrueCond();
184  }
185  if(isTestNotNullExpr(brInst->getCondition(),val))
186  {
187  // succ is then branch
188  if(succ1 == succ)
189  return getTrueCond();
190  // succ is else branch
191  else
192  return getFalseCond();
193  }
194 
195  return nullptr;
196 }
197 
202 {
203  const BasicBlock* succ1 = brInst->getSuccessor(0);
204  const BasicBlock* succ2 = brInst->getSuccessor(1);
205 
206  bool branch1 = isBBCallsProgExit(succ1);
207  bool branch2 = isBBCallsProgExit(succ2);
208 
210  if(branch1 == true && branch2 == false)
211  {
212  // succ is then branch
213  if(succ1 == succ)
214  return getFalseCond();
215  // succ is else branch
216  else
217  return getTrueCond();
218  }
220  else if(branch1 == false && branch2 == true)
221  {
222  // succ is else branch
223  if(succ2 == succ)
224  return getFalseCond();
225  // succ is then branch
226  else
227  return getTrueCond();
228  }
229  // two branches both call program exit
230  else if(branch1 == true && branch2 == true)
231  {
232  return getFalseCond();
233  }
235  else
236  return nullptr;
237 
238 }
239 
246 {
247  const Function* fun = bb->getParent();
248  assert(fun==dst->getParent() && "two basic blocks should be in the same function");
249 
250  const LoopInfo* loopInfo = getLoopInfo(fun);
251  if(loopInfo->isLoopHeader(const_cast<BasicBlock*>(bb)))
252  {
253  const Loop *loop = loopInfo->getLoopFor(bb);
254  SmallBBVector exitbbs;
255  Set<BasicBlock*> filteredbbs;
256  loop->getExitBlocks(exitbbs);
258  while(!exitbbs.empty())
259  {
260  BasicBlock* eb = exitbbs.pop_back_val();
261  if(isBBCallsProgExit(eb) == false)
262  filteredbbs.insert(eb);
263  }
264 
266  bool allPDT = true;
267  PostDominatorTree* pdt = getPostDT(fun);
268  for(Set<BasicBlock*>::const_iterator it = filteredbbs.begin(), eit = filteredbbs.end(); it!=eit; ++it)
269  {
270  if(pdt->dominates(dst,*it) == false)
271  allPDT =false;
272  }
273 
274  if(allPDT)
275  return getTrueCond();
276  }
277  return nullptr;
278 }
279 
286 {
287  if(getBBSuccessorNum(bb) == 1)
288  {
289  assert(bb->getTerminator()->getSuccessor(0) == succ && "not the unique successor?");
290  return getTrueCond();
291  }
292 
293  if(const BranchInst* brInst = SVFUtil::dyn_cast<BranchInst>(bb->getTerminator()))
294  {
295  assert(brInst->getNumSuccessors() == 2 && "not a two successors branch??");
296  const BasicBlock* succ1 = brInst->getSuccessor(0);
297  const BasicBlock* succ2 = brInst->getSuccessor(1);
298  assert((succ1 == succ || succ2 == succ) && "not a successor??");
299 
300  Condition* evalLoopExit = evaluateLoopExitBranch(bb,succ);
301  if(evalLoopExit)
302  return evalLoopExit;
303 
304  Condition* evalProgExit = evaluateProgExit(brInst,succ);
305  if(evalProgExit)
306  return evalProgExit;
307 
308  Condition* evalTestNullLike = evaluateTestNullLikeExpr(brInst,succ,val);
309  if(evalTestNullLike)
310  return evalTestNullLike;
311 
312  }
313  return getBranchCond(bb, succ);
314 }
315 
316 bool PathCondAllocator::isEQCmp(const CmpInst* cmp) const
317 {
318  return (cmp->getPredicate() == CmpInst::ICMP_EQ);
319 }
320 
321 bool PathCondAllocator::isNECmp(const CmpInst* cmp) const
322 {
323  return (cmp->getPredicate() == CmpInst::ICMP_NE);
324 }
325 
326 bool PathCondAllocator::isTestNullExpr(const Value* test,const Value* val) const
327 {
328  if(const CmpInst* cmp = SVFUtil::dyn_cast<CmpInst>(test))
329  {
330  return isTestContainsNullAndTheValue(cmp,val) && isEQCmp(cmp);
331  }
332  return false;
333 }
334 
335 bool PathCondAllocator::isTestNotNullExpr(const Value* test,const Value* val) const
336 {
337  if(const CmpInst* cmp = SVFUtil::dyn_cast<CmpInst>(test))
338  {
339  return isTestContainsNullAndTheValue(cmp,val) && isNECmp(cmp);
340  }
341  return false;
342 }
343 
345 {
346 
347  const Value* op0 = cmp->getOperand(0);
348  const Value* op1 = cmp->getOperand(1);
349  if((op0 == val && SVFUtil::isa<ConstantPointerNull>(op1))
350  || (op1 == val && SVFUtil::isa<ConstantPointerNull>(op0)) )
351  return true;
352 
353  return false;
354 }
355 
360 {
361 
362  for(BasicBlock::const_iterator it = bb.begin(), eit = bb.end(); it!=eit; it++)
363  {
364  const Instruction* inst = &*it;
365  if(SVFUtil::isa<CallInst>(inst) || SVFUtil::isa<InvokeInst>(inst))
366  if(SVFUtil::isProgExitCall(inst))
367  {
368  funToExitBBsMap[bb.getParent()].insert(&bb);
369  }
370  }
371 }
372 
377 {
378  const Function* fun = bb->getParent();
379  FunToExitBBsMap::const_iterator it = funToExitBBsMap.find(fun);
380  if(it!=funToExitBBsMap.end())
381  {
382  PostDominatorTree* pdt = getPostDT(fun);
383  for(BasicBlockSet::const_iterator bit = it->second.begin(), ebit= it->second.end(); bit!=ebit; bit++)
384  {
385  if(pdt->dominates(*bit,bb))
386  return true;
387  }
388  }
389  return false;
390 }
391 
399 {
400  assert(BB1 && BB2 && "expect nullptr BB here!");
401 
402  DominatorTree* dt = getDT(BB1->getParent());
404  if(dt->dominates(BB1,BB2) && !dt->dominates(BB0,BB2))
405  {
406  Condition* cond = ComputeIntraVFGGuard(BB1,BB2);
407  return condNeg(cond);
408  }
409 
410  return trueCond();
411 }
412 
419 {
420  const BasicBlock* funEntryBB = &dstBB->getParent()->getEntryBlock();
421 
422  Condition* c1 = ComputeIntraVFGGuard(srcBB,callBB);
423  setCFCond(funEntryBB,condOr(getCFCond(funEntryBB),getCFCond(callBB)));
424  Condition* c2 = ComputeIntraVFGGuard(funEntryBB,dstBB);
425  return condAnd(c1,c2);
426 }
427 
434 {
435  const BasicBlock* funExitBB = getFunExitBB(srcBB->getParent());
436 
437  Condition* c1 = ComputeIntraVFGGuard(srcBB,funExitBB);
438  setCFCond(retBB,condOr(getCFCond(retBB),getCFCond(funExitBB)));
439  Condition* c2 = ComputeIntraVFGGuard(retBB,dstBB);
440  return condAnd(c1,c2);
441 }
442 
447 {
448 
449  assert(srcBB->getParent() == dstBB->getParent() && "two basic blocks are not in the same function??");
450 
451  PostDominatorTree* postDT = getPostDT(srcBB->getParent());
452  if(postDT->dominates(dstBB,srcBB))
453  return getTrueCond();
454 
455  CFWorkList worklist;
456  worklist.push(srcBB);
457  setCFCond(srcBB,getTrueCond());
458 
459  while(!worklist.empty())
460  {
461  const BasicBlock* bb = worklist.pop();
462  Condition* cond = getCFCond(bb);
463 
466  if(Condition* loopExitCond = evaluateLoopExitBranch(bb,dstBB))
467  return condAnd(cond, loopExitCond);
468 
469 
470  for (succ_const_iterator succ_it = succ_begin(bb);
471  succ_it != succ_end(bb); succ_it++)
472  {
473  const BasicBlock* succ = *succ_it;
478  Condition* brCond;
479  if(postDT->dominates(succ,bb))
480  brCond = getTrueCond();
481  else
482  brCond = getEvalBrCond(bb, succ);
483 
484  DBOUT(DSaber, outs() << " bb (" << bb->getName() <<
485  ") --> " << "succ_bb (" << succ->getName() << ") condition: " << brCond << "\n");
486  Condition* succPathCond = condAnd(cond, brCond);
487  if(setCFCond(succ, condOr(getCFCond(succ), succPathCond)))
488  worklist.push(succ);
489  }
490  }
491 
492  DBOUT(DSaber, outs() << " src_bb (" << srcBB->getName() <<
493  ") --> " << "dst_bb (" << dstBB->getName() << ") condition: " << getCFCond(dstBB) << "\n");
494 
495  return getCFCond(dstBB);
496 }
497 
498 
503 {
504  delete bddCondMgr;
505  bddCondMgr = nullptr;
506 }
507 
512 {
513 
514  outs() << "print path condition\n";
515 
516  for(BBCondMap::const_iterator it = bbConds.begin(), eit = bbConds.end(); it!=eit; ++it)
517  {
518  const BasicBlock* bb = it->first;
519  for(CondPosMap::const_iterator cit = it->second.begin(), ecit = it->second.end(); cit!=ecit; ++cit)
520  {
521  u32_t i=0;
522  for (const BasicBlock *succ: successors(bb))
523  {
524  if (i == cit->first)
525  {
526  Condition* cond = cit->second;
527  outs() << bb->getName() << "-->" << succ->getName() << ":";
528  outs() << dumpCond(cond) << "\n";
529  break;
530  }
531  i++;
532  }
533  }
534  }
535 }
bool isTestNullExpr(const Value *test, const Value *val) const
Return true if this is a test null expression.
virtual void allocateForBB(const BasicBlock &bb)
Allocate path condition for every basic block.
Condition * getBranchCond(const BasicBlock *bb, const BasicBlock *succ) const
Get branch condition.
llvm::BranchInst BranchInst
Definition: BasicTypes.h:157
static u32_t maximumCxtLen
Definition: DPItem.h:342
virtual Condition * ComputeInterCallVFGGuard(const BasicBlock *src, const BasicBlock *dst, const BasicBlock *callBB)
llvm::BasicBlock BasicBlock
Definition: BasicTypes.h:77
Definition: cudd.h:270
Condition * evaluateBranchCond(const BasicBlock *bb, const BasicBlock *succ, const Value *val)
Evaluate branch conditions.
Condition * evaluateTestNullLikeExpr(const BranchInst *brInst, const BasicBlock *succ, const Value *val)
Return branch condition after evaluating test null like expression.
std::string pasMsg(std::string msg)
Print each pass/phase message by converting a string into blue string output.
Definition: SVFUtil.cpp:99
iterator begin()
Definition: SVFModule.h:134
#define assert(ex)
Definition: util.h:141
bool empty() const
Definition: WorkList.h:146
Condition * evaluateLoopExitBranch(const BasicBlock *bb, const BasicBlock *succ)
Evaluate loop exit branch.
u32_t getBBSuccessorPos(const BasicBlock *BB, const BasicBlock *Succ)
Get basic block successor position.
Definition: LLVMUtil.cpp:300
llvm::LoopInfo LoopInfo
Definition: BasicTypes.h:89
void printPathCond()
Print out the path condition information.
static u64_t maximumBudget
Definition: DPItem.h:50
static BddCondManager * bddCondMgr
bbd manager
llvm::succ_const_iterator succ_const_iterator
Definition: BasicTypes.h:205
unsigned u32_t
Definition: SVFBasicTypes.h:75
#define DSaber
llvm::PostDominatorTree PostDominatorTree
Definition: BasicTypes.h:194
bool isTestContainsNullAndTheValue(const CmpInst *cmp, const Value *val) const
Return true if two values on the predicate are what we want.
static u32_t maximumCxt
Definition: DPItem.h:345
bool isProgExitCall(const CallSite cs)
Definition: LLVMUtil.h:459
static u32_t maximumPath
Definition: DPItem.h:614
void setBranchCond(const BasicBlock *bb, const BasicBlock *succ, Condition *cond)
Get/Set a branch condition, and its terminator instruction.
std::unordered_set< Key, Hash, KeyEqual, Allocator > Set
Definition: SVFBasicTypes.h:93
llvm::Function Function
Definition: BasicTypes.h:76
bool push(Data data)
Definition: WorkList.h:159
llvm::Instruction Instruction
Definition: BasicTypes.h:79
llvm::Loop Loop
Definition: BasicTypes.h:88
llvm::SmallVector< BasicBlock *, 8 > SmallBBVector
Definition: BasicTypes.h:117
bool isNECmp(const CmpInst *cmp) const
Return true if the predicate of this compare instruction is not equal.
Condition * evaluateProgExit(const BranchInst *brInst, const BasicBlock *succ)
Return condition when there is a branch calls program exit.
bool isEQCmp(const CmpInst *cmp) const
Evaluate test null/not null like expressions.
virtual Condition * ComputeInterRetVFGGuard(const BasicBlock *src, const BasicBlock *dst, const BasicBlock *retBB)
llvm::DominatorTree DominatorTree
Definition: BasicTypes.h:193
const BasicBlock * getFunExitBB(const Function *fun)
Definition: LLVMUtil.h:494
raw_ostream & outs()
Overwrite llvm::outs()
Definition: SVFUtil.h:47
void allocate(const SVFModule *module)
Perform path allocation.
bool isTestNotNullExpr(const Value *test, const Value *val) const
Return true if this is a test not null expression.
Map< u32_t, Condition * > CondPosMap
map a branch to its Condition
#define DGENERAL
General debug flag is for each phase of a pass, it is often in a colorful output format.
void destroy()
Release memory.
static u32_t maximumPathLen
Definition: DPItem.h:612
Function * getLLVMFun() const
Definition: BasicTypes.h:245
for isBitcode
Definition: ContextDDA.h:15
bool isBBCallsProgExit(const BasicBlock *bb)
iterator end()
Definition: SVFModule.h:142
void collectBBCallingProgExit(const BasicBlock &bb)
Collect basic block contains program exit function call.
virtual Condition * ComputeIntraVFGGuard(const BasicBlock *src, const BasicBlock *dst)
Guard Computation for a value-flow (between two basic blocks)
virtual Condition * getPHIComplementCond(const BasicBlock *BB1, const BasicBlock *BB2, const BasicBlock *BB0)
#define DBOUT(TYPE, X)
LLVM debug macros, define type of your DEBUG model of each pass.
llvm::Value Value
Definition: BasicTypes.h:78
u32_t getBBSuccessorNum(const BasicBlock *BB)
Get num of BB&#39;s successors.
Definition: LLVMUtil.cpp:332
FunctionSetType::const_iterator const_iterator
Definition: SVFModule.h:49
bool isExtCall(const SVFFunction *fun)
Definition: LLVMUtil.h:64
unsigned long long u64_t
Definition: SVFBasicTypes.h:76
llvm::CmpInst CmpInst
Definition: BasicTypes.h:156
static const llvm::cl::opt< bool > PrintPathCond
Definition: Options.h:173