Static Value-Flow Analysis
Loading...
Searching...
No Matches
Public Types | Public Member Functions | Protected Attributes | Private Member Functions | Private Attributes | Static Private Attributes | List of all members
SVF::SaberCondAllocator Class Reference

#include <SaberCondAllocator.h>

Public Types

typedef Z3Expr Condition
 
typedef Map< u32_t, const ICFGNode * > IndexToTermInstMap
 z3 condition
 
typedef Map< u32_t, ConditionCondPosMap
 id to instruction map for z3
 
typedef Map< const SVFBasicBlock *, CondPosMapBBCondMap
 
typedef Set< const SVFBasicBlock * > BasicBlockSet
 map bb to a Condition
 
typedef Map< const SVFFunction *, BasicBlockSetFunToExitBBsMap
 map a function to all its basic blocks calling program exit
 
typedef Map< const SVFBasicBlock *, ConditionBBToCondMap
 map a basic block to its condition during control-flow guard computation
 
typedef FIFOWorkList< const SVFBasicBlock * > CFWorkList
 worklist for control-flow guard computation
 
typedef Map< const SVFGNode *, Set< const SVFGNode * > > SVFGNodeToSVFGNodeSetMap
 

Public Member Functions

 SaberCondAllocator ()
 Constructor.
 
virtual ~SaberCondAllocator ()
 Destructor.
 
std::string getMemUsage ()
 Statistics.
 
u32_t getCondNum ()
 
Condition condAnd (const Condition &lhs, const Condition &rhs)
 Condition operations.
 
Condition condOr (const Condition &lhs, const Condition &rhs)
 
Condition condNeg (const Condition &cond)
 
Condition getTrueCond () const
 
Condition getFalseCond () const
 
NodeBS exactCondElem (const Condition &cond)
 Iterator every element of the condition.
 
std::string dumpCond (const Condition &cond) const
 
Condition newCond (const ICFGNode *inst)
 Allocate a new condition.
 
void allocate (const SVFModule *module)
 Perform path allocation.
 
const ICFGNodegetCondInst (u32_t id) const
 Get/Set instruction based on Z3 expression id.
 
void setCondInst (const Condition &condition, const ICFGNode *inst)
 
bool isNegCond (u32_t id) const
 
bool postDominate (const SVFBasicBlock *bbKey, const SVFBasicBlock *bbValue) const
 
bool dominate (const SVFBasicBlock *bbKey, const SVFBasicBlock *bbValue) const
 
virtual Condition ComputeIntraVFGGuard (const SVFBasicBlock *src, const SVFBasicBlock *dst)
 Guard Computation for a value-flow (between two basic blocks)
 
virtual Condition ComputeInterCallVFGGuard (const SVFBasicBlock *src, const SVFBasicBlock *dst, const SVFBasicBlock *callBB)
 
virtual Condition ComputeInterRetVFGGuard (const SVFBasicBlock *src, const SVFBasicBlock *dst, const SVFBasicBlock *retBB)
 
virtual Condition getPHIComplementCond (const SVFBasicBlock *BB1, const SVFBasicBlock *BB2, const SVFBasicBlock *BB0)
 
void clearCFCond ()
 
void setCurEvalSVFGNode (const SVFGNode *node)
 Set current value for branch condition evaluation.
 
const SVFGNodegetCurEvalSVFGNode () const
 Get current value for branch condition evaluation.
 
void printPathCond ()
 Print out the path condition information.
 
bool isSatisfiable (const Condition &condition)
 whether condition is satisfiable
 
bool isAllPathReachable (Condition &condition)
 whether condition is satisfiable for all possible boolean guards
 
bool isEquivalentBranchCond (const Condition &lhs, const Condition &rhs) const
 Whether lhs and rhs are equivalent branch conditions.
 
ICFGgetICFG () const
 
bool setCFCond (const SVFBasicBlock *bb, const Condition &cond)
 Get/Set control-flow conditions.
 
Condition getCFCond (const SVFBasicBlock *bb) const
 
void setNegCondInst (const Condition &condition, const ICFGNode *inst)
 mark neg Z3 expression
 
SVFGNodeToSVFGNodeSetMapgetRemovedSUVFEdges ()
 

Protected Attributes

BBCondMap bbConds
 map basic block to its successors/predecessors branch conditions
 

Private Member Functions

virtual void allocateForBB (const SVFBasicBlock &bb)
 Allocate path condition for every basic block.
 
void setBranchCond (const SVFBasicBlock *bb, const SVFBasicBlock *succ, const Condition &cond)
 Get/Set a branch condition, and its terminator instruction.
 
Condition getBranchCond (const SVFBasicBlock *bb, const SVFBasicBlock *succ) const
 Get branch condition.
 
Condition getEvalBrCond (const SVFBasicBlock *bb, const SVFBasicBlock *succ)
 Get a condition, evaluate the value for conditions if necessary (e.g., testNull like express)
 
Condition evaluateBranchCond (const SVFBasicBlock *bb, const SVFBasicBlock *succ)
 Evaluate branch conditions.
 
Condition evaluateLoopExitBranch (const SVFBasicBlock *bb, const SVFBasicBlock *succ)
 Evaluate loop exit branch.
 
Condition evaluateTestNullLikeExpr (const BranchStmt *branchStmt, const SVFBasicBlock *succ)
 Return branch condition after evaluating test null like expression.
 
Condition evaluateProgExit (const BranchStmt *branchStmt, const SVFBasicBlock *succ)
 Return condition when there is a branch calls program exit.
 
void collectBBCallingProgExit (const SVFBasicBlock &bb)
 Collect basic block contains program exit function call.
 
bool isBBCallsProgExit (const SVFBasicBlock *bb)
 
bool isEQCmp (const CmpStmt *cmp) const
 Evaluate test null/not null like expressions.
 
bool isNECmp (const CmpStmt *cmp) const
 Return true if the predicate of this compare instruction is not equal.
 
bool isTestNullExpr (const ICFGNode *test) const
 Return true if this is a test null expression.
 
bool isTestNotNullExpr (const ICFGNode *test) const
 Return true if this is a test not null expression.
 
bool isTestContainsNullAndTheValue (const CmpStmt *cmp) const
 Return true if two values on the predicate are what we want.
 
void destroy ()
 Release memory.
 
void extractSubConds (const Condition &condition, NodeBS &support) const
 extract subexpression from a Z3 expression
 

Private Attributes

FunToExitBBsMap funToExitBBsMap
 map a function to all its basic blocks calling program exit
 
BBToCondMap bbToCondMap
 map a basic block to its path condition starting from root
 
const SVFGNodecurEvalSVFGNode {}
 current llvm value to evaluate branch condition when computing guards
 
IndexToTermInstMap idToTermInstMap
 
NodeBS negConds
 key: z3 expression id, value: instruction
 
std::vector< ConditionconditionVec
 bit vector for distinguish neg
 
SVFGNodeToSVFGNodeSetMap removedSUVFEdges
 a counter for fresh condition
 

Static Private Attributes

static u32_t totalCondNum = 0
 vector storing z3expression
 

Detailed Description

SaberCondAllocator allocates conditions for each basic block of a certain CFG.

Definition at line 46 of file SaberCondAllocator.h.

Member Typedef Documentation

◆ BasicBlockSet

map bb to a Condition

Definition at line 55 of file SaberCondAllocator.h.

◆ BBCondMap

Definition at line 54 of file SaberCondAllocator.h.

◆ BBToCondMap

map a basic block to its condition during control-flow guard computation

Definition at line 57 of file SaberCondAllocator.h.

◆ CFWorkList

worklist for control-flow guard computation

Definition at line 58 of file SaberCondAllocator.h.

◆ Condition

Definition at line 51 of file SaberCondAllocator.h.

◆ CondPosMap

id to instruction map for z3

map a branch to its Condition

Definition at line 53 of file SaberCondAllocator.h.

◆ FunToExitBBsMap

map a function to all its basic blocks calling program exit

Definition at line 56 of file SaberCondAllocator.h.

◆ IndexToTermInstMap

z3 condition

Definition at line 52 of file SaberCondAllocator.h.

◆ SVFGNodeToSVFGNodeSetMap

Definition at line 59 of file SaberCondAllocator.h.

Constructor & Destructor Documentation

◆ SaberCondAllocator()

SaberCondAllocator::SaberCondAllocator ( )

Constructor.

Definition at line 51 of file SaberCondAllocator.cpp.

52{
53
54}

◆ ~SaberCondAllocator()

virtual SVF::SaberCondAllocator::~SaberCondAllocator ( )
inlinevirtual

Destructor.

Definition at line 66 of file SaberCondAllocator.h.

67 {
68 }

Member Function Documentation

◆ allocate()

void SaberCondAllocator::allocate ( const SVFModule M)

Perform path allocation.

Allocate path condition for each branch

Definition at line 59 of file SaberCondAllocator.cpp.

60{
61 DBOUT(DGENERAL, outs() << pasMsg("path condition allocation starts\n"));
62
64 for (const auto& item: *svfirCallGraph)
65 {
66 const SVFFunction *func = (item.second)->getFunction();
67 if (!SVFUtil::isExtCall(func))
68 {
69 // Allocate conditions for a program.
70 for (SVFFunction::const_iterator bit = func->begin(), ebit = func->end();
71 bit != ebit; ++bit)
72 {
73 const SVFBasicBlock* bb = *bit;
75 allocateForBB(*bb);
76 }
77 }
78 }
79
82
83 DBOUT(DGENERAL, outs() << pasMsg("path condition allocation ends\n"));
84}
#define DBOUT(TYPE, X)
LLVM debug macros, define type of your DBUG model of each pass.
Definition SVFType.h:484
#define DGENERAL
Definition SVFType.h:490
cJSON * item
Definition cJSON.h:222
static const Option< bool > PrintPathCond
Definition Options.h:199
const_iterator end() const
Definition SVFValue.h:451
const_iterator begin() const
Definition SVFValue.h:446
std::vector< constSVFBasicBlock * >::const_iterator const_iterator
Definition SVFValue.h:305
CallGraph * getCallGraph()
Definition SVFIR.h:193
static SVFIR * getPAG(bool buildFromFile=false)
Singleton design here to make sure we only have one instance during any analysis.
Definition SVFIR.h:116
virtual void allocateForBB(const SVFBasicBlock &bb)
Allocate path condition for every basic block.
void printPathCond()
Print out the path condition information.
void collectBBCallingProgExit(const SVFBasicBlock &bb)
Collect basic block contains program exit function call.
const SVFFunction * getFunction(const std::string &name)
Get the corresponding Function based on its name.
Definition LLVMUtil.cpp:411
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:100
std::ostream & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:50
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74

◆ allocateForBB()

void SaberCondAllocator::allocateForBB ( const SVFBasicBlock bb)
privatevirtual

Allocate path condition for every basic block.

Allocate conditions for a basic block and propagate its condition to its successors.

TODO: handle BranchInst and SwitchInst individually here!!

Definition at line 89 of file SaberCondAllocator.cpp.

90{
91
93
94 // if successor number greater than 1, allocate new decision variable for successors
95 if (succ_number > 1)
96 {
97
98 //allocate log2(num_succ) decision variables
99 double num = log(succ_number) / log(2);
101 u32_t succ_index = 0;
102 std::vector<Condition> condVec;
103 for (u32_t i = 0; i < bit_num; i++)
104 {
105 condVec.push_back(newCond(bb.back()));
106 }
107
108 // iterate each successor
109 for (const SVFBasicBlock* svf_succ_bb : bb.getSuccessors())
110 {
112
114
115 // for each successor decide its bit representation
116 // decide whether each bit of succ_index is 1 or 0, if (three successor) succ_index is 000 then use C1^C2^C3
117 // if 001 use C1^C2^negC3
118 for (u32_t j = 0; j < bit_num; j++)
119 {
120 //test each bit of this successor's index (binary representation)
121 u32_t tool = 0x01 << j;
122 if (tool & succ_index)
123 {
125 }
126 else
127 {
129 }
130 }
132
133 succ_index++;
134 }
135
136 }
137}
unsigned u32_t
Definition CommandLine.h:18
u32_t getNumSuccessors() const
Definition SVFValue.h:626
const ICFGNode * back() const
Definition SVFValue.h:611
Condition newCond(const ICFGNode *inst)
Allocate a new condition.
void setBranchCond(const SVFBasicBlock *bb, const SVFBasicBlock *succ, const Condition &cond)
Get/Set a branch condition, and its terminator instruction.
Condition condNeg(const Condition &cond)
Condition condAnd(const Condition &lhs, const Condition &rhs)
Condition operations.
Condition getTrueCond() const
unsigned u32_t
Definition GeneralType.h:46

◆ clearCFCond()

void SVF::SaberCondAllocator::clearCFCond ( )
inline

Definition at line 177 of file SaberCondAllocator.h.

178 {
179 bbToCondMap.clear();
180 }
BBToCondMap bbToCondMap
map a basic block to its path condition starting from root

◆ collectBBCallingProgExit()

void SaberCondAllocator::collectBBCallingProgExit ( const SVFBasicBlock bb)
private

Collect basic block contains program exit function call.

Whether this basic block contains program exit function call

Definition at line 430 of file SaberCondAllocator.cpp.

431{
432
433 for (const auto& icfgNode: bb.getICFGNodeList())
434 {
435 if (const CallICFGNode* cs = SVFUtil::dyn_cast<CallICFGNode>(icfgNode))
437 {
438 const SVFFunction* svfun = bb.getParent();
439 funToExitBBsMap[svfun].insert(&bb);
440 }
441 }
442}
const SVFFunction * getParent() const
Definition SVFValue.h:595
FunToExitBBsMap funToExitBBsMap
map a function to all its basic blocks calling program exit
bool isProgExitCall(const CallICFGNode *cs)
Definition SVFUtil.cpp:397

◆ ComputeInterCallVFGGuard()

SaberCondAllocator::Condition SaberCondAllocator::ComputeInterCallVFGGuard ( const SVFBasicBlock srcBB,
const SVFBasicBlock dstBB,
const SVFBasicBlock callBB 
)
virtual

Compute calling inter-procedural guards between two SVFGNodes (from caller to callee) src –c1--> callBB –true--> funEntryBB –c2--> dst the InterCallVFGGuard is c1 ^ c2

Definition at line 489 of file SaberCondAllocator.cpp.

491{
493
497 return condAnd(c1, c2);
498}
const SVFBasicBlock * getEntryBlock() const
Definition SVFValue.h:420
Condition condOr(const Condition &lhs, const Condition &rhs)
bool setCFCond(const SVFBasicBlock *bb, const Condition &cond)
Get/Set control-flow conditions.
Condition getCFCond(const SVFBasicBlock *bb) const
virtual Condition ComputeIntraVFGGuard(const SVFBasicBlock *src, const SVFBasicBlock *dst)
Guard Computation for a value-flow (between two basic blocks)

◆ ComputeInterRetVFGGuard()

SaberCondAllocator::Condition SaberCondAllocator::ComputeInterRetVFGGuard ( const SVFBasicBlock srcBB,
const SVFBasicBlock dstBB,
const SVFBasicBlock retBB 
)
virtual

Compute return inter-procedural guards between two SVFGNodes (from callee to caller) src –c1--> funExitBB –true--> retBB –c2--> dst the InterRetVFGGuard is c1 ^ c2

Definition at line 506 of file SaberCondAllocator.cpp.

507{
508 const SVFFunction* parent = srcBB->getParent();
509 const SVFBasicBlock* funExitBB = parent->getExitBB();
510
514 return condAnd(c1, c2);
515}

◆ ComputeIntraVFGGuard()

SaberCondAllocator::Condition SaberCondAllocator::ComputeIntraVFGGuard ( const SVFBasicBlock srcBB,
const SVFBasicBlock dstBB 
)
virtual

Guard Computation for a value-flow (between two basic blocks)

Compute intra-procedural guards between two SVFGNodes (inside same function)

if the dstBB is the eligible loop exit of the current basic block we can early terminate the computation

calculate the branch condition if succ post dominate bb, then we get brCond quicker by using postDT note that we assume loop exit always post dominate loop bodys which means loops are approximated only once.

Definition at line 520 of file SaberCondAllocator.cpp.

521{
522
523 assert(srcBB->getParent() == dstBB->getParent() && "two basic blocks are not in the same function??");
524
526 return getTrueCond();
527
528 CFWorkList worklist;
529 worklist.push(srcBB);
531
532 while (!worklist.empty())
533 {
534 const SVFBasicBlock* bb = worklist.pop();
535 Condition cond = getCFCond(bb);
536
541 return condAnd(cond, loopExitCond);
542
543 for (const SVFBasicBlock* succ : bb->getSuccessors())
544 {
550 if (postDominate(succ, bb))
552 else
554
555 DBOUT(DSaber, outs() << " bb (" << bb->getName() <<
556 ") --> " << "succ_bb (" << succ->getName() << ") condition: " << brCond << "\n");
559 worklist.push(succ);
560 }
561 }
562
563 DBOUT(DSaber, outs() << " src_bb (" << srcBB->getName() <<
564 ") --> " << "dst_bb (" << dstBB->getName() << ") condition: " << getCFCond(dstBB)
565 << "\n");
566
567 return getCFCond(dstBB);
568}
#define DSaber
Definition SVFType.h:504
const std::string & getName() const
Definition SVFValue.h:243
bool postDominate(const SVFBasicBlock *bbKey, const SVFBasicBlock *bbValue) const
Condition evaluateLoopExitBranch(const SVFBasicBlock *bb, const SVFBasicBlock *succ)
Evaluate loop exit branch.
FIFOWorkList< const SVFBasicBlock * > CFWorkList
worklist for control-flow guard computation
Condition getEvalBrCond(const SVFBasicBlock *bb, const SVFBasicBlock *succ)
Get a condition, evaluate the value for conditions if necessary (e.g., testNull like express)
static z3::expr nullExpr()
null expression
Definition Z3Expr.h:105

◆ condAnd()

Condition SVF::SaberCondAllocator::condAnd ( const Condition lhs,
const Condition rhs 
)
inline

Condition operations.

Definition at line 87 of file SaberCondAllocator.h.

88 {
89 return Condition::AND(lhs,rhs);
90 }
static Z3Expr AND(const Z3Expr &lhs, const Z3Expr &rhs)
compute AND, used for branch condition
Definition Z3Expr.cpp:92

◆ condNeg()

Condition SVF::SaberCondAllocator::condNeg ( const Condition cond)
inline

Definition at line 95 of file SaberCondAllocator.h.

96 {
97 return Condition::NEG(cond);
98 }
static Z3Expr NEG(const Z3Expr &z3Expr)
compute NEG
Definition Z3Expr.h:301

◆ condOr()

Condition SVF::SaberCondAllocator::condOr ( const Condition lhs,
const Condition rhs 
)
inline

Definition at line 91 of file SaberCondAllocator.h.

92 {
93 return Condition::OR(lhs,rhs);
94 }
static Z3Expr OR(const Z3Expr &lhs, const Z3Expr &rhs)
compute OR, used for branch condition
Definition Z3Expr.cpp:130

◆ destroy()

void SVF::SaberCondAllocator::destroy ( )
inlineprivate

Release memory.

Definition at line 293 of file SaberCondAllocator.h.

294 {
295
296 }

◆ dominate()

bool SVF::SaberCondAllocator::dominate ( const SVFBasicBlock bbKey,
const SVFBasicBlock bbValue 
) const
inline

Definition at line 157 of file SaberCondAllocator.h.

158 {
159 const SVFFunction* keyFunc = bbKey->getParent();
160 const SVFFunction* valueFunc = bbValue->getParent();
161 bool funcEq = (keyFunc == valueFunc);
162 (void)funcEq; // Suppress warning of unused variable under release build
163 assert(funcEq && "two basicblocks should be in the same function!");
164 return keyFunc->dominate(bbKey,bbValue);
165 }

◆ dumpCond()

std::string SVF::SaberCondAllocator::dumpCond ( const Condition cond) const
inline

Definition at line 115 of file SaberCondAllocator.h.

116 {
117 return Condition::dumpStr(cond);
118 }
static std::string dumpStr(const Z3Expr &z3Expr)
output Z3 expression as a string
Definition Z3Expr.cpp:168

◆ evaluateBranchCond()

SaberCondAllocator::Condition SaberCondAllocator::evaluateBranchCond ( const SVFBasicBlock bb,
const SVFBasicBlock succ 
)
private

Evaluate branch conditions.

Evaluate the branch condition

(1) Evaluate a branch when it reaches a program exit (2) Evaluate a branch when it is loop exit branch (3) Evaluate a branch when it is a test null like condition

Definition at line 302 of file SaberCondAllocator.cpp.

303{
304 if(bb->getNumSuccessors() == 1)
305 {
306 return getTrueCond();
307 }
308
309 assert(!bb->getICFGNodeList().empty() && "bb not empty");
310 if (const ICFGNode* icfgNode = bb->back())
311 {
312 for (const auto &svfStmt: icfgNode->getSVFStmts())
313 {
314 if (const BranchStmt *branchStmt = SVFUtil::dyn_cast<BranchStmt>(svfStmt))
315 {
316 if (branchStmt->getNumSuccessors() == 2)
317 {
318 const SVFBasicBlock* succ1 = branchStmt->getSuccessor(0)->getBB();
319 const SVFBasicBlock* succ2 = branchStmt->getSuccessor(1)->getBB();
320 bool is_succ = (succ1 == succ || succ2 == succ);
321 (void)is_succ; // Suppress warning of unused variable under release build
322 assert(is_succ && "not a successor??");
325 return evalLoopExit;
326
329 return evalProgExit;
330
333 return evalTestNullLike;
334 break;
335 }
336 }
337 }
338 }
339
340 return getBranchCond(bb, succ);
341}
const std::vector< const ICFGNode * > & getICFGNodeList() const
Definition SVFValue.h:580
Condition evaluateTestNullLikeExpr(const BranchStmt *branchStmt, const SVFBasicBlock *succ)
Return branch condition after evaluating test null like expression.
Condition evaluateProgExit(const BranchStmt *branchStmt, const SVFBasicBlock *succ)
Return condition when there is a branch calls program exit.
Condition getBranchCond(const SVFBasicBlock *bb, const SVFBasicBlock *succ) const
Get branch condition.

◆ evaluateLoopExitBranch()

SaberCondAllocator::Condition SaberCondAllocator::evaluateLoopExitBranch ( const SVFBasicBlock bb,
const SVFBasicBlock dst 
)
private

Evaluate loop exit branch.

Evaluate loop exit branch to be true if bb is loop header and succ is the only exit basic block outside the loop (excluding exit bbs which call program exit) for all other case, we conservatively evaluate false for now

exclude exit bb which calls program exit

if the dst dominate all other loop exit bbs, then dst can certainly be reached

Definition at line 266 of file SaberCondAllocator.cpp.

267{
268 const SVFFunction* svffun = bb->getParent();
269 assert(svffun == dst->getParent() && "two basic blocks should be in the same function");
270
271 if (svffun->isLoopHeader(bb))
272 {
274 std::vector<const SVFBasicBlock*> exitbbs;
275 svffun->getExitBlocksOfLoop(bb,exitbbs);
277 for(const SVFBasicBlock* eb : exitbbs)
278 {
280 filteredbbs.insert(eb);
281 }
282
284 bool allPDT = true;
285 for (const auto &filteredbb: filteredbbs)
286 {
287 if (!postDominate(dst, filteredbb))
288 allPDT = false;
289 }
290
291 if (allPDT)
292 return getTrueCond();
293 }
294 return Condition::nullExpr();
295}
bool isBBCallsProgExit(const SVFBasicBlock *bb)

◆ evaluateProgExit()

SaberCondAllocator::Condition SaberCondAllocator::evaluateProgExit ( const BranchStmt branchStmt,
const SVFBasicBlock succ 
)
private

Return condition when there is a branch calls program exit.

Evaluate condition for program exit (e.g., exit(0))

then branch calls program exit

else branch calls program exit

no branch call program exit

Definition at line 222 of file SaberCondAllocator.cpp.

223{
224 const SVFBasicBlock* succ1 = branchStmt->getSuccessor(0)->getBB();
225 const SVFBasicBlock* succ2 = branchStmt->getSuccessor(1)->getBB();
226
229
231 if (branch1 && !branch2)
232 {
233 // succ is then branch
234 if (succ1 == succ)
235 return getFalseCond();
236 // succ is else branch
237 else
238 return getTrueCond();
239 }
241 else if (!branch1 && branch2)
242 {
243 // succ is else branch
244 if (succ2 == succ)
245 return getFalseCond();
246 // succ is then branch
247 else
248 return getTrueCond();
249 }
250 // two branches both call program exit
251 else if (branch1 && branch2)
252 {
253 return getFalseCond();
254 }
256 else
257 return Condition::nullExpr();
258
259}
Condition getFalseCond() const

◆ evaluateTestNullLikeExpr()

SaberCondAllocator::Condition SaberCondAllocator::evaluateTestNullLikeExpr ( const BranchStmt branchStmt,
const SVFBasicBlock succ 
)
private

Return branch condition after evaluating test null like expression.

Evaluate null like expression for source-sink related bug detection in SABER

Definition at line 186 of file SaberCondAllocator.cpp.

187{
188
189 const SVFBasicBlock* succ1 = branchStmt->getSuccessor(0)->getBB();
190
191 const ValVar* condVar = SVFUtil::cast<ValVar>(branchStmt->getCondition());
192 if (condVar->isConstDataOrAggDataButNotNullPtr())
193 {
194 // branch condition is a constant value, return nullexpr because it cannot be test null
195 // br i1 false, label %44, label %75, !dbg !7669 { "ln": 2033, "cl": 7, "fl": "re_lexer.c" }
196 return Condition::nullExpr();
197 }
198 if (isTestNullExpr(SVFUtil::cast<ICFGNode>(condVar->getICFGNode())))
199 {
200 // succ is then branch
201 if (succ1 == succ)
202 return getFalseCond();
203 // succ is else branch
204 else
205 return getTrueCond();
206 }
207 if (isTestNotNullExpr(condVar->getICFGNode()))
208 {
209 // succ is then branch
210 if (succ1 == succ)
211 return getTrueCond();
212 // succ is else branch
213 else
214 return getFalseCond();
215 }
216 return Condition::nullExpr();
217}
bool isTestNullExpr(const ICFGNode *test) const
Return true if this is a test null expression.
bool isTestNotNullExpr(const ICFGNode *test) const
Return true if this is a test not null expression.

◆ exactCondElem()

NodeBS SVF::SaberCondAllocator::exactCondElem ( const Condition cond)
inline

Iterator every element of the condition.

Definition at line 108 of file SaberCondAllocator.h.

109 {
111 extractSubConds(cond, elems);
112 return elems;
113 }
void extractSubConds(const Condition &condition, NodeBS &support) const
extract subexpression from a Z3 expression
SparseBitVector NodeBS
Definition GeneralType.h:62

◆ extractSubConds()

void SaberCondAllocator::extractSubConds ( const Condition condition,
NodeBS support 
) const
private

extract subexpression from a Z3 expression

Definition at line 637 of file SaberCondAllocator.cpp.

638{
639 if (condition.getExpr().num_args() == 1 && isNegCond(condition.id()))
640 {
641 support.set(condition.getExpr().id());
642 return;
643 }
644 if (condition.getExpr().num_args() == 0)
645 if (!condition.getExpr().is_true() && !condition.getExpr().is_false())
646 support.set(condition.getExpr().id());
647 for (u32_t i = 0; i < condition.getExpr().num_args(); ++i)
648 {
649 Condition expr = condition.getExpr().arg(i);
651 }
652
653}
bool isNegCond(u32_t id) const
const z3::expr & getExpr() const
Definition Z3Expr.h:86

◆ getBranchCond()

SaberCondAllocator::Condition SaberCondAllocator::getBranchCond ( const SVFBasicBlock bb,
const SVFBasicBlock succ 
) const
private

Get branch condition.

Get a branch condition

Definition at line 142 of file SaberCondAllocator.cpp.

143{
145 if(bb->getNumSuccessors() == 1)
146 return getTrueCond();
147 else
148 {
149 BBCondMap::const_iterator it = bbConds.find(bb);
150 assert(it != bbConds.end() && "basic block does not have branch and conditions??");
151 CondPosMap::const_iterator cit = it->second.find(pos);
152 assert(cit != it->second.end() && "no condition on the branch??");
153 return cit->second;
154 }
155}
u32_t getBBSuccessorPos(const SVFBasicBlock *succbb)
Definition SVFValue.cpp:212
BBCondMap bbConds
map basic block to its successors/predecessors branch conditions

◆ getCFCond()

Condition SVF::SaberCondAllocator::getCFCond ( const SVFBasicBlock bb) const
inline

Definition at line 225 of file SaberCondAllocator.h.

226 {
227 BBToCondMap::const_iterator it = bbToCondMap.find(bb);
228 if(it==bbToCondMap.end())
229 {
230 return getFalseCond();
231 }
232 return it->second;
233 }

◆ getCondInst()

const ICFGNode * SVF::SaberCondAllocator::getCondInst ( u32_t  id) const
inline

Get/Set instruction based on Z3 expression id.

Definition at line 128 of file SaberCondAllocator.h.

129 {
130 IndexToTermInstMap::const_iterator it = idToTermInstMap.find(id);
131 assert(it != idToTermInstMap.end() && "this should be a fresh condition");
132 return it->second;
133 }
IndexToTermInstMap idToTermInstMap

◆ getCondNum()

u32_t SVF::SaberCondAllocator::getCondNum ( )
inline

Definition at line 79 of file SaberCondAllocator.h.

80 {
81 return totalCondNum;
82 }
static u32_t totalCondNum
vector storing z3expression

◆ getCurEvalSVFGNode()

const SVFGNode * SVF::SaberCondAllocator::getCurEvalSVFGNode ( ) const
inline

Get current value for branch condition evaluation.

Definition at line 187 of file SaberCondAllocator.h.

188 {
189 return curEvalSVFGNode;
190 }
const SVFGNode * curEvalSVFGNode
current llvm value to evaluate branch condition when computing guards

◆ getEvalBrCond()

SaberCondAllocator::Condition SaberCondAllocator::getEvalBrCond ( const SVFBasicBlock bb,
const SVFBasicBlock succ 
)
private

Get a condition, evaluate the value for conditions if necessary (e.g., testNull like express)

Definition at line 157 of file SaberCondAllocator.cpp.

158{
159 if (getCurEvalSVFGNode() && getCurEvalSVFGNode()->getValue())
160 return evaluateBranchCond(bb, succ);
161 else
162 return getBranchCond(bb, succ);
163}
const SVFGNode * getCurEvalSVFGNode() const
Get current value for branch condition evaluation.
Condition evaluateBranchCond(const SVFBasicBlock *bb, const SVFBasicBlock *succ)
Evaluate branch conditions.

◆ getFalseCond()

Condition SVF::SaberCondAllocator::getFalseCond ( ) const
inline

Definition at line 103 of file SaberCondAllocator.h.

104 {
106 }
static Z3Expr getFalseCond()
Return the unique false condition.
Definition Z3Expr.h:295

◆ getICFG()

ICFG * SVF::SaberCondAllocator::getICFG ( ) const
inline

Definition at line 208 of file SaberCondAllocator.h.

209 {
210 return PAG::getPAG()->getICFG();
211 }
ICFG * getICFG() const
Definition SVFIR.h:172

◆ getMemUsage()

std::string SVF::SaberCondAllocator::getMemUsage ( )
inline

Statistics.

Definition at line 71 of file SaberCondAllocator.h.

72 {
75 return std::to_string(vmsize) + "KB";
76 else
77 return "cannot read memory usage";
78 }
bool getMemoryUsageKB(u32_t *vmrss_kb, u32_t *vmsize_kb)
Get memory usage from system file. Return TRUE if succeed.
Definition SVFUtil.cpp:178

◆ getPHIComplementCond()

SaberCondAllocator::Condition SaberCondAllocator::getPHIComplementCond ( const SVFBasicBlock BB1,
const SVFBasicBlock BB2,
const SVFBasicBlock BB0 
)
virtual

Get complement condition (from B1 to B0) according to a complementBB (BB2) at a phi e.g., B0: dstBB; B1:incomingBB; B2:complementBB

Get complement phi condition e.g., B0: dstBB; B1:incomingBB; B2:complementBB Assume B0 (phi node) is the successor of both B1 and B2. If B1 dominates B2, and B0 not dominate B2 then condition from B1-->B0 = neg(B1-->B2)^(B1-->B0)

avoid both BB0 and BB1 dominate BB2 (e.g., while loop), then BB2 is not necessarily a complement BB

Definition at line 469 of file SaberCondAllocator.cpp.

470{
471 assert(BB1 && BB2 && "expect nullptr BB here!");
472
474 if (dominate(BB1, BB2) && ! dominate(BB0, BB2))
475 {
477 return condNeg(cond);
478 }
479
480 return getTrueCond();
481}
bool dominate(const SVFBasicBlock *bbKey, const SVFBasicBlock *bbValue) const

◆ getRemovedSUVFEdges()

SVFGNodeToSVFGNodeSetMap & SVF::SaberCondAllocator::getRemovedSUVFEdges ( )
inline

Definition at line 244 of file SaberCondAllocator.h.

245 {
246 return removedSUVFEdges;
247 }
SVFGNodeToSVFGNodeSetMap removedSUVFEdges
a counter for fresh condition

◆ getTrueCond()

Condition SVF::SaberCondAllocator::getTrueCond ( ) const
inline

Definition at line 99 of file SaberCondAllocator.h.

100 {
101 return Condition::getTrueCond();
102 }
static Z3Expr getTrueCond()
Return the unique true condition.
Definition Z3Expr.h:288

◆ isAllPathReachable()

bool SVF::SaberCondAllocator::isAllPathReachable ( Condition condition)
inline

whether condition is satisfiable for all possible boolean guards

Definition at line 200 of file SaberCondAllocator.h.

201 {
203 }
bool isEquivalentBranchCond(const Condition &lhs, const Condition &rhs) const
Whether lhs and rhs are equivalent branch conditions.

◆ isBBCallsProgExit()

bool SaberCondAllocator::isBBCallsProgExit ( const SVFBasicBlock bb)
private

Whether this basic block contains program exit function call

Definition at line 447 of file SaberCondAllocator.cpp.

448{
449 const SVFFunction* svfun = bb->getParent();
450 FunToExitBBsMap::const_iterator it = funToExitBBsMap.find(svfun);
451 if (it != funToExitBBsMap.end())
452 {
453 for (const auto &bit: it->second)
454 {
455 if (postDominate(bit, bb))
456 return true;
457 }
458 }
459 return false;
460}

◆ isEQCmp()

bool SaberCondAllocator::isEQCmp ( const CmpStmt cmp) const
private

Evaluate test null/not null like expressions.

Return true if the predicate of this compare instruction is equal

Definition at line 343 of file SaberCondAllocator.cpp.

344{
345 return (cmp->getPredicate() == CmpStmt::ICMP_EQ);
346}

◆ isEquivalentBranchCond()

bool SaberCondAllocator::isEquivalentBranchCond ( const Condition lhs,
const Condition rhs 
) const

Whether lhs and rhs are equivalent branch conditions.

check equal using z3 solver

Definition at line 614 of file SaberCondAllocator.cpp.

616{
617 Condition::getSolver().push();
618 Condition::getSolver().add(lhs.getExpr() != rhs.getExpr());
619 z3::check_result res = Condition::getSolver().check();
620 Condition::getSolver().pop();
621 return res == z3::unsat;
622}
static z3::solver & getSolver()
Get z3 solver, singleton design here to make sure we only have one context.
Definition Z3Expr.cpp:56

◆ isNECmp()

bool SaberCondAllocator::isNECmp ( const CmpStmt cmp) const
private

Return true if the predicate of this compare instruction is not equal.

Definition at line 348 of file SaberCondAllocator.cpp.

349{
350 return (cmp->getPredicate() == CmpStmt::ICMP_NE);
351}
@ ICMP_NE
not equal

◆ isNegCond()

bool SVF::SaberCondAllocator::isNegCond ( u32_t  id) const
inline

Definition at line 142 of file SaberCondAllocator.h.

143 {
144 return negConds.test(id);
145 }
NodeBS negConds
key: z3 expression id, value: instruction
bool test(unsigned Idx) const

◆ isSatisfiable()

bool SaberCondAllocator::isSatisfiable ( const Condition condition)

whether condition is satisfiable

Definition at line 625 of file SaberCondAllocator.cpp.

626{
627 Condition::getSolver().add(condition.getExpr());
628 z3::check_result result = Condition::getSolver().check();
629 Condition::getSolver().pop();
630 if (result == z3::sat || result == z3::unknown)
631 return true;
632 else
633 return false;
634}

◆ isTestContainsNullAndTheValue()

bool SaberCondAllocator::isTestContainsNullAndTheValue ( const CmpStmt cmp) const
private

Return true if two values on the predicate are what we want.

Return true if: (1) cmp contains a null value (2) there is an indirect/direct edge from cur evaluated SVFG node to cmp operand

e.g., indirect edge: cur svfg node -> 1. store i32* %0, i32** p, align 8, !dbg !157 cmp operand -> 2. %1 = load i32*, i32** p, align 8, !dbg !159

  1. tobool = icmp ne i32* %1, null, !dbg !159
  2. br i1 tobool, label if.end, label if.then, !dbg !161 There is an indirect edge 1->2 with value %0

direct edge: cur svfg node -> 1. %3 = tail call i8* @malloc(i64 16), !dbg !22 (cmp operand) 2. %4 = icmp eq i8* %3, null, !dbg !28

  1. br i1 %4, label %7, label %5, !dbg !30 There is an direct edge 1->2 with value %3

Definition at line 399 of file SaberCondAllocator.cpp.

400{
401
402 const SVFVar* op0 = cmp->getOpVar(0);
403 const SVFVar* op1 = cmp->getOpVar(1);
404 if (SVFUtil::isa<ConstantNullPtrValVar>(op1))
405 {
407 inDirVal.insert(getCurEvalSVFGNode()->getValue());
408 for (const auto &it: getCurEvalSVFGNode()->getOutEdges())
409 {
410 inDirVal.insert(it->getDstNode()->getValue());
411 }
412 return inDirVal.find(op0->getValue()) != inDirVal.end();
413 }
414 else if (SVFUtil::isa<ConstantNullPtrValVar>(op0))
415 {
417 inDirVal.insert(getCurEvalSVFGNode()->getValue());
418 for (const auto &it: getCurEvalSVFGNode()->getOutEdges())
419 {
420 inDirVal.insert(it->getDstNode()->getValue());
421 }
422 return inDirVal.find(op1->getValue()) != inDirVal.end();
423 }
424 return false;
425}

◆ isTestNotNullExpr()

bool SaberCondAllocator::isTestNotNullExpr ( const ICFGNode test) const
private

Return true if this is a test not null expression.

Definition at line 366 of file SaberCondAllocator.cpp.

367{
368 if(!test) return false;
369 for(const SVFStmt* stmt : PAG::getPAG()->getSVFStmtList(test))
370 {
371 if(const CmpStmt* cmp = SVFUtil::dyn_cast<CmpStmt>(stmt))
372 {
374 }
375 }
376 return false;
377}
bool isTestContainsNullAndTheValue(const CmpStmt *cmp) const
Return true if two values on the predicate are what we want.
bool isNECmp(const CmpStmt *cmp) const
Return true if the predicate of this compare instruction is not equal.

◆ isTestNullExpr()

bool SaberCondAllocator::isTestNullExpr ( const ICFGNode test) const
private

Return true if this is a test null expression.

Definition at line 353 of file SaberCondAllocator.cpp.

354{
355 if(!test) return false;
356 for(const SVFStmt* stmt : PAG::getPAG()->getSVFStmtList(test))
357 {
358 if(const CmpStmt* cmp = SVFUtil::dyn_cast<CmpStmt>(stmt))
359 {
361 }
362 }
363 return false;
364}
bool isEQCmp(const CmpStmt *cmp) const
Evaluate test null/not null like expressions.

◆ newCond()

SaberCondAllocator::Condition SaberCondAllocator::newCond ( const ICFGNode inst)

Allocate a new condition.

Definition at line 601 of file SaberCondAllocator.cpp.

602{
604 Condition expr = Condition::getContext().bool_const(("c" + std::to_string(condCountIdx)).c_str());
606 setCondInst(expr, inst);
607 setNegCondInst(negCond, inst);
608 conditionVec.push_back(expr);
609 conditionVec.push_back(negCond);
610 return expr;
611}
void setNegCondInst(const Condition &condition, const ICFGNode *inst)
mark neg Z3 expression
void setCondInst(const Condition &condition, const ICFGNode *inst)
std::vector< Condition > conditionVec
bit vector for distinguish neg
static z3::context & getContext()
Get z3 context, singleton design here to make sure we only have one context.
Definition Z3Expr.cpp:66

◆ postDominate()

bool SVF::SaberCondAllocator::postDominate ( const SVFBasicBlock bbKey,
const SVFBasicBlock bbValue 
) const
inline

Definition at line 147 of file SaberCondAllocator.h.

148 {
149 const SVFFunction* keyFunc = bbKey->getParent();
150 const SVFFunction* valueFunc = bbValue->getParent();
151 bool funcEq = (keyFunc == valueFunc);
152 (void)funcEq; // Suppress warning of unused variable under release build
153 assert(funcEq && "two basicblocks should be in the same function!");
154 return keyFunc->postDominate(bbKey,bbValue);
155 }

◆ printPathCond()

void SaberCondAllocator::printPathCond ( )

Print out the path condition information.

Print path conditions

Definition at line 574 of file SaberCondAllocator.cpp.

575{
576
577 outs() << "print path condition\n";
578
579 for (const auto &bbCond: bbConds)
580 {
581 const SVFBasicBlock* bb = bbCond.first;
582 for (const auto &cit: bbCond.second)
583 {
584 u32_t i = 0;
585 for (const SVFBasicBlock* succ: bb->getSuccessors())
586 {
587 if (i == cit.first)
588 {
589 Condition cond = cit.second;
590 outs() << bb->getName() << "-->" << succ->getName() << ":";
591 outs() << dumpCond(cond) << "\n";
592 break;
593 }
594 i++;
595 }
596 }
597 }
598}
std::string dumpCond(const Condition &cond) const

◆ setBranchCond()

void SaberCondAllocator::setBranchCond ( const SVFBasicBlock bb,
const SVFBasicBlock succ,
const Condition cond 
)
private

Get/Set a branch condition, and its terminator instruction.

Set branch condition

Set a branch condition

we only care about basic blocks have more than one successor

FIXME: llvm getNumSuccessors allows duplicated block in the successors, it makes this assertion fail In this case we may waste a condition allocation, because the overwrite of the previous cond

Definition at line 168 of file SaberCondAllocator.cpp.

169{
171 assert(bb->getNumSuccessors() > 1 && "not more than one successor??");
174
177 //assert(condPosMap.find(pos) == condPosMap.end() && "this branch has already been set ");
178
179 condPosMap[pos] = cond;
180}
Map< u32_t, Condition > CondPosMap
id to instruction map for z3

◆ setCFCond()

bool SVF::SaberCondAllocator::setCFCond ( const SVFBasicBlock bb,
const Condition cond 
)
inline

Get/Set control-flow conditions.

Definition at line 215 of file SaberCondAllocator.h.

216 {
217 BBToCondMap::iterator it = bbToCondMap.find(bb);
218 // until a fixed-point is reached (condition is not changed)
219 if(it!=bbToCondMap.end() && isEquivalentBranchCond(it->second, cond))
220 return false;
221
222 bbToCondMap[bb] = cond;
223 return true;
224 }

◆ setCondInst()

void SVF::SaberCondAllocator::setCondInst ( const Condition condition,
const ICFGNode inst 
)
inline

Definition at line 135 of file SaberCondAllocator.h.

136 {
137 assert(idToTermInstMap.find(condition.id()) == idToTermInstMap.end() && "this should be a fresh condition");
138 idToTermInstMap[condition.id()] = inst;
139 }

◆ setCurEvalSVFGNode()

void SVF::SaberCondAllocator::setCurEvalSVFGNode ( const SVFGNode node)
inline

Set current value for branch condition evaluation.

Definition at line 182 of file SaberCondAllocator.h.

183 {
184 curEvalSVFGNode = node;
185 }

◆ setNegCondInst()

void SVF::SaberCondAllocator::setNegCondInst ( const Condition condition,
const ICFGNode inst 
)
inline

mark neg Z3 expression

Definition at line 238 of file SaberCondAllocator.h.

239 {
240 setCondInst(condition, inst);
241 negConds.set(condition.id());
242 }
void set(unsigned Idx)

Member Data Documentation

◆ bbConds

BBCondMap SVF::SaberCondAllocator::bbConds
protected

map basic block to its successors/predecessors branch conditions

Definition at line 312 of file SaberCondAllocator.h.

◆ bbToCondMap

BBToCondMap SVF::SaberCondAllocator::bbToCondMap
private

map a basic block to its path condition starting from root

Definition at line 303 of file SaberCondAllocator.h.

◆ conditionVec

std::vector<Condition> SVF::SaberCondAllocator::conditionVec
private

bit vector for distinguish neg

Definition at line 307 of file SaberCondAllocator.h.

◆ curEvalSVFGNode

const SVFGNode* SVF::SaberCondAllocator::curEvalSVFGNode {}
private

current llvm value to evaluate branch condition when computing guards

Definition at line 304 of file SaberCondAllocator.h.

304{};

◆ funToExitBBsMap

FunToExitBBsMap SVF::SaberCondAllocator::funToExitBBsMap
private

map a function to all its basic blocks calling program exit

Definition at line 302 of file SaberCondAllocator.h.

◆ idToTermInstMap

IndexToTermInstMap SVF::SaberCondAllocator::idToTermInstMap
private

Definition at line 305 of file SaberCondAllocator.h.

◆ negConds

NodeBS SVF::SaberCondAllocator::negConds
private

key: z3 expression id, value: instruction

Definition at line 306 of file SaberCondAllocator.h.

◆ removedSUVFEdges

SVFGNodeToSVFGNodeSetMap SVF::SaberCondAllocator::removedSUVFEdges
private

a counter for fresh condition

Definition at line 309 of file SaberCondAllocator.h.

◆ totalCondNum

u32_t SaberCondAllocator::totalCondNum = 0
staticprivate

vector storing z3expression

Definition at line 308 of file SaberCondAllocator.h.


The documentation for this class was generated from the following files: