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
81
85
89 void analyze();
93
94 void collectCxtLock();
96
99
101
102
103 inline bool isIntraLock(const ICFGNode* lock) const
104 {
105 assert(locksites.find(lock)!=locksites.end() && "not a lock site?");
106 return ciLocktoSpan.find(lock)!=ciLocktoSpan.end();
107 }
108
110 inline void addIntraLock(const ICFGNode* lockSite, const InstSet& stmts)
111 {
112 for(InstSet::const_iterator it = stmts.begin(), eit = stmts.end(); it!=eit; ++it)
113 {
114 instCILocksMap[*it].insert(lockSite);
115 ciLocktoSpan[lockSite].insert(*it);
116 }
117 }
118
120 inline void addCondIntraLock(const ICFGNode* lockSite, const InstSet& stmts)
121 {
122 for(InstSet::const_iterator it = stmts.begin(), eit = stmts.end(); it!=eit; ++it)
123 {
125 }
126 }
127
129 inline bool isInsideIntraLock(const ICFGNode* stmt) const
130 {
132 }
133
135 inline bool isInsideCondIntraLock(const ICFGNode* stmt) const
136 {
138 }
139
140 inline const InstSet& getIntraLockSet(const ICFGNode* stmt) const
141 {
142 InstToInstSetMap::const_iterator it = instCILocksMap.find(stmt);
143 assert(it!=instCILocksMap.end() && "intralock not found!");
144 return it->second;
145 }
147
149
150
151 inline void addCxtLock(const CallStrCxt& cxt,const ICFGNode* inst)
152 {
153 CxtLock cxtlock(cxt,inst);
154 cxtLockset.insert(cxtlock);
155 DBOUT(DMTA, SVFUtil::outs() << "LockAnalysis Process new lock "; cxtlock.dump());
156 }
157
159 inline bool hasCxtLock(const CxtLock& cxtLock) const
160 {
161 return cxtLockset.find(cxtLock)!=cxtLockset.end();
162 }
163
165 inline bool intersects(const CxtLockSet& lockset1,const CxtLockSet& lockset2) const
166 {
167 for(CxtLockSet::const_iterator it = lockset1.begin(), eit = lockset1.end(); it!=eit; ++it)
168 {
169 const CxtLock& lock = *it;
170 for(CxtLockSet::const_iterator lit = lockset2.begin(), elit = lockset2.end(); lit!=elit; ++lit)
171 {
172 if(lock==*lit)
173 return true;
174 }
175 }
176 return false;
177 }
179 inline bool alias(const CxtLockSet& lockset1,const CxtLockSet& lockset2)
180 {
181 for(CxtLockSet::const_iterator it = lockset1.begin(), eit = lockset1.end(); it!=eit; ++it)
182 {
183 const CxtLock& lock = *it;
184 for(CxtLockSet::const_iterator lit = lockset2.begin(), elit = lockset2.end(); lit!=elit; ++lit)
185 {
187 return true;
188 }
189 }
190 return false;
191 }
193
195 inline bool isLockCandidateFun(const SVFFunction* fun) const
196 {
197 return lockcandidateFuncSet.find(fun)!=lockcandidateFuncSet.end();
198 }
199
201
202
203 inline bool hasCxtStmtfromInst(const ICFGNode* inst) const
204 {
205 InstToCxtStmtSet::const_iterator it = instToCxtStmtSet.find(inst);
206 return (it != instToCxtStmtSet.end());
207 }
208 inline const CxtStmtSet& getCxtStmtfromInst(const ICFGNode* inst) const
209 {
210 InstToCxtStmtSet::const_iterator it = instToCxtStmtSet.find(inst);
211 assert(it != instToCxtStmtSet.end());
212 return it->second;
213 }
214 inline bool hasCxtLockfromCxtStmt(const CxtStmt& cts) const
215 {
216 CxtStmtToCxtLockSet::const_iterator it = cxtStmtToCxtLockSet.find(cts);
217 return (it != cxtStmtToCxtLockSet.end());
218 }
219 inline const CxtLockSet& getCxtLockfromCxtStmt(const CxtStmt& cts) const
220 {
221 CxtStmtToCxtLockSet::const_iterator it = cxtStmtToCxtLockSet.find(cts);
222 assert(it != cxtStmtToCxtLockSet.end());
223 return it->second;
224 }
226 {
227 CxtStmtToCxtLockSet::iterator it = cxtStmtToCxtLockSet.find(cts);
228 assert(it != cxtStmtToCxtLockSet.end());
229 return it->second;
230 }
232 inline bool addCxtStmtToSpan(const CxtStmt& cts, const CxtLock& cl)
233 {
234 cxtLocktoSpan[cl].insert(cts);
235 return cxtStmtToCxtLockSet[cts].insert(cl).second;
236 }
239 {
240 bool find = cxtStmtToCxtLockSet[cts].find(cl)!=cxtStmtToCxtLockSet[cts].end();
241 if(find)
242 {
243 cxtStmtToCxtLockSet[cts].erase(cl);
244 cxtLocktoSpan[cl].erase(cts);
245 }
246 return find;
247 }
248
255 {
257 }
258 inline bool hasSpanfromCxtLock(const CxtLock& cl)
259 {
260 return cxtLocktoSpan.find(cl) != cxtLocktoSpan.end();
261 }
263 {
264 assert(cxtLocktoSpan.find(cl) != cxtLocktoSpan.end());
265 return cxtLocktoSpan[cl];
266 }
268
269
270
272 inline bool hasOneCxtInLockSpan(const ICFGNode *I, LockSpan lspan) const
273 {
274 if(!hasCxtStmtfromInst(I))
275 return false;
277 for (LockSpan::const_iterator cts = ctsset.begin(), ects = ctsset.end(); cts != ects; cts++)
278 {
279 if(lspan.find(*cts) != lspan.end())
280 {
281 return true;
282 }
283 }
284 return false;
285 }
286
287 inline bool hasAllCxtInLockSpan(const ICFGNode *I, LockSpan lspan) const
288 {
289 if(!hasCxtStmtfromInst(I))
290 return false;
292 for (LockSpan::const_iterator cts = ctsset.begin(), ects = ctsset.end(); cts != ects; cts++)
293 {
294 if (lspan.find(*cts) == lspan.end())
295 {
296 return false;
297 }
298 }
299 return true;
300 }
301
302
306 bool isProtectedByCommonLock(const ICFGNode *i1, const ICFGNode *i2);
307 bool isProtectedByCommonCxtLock(const ICFGNode *i1, const ICFGNode *i2);
309 bool isProtectedByCommonCILock(const ICFGNode *i1, const ICFGNode *i2);
310
311 bool isInSameSpan(const ICFGNode *I1, const ICFGNode *I2);
312 bool isInSameCSSpan(const ICFGNode *i1, const ICFGNode *i2) const;
313 bool isInSameCSSpan(const CxtStmt& cxtStmt1, const CxtStmt& cxtStmt2) const;
314 bool isInSameCISpan(const ICFGNode *i1, const ICFGNode *i2) const;
315
317 {
318 return cxtLockset.size();
319 }
321 void printLocks(const CxtStmt& cts);
322
325 {
326 return tct;
327 }
328private:
330 void handleFork(const CxtStmt& cts);
331
333 void handleCall(const CxtStmt& cts);
334
336 void handleRet(const CxtStmt& cts);
337
339 void handleIntra(const CxtStmt& cts);
340
343
345 bool isAliasedLocks(const CxtLock& cl1, const CxtLock& cl2)
346 {
347 return isAliasedLocks(cl1.getStmt(), cl2.getStmt());
348 }
349 bool isAliasedLocks(const ICFGNode* i1, const ICFGNode* i2)
350 {
352 return tct->getPTA()->alias(getLockVal(i1)->getId(), getLockVal(i2)->getId());
353 }
354
356
357
358 void markCxtStmtFlag(const CxtStmt& tgr, const CxtStmt& src)
359 {
361 if(hasCxtLockfromCxtStmt(tgr)== false)
362 {
363 for(CxtLockSet::const_iterator it = srclockset.begin(), eit = srclockset.end(); it!=eit; ++it)
364 {
366 }
368 }
369 else
370 {
373 }
374 }
376 {
378 for(CxtLockSet::const_iterator it = tgrlockset.begin(), eit = tgrlockset.end(); it!=eit; ++it)
379 {
380 if(srclockset.find(*it)==srclockset.end())
381 toBeDeleted.insert(*it);
382 }
383 for(CxtLockSet::const_iterator it = toBeDeleted.begin(), eit = toBeDeleted.end(); it!=eit; ++it)
384 {
385 tgrlockset.erase(*it);
386 }
387 return !toBeDeleted.empty();
388 }
389
391 inline void clearFlagMap()
392 {
394 }
396
398
400 {
401 if (isVisitedCTPs(clp) == false)
402 {
403 visitedCTPs.insert(clp);
404 return clpList.push(clp);
405 }
406 return false;
407 }
409 {
411 return clp;
412 }
413 inline bool isVisitedCTPs(const CxtLockProc& clp) const
414 {
415 return visitedCTPs.find(clp) != visitedCTPs.end();
416 }
418
420
421 inline bool pushToCTSWorkList(const CxtStmt& cs)
422 {
423 return cxtStmtList.push(cs);
424 }
426 {
428 return clp;
429 }
431
433 void pushCxt(CallStrCxt& cxt, const CallICFGNode* call, const SVFFunction* callee);
435 bool matchCxt(CallStrCxt& cxt, const CallICFGNode* call, const SVFFunction* callee);
436
438 inline bool isTDFork(const ICFGNode* call)
439 {
440 if(SVFUtil::isa<CallICFGNode>(call) == false)
441 return false;
442 return getTCG()->getThreadAPI()->isTDFork(SVFUtil::cast<CallICFGNode>(call));
443 }
445 inline bool isTDAcquire(const ICFGNode* call)
446 {
447 if(SVFUtil::isa<CallICFGNode>(call) == false)
448 return false;
449 return getTCG()->getThreadAPI()->isTDAcquire(SVFUtil::cast<CallICFGNode>(call));
450 }
452 inline bool isTDRelease(const ICFGNode* call)
453 {
454 if(SVFUtil::isa<CallICFGNode>(call) == false)
455 return false;
456 return getTCG()->getThreadAPI()->isTDRelease(SVFUtil::cast<CallICFGNode>(call));
457 }
459 inline bool isCallSite(const ICFGNode* inst)
460 {
461 return tct->isCallSite(inst);
462 }
464 inline bool isExtCall(const ICFGNode* inst)
465 {
466 return tct->isExtCall(inst);
467 }
469 inline const SVFVar* getLockVal(const ICFGNode* call)
470 {
471 return getTCG()->getThreadAPI()->getLockVal(call);
472 }
474 inline ThreadCallGraph* getTCG() const
475 {
476 return tct->getThreadCallGraph();
477 }
478
481
484
487
488
491
494
498
500
504
506
510
512
515
517
522
523
524public:
525 double lockTime;
529};
530
531} // End namespace SVF
532
533#endif /* INCLUDE_MTA_LockAnalysis_H_ */
#define DBOUT(TYPE, X)
LLVM debug macros, define type of your DBUG model of each pass.
Definition SVFType.h:484
#define DMTA
Definition SVFType.h:505
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
Map< const ICFGNode *, LockSpan > InstToCxtStmtSet
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.
void pushCxt(CallStrCxt &cxt, const CallICFGNode *call, const SVFFunction *callee)
Push calling context.
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 addCondIntraLock(const ICFGNode *lockSite, const InstSet &stmts)
Add intra-procedural lock.
bool hasCxtLock(const CxtLock &cxtLock) const
Get context-sensitive lock.
Map< const ICFGNode *, CxtStmtSet > InstToCxtStmt
Map< CxtStmt, CxtLockSet > CxtStmtToCxtLockSet
void handleIntra(const CxtStmt &cts)
Handle intra.
bool isTDRelease(const ICFGNode *call)
Whether it is a unlock site.
const CxtStmtSet & getCxtStmtfromInst(const ICFGNode *inst) const
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.
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
Set< const SVFFunction * > FunSet
LockSpan & getSpanfromCxtLock(const CxtLock &cl)
Map< CxtLock, NodeBS > CxtLockToLockSet
bool intraForwardTraverse(const ICFGNode *lock, InstSet &unlockset, InstSet &forwardInsts)
bool matchCxt(CallStrCxt &cxt, const CallICFGNode *call, const SVFFunction *callee)
Match context.
void printLocks(const CxtStmt &cts)
Print locks and spans.
ValDomain
semilattice Empty==>TDUnlocked==>TDLocked
CxtLockProc popFromCTPWorkList()
Map< const ICFGNode *, InstSet > InstToInstSetMap
void handleRet(const CxtStmt &cts)
Handle return.
void handleCallRelation(CxtLockProc &clp, const PTACallGraphEdge *cgEdge, const CallICFGNode *call)
Handle call relations.
Map< const ICFGNode *, NodeBS > LockSiteToLockSet
Map< const ICFGNode *, CISpan > CILockToSpan
bool isInSameCISpan(const ICFGNode *i1, const ICFGNode *i2) const
bool isVisitedCTPs(const CxtLockProc &clp) const
bool hasCxtStmtfromInst(const ICFGNode *inst) const
Context-sensitive statement and lock spans.
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
bool isLockCandidateFun(const SVFFunction *fun) const
Return true if it is a candidate function.
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 SVFValue *V1, const SVFValue *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:271
PointerAnalysis * getPTA() const
Get PTA.
Definition TCT.h:201
ThreadCallGraph * getThreadCallGraph() const
Get TCG.
Definition TCT.h:196
std::vector< const ICFGNode * > InstVec
Definition TCT.h:161
bool isExtCall(const ICFGNode *inst)
Whether it is calling an external function.
Definition TCT.h:264
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:50
for isBitcode
Definition BasicTypes.h:68
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74
std::vector< u32_t > CallStrCxt
unsigned u32_t
Definition GeneralType.h:46