svf-lib 1.0.2437 → 1.0.2439
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SVF-linux-aarch64/include/MTA/LockAnalysis.h +12 -9
- package/SVF-linux-aarch64/include/MTA/MHP.h +56 -20
- package/SVF-linux-aarch64/include/MTA/MTA.h +1 -1
- package/SVF-linux-aarch64/include/MTA/TCT.h +47 -46
- package/SVF-linux-aarch64/lib/libSvfCore.so.3.2 +0 -0
- package/SVF-linux-x86_64/include/MTA/LockAnalysis.h +12 -9
- package/SVF-linux-x86_64/include/MTA/MHP.h +56 -20
- package/SVF-linux-x86_64/include/MTA/MTA.h +1 -1
- package/SVF-linux-x86_64/include/MTA/TCT.h +47 -46
- package/SVF-linux-x86_64/lib/libSvfCore.so.3.2 +0 -0
- package/package.json +1 -1
|
@@ -72,13 +72,11 @@ public:
|
|
|
72
72
|
typedef Map<CxtLock, LockSpan> CxtLockToSpan;
|
|
73
73
|
typedef Map<CxtLock, NodeBS> CxtLockToLockSet;
|
|
74
74
|
typedef Map<const ICFGNode*, NodeBS> LockSiteToLockSet;
|
|
75
|
-
typedef Map<const ICFGNode*,
|
|
75
|
+
typedef Map<const ICFGNode*, CxtStmtSet> InstToCxtStmtSet;
|
|
76
76
|
typedef Map<CxtStmt, CxtLockSet> CxtStmtToCxtLockSet;
|
|
77
77
|
typedef FIFOWorkList<CxtLockProc> CxtLockProcVec;
|
|
78
78
|
typedef Set<CxtLockProc> CxtLockProcSet;
|
|
79
79
|
|
|
80
|
-
typedef Map<const ICFGNode*, CxtStmtSet> InstToCxtStmt;
|
|
81
|
-
|
|
82
80
|
LockAnalysis(TCT* t) : tct(t), lockTime(0),numOfTotalQueries(0), numOfLockedQueries(0), lockQueriesTime(0)
|
|
83
81
|
{
|
|
84
82
|
}
|
|
@@ -200,12 +198,12 @@ public:
|
|
|
200
198
|
/// Context-sensitive statement and lock spans
|
|
201
199
|
//@{
|
|
202
200
|
/// Get LockSet and LockSpan
|
|
203
|
-
inline bool
|
|
201
|
+
inline bool hasCxtStmtFromInst(const ICFGNode* inst) const
|
|
204
202
|
{
|
|
205
203
|
InstToCxtStmtSet::const_iterator it = instToCxtStmtSet.find(inst);
|
|
206
204
|
return (it != instToCxtStmtSet.end());
|
|
207
205
|
}
|
|
208
|
-
inline const CxtStmtSet&
|
|
206
|
+
inline const CxtStmtSet& getCxtStmtsFromInst(const ICFGNode* inst) const
|
|
209
207
|
{
|
|
210
208
|
InstToCxtStmtSet::const_iterator it = instToCxtStmtSet.find(inst);
|
|
211
209
|
assert(it != instToCxtStmtSet.end());
|
|
@@ -271,9 +269,9 @@ public:
|
|
|
271
269
|
/// Check if one instruction's context stmt is in a lock span
|
|
272
270
|
inline bool hasOneCxtInLockSpan(const ICFGNode *I, LockSpan lspan) const
|
|
273
271
|
{
|
|
274
|
-
if(!
|
|
272
|
+
if(!hasCxtStmtFromInst(I))
|
|
275
273
|
return false;
|
|
276
|
-
const LockSpan ctsset =
|
|
274
|
+
const LockSpan ctsset = getCxtStmtsFromInst(I);
|
|
277
275
|
for (LockSpan::const_iterator cts = ctsset.begin(), ects = ctsset.end(); cts != ects; cts++)
|
|
278
276
|
{
|
|
279
277
|
if(lspan.find(*cts) != lspan.end())
|
|
@@ -286,9 +284,9 @@ public:
|
|
|
286
284
|
|
|
287
285
|
inline bool hasAllCxtInLockSpan(const ICFGNode *I, LockSpan lspan) const
|
|
288
286
|
{
|
|
289
|
-
if(!
|
|
287
|
+
if(!hasCxtStmtFromInst(I))
|
|
290
288
|
return false;
|
|
291
|
-
const LockSpan ctsset =
|
|
289
|
+
const LockSpan ctsset = getCxtStmtsFromInst(I);
|
|
292
290
|
for (LockSpan::const_iterator cts = ctsset.begin(), ects = ctsset.end(); cts != ects; cts++)
|
|
293
291
|
{
|
|
294
292
|
if (lspan.find(*cts) == lspan.end())
|
|
@@ -429,10 +427,15 @@ private:
|
|
|
429
427
|
}
|
|
430
428
|
//@}
|
|
431
429
|
|
|
430
|
+
/// Context helper functions
|
|
431
|
+
//@{
|
|
432
432
|
/// Push calling context
|
|
433
433
|
void pushCxt(CallStrCxt& cxt, const CallICFGNode* call, const FunObjVar* callee);
|
|
434
434
|
/// Match context
|
|
435
435
|
bool matchCxt(CallStrCxt& cxt, const CallICFGNode* call, const FunObjVar* callee);
|
|
436
|
+
/// If lhs is a suffix of rhs, including equal
|
|
437
|
+
bool isContextSuffix(const CallStrCxt& lhs, const CallStrCxt& call);
|
|
438
|
+
//@}
|
|
436
439
|
|
|
437
440
|
/// Whether it is a lock site
|
|
438
441
|
inline bool isTDFork(const ICFGNode* call)
|
|
@@ -96,11 +96,11 @@ public:
|
|
|
96
96
|
//@{
|
|
97
97
|
inline const NodeBS& getInterleavingThreads(const CxtThreadStmt& cts)
|
|
98
98
|
{
|
|
99
|
-
return
|
|
99
|
+
return threadStmtToThreadInterLeav[cts];
|
|
100
100
|
}
|
|
101
101
|
inline bool hasInterleavingThreads(const CxtThreadStmt& cts) const
|
|
102
102
|
{
|
|
103
|
-
return
|
|
103
|
+
return threadStmtToThreadInterLeav.find(cts)!=threadStmtToThreadInterLeav.end();
|
|
104
104
|
}
|
|
105
105
|
//@}
|
|
106
106
|
|
|
@@ -154,7 +154,7 @@ private:
|
|
|
154
154
|
//@{
|
|
155
155
|
inline void addInterleavingThread(const CxtThreadStmt& tgr, NodeID tid)
|
|
156
156
|
{
|
|
157
|
-
if(
|
|
157
|
+
if(threadStmtToThreadInterLeav[tgr].test_and_set(tid))
|
|
158
158
|
{
|
|
159
159
|
instToTSMap[tgr.getStmt()].insert(tgr);
|
|
160
160
|
pushToCTSWorkList(tgr);
|
|
@@ -162,7 +162,7 @@ private:
|
|
|
162
162
|
}
|
|
163
163
|
inline void addInterleavingThread(const CxtThreadStmt& tgr, const CxtThreadStmt& src)
|
|
164
164
|
{
|
|
165
|
-
bool changed =
|
|
165
|
+
bool changed = threadStmtToThreadInterLeav[tgr] |= threadStmtToThreadInterLeav[src];
|
|
166
166
|
if(changed)
|
|
167
167
|
{
|
|
168
168
|
instToTSMap[tgr.getStmt()].insert(tgr);
|
|
@@ -177,7 +177,7 @@ private:
|
|
|
177
177
|
if(isMustJoin(tgr.getTid(),joinsite))
|
|
178
178
|
joinedTids.set(*it);
|
|
179
179
|
}
|
|
180
|
-
if(
|
|
180
|
+
if(threadStmtToThreadInterLeav[tgr].intersectWithComplement(joinedTids))
|
|
181
181
|
{
|
|
182
182
|
pushToCTSWorkList(tgr);
|
|
183
183
|
}
|
|
@@ -201,16 +201,28 @@ private:
|
|
|
201
201
|
{
|
|
202
202
|
return tct->getTCTNode(curTid)->isMultiforked();
|
|
203
203
|
}
|
|
204
|
+
|
|
205
|
+
/// Context helper functions
|
|
206
|
+
//@{
|
|
204
207
|
/// Push calling context
|
|
205
208
|
inline void pushCxt(CallStrCxt& cxt, const CallICFGNode* call, const FunObjVar* callee)
|
|
206
209
|
{
|
|
210
|
+
/// handle calling context for candidate functions only
|
|
211
|
+
if(tct->isCandidateFun(call->getFun()) == false)
|
|
212
|
+
return;
|
|
207
213
|
tct->pushCxt(cxt,call,callee);
|
|
208
214
|
}
|
|
209
215
|
/// Match context
|
|
210
|
-
inline bool
|
|
216
|
+
inline bool matchAndPopCxt(CallStrCxt& cxt, const CallICFGNode* call, const FunObjVar* callee)
|
|
217
|
+
{
|
|
218
|
+
return tct->matchAndPopCxt(cxt,call,callee);
|
|
219
|
+
}
|
|
220
|
+
/// If lhs is a suffix of rhs, including equal
|
|
221
|
+
inline bool isContextSuffix(const CallStrCxt& lhs, const CallStrCxt call)
|
|
211
222
|
{
|
|
212
|
-
return tct->
|
|
223
|
+
return tct->isContextSuffix(lhs,call);
|
|
213
224
|
}
|
|
225
|
+
//@}
|
|
214
226
|
|
|
215
227
|
/// WorkList helper functions
|
|
216
228
|
//@{
|
|
@@ -253,7 +265,7 @@ private:
|
|
|
253
265
|
TCT* tct; ///< TCT
|
|
254
266
|
ForkJoinAnalysis* fja; ///< ForJoin Analysis
|
|
255
267
|
CxtThreadStmtWorkList cxtStmtList; ///< CxtThreadStmt worklist
|
|
256
|
-
ThreadStmtToThreadInterleav
|
|
268
|
+
ThreadStmtToThreadInterleav threadStmtToThreadInterLeav; /// Map a statement to its thread interleavings
|
|
257
269
|
InstToThreadStmtSetMap instToTSMap; ///< Map an instruction to its ThreadStmtSet
|
|
258
270
|
FuncPairToBool nonCandidateFuncMHPRelMap;
|
|
259
271
|
|
|
@@ -290,6 +302,10 @@ public:
|
|
|
290
302
|
typedef Map<CxtStmt, LoopBBs> CxtStmtToLoopMap;
|
|
291
303
|
typedef FIFOWorkList<CxtStmt> CxtStmtWorkList;
|
|
292
304
|
|
|
305
|
+
typedef Set<CxtStmt> CxtStmtSet;
|
|
306
|
+
typedef Map<const ICFGNode*, CxtStmtSet> InstToCxtStmt;
|
|
307
|
+
|
|
308
|
+
|
|
293
309
|
ForkJoinAnalysis(TCT* t) : tct(t)
|
|
294
310
|
{
|
|
295
311
|
collectSCEVInfo();
|
|
@@ -337,15 +353,6 @@ public:
|
|
|
337
353
|
return full && !partial;
|
|
338
354
|
}
|
|
339
355
|
|
|
340
|
-
/// Get exit instruction of the start routine function of tid's parent thread
|
|
341
|
-
inline const ICFGNode* getExitInstOfParentRoutineFun(NodeID tid) const
|
|
342
|
-
{
|
|
343
|
-
NodeID parentTid = tct->getParentThread(tid);
|
|
344
|
-
const CxtThread& parentct = tct->getTCTNode(parentTid)->getCxtThread();
|
|
345
|
-
const FunObjVar* parentRoutine = tct->getStartRoutineOfCxtThread(parentct);
|
|
346
|
-
return parentRoutine->getExitBB()->back();
|
|
347
|
-
}
|
|
348
|
-
|
|
349
356
|
/// Get loop for join site
|
|
350
357
|
inline LoopBBs& getJoinLoop(const CallICFGNode* inst)
|
|
351
358
|
{
|
|
@@ -381,7 +388,7 @@ private:
|
|
|
381
388
|
/// Whether it is a matched fork join pair
|
|
382
389
|
bool isAliasedForkJoin(const CallICFGNode* forkSite, const CallICFGNode* joinSite)
|
|
383
390
|
{
|
|
384
|
-
return tct->getPTA()->alias(getForkedThread(forkSite)->getId(), getJoinedThread(joinSite)->getId())
|
|
391
|
+
return tct->getPTA()->alias(getForkedThread(forkSite)->getId(), getJoinedThread(joinSite)->getId());
|
|
385
392
|
}
|
|
386
393
|
/// Mark thread flags for cxtStmt
|
|
387
394
|
//@{
|
|
@@ -403,7 +410,11 @@ private:
|
|
|
403
410
|
ValDomain flag_tgr = getMarkedFlag(tgr);
|
|
404
411
|
cxtStmtToAliveFlagMap[tgr] = flag;
|
|
405
412
|
if(flag_tgr!=getMarkedFlag(tgr))
|
|
413
|
+
{
|
|
414
|
+
instToCxtStmt[tgr.getStmt()].insert(tgr);
|
|
406
415
|
pushToCTSWorkList(tgr);
|
|
416
|
+
}
|
|
417
|
+
|
|
407
418
|
}
|
|
408
419
|
/// Transfer function for marking context-sensitive statement
|
|
409
420
|
void markCxtStmtFlag(const CxtStmt& tgr, const CxtStmt& src)
|
|
@@ -425,6 +436,7 @@ private:
|
|
|
425
436
|
}
|
|
426
437
|
if(flag_tgr!=getMarkedFlag(tgr))
|
|
427
438
|
{
|
|
439
|
+
instToCxtStmt[tgr.getStmt()].insert(tgr);
|
|
428
440
|
pushToCTSWorkList(tgr);
|
|
429
441
|
}
|
|
430
442
|
}
|
|
@@ -449,16 +461,27 @@ private:
|
|
|
449
461
|
}
|
|
450
462
|
//@}
|
|
451
463
|
|
|
464
|
+
/// Context helper functions
|
|
465
|
+
//@{
|
|
452
466
|
/// Push calling context
|
|
453
467
|
inline void pushCxt(CallStrCxt& cxt, const CallICFGNode* call, const FunObjVar* callee)
|
|
454
468
|
{
|
|
469
|
+
/// handle calling context for candidate functions only
|
|
470
|
+
if(tct->isCandidateFun(call->getFun()) == false)
|
|
471
|
+
return;
|
|
455
472
|
tct->pushCxt(cxt,call,callee);
|
|
456
473
|
}
|
|
457
474
|
/// Match context
|
|
458
|
-
inline bool
|
|
475
|
+
inline bool matchAndPopCxt(CallStrCxt& cxt, const CallICFGNode* call, const FunObjVar* callee)
|
|
476
|
+
{
|
|
477
|
+
return tct->matchAndPopCxt(cxt,call,callee);
|
|
478
|
+
}
|
|
479
|
+
/// If lhs is a suffix of rhs, including equal
|
|
480
|
+
inline bool isContextSuffix(const CallStrCxt& lhs, const CallStrCxt call)
|
|
459
481
|
{
|
|
460
|
-
return tct->
|
|
482
|
+
return tct->isContextSuffix(lhs,call);
|
|
461
483
|
}
|
|
484
|
+
//@}
|
|
462
485
|
|
|
463
486
|
/// Whether it is a fork site
|
|
464
487
|
inline bool isTDFork(const ICFGNode* call)
|
|
@@ -524,6 +547,18 @@ private:
|
|
|
524
547
|
}
|
|
525
548
|
//@}
|
|
526
549
|
|
|
550
|
+
/// Get CxtStmtSet for an instruction
|
|
551
|
+
inline const CxtStmtSet& getCxtStmtsFromInst(const ICFGNode* inst) const
|
|
552
|
+
{
|
|
553
|
+
InstToCxtStmt::const_iterator it = instToCxtStmt.find(inst);
|
|
554
|
+
assert(it!=instToCxtStmt.end() && "no CxtStmt for the instruction?");
|
|
555
|
+
return it->second;
|
|
556
|
+
}
|
|
557
|
+
inline bool hasCxtStmtsFromInst(const ICFGNode* inst) const
|
|
558
|
+
{
|
|
559
|
+
return instToCxtStmt.find(inst)!=instToCxtStmt.end();
|
|
560
|
+
}
|
|
561
|
+
|
|
527
562
|
/// Add inloop join
|
|
528
563
|
inline void addSymmetricLoopJoin(const CxtStmt& cs, LoopBBs& lp)
|
|
529
564
|
{
|
|
@@ -539,6 +574,7 @@ private:
|
|
|
539
574
|
ThreadPairSet HPPair; ///< threads happen-in-parallel
|
|
540
575
|
ThreadPairSet fullJoin; ///< t1 fully joins t2 along all program path
|
|
541
576
|
ThreadPairSet partialJoin; ///< t1 partially joins t2 along some program path(s)
|
|
577
|
+
InstToCxtStmt instToCxtStmt; ///<Map a statement to all its context-sensitive statements
|
|
542
578
|
};
|
|
543
579
|
|
|
544
580
|
} // End namespace SVF
|
|
@@ -66,7 +66,7 @@ public:
|
|
|
66
66
|
/// We start the pass here
|
|
67
67
|
virtual bool runOnModule(SVFIR* module);
|
|
68
68
|
/// Compute MHP
|
|
69
|
-
virtual MHP* computeMHP();
|
|
69
|
+
virtual MHP* computeMHP(TCT* tct);
|
|
70
70
|
/// Compute locksets
|
|
71
71
|
virtual LockAnalysis* computeLocksets(TCT* tct);
|
|
72
72
|
/// Perform detection
|
|
@@ -97,7 +97,7 @@ public:
|
|
|
97
97
|
SVFUtil::outs() << "---\ntid: " << this->getId() << " inloop:" << ctx.isInloop() << " incycle:" << ctx.isIncycle() << " multiforked:"<< isMultiforked();
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
/// Get
|
|
100
|
+
/// Get thread creation context, <fork site, call string context>
|
|
101
101
|
inline const CxtThread& getCxtThread() const
|
|
102
102
|
{
|
|
103
103
|
return ctx;
|
|
@@ -142,7 +142,7 @@ public:
|
|
|
142
142
|
|
|
143
143
|
|
|
144
144
|
private:
|
|
145
|
-
const CxtThread ctx;
|
|
145
|
+
const CxtThread ctx; /// Thread creation context, <fork site, call string context>
|
|
146
146
|
bool multiforked;
|
|
147
147
|
};
|
|
148
148
|
|
|
@@ -162,7 +162,8 @@ public:
|
|
|
162
162
|
typedef Set<const ICFGNode*> InstSet;
|
|
163
163
|
typedef Set<const CallGraphNode*> PTACGNodeSet;
|
|
164
164
|
typedef Map<CxtThread,TCTNode*> CxtThreadToNodeMap;
|
|
165
|
-
typedef
|
|
165
|
+
typedef Set<std::pair<NodeID, CallStrCxt>> CallStrCxtSet;
|
|
166
|
+
typedef Map<CxtThread,CallStrCxtSet> CxtThreadToForkCxtSet;
|
|
166
167
|
typedef Map<CxtThread,const FunObjVar*> CxtThreadToFun;
|
|
167
168
|
typedef Map<const ICFGNode*, LoopBBs> InstToLoopMap;
|
|
168
169
|
typedef FIFOWorkList<CxtThreadProc> CxtThreadProcVec;
|
|
@@ -172,7 +173,8 @@ public:
|
|
|
172
173
|
/// Constructor
|
|
173
174
|
TCT(PointerAnalysis* p) :pta(p),TCTNodeNum(0),TCTEdgeNum(0),MaxCxtSize(0)
|
|
174
175
|
{
|
|
175
|
-
tcg = SVFUtil::
|
|
176
|
+
tcg = SVFUtil::dyn_cast<ThreadCallGraph>(pta->getCallGraph());
|
|
177
|
+
assert(tcg != nullptr && "TCT::TCT: call graph is not a ThreadCallGraph!");
|
|
176
178
|
tcg->updateCallGraph(pta);
|
|
177
179
|
//tcg->updateJoinEdge(pta);
|
|
178
180
|
tcgSCC = pta->getCallGraphSCC();
|
|
@@ -182,9 +184,7 @@ public:
|
|
|
182
184
|
|
|
183
185
|
/// Destructor
|
|
184
186
|
virtual ~TCT()
|
|
185
|
-
{
|
|
186
|
-
destroy();
|
|
187
|
-
}
|
|
187
|
+
{ }
|
|
188
188
|
|
|
189
189
|
/// Get TCG
|
|
190
190
|
inline ThreadCallGraph* getThreadCallGraph() const
|
|
@@ -310,24 +310,29 @@ public:
|
|
|
310
310
|
const TCTNode* node = getTCTNode(tid);
|
|
311
311
|
return node->getInEdges().size()==1;
|
|
312
312
|
}
|
|
313
|
-
/// Get parent
|
|
314
|
-
inline
|
|
313
|
+
/// Get parent threads
|
|
314
|
+
inline NodeBS getParentThreads(NodeID tid) const
|
|
315
315
|
{
|
|
316
|
+
NodeBS parentTds;
|
|
316
317
|
const TCTNode* node = getTCTNode(tid);
|
|
317
|
-
assert(node->getInEdges().size()
|
|
318
|
-
|
|
319
|
-
const TCTEdge* edge
|
|
320
|
-
|
|
318
|
+
assert(node->getInEdges().size()>=1 && "does not have a parent thread");
|
|
319
|
+
|
|
320
|
+
for (const TCTEdge* edge : node->getInEdges())
|
|
321
|
+
{
|
|
322
|
+
parentTds.set(edge->getSrcID());
|
|
323
|
+
}
|
|
324
|
+
return parentTds;
|
|
321
325
|
}
|
|
322
326
|
/// Get all ancestor threads
|
|
323
|
-
const NodeBS
|
|
327
|
+
const NodeBS getAncestorThreads(NodeID tid) const
|
|
324
328
|
{
|
|
325
329
|
NodeBS tds;
|
|
326
330
|
if(hasParentThread(tid) == false)
|
|
327
331
|
return tds;
|
|
328
332
|
|
|
329
333
|
FIFOWorkList<NodeID> worklist;
|
|
330
|
-
|
|
334
|
+
for(NodeID parentTid : getParentThreads(tid))
|
|
335
|
+
worklist.push(parentTid);
|
|
331
336
|
|
|
332
337
|
while(!worklist.empty())
|
|
333
338
|
{
|
|
@@ -335,7 +340,8 @@ public:
|
|
|
335
340
|
if(tds.test_and_set(t))
|
|
336
341
|
{
|
|
337
342
|
if(hasParentThread(t))
|
|
338
|
-
|
|
343
|
+
for(NodeID parentTid : getParentThreads(t))
|
|
344
|
+
worklist.push(parentTid);
|
|
339
345
|
}
|
|
340
346
|
}
|
|
341
347
|
return tds;
|
|
@@ -346,24 +352,26 @@ public:
|
|
|
346
352
|
NodeBS tds;
|
|
347
353
|
if(hasParentThread(tid) == false)
|
|
348
354
|
return tds;
|
|
349
|
-
|
|
350
|
-
const TCTNode* node = getTCTNode(getParentThread(tid));
|
|
351
|
-
for(ThreadCreateEdgeSet::const_iterator it = getChildrenBegin(node), eit = getChildrenEnd(node); it!=eit; ++it)
|
|
355
|
+
for (NodeID parentTid : getParentThreads(tid))
|
|
352
356
|
{
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
357
|
+
const TCTNode* parentNode = getTCTNode(parentTid);
|
|
358
|
+
for(ThreadCreateEdgeSet::const_iterator it = getChildrenBegin(parentNode),
|
|
359
|
+
eit = getChildrenEnd(parentNode); it!=eit; ++it)
|
|
360
|
+
{
|
|
361
|
+
NodeID child = (*it)->getDstNode()->getId();
|
|
362
|
+
if(child!=tid)
|
|
363
|
+
tds.set(child);
|
|
364
|
+
}
|
|
356
365
|
}
|
|
357
|
-
|
|
358
366
|
return tds;
|
|
359
367
|
}
|
|
360
368
|
//@}
|
|
361
369
|
|
|
362
|
-
/// get the
|
|
363
|
-
const
|
|
370
|
+
/// get the contexts of a thread at its spawning sites (fork sites)
|
|
371
|
+
const CallStrCxtSet& getCxtOfCxtThread(const CxtThread& ct) const
|
|
364
372
|
{
|
|
365
|
-
|
|
366
|
-
assert(it!=
|
|
373
|
+
CxtThreadToForkCxtSet::const_iterator it = ctToForkCxtsMap.find(ct);
|
|
374
|
+
assert(it!=ctToForkCxtsMap.end() && "Cxt Thread not found!!");
|
|
367
375
|
return it->second;
|
|
368
376
|
}
|
|
369
377
|
|
|
@@ -407,17 +415,16 @@ public:
|
|
|
407
415
|
/// Get loop for fork/join site
|
|
408
416
|
const LoopBBs& getLoop(const SVFBasicBlock* bb);
|
|
409
417
|
|
|
418
|
+
/// Context helper functions
|
|
419
|
+
//@{
|
|
410
420
|
/// Push calling context
|
|
411
421
|
void pushCxt(CallStrCxt& cxt, const CallICFGNode* call, const FunObjVar* callee);
|
|
412
422
|
/// Match context
|
|
413
|
-
bool
|
|
423
|
+
bool matchAndPopCxt(CallStrCxt& cxt, const CallICFGNode* call, const FunObjVar* callee);
|
|
424
|
+
/// If lhs is a suffix of rhs, including equal
|
|
425
|
+
bool isContextSuffix(const CallStrCxt& lhs, const CallStrCxt& call);
|
|
426
|
+
//@}
|
|
414
427
|
|
|
415
|
-
inline void pushCxt(CallStrCxt& cxt, CallSiteID csId)
|
|
416
|
-
{
|
|
417
|
-
cxt.push_back(csId);
|
|
418
|
-
if (cxt.size() > MaxCxtSize)
|
|
419
|
-
MaxCxtSize = cxt.size();
|
|
420
|
-
}
|
|
421
428
|
/// Whether a join site is in recursion
|
|
422
429
|
inline bool isJoinSiteInRecursion(const CallICFGNode* join) const
|
|
423
430
|
{
|
|
@@ -504,7 +511,7 @@ private:
|
|
|
504
511
|
|
|
505
512
|
/// Get or create a tct node based on CxtThread
|
|
506
513
|
//@{
|
|
507
|
-
inline TCTNode* getOrCreateTCTNode(const CallStrCxt& cxt, const ICFGNode* fork,const
|
|
514
|
+
inline TCTNode* getOrCreateTCTNode(const CallStrCxt& cxt, const ICFGNode* fork, const CxtThreadProc& forkSiteCtp, const FunObjVar* routine)
|
|
508
515
|
{
|
|
509
516
|
CxtThread ct(cxt,fork);
|
|
510
517
|
CxtThreadToNodeMap::const_iterator it = ctpToNodeMap.find(ct);
|
|
@@ -513,7 +520,7 @@ private:
|
|
|
513
520
|
return it->second;
|
|
514
521
|
}
|
|
515
522
|
|
|
516
|
-
addCxtOfCxtThread(
|
|
523
|
+
addCxtOfCxtThread(forkSiteCtp.getTid(), forkSiteCtp.getContext(), ct);
|
|
517
524
|
addStartRoutineOfCxtThread(routine,ct);
|
|
518
525
|
|
|
519
526
|
setMultiForkedAttrs(ct);
|
|
@@ -540,10 +547,11 @@ private:
|
|
|
540
547
|
}
|
|
541
548
|
|
|
542
549
|
/// Add context for a thread at its spawning site (fork site)
|
|
543
|
-
void addCxtOfCxtThread(const CallStrCxt& cxt, const CxtThread& ct)
|
|
550
|
+
void addCxtOfCxtThread(NodeID pTid, const CallStrCxt& cxt, const CxtThread& ct)
|
|
544
551
|
{
|
|
545
|
-
|
|
552
|
+
ctToForkCxtsMap[ct].insert(std::make_pair(pTid, cxt));
|
|
546
553
|
}
|
|
554
|
+
|
|
547
555
|
/// Add start routine function of a cxt thread
|
|
548
556
|
void addStartRoutineOfCxtThread(const FunObjVar* fun, const CxtThread& ct)
|
|
549
557
|
{
|
|
@@ -571,13 +579,6 @@ private:
|
|
|
571
579
|
return visitedCTPs.find(ctp)!=visitedCTPs.end();
|
|
572
580
|
}
|
|
573
581
|
//@}
|
|
574
|
-
/// Clean up memory
|
|
575
|
-
inline void destroy()
|
|
576
|
-
{
|
|
577
|
-
if(tcgSCC)
|
|
578
|
-
delete tcgSCC;
|
|
579
|
-
tcgSCC=nullptr;
|
|
580
|
-
}
|
|
581
582
|
|
|
582
583
|
FunSet entryFuncSet; /// Procedures that are neither called by other functions nor extern functions
|
|
583
584
|
FunSet candidateFuncSet; /// Procedures we care about during call graph traversing when creating TCT
|
|
@@ -585,7 +586,7 @@ private:
|
|
|
585
586
|
CxtThreadProcVec ctpList; /// CxtThreadProc List
|
|
586
587
|
CxtThreadProcSet visitedCTPs; /// Record all visited ctps
|
|
587
588
|
CxtThreadToNodeMap ctpToNodeMap; /// Map a ctp to its graph node
|
|
588
|
-
|
|
589
|
+
CxtThreadToForkCxtSet ctToForkCxtsMap; /// Map a CxtThread to the context at its spawning site (fork site).
|
|
589
590
|
CxtThreadToFun ctToRoutineFunMap; /// Map a CxtThread to its start routine function.
|
|
590
591
|
InstToLoopMap joinSiteToLoopMap; ///< map an inloop join to its loop class
|
|
591
592
|
Set<const ICFGNode*> inRecurJoinSites; ///< Fork or Join sites in recursions
|
|
Binary file
|
|
@@ -72,13 +72,11 @@ public:
|
|
|
72
72
|
typedef Map<CxtLock, LockSpan> CxtLockToSpan;
|
|
73
73
|
typedef Map<CxtLock, NodeBS> CxtLockToLockSet;
|
|
74
74
|
typedef Map<const ICFGNode*, NodeBS> LockSiteToLockSet;
|
|
75
|
-
typedef Map<const ICFGNode*,
|
|
75
|
+
typedef Map<const ICFGNode*, CxtStmtSet> InstToCxtStmtSet;
|
|
76
76
|
typedef Map<CxtStmt, CxtLockSet> CxtStmtToCxtLockSet;
|
|
77
77
|
typedef FIFOWorkList<CxtLockProc> CxtLockProcVec;
|
|
78
78
|
typedef Set<CxtLockProc> CxtLockProcSet;
|
|
79
79
|
|
|
80
|
-
typedef Map<const ICFGNode*, CxtStmtSet> InstToCxtStmt;
|
|
81
|
-
|
|
82
80
|
LockAnalysis(TCT* t) : tct(t), lockTime(0),numOfTotalQueries(0), numOfLockedQueries(0), lockQueriesTime(0)
|
|
83
81
|
{
|
|
84
82
|
}
|
|
@@ -200,12 +198,12 @@ public:
|
|
|
200
198
|
/// Context-sensitive statement and lock spans
|
|
201
199
|
//@{
|
|
202
200
|
/// Get LockSet and LockSpan
|
|
203
|
-
inline bool
|
|
201
|
+
inline bool hasCxtStmtFromInst(const ICFGNode* inst) const
|
|
204
202
|
{
|
|
205
203
|
InstToCxtStmtSet::const_iterator it = instToCxtStmtSet.find(inst);
|
|
206
204
|
return (it != instToCxtStmtSet.end());
|
|
207
205
|
}
|
|
208
|
-
inline const CxtStmtSet&
|
|
206
|
+
inline const CxtStmtSet& getCxtStmtsFromInst(const ICFGNode* inst) const
|
|
209
207
|
{
|
|
210
208
|
InstToCxtStmtSet::const_iterator it = instToCxtStmtSet.find(inst);
|
|
211
209
|
assert(it != instToCxtStmtSet.end());
|
|
@@ -271,9 +269,9 @@ public:
|
|
|
271
269
|
/// Check if one instruction's context stmt is in a lock span
|
|
272
270
|
inline bool hasOneCxtInLockSpan(const ICFGNode *I, LockSpan lspan) const
|
|
273
271
|
{
|
|
274
|
-
if(!
|
|
272
|
+
if(!hasCxtStmtFromInst(I))
|
|
275
273
|
return false;
|
|
276
|
-
const LockSpan ctsset =
|
|
274
|
+
const LockSpan ctsset = getCxtStmtsFromInst(I);
|
|
277
275
|
for (LockSpan::const_iterator cts = ctsset.begin(), ects = ctsset.end(); cts != ects; cts++)
|
|
278
276
|
{
|
|
279
277
|
if(lspan.find(*cts) != lspan.end())
|
|
@@ -286,9 +284,9 @@ public:
|
|
|
286
284
|
|
|
287
285
|
inline bool hasAllCxtInLockSpan(const ICFGNode *I, LockSpan lspan) const
|
|
288
286
|
{
|
|
289
|
-
if(!
|
|
287
|
+
if(!hasCxtStmtFromInst(I))
|
|
290
288
|
return false;
|
|
291
|
-
const LockSpan ctsset =
|
|
289
|
+
const LockSpan ctsset = getCxtStmtsFromInst(I);
|
|
292
290
|
for (LockSpan::const_iterator cts = ctsset.begin(), ects = ctsset.end(); cts != ects; cts++)
|
|
293
291
|
{
|
|
294
292
|
if (lspan.find(*cts) == lspan.end())
|
|
@@ -429,10 +427,15 @@ private:
|
|
|
429
427
|
}
|
|
430
428
|
//@}
|
|
431
429
|
|
|
430
|
+
/// Context helper functions
|
|
431
|
+
//@{
|
|
432
432
|
/// Push calling context
|
|
433
433
|
void pushCxt(CallStrCxt& cxt, const CallICFGNode* call, const FunObjVar* callee);
|
|
434
434
|
/// Match context
|
|
435
435
|
bool matchCxt(CallStrCxt& cxt, const CallICFGNode* call, const FunObjVar* callee);
|
|
436
|
+
/// If lhs is a suffix of rhs, including equal
|
|
437
|
+
bool isContextSuffix(const CallStrCxt& lhs, const CallStrCxt& call);
|
|
438
|
+
//@}
|
|
436
439
|
|
|
437
440
|
/// Whether it is a lock site
|
|
438
441
|
inline bool isTDFork(const ICFGNode* call)
|
|
@@ -96,11 +96,11 @@ public:
|
|
|
96
96
|
//@{
|
|
97
97
|
inline const NodeBS& getInterleavingThreads(const CxtThreadStmt& cts)
|
|
98
98
|
{
|
|
99
|
-
return
|
|
99
|
+
return threadStmtToThreadInterLeav[cts];
|
|
100
100
|
}
|
|
101
101
|
inline bool hasInterleavingThreads(const CxtThreadStmt& cts) const
|
|
102
102
|
{
|
|
103
|
-
return
|
|
103
|
+
return threadStmtToThreadInterLeav.find(cts)!=threadStmtToThreadInterLeav.end();
|
|
104
104
|
}
|
|
105
105
|
//@}
|
|
106
106
|
|
|
@@ -154,7 +154,7 @@ private:
|
|
|
154
154
|
//@{
|
|
155
155
|
inline void addInterleavingThread(const CxtThreadStmt& tgr, NodeID tid)
|
|
156
156
|
{
|
|
157
|
-
if(
|
|
157
|
+
if(threadStmtToThreadInterLeav[tgr].test_and_set(tid))
|
|
158
158
|
{
|
|
159
159
|
instToTSMap[tgr.getStmt()].insert(tgr);
|
|
160
160
|
pushToCTSWorkList(tgr);
|
|
@@ -162,7 +162,7 @@ private:
|
|
|
162
162
|
}
|
|
163
163
|
inline void addInterleavingThread(const CxtThreadStmt& tgr, const CxtThreadStmt& src)
|
|
164
164
|
{
|
|
165
|
-
bool changed =
|
|
165
|
+
bool changed = threadStmtToThreadInterLeav[tgr] |= threadStmtToThreadInterLeav[src];
|
|
166
166
|
if(changed)
|
|
167
167
|
{
|
|
168
168
|
instToTSMap[tgr.getStmt()].insert(tgr);
|
|
@@ -177,7 +177,7 @@ private:
|
|
|
177
177
|
if(isMustJoin(tgr.getTid(),joinsite))
|
|
178
178
|
joinedTids.set(*it);
|
|
179
179
|
}
|
|
180
|
-
if(
|
|
180
|
+
if(threadStmtToThreadInterLeav[tgr].intersectWithComplement(joinedTids))
|
|
181
181
|
{
|
|
182
182
|
pushToCTSWorkList(tgr);
|
|
183
183
|
}
|
|
@@ -201,16 +201,28 @@ private:
|
|
|
201
201
|
{
|
|
202
202
|
return tct->getTCTNode(curTid)->isMultiforked();
|
|
203
203
|
}
|
|
204
|
+
|
|
205
|
+
/// Context helper functions
|
|
206
|
+
//@{
|
|
204
207
|
/// Push calling context
|
|
205
208
|
inline void pushCxt(CallStrCxt& cxt, const CallICFGNode* call, const FunObjVar* callee)
|
|
206
209
|
{
|
|
210
|
+
/// handle calling context for candidate functions only
|
|
211
|
+
if(tct->isCandidateFun(call->getFun()) == false)
|
|
212
|
+
return;
|
|
207
213
|
tct->pushCxt(cxt,call,callee);
|
|
208
214
|
}
|
|
209
215
|
/// Match context
|
|
210
|
-
inline bool
|
|
216
|
+
inline bool matchAndPopCxt(CallStrCxt& cxt, const CallICFGNode* call, const FunObjVar* callee)
|
|
217
|
+
{
|
|
218
|
+
return tct->matchAndPopCxt(cxt,call,callee);
|
|
219
|
+
}
|
|
220
|
+
/// If lhs is a suffix of rhs, including equal
|
|
221
|
+
inline bool isContextSuffix(const CallStrCxt& lhs, const CallStrCxt call)
|
|
211
222
|
{
|
|
212
|
-
return tct->
|
|
223
|
+
return tct->isContextSuffix(lhs,call);
|
|
213
224
|
}
|
|
225
|
+
//@}
|
|
214
226
|
|
|
215
227
|
/// WorkList helper functions
|
|
216
228
|
//@{
|
|
@@ -253,7 +265,7 @@ private:
|
|
|
253
265
|
TCT* tct; ///< TCT
|
|
254
266
|
ForkJoinAnalysis* fja; ///< ForJoin Analysis
|
|
255
267
|
CxtThreadStmtWorkList cxtStmtList; ///< CxtThreadStmt worklist
|
|
256
|
-
ThreadStmtToThreadInterleav
|
|
268
|
+
ThreadStmtToThreadInterleav threadStmtToThreadInterLeav; /// Map a statement to its thread interleavings
|
|
257
269
|
InstToThreadStmtSetMap instToTSMap; ///< Map an instruction to its ThreadStmtSet
|
|
258
270
|
FuncPairToBool nonCandidateFuncMHPRelMap;
|
|
259
271
|
|
|
@@ -290,6 +302,10 @@ public:
|
|
|
290
302
|
typedef Map<CxtStmt, LoopBBs> CxtStmtToLoopMap;
|
|
291
303
|
typedef FIFOWorkList<CxtStmt> CxtStmtWorkList;
|
|
292
304
|
|
|
305
|
+
typedef Set<CxtStmt> CxtStmtSet;
|
|
306
|
+
typedef Map<const ICFGNode*, CxtStmtSet> InstToCxtStmt;
|
|
307
|
+
|
|
308
|
+
|
|
293
309
|
ForkJoinAnalysis(TCT* t) : tct(t)
|
|
294
310
|
{
|
|
295
311
|
collectSCEVInfo();
|
|
@@ -337,15 +353,6 @@ public:
|
|
|
337
353
|
return full && !partial;
|
|
338
354
|
}
|
|
339
355
|
|
|
340
|
-
/// Get exit instruction of the start routine function of tid's parent thread
|
|
341
|
-
inline const ICFGNode* getExitInstOfParentRoutineFun(NodeID tid) const
|
|
342
|
-
{
|
|
343
|
-
NodeID parentTid = tct->getParentThread(tid);
|
|
344
|
-
const CxtThread& parentct = tct->getTCTNode(parentTid)->getCxtThread();
|
|
345
|
-
const FunObjVar* parentRoutine = tct->getStartRoutineOfCxtThread(parentct);
|
|
346
|
-
return parentRoutine->getExitBB()->back();
|
|
347
|
-
}
|
|
348
|
-
|
|
349
356
|
/// Get loop for join site
|
|
350
357
|
inline LoopBBs& getJoinLoop(const CallICFGNode* inst)
|
|
351
358
|
{
|
|
@@ -381,7 +388,7 @@ private:
|
|
|
381
388
|
/// Whether it is a matched fork join pair
|
|
382
389
|
bool isAliasedForkJoin(const CallICFGNode* forkSite, const CallICFGNode* joinSite)
|
|
383
390
|
{
|
|
384
|
-
return tct->getPTA()->alias(getForkedThread(forkSite)->getId(), getJoinedThread(joinSite)->getId())
|
|
391
|
+
return tct->getPTA()->alias(getForkedThread(forkSite)->getId(), getJoinedThread(joinSite)->getId());
|
|
385
392
|
}
|
|
386
393
|
/// Mark thread flags for cxtStmt
|
|
387
394
|
//@{
|
|
@@ -403,7 +410,11 @@ private:
|
|
|
403
410
|
ValDomain flag_tgr = getMarkedFlag(tgr);
|
|
404
411
|
cxtStmtToAliveFlagMap[tgr] = flag;
|
|
405
412
|
if(flag_tgr!=getMarkedFlag(tgr))
|
|
413
|
+
{
|
|
414
|
+
instToCxtStmt[tgr.getStmt()].insert(tgr);
|
|
406
415
|
pushToCTSWorkList(tgr);
|
|
416
|
+
}
|
|
417
|
+
|
|
407
418
|
}
|
|
408
419
|
/// Transfer function for marking context-sensitive statement
|
|
409
420
|
void markCxtStmtFlag(const CxtStmt& tgr, const CxtStmt& src)
|
|
@@ -425,6 +436,7 @@ private:
|
|
|
425
436
|
}
|
|
426
437
|
if(flag_tgr!=getMarkedFlag(tgr))
|
|
427
438
|
{
|
|
439
|
+
instToCxtStmt[tgr.getStmt()].insert(tgr);
|
|
428
440
|
pushToCTSWorkList(tgr);
|
|
429
441
|
}
|
|
430
442
|
}
|
|
@@ -449,16 +461,27 @@ private:
|
|
|
449
461
|
}
|
|
450
462
|
//@}
|
|
451
463
|
|
|
464
|
+
/// Context helper functions
|
|
465
|
+
//@{
|
|
452
466
|
/// Push calling context
|
|
453
467
|
inline void pushCxt(CallStrCxt& cxt, const CallICFGNode* call, const FunObjVar* callee)
|
|
454
468
|
{
|
|
469
|
+
/// handle calling context for candidate functions only
|
|
470
|
+
if(tct->isCandidateFun(call->getFun()) == false)
|
|
471
|
+
return;
|
|
455
472
|
tct->pushCxt(cxt,call,callee);
|
|
456
473
|
}
|
|
457
474
|
/// Match context
|
|
458
|
-
inline bool
|
|
475
|
+
inline bool matchAndPopCxt(CallStrCxt& cxt, const CallICFGNode* call, const FunObjVar* callee)
|
|
476
|
+
{
|
|
477
|
+
return tct->matchAndPopCxt(cxt,call,callee);
|
|
478
|
+
}
|
|
479
|
+
/// If lhs is a suffix of rhs, including equal
|
|
480
|
+
inline bool isContextSuffix(const CallStrCxt& lhs, const CallStrCxt call)
|
|
459
481
|
{
|
|
460
|
-
return tct->
|
|
482
|
+
return tct->isContextSuffix(lhs,call);
|
|
461
483
|
}
|
|
484
|
+
//@}
|
|
462
485
|
|
|
463
486
|
/// Whether it is a fork site
|
|
464
487
|
inline bool isTDFork(const ICFGNode* call)
|
|
@@ -524,6 +547,18 @@ private:
|
|
|
524
547
|
}
|
|
525
548
|
//@}
|
|
526
549
|
|
|
550
|
+
/// Get CxtStmtSet for an instruction
|
|
551
|
+
inline const CxtStmtSet& getCxtStmtsFromInst(const ICFGNode* inst) const
|
|
552
|
+
{
|
|
553
|
+
InstToCxtStmt::const_iterator it = instToCxtStmt.find(inst);
|
|
554
|
+
assert(it!=instToCxtStmt.end() && "no CxtStmt for the instruction?");
|
|
555
|
+
return it->second;
|
|
556
|
+
}
|
|
557
|
+
inline bool hasCxtStmtsFromInst(const ICFGNode* inst) const
|
|
558
|
+
{
|
|
559
|
+
return instToCxtStmt.find(inst)!=instToCxtStmt.end();
|
|
560
|
+
}
|
|
561
|
+
|
|
527
562
|
/// Add inloop join
|
|
528
563
|
inline void addSymmetricLoopJoin(const CxtStmt& cs, LoopBBs& lp)
|
|
529
564
|
{
|
|
@@ -539,6 +574,7 @@ private:
|
|
|
539
574
|
ThreadPairSet HPPair; ///< threads happen-in-parallel
|
|
540
575
|
ThreadPairSet fullJoin; ///< t1 fully joins t2 along all program path
|
|
541
576
|
ThreadPairSet partialJoin; ///< t1 partially joins t2 along some program path(s)
|
|
577
|
+
InstToCxtStmt instToCxtStmt; ///<Map a statement to all its context-sensitive statements
|
|
542
578
|
};
|
|
543
579
|
|
|
544
580
|
} // End namespace SVF
|
|
@@ -66,7 +66,7 @@ public:
|
|
|
66
66
|
/// We start the pass here
|
|
67
67
|
virtual bool runOnModule(SVFIR* module);
|
|
68
68
|
/// Compute MHP
|
|
69
|
-
virtual MHP* computeMHP();
|
|
69
|
+
virtual MHP* computeMHP(TCT* tct);
|
|
70
70
|
/// Compute locksets
|
|
71
71
|
virtual LockAnalysis* computeLocksets(TCT* tct);
|
|
72
72
|
/// Perform detection
|
|
@@ -97,7 +97,7 @@ public:
|
|
|
97
97
|
SVFUtil::outs() << "---\ntid: " << this->getId() << " inloop:" << ctx.isInloop() << " incycle:" << ctx.isIncycle() << " multiforked:"<< isMultiforked();
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
/// Get
|
|
100
|
+
/// Get thread creation context, <fork site, call string context>
|
|
101
101
|
inline const CxtThread& getCxtThread() const
|
|
102
102
|
{
|
|
103
103
|
return ctx;
|
|
@@ -142,7 +142,7 @@ public:
|
|
|
142
142
|
|
|
143
143
|
|
|
144
144
|
private:
|
|
145
|
-
const CxtThread ctx;
|
|
145
|
+
const CxtThread ctx; /// Thread creation context, <fork site, call string context>
|
|
146
146
|
bool multiforked;
|
|
147
147
|
};
|
|
148
148
|
|
|
@@ -162,7 +162,8 @@ public:
|
|
|
162
162
|
typedef Set<const ICFGNode*> InstSet;
|
|
163
163
|
typedef Set<const CallGraphNode*> PTACGNodeSet;
|
|
164
164
|
typedef Map<CxtThread,TCTNode*> CxtThreadToNodeMap;
|
|
165
|
-
typedef
|
|
165
|
+
typedef Set<std::pair<NodeID, CallStrCxt>> CallStrCxtSet;
|
|
166
|
+
typedef Map<CxtThread,CallStrCxtSet> CxtThreadToForkCxtSet;
|
|
166
167
|
typedef Map<CxtThread,const FunObjVar*> CxtThreadToFun;
|
|
167
168
|
typedef Map<const ICFGNode*, LoopBBs> InstToLoopMap;
|
|
168
169
|
typedef FIFOWorkList<CxtThreadProc> CxtThreadProcVec;
|
|
@@ -172,7 +173,8 @@ public:
|
|
|
172
173
|
/// Constructor
|
|
173
174
|
TCT(PointerAnalysis* p) :pta(p),TCTNodeNum(0),TCTEdgeNum(0),MaxCxtSize(0)
|
|
174
175
|
{
|
|
175
|
-
tcg = SVFUtil::
|
|
176
|
+
tcg = SVFUtil::dyn_cast<ThreadCallGraph>(pta->getCallGraph());
|
|
177
|
+
assert(tcg != nullptr && "TCT::TCT: call graph is not a ThreadCallGraph!");
|
|
176
178
|
tcg->updateCallGraph(pta);
|
|
177
179
|
//tcg->updateJoinEdge(pta);
|
|
178
180
|
tcgSCC = pta->getCallGraphSCC();
|
|
@@ -182,9 +184,7 @@ public:
|
|
|
182
184
|
|
|
183
185
|
/// Destructor
|
|
184
186
|
virtual ~TCT()
|
|
185
|
-
{
|
|
186
|
-
destroy();
|
|
187
|
-
}
|
|
187
|
+
{ }
|
|
188
188
|
|
|
189
189
|
/// Get TCG
|
|
190
190
|
inline ThreadCallGraph* getThreadCallGraph() const
|
|
@@ -310,24 +310,29 @@ public:
|
|
|
310
310
|
const TCTNode* node = getTCTNode(tid);
|
|
311
311
|
return node->getInEdges().size()==1;
|
|
312
312
|
}
|
|
313
|
-
/// Get parent
|
|
314
|
-
inline
|
|
313
|
+
/// Get parent threads
|
|
314
|
+
inline NodeBS getParentThreads(NodeID tid) const
|
|
315
315
|
{
|
|
316
|
+
NodeBS parentTds;
|
|
316
317
|
const TCTNode* node = getTCTNode(tid);
|
|
317
|
-
assert(node->getInEdges().size()
|
|
318
|
-
|
|
319
|
-
const TCTEdge* edge
|
|
320
|
-
|
|
318
|
+
assert(node->getInEdges().size()>=1 && "does not have a parent thread");
|
|
319
|
+
|
|
320
|
+
for (const TCTEdge* edge : node->getInEdges())
|
|
321
|
+
{
|
|
322
|
+
parentTds.set(edge->getSrcID());
|
|
323
|
+
}
|
|
324
|
+
return parentTds;
|
|
321
325
|
}
|
|
322
326
|
/// Get all ancestor threads
|
|
323
|
-
const NodeBS
|
|
327
|
+
const NodeBS getAncestorThreads(NodeID tid) const
|
|
324
328
|
{
|
|
325
329
|
NodeBS tds;
|
|
326
330
|
if(hasParentThread(tid) == false)
|
|
327
331
|
return tds;
|
|
328
332
|
|
|
329
333
|
FIFOWorkList<NodeID> worklist;
|
|
330
|
-
|
|
334
|
+
for(NodeID parentTid : getParentThreads(tid))
|
|
335
|
+
worklist.push(parentTid);
|
|
331
336
|
|
|
332
337
|
while(!worklist.empty())
|
|
333
338
|
{
|
|
@@ -335,7 +340,8 @@ public:
|
|
|
335
340
|
if(tds.test_and_set(t))
|
|
336
341
|
{
|
|
337
342
|
if(hasParentThread(t))
|
|
338
|
-
|
|
343
|
+
for(NodeID parentTid : getParentThreads(t))
|
|
344
|
+
worklist.push(parentTid);
|
|
339
345
|
}
|
|
340
346
|
}
|
|
341
347
|
return tds;
|
|
@@ -346,24 +352,26 @@ public:
|
|
|
346
352
|
NodeBS tds;
|
|
347
353
|
if(hasParentThread(tid) == false)
|
|
348
354
|
return tds;
|
|
349
|
-
|
|
350
|
-
const TCTNode* node = getTCTNode(getParentThread(tid));
|
|
351
|
-
for(ThreadCreateEdgeSet::const_iterator it = getChildrenBegin(node), eit = getChildrenEnd(node); it!=eit; ++it)
|
|
355
|
+
for (NodeID parentTid : getParentThreads(tid))
|
|
352
356
|
{
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
357
|
+
const TCTNode* parentNode = getTCTNode(parentTid);
|
|
358
|
+
for(ThreadCreateEdgeSet::const_iterator it = getChildrenBegin(parentNode),
|
|
359
|
+
eit = getChildrenEnd(parentNode); it!=eit; ++it)
|
|
360
|
+
{
|
|
361
|
+
NodeID child = (*it)->getDstNode()->getId();
|
|
362
|
+
if(child!=tid)
|
|
363
|
+
tds.set(child);
|
|
364
|
+
}
|
|
356
365
|
}
|
|
357
|
-
|
|
358
366
|
return tds;
|
|
359
367
|
}
|
|
360
368
|
//@}
|
|
361
369
|
|
|
362
|
-
/// get the
|
|
363
|
-
const
|
|
370
|
+
/// get the contexts of a thread at its spawning sites (fork sites)
|
|
371
|
+
const CallStrCxtSet& getCxtOfCxtThread(const CxtThread& ct) const
|
|
364
372
|
{
|
|
365
|
-
|
|
366
|
-
assert(it!=
|
|
373
|
+
CxtThreadToForkCxtSet::const_iterator it = ctToForkCxtsMap.find(ct);
|
|
374
|
+
assert(it!=ctToForkCxtsMap.end() && "Cxt Thread not found!!");
|
|
367
375
|
return it->second;
|
|
368
376
|
}
|
|
369
377
|
|
|
@@ -407,17 +415,16 @@ public:
|
|
|
407
415
|
/// Get loop for fork/join site
|
|
408
416
|
const LoopBBs& getLoop(const SVFBasicBlock* bb);
|
|
409
417
|
|
|
418
|
+
/// Context helper functions
|
|
419
|
+
//@{
|
|
410
420
|
/// Push calling context
|
|
411
421
|
void pushCxt(CallStrCxt& cxt, const CallICFGNode* call, const FunObjVar* callee);
|
|
412
422
|
/// Match context
|
|
413
|
-
bool
|
|
423
|
+
bool matchAndPopCxt(CallStrCxt& cxt, const CallICFGNode* call, const FunObjVar* callee);
|
|
424
|
+
/// If lhs is a suffix of rhs, including equal
|
|
425
|
+
bool isContextSuffix(const CallStrCxt& lhs, const CallStrCxt& call);
|
|
426
|
+
//@}
|
|
414
427
|
|
|
415
|
-
inline void pushCxt(CallStrCxt& cxt, CallSiteID csId)
|
|
416
|
-
{
|
|
417
|
-
cxt.push_back(csId);
|
|
418
|
-
if (cxt.size() > MaxCxtSize)
|
|
419
|
-
MaxCxtSize = cxt.size();
|
|
420
|
-
}
|
|
421
428
|
/// Whether a join site is in recursion
|
|
422
429
|
inline bool isJoinSiteInRecursion(const CallICFGNode* join) const
|
|
423
430
|
{
|
|
@@ -504,7 +511,7 @@ private:
|
|
|
504
511
|
|
|
505
512
|
/// Get or create a tct node based on CxtThread
|
|
506
513
|
//@{
|
|
507
|
-
inline TCTNode* getOrCreateTCTNode(const CallStrCxt& cxt, const ICFGNode* fork,const
|
|
514
|
+
inline TCTNode* getOrCreateTCTNode(const CallStrCxt& cxt, const ICFGNode* fork, const CxtThreadProc& forkSiteCtp, const FunObjVar* routine)
|
|
508
515
|
{
|
|
509
516
|
CxtThread ct(cxt,fork);
|
|
510
517
|
CxtThreadToNodeMap::const_iterator it = ctpToNodeMap.find(ct);
|
|
@@ -513,7 +520,7 @@ private:
|
|
|
513
520
|
return it->second;
|
|
514
521
|
}
|
|
515
522
|
|
|
516
|
-
addCxtOfCxtThread(
|
|
523
|
+
addCxtOfCxtThread(forkSiteCtp.getTid(), forkSiteCtp.getContext(), ct);
|
|
517
524
|
addStartRoutineOfCxtThread(routine,ct);
|
|
518
525
|
|
|
519
526
|
setMultiForkedAttrs(ct);
|
|
@@ -540,10 +547,11 @@ private:
|
|
|
540
547
|
}
|
|
541
548
|
|
|
542
549
|
/// Add context for a thread at its spawning site (fork site)
|
|
543
|
-
void addCxtOfCxtThread(const CallStrCxt& cxt, const CxtThread& ct)
|
|
550
|
+
void addCxtOfCxtThread(NodeID pTid, const CallStrCxt& cxt, const CxtThread& ct)
|
|
544
551
|
{
|
|
545
|
-
|
|
552
|
+
ctToForkCxtsMap[ct].insert(std::make_pair(pTid, cxt));
|
|
546
553
|
}
|
|
554
|
+
|
|
547
555
|
/// Add start routine function of a cxt thread
|
|
548
556
|
void addStartRoutineOfCxtThread(const FunObjVar* fun, const CxtThread& ct)
|
|
549
557
|
{
|
|
@@ -571,13 +579,6 @@ private:
|
|
|
571
579
|
return visitedCTPs.find(ctp)!=visitedCTPs.end();
|
|
572
580
|
}
|
|
573
581
|
//@}
|
|
574
|
-
/// Clean up memory
|
|
575
|
-
inline void destroy()
|
|
576
|
-
{
|
|
577
|
-
if(tcgSCC)
|
|
578
|
-
delete tcgSCC;
|
|
579
|
-
tcgSCC=nullptr;
|
|
580
|
-
}
|
|
581
582
|
|
|
582
583
|
FunSet entryFuncSet; /// Procedures that are neither called by other functions nor extern functions
|
|
583
584
|
FunSet candidateFuncSet; /// Procedures we care about during call graph traversing when creating TCT
|
|
@@ -585,7 +586,7 @@ private:
|
|
|
585
586
|
CxtThreadProcVec ctpList; /// CxtThreadProc List
|
|
586
587
|
CxtThreadProcSet visitedCTPs; /// Record all visited ctps
|
|
587
588
|
CxtThreadToNodeMap ctpToNodeMap; /// Map a ctp to its graph node
|
|
588
|
-
|
|
589
|
+
CxtThreadToForkCxtSet ctToForkCxtsMap; /// Map a CxtThread to the context at its spawning site (fork site).
|
|
589
590
|
CxtThreadToFun ctToRoutineFunMap; /// Map a CxtThread to its start routine function.
|
|
590
591
|
InstToLoopMap joinSiteToLoopMap; ///< map an inloop join to its loop class
|
|
591
592
|
Set<const ICFGNode*> inRecurJoinSites; ///< Fork or Join sites in recursions
|
|
Binary file
|