Static Value-Flow Analysis
Loading...
Searching...
No Matches
LockAnalysis.h
Go to the documentation of this file.
1//===- LockAnalysis.h -- Analysis of locksets-------------//
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 * LockAnalysis.h
25 *
26 * Created on: 26 Aug 2015
27 * Author: pengd
28 */
29
30#ifndef INCLUDE_MTA_LockAnalysis_H_
31#define INCLUDE_MTA_LockAnalysis_H_
32
36#include "MTA/TCT.h"
37
38namespace SVF
39{
40
45{
46
47public:
50 {
51 Empty, // initial(dummy) state
52 TDLocked, // stmt is locked
53 TDUnlocked, // stmt is unlocked
54 };
55
58
59 typedef NodeBS LockSet;
62 typedef InstSet CISpan;
71
79
83
87 void analyze();
91
92 void collectCxtLock();
94
97
99
100
101 inline bool isIntraLock(const ICFGNode* lock) const
102 {
103 assert(locksites.find(lock)!=locksites.end() && "not a lock site?");
104 return ciLocktoSpan.find(lock)!=ciLocktoSpan.end();
105 }
106
108 inline void addIntraLock(const ICFGNode* lockSite, const InstSet& stmts)
109 {
110 for(InstSet::const_iterator it = stmts.begin(), eit = stmts.end(); it!=eit; ++it)
111 {
112 instCILocksMap[*it].insert(lockSite);
113 ciLocktoSpan[lockSite].insert(*it);
114 }
115 }
116
118 inline void addCondIntraLock(const ICFGNode* lockSite, const InstSet& stmts)
119 {
120 for(InstSet::const_iterator it = stmts.begin(), eit = stmts.end(); it!=eit; ++it)
121 {
123 }
124 }
125
127 inline bool isInsideIntraLock(const ICFGNode* stmt) const
128 {
130 }
131
133 inline bool isInsideCondIntraLock(const ICFGNode* stmt) const
134 {
136 }
137
138 inline const InstSet& getIntraLockSet(const ICFGNode* stmt) const
139 {
140 InstToInstSetMap::const_iterator it = instCILocksMap.find(stmt);
141 assert(it!=instCILocksMap.end() && "intralock not found!");
142 return it->second;
143 }
145
147
148
149 inline void addCxtLock(const CallStrCxt& cxt,const ICFGNode* inst)
150 {
151 CxtLock cxtlock(cxt,inst);
152 cxtLockset.insert(cxtlock);
153 DBOUT(DMTA, SVFUtil::outs() << "LockAnalysis Process new lock "; cxtlock.dump());
154 }
155
157 inline bool hasCxtLock(const CxtLock& cxtLock) const
158 {
159 return cxtLockset.find(cxtLock)!=cxtLockset.end();
160 }
161
163 inline bool intersects(const CxtLockSet& lockset1,const CxtLockSet& lockset2) const
164 {
165 for(CxtLockSet::const_iterator it = lockset1.begin(), eit = lockset1.end(); it!=eit; ++it)
166 {
167 const CxtLock& lock = *it;
168 for(CxtLockSet::const_iterator lit = lockset2.begin(), elit = lockset2.end(); lit!=elit; ++lit)
169 {
170 if(lock==*lit)
171 return true;
172 }
173 }
174 return false;
175 }
177 inline bool alias(const CxtLockSet& lockset1,const CxtLockSet& lockset2)
178 {
179 for(CxtLockSet::const_iterator it = lockset1.begin(), eit = lockset1.end(); it!=eit; ++it)
180 {
181 const CxtLock& lock = *it;
182 for(CxtLockSet::const_iterator lit = lockset2.begin(), elit = lockset2.end(); lit!=elit; ++lit)
183 {
185 return true;
186 }
187 }
188 return false;
189 }
191
193 inline bool isLockCandidateFun(const FunObjVar* fun) const
194 {
195 return lockcandidateFuncSet.find(fun)!=lockcandidateFuncSet.end();
196 }
197
199
200
201 inline bool hasCxtStmtFromInst(const ICFGNode* inst) const
202 {
203 InstToCxtStmtSet::const_iterator it = instToCxtStmtSet.find(inst);
204 return (it != instToCxtStmtSet.end());
205 }
206 inline const CxtStmtSet& getCxtStmtsFromInst(const ICFGNode* inst) const
207 {
208 InstToCxtStmtSet::const_iterator it = instToCxtStmtSet.find(inst);
209 assert(it != instToCxtStmtSet.end());
210 return it->second;
211 }
212 inline bool hasCxtLockfromCxtStmt(const CxtStmt& cts) const
213 {
214 CxtStmtToCxtLockSet::const_iterator it = cxtStmtToCxtLockSet.find(cts);
215 return (it != cxtStmtToCxtLockSet.end());
216 }
217 inline const CxtLockSet& getCxtLockfromCxtStmt(const CxtStmt& cts) const
218 {
219 CxtStmtToCxtLockSet::const_iterator it = cxtStmtToCxtLockSet.find(cts);
220 assert(it != cxtStmtToCxtLockSet.end());
221 return it->second;
222 }
224 {
225 CxtStmtToCxtLockSet::iterator it = cxtStmtToCxtLockSet.find(cts);
226 assert(it != cxtStmtToCxtLockSet.end());
227 return it->second;
228 }
230 inline bool addCxtStmtToSpan(const CxtStmt& cts, const CxtLock& cl)
231 {
232 cxtLocktoSpan[cl].insert(cts);
233 return cxtStmtToCxtLockSet[cts].insert(cl).second;
234 }
237 {
238 bool find = cxtStmtToCxtLockSet[cts].find(cl)!=cxtStmtToCxtLockSet[cts].end();
239 if(find)
240 {
241 cxtStmtToCxtLockSet[cts].erase(cl);
242 cxtLocktoSpan[cl].erase(cts);
243 }
244 return find;
245 }
246
253 {
255 }
256 inline bool hasSpanfromCxtLock(const CxtLock& cl)
257 {
258 return cxtLocktoSpan.find(cl) != cxtLocktoSpan.end();
259 }
261 {
262 assert(cxtLocktoSpan.find(cl) != cxtLocktoSpan.end());
263 return cxtLocktoSpan[cl];
264 }
266
267
268
270 inline bool hasOneCxtInLockSpan(const ICFGNode *I, LockSpan lspan) const
271 {
272 if(!hasCxtStmtFromInst(I))
273 return false;
275 for (LockSpan::const_iterator cts = ctsset.begin(), ects = ctsset.end(); cts != ects; cts++)
276 {
277 if(lspan.find(*cts) != lspan.end())
278 {
279 return true;
280 }
281 }
282 return false;
283 }
284
285 inline bool hasAllCxtInLockSpan(const ICFGNode *I, LockSpan lspan) const
286 {
287 if(!hasCxtStmtFromInst(I))
288 return false;
290 for (LockSpan::const_iterator cts = ctsset.begin(), ects = ctsset.end(); cts != ects; cts++)
291 {
292 if (lspan.find(*cts) == lspan.end())
293 {
294 return false;
295 }
296 }
297 return true;
298 }
299
300
304 bool isProtectedByCommonLock(const ICFGNode *i1, const ICFGNode *i2);
305 bool isProtectedByCommonCxtLock(const ICFGNode *i1, const ICFGNode *i2);
307 bool isProtectedByCommonCILock(const ICFGNode *i1, const ICFGNode *i2);
308
309 bool isInSameSpan(const ICFGNode *I1, const ICFGNode *I2);
310 bool isInSameCSSpan(const ICFGNode *i1, const ICFGNode *i2) const;
311 bool isInSameCSSpan(const CxtStmt& cxtStmt1, const CxtStmt& cxtStmt2) const;
312 bool isInSameCISpan(const ICFGNode *i1, const ICFGNode *i2) const;
313
315 {
316 return cxtLockset.size();
317 }
319 void printLocks(const CxtStmt& cts);
320
323 {
324 return tct;
325 }
326private:
328 void handleFork(const CxtStmt& cts);
329
331 void handleCall(const CxtStmt& cts);
332
334 void handleRet(const CxtStmt& cts);
335
337 void handleIntra(const CxtStmt& cts);
338
341
343 bool isAliasedLocks(const CxtLock& cl1, const CxtLock& cl2)
344 {
345 return isAliasedLocks(cl1.getStmt(), cl2.getStmt());
346 }
347 bool isAliasedLocks(const ICFGNode* i1, const ICFGNode* i2)
348 {
350 return tct->getPTA()->alias(getLockVal(i1)->getId(), getLockVal(i2)->getId());
351 }
352
354
355
356 void markCxtStmtFlag(const CxtStmt& tgr, const CxtStmt& src)
357 {
359 if(hasCxtLockfromCxtStmt(tgr)== false)
360 {
361 for(CxtLockSet::const_iterator it = srclockset.begin(), eit = srclockset.end(); it!=eit; ++it)
362 {
364 }
366 }
367 else
368 {
371 }
372 }
374 {
376 for(CxtLockSet::const_iterator it = tgrlockset.begin(), eit = tgrlockset.end(); it!=eit; ++it)
377 {
378 if(srclockset.find(*it)==srclockset.end())
379 toBeDeleted.insert(*it);
380 }
381 for(CxtLockSet::const_iterator it = toBeDeleted.begin(), eit = toBeDeleted.end(); it!=eit; ++it)
382 {
383 tgrlockset.erase(*it);
384 }
385 return !toBeDeleted.empty();
386 }
387
389 inline void clearFlagMap()
390 {
392 }
394
396
398 {
399 if (isVisitedCTPs(clp) == false)
400 {
401 visitedCTPs.insert(clp);
402 return clpList.push(clp);
403 }
404 return false;
405 }
407 {
409 return clp;
410 }
411 inline bool isVisitedCTPs(const CxtLockProc& clp) const
412 {
413 return visitedCTPs.find(clp) != visitedCTPs.end();
414 }
416
418
419 inline bool pushToCTSWorkList(const CxtStmt& cs)
420 {
421 return cxtStmtList.push(cs);
422 }
424 {
426 return clp;
427 }
429
431
432
433 void pushCxt(CallStrCxt& cxt, const CallICFGNode* call, const FunObjVar* callee);
435 bool matchCxt(CallStrCxt& cxt, const CallICFGNode* call, const FunObjVar* callee);
437 bool isContextSuffix(const CallStrCxt& lhs, const CallStrCxt& call);
439
441 inline bool isTDFork(const ICFGNode* call)
442 {
443 if(SVFUtil::isa<CallICFGNode>(call) == false)
444 return false;
445 return getTCG()->getThreadAPI()->isTDFork(SVFUtil::cast<CallICFGNode>(call));
446 }
448 inline bool isTDAcquire(const ICFGNode* call)
449 {
450 if(SVFUtil::isa<CallICFGNode>(call) == false)
451 return false;
452 return getTCG()->getThreadAPI()->isTDAcquire(SVFUtil::cast<CallICFGNode>(call));
453 }
455 inline bool isTDRelease(const ICFGNode* call)
456 {
457 if(SVFUtil::isa<CallICFGNode>(call) == false)
458 return false;
459 return getTCG()->getThreadAPI()->isTDRelease(SVFUtil::cast<CallICFGNode>(call));
460 }
462 inline bool isCallSite(const ICFGNode* inst)
463 {
464 return tct->isCallSite(inst);
465 }
467 inline bool isExtCall(const ICFGNode* inst)
468 {
469 return tct->isExtCall(inst);
470 }
472 inline const SVFVar* getLockVal(const ICFGNode* call)
473 {
474 return getTCG()->getThreadAPI()->getLockVal(call);
475 }
477 inline ThreadCallGraph* getTCG() const
478 {
479 return tct->getThreadCallGraph();
480 }
481
484
487
490
491
494
497
501
503
507
509
513
515
518
520
525
526
527public:
528 double lockTime;
532};
533
534} // End namespace SVF
535
536#endif /* INCLUDE_MTA_LockAnalysis_H_ */
#define DBOUT(TYPE, X)
LLVM debug macros, define type of your DBUG model of each pass.
Definition SVFType.h:497
#define DMTA
Definition SVFType.h:518
bool push(const Data &data)
Definition WorkList.h:165
FIFOWorkList< CxtLockProc > CxtLockProcVec
Set< CxtLock > CxtLockSet
Set< CxtStmt > LockSpan
bool removeCxtStmtToSpan(CxtStmt &cts, const CxtLock &cl)
Add context-sensitive statement.
CxtStmtWorkList cxtStmtList
context-sensitive statement worklist
bool isProtectedByCommonCILock(const ICFGNode *i1, const ICFGNode *i2)
bool isInSameCSSpan(const ICFGNode *i1, const ICFGNode *i2) const
bool isProtectedByCommonLock(const ICFGNode *i1, const ICFGNode *i2)
bool isInSameSpan(const ICFGNode *I1, const ICFGNode *I2)
void buildCandidateFuncSetforLock()
InstToInstSetMap instCILocksMap
CxtLockToSpan cxtLocktoSpan
CxtLockSet cxtLockset
Context-sensitive locks.
bool hasOneCxtInLockSpan(const ICFGNode *I, LockSpan lspan) const
Check if one instruction's context stmt is in a lock span.
void markCxtStmtFlag(const CxtStmt &tgr, const CxtStmt &src)
Mark thread flags for cxtStmt.
bool hasCxtLockfromCxtStmt(const CxtStmt &cts) const
bool isExtCall(const ICFGNode *inst)
Whether it is calling an external function.
bool isIntraLock(const ICFGNode *lock) const
Intraprocedural locks.
bool isAliasedLocks(const ICFGNode *i1, const ICFGNode *i2)
TCT * getTCT()
Get tct.
Set< CxtStmt > CxtStmtSet
bool alias(const CxtLockSet &lockset1, const CxtLockSet &lockset2)
Return true if two locksets has at least one alias lock.
Map< CxtStmt, ValDomain > CxtStmtToLockFlagMap
CxtStmt popFromCTSWorkList()
FunSet lockcandidateFuncSet
Candidate functions which relevant to locks/unlocks.
bool isInsideIntraLock(const ICFGNode *stmt) const
Return true if a statement is inside an intra-procedural lock.
const SVFVar * getLockVal(const ICFGNode *call)
Get lock value.
ThreadCallGraph * getTCG() const
ThreadCallGraph.
void handleFork(const CxtStmt &cts)
Handle fork.
InstToInstSetMap instTocondCILocksMap
bool isInsideCondIntraLock(const ICFGNode *stmt) const
Return true if a statement is inside a partial lock/unlock pair (conditional lock with unconditional ...
bool intraBackwardTraverse(const InstSet &unlockset, InstSet &backwardInsts)
CxtLockSet & getCxtLockfromCxtStmt(const CxtStmt &cts)
void pushCxt(CallStrCxt &cxt, const CallICFGNode *call, const FunObjVar *callee)
Context helper functions.
void addCondIntraLock(const ICFGNode *lockSite, const InstSet &stmts)
Add intra-procedural lock.
bool hasCxtLock(const CxtLock &cxtLock) const
Get context-sensitive lock.
Map< CxtStmt, CxtLockSet > CxtStmtToCxtLockSet
void handleIntra(const CxtStmt &cts)
Handle intra.
bool isTDRelease(const ICFGNode *call)
Whether it is a unlock site.
bool addCxtStmtToSpan(const CxtStmt &cts, const CxtLock &cl)
Add context-sensitive statement.
Map< CxtLock, LockSpan > CxtLockToSpan
Set< CxtLockProc > CxtLockProcSet
bool isTDFork(const ICFGNode *call)
Whether it is a lock site.
CxtStmtToCxtLockSet getCSTCLS()
InstSet locksites
Record all visited clps.
bool isProtectedByCommonCxtLock(const ICFGNode *i1, const ICFGNode *i2)
void analyzeIntraProcedualLock()
bool pushToCTPWorkList(const CxtLockProc &clp)
WorkList helper functions.
const InstSet & getIntraLockSet(const ICFGNode *stmt) const
void handleCall(const CxtStmt &cts)
Handle call.
Map< const ICFGNode *, CxtStmtSet > InstToCxtStmtSet
bool hasCxtStmtFromInst(const ICFGNode *inst) const
Context-sensitive statement and lock spans.
bool pushToCTSWorkList(const CxtStmt &cs)
Worklist operations.
void addIntraLock(const ICFGNode *lockSite, const InstSet &stmts)
Add intra-procedural lock.
void collectLockUnlocksites()
CxtLockProcSet visitedCTPs
CxtLockProc List.
void touchCxtStmt(CxtStmt &cts)
Touch this context statement.
Set< const ICFGNode * > InstSet
bool hasAllCxtInLockSpan(const ICFGNode *I, LockSpan lspan) const
bool isLockCandidateFun(const FunObjVar *fun) const
Return true if it is a candidate function.
LockSpan & getSpanfromCxtLock(const CxtLock &cl)
void handleCallRelation(CxtLockProc &clp, const CallGraphEdge *cgEdge, const CallICFGNode *call)
Handle call relations.
Map< CxtLock, NodeBS > CxtLockToLockSet
bool intraForwardTraverse(const ICFGNode *lock, InstSet &unlockset, InstSet &forwardInsts)
void printLocks(const CxtStmt &cts)
Print locks and spans.
bool isContextSuffix(const CallStrCxt &lhs, const CallStrCxt &call)
If lhs is a suffix of rhs, including equal.
ValDomain
semilattice Empty==>TDUnlocked==>TDLocked
CxtLockProc popFromCTPWorkList()
bool matchCxt(CallStrCxt &cxt, const CallICFGNode *call, const FunObjVar *callee)
Match context.
Map< const ICFGNode *, InstSet > InstToInstSetMap
void handleRet(const CxtStmt &cts)
Handle return.
Set< const FunObjVar * > FunSet
Map< const ICFGNode *, NodeBS > LockSiteToLockSet
const CxtStmtSet & getCxtStmtsFromInst(const ICFGNode *inst) const
Map< const ICFGNode *, CISpan > CILockToSpan
bool isInSameCISpan(const ICFGNode *i1, const ICFGNode *i2) const
bool isVisitedCTPs(const CxtLockProc &clp) const
bool isAliasedLocks(const CxtLock &cl1, const CxtLock &cl2)
Return true it a lock matches an unlock.
void clearFlagMap()
Clear flags.
FIFOWorkList< CxtStmt > CxtStmtWorkList
CxtStmtToCxtLockSet cxtStmtToCxtLockSet
InstToCxtStmtSet instToCxtStmtSet
Map a statement to all its context-sensitive statements.
bool intersect(CxtLockSet &tgrlockset, const CxtLockSet &srclockset)
TCT::InstVec InstVec
const CxtLockSet & getCxtLockfromCxtStmt(const CxtStmt &cts) const
void addCxtLock(const CallStrCxt &cxt, const ICFGNode *inst)
Context-sensitive locks.
bool intersects(const CxtLockSet &lockset1, const CxtLockSet &lockset2) const
Return true if the intersection of two locksets is not empty.
bool isCallSite(const ICFGNode *inst)
Whether it is a callsite.
bool hasSpanfromCxtLock(const CxtLock &cl)
CILockToSpan ciLocktoSpan
Used for context-insensitive intra-procedural locks.
CxtLockProcVec clpList
Following data structures are used for collecting context-sensitive locks.
bool isTDAcquire(const ICFGNode *call)
Whether it is a lock site.
virtual AliasResult alias(const SVFVar *V1, const SVFVar *V2)=0
Interface exposed to users of our pointer analysis, given Value infos.
bool isCallSite(const ICFGNode *inst)
Whether it is a callsite.
Definition TCT.h:265
PointerAnalysis * getPTA() const
Get PTA.
Definition TCT.h:195
ThreadCallGraph * getThreadCallGraph() const
Get TCG.
Definition TCT.h:190
std::vector< const ICFGNode * > InstVec
Definition TCT.h:161
bool isExtCall(const ICFGNode *inst)
Whether it is calling an external function.
Definition TCT.h:258
bool isTDFork(const CallICFGNode *inst) const
Return true if this call create a new thread.
bool isTDRelease(const CallICFGNode *inst) const
Return true if this call release a lock.
const SVFVar * getLockVal(const ICFGNode *inst) const
Return lock value.
bool isTDAcquire(const CallICFGNode *inst) const
Return true if this call acquire a lock.
ThreadAPI * getThreadAPI() const
Thread API.
std::ostream & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:52
for isBitcode
Definition BasicTypes.h:68
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74
std::vector< u32_t > CallStrCxt
unsigned u32_t
Definition GeneralType.h:47