Static Value-Flow Analysis
Loading...
Searching...
No Matches
LockAnalysis.cpp
Go to the documentation of this file.
1//===- LockAnalysis.cpp -- 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 * LocksetAnalysis.cpp
25 *
26 * Created on: 26 Aug 2015
27 * Author: pengd
28 */
29
30#include "Util/Options.h"
31#include "MTA/LockAnalysis.h"
32#include "MTA/MTA.h"
33#include "Util/SVFUtil.h"
34#include "Util/PTAStat.h"
35
36
37using namespace SVF;
38using namespace SVFUtil;
39
40
42{
43
46
47 DOTIMESTAT(double lockStart = PTAStat::getClk(true));
48
49 DBOUT(DGENERAL, outs() << "\tIntra-procedural LockAnalysis\n");
50 DBOUT(DMTA, outs() << "\tIntra-procedural LockAnalysis\n");
52
53 DBOUT(DGENERAL, outs() << "\tCollect context-sensitive locks\n");
54 DBOUT(DMTA, outs() << "\tCollect context-sensitive locks\n");
56
57 DBOUT(DGENERAL, outs() << "\tInter-procedural LockAnalysis\n");
58 DBOUT(DMTA, outs() << "\tInter-procedural LockAnalysis\n");
60
61 DOTIMESTAT(double lockEnd = PTAStat::getClk(true));
63}
64
65
70{
72
73 for (const auto& item : *PAG::getPAG()->getCallGraph())
74 {
75 const FunObjVar* F = item.second->getFunction();
76 for (auto it : *F)
77 {
78 const SVFBasicBlock* bb = it.second;
79 for (const ICFGNode* icfgNode : bb->getICFGNodeList())
80 {
81 if (isa<CallICFGNode>(icfgNode) && tcg->getThreadAPI()->isTDRelease(cast<CallICFGNode>(icfgNode)))
82 {
83 unlocksites.insert(icfgNode);
84 }
85 if (isa<CallICFGNode>(icfgNode) && tcg->getThreadAPI()->isTDAcquire(cast<CallICFGNode>(icfgNode)))
86 {
87 locksites.insert(icfgNode);
88 }
89 }
90 }
91 }
92}
93
98{
99
101
102 TCT::PTACGNodeSet visited;
104
105 for (InstSet::iterator it = locksites.begin(), eit = locksites.end(); it != eit; ++it)
106 {
107 const FunObjVar* fun=(*it)->getFun();
109 if (visited.find(cgnode) == visited.end())
110 {
111 worklist.push(cgnode);
112 visited.insert(cgnode);
113 }
114 }
115 for (InstSet::iterator it = unlocksites.begin(), eit = unlocksites.end(); it != eit; ++it)
116 {
117 const FunObjVar* fun = (*it)->getFun();
119 if (visited.find(cgnode) == visited.end())
120 {
121 worklist.push(cgnode);
122 visited.insert(cgnode);
123 }
124 }
125 while (!worklist.empty())
126 {
127 const CallGraphNode* node = worklist.pop();
128 lockcandidateFuncSet.insert(node->getFunction());
129 for (CallGraphNode::const_iterator nit = node->InEdgeBegin(), neit = node->InEdgeEnd(); nit != neit; nit++)
130 {
131 const CallGraphNode* srcNode = (*nit)->getSrcNode();
132 if (visited.find(srcNode) == visited.end())
133 {
134 visited.insert(srcNode);
135 worklist.push(srcNode);
136 }
137 }
138 }
139}
140
146{
147
148 // Identify the protected Instructions.
149 for (InstSet::const_iterator it = locksites.begin(), ie = locksites.end(); it != ie; ++it)
150 {
151 const ICFGNode* lockSite = *it;
152 assert(isCallSite(lockSite) && "Lock acquire instruction must be a CallSite");
153
154 // Perform forward traversal
158
161
163 if(forward && backward)
165 else if(forward && !backward)
167 }
168}
169
174{
175
176 const FunObjVar* svfFun = lockSite->getFun();
177
178 InstVec worklist;
179 worklist.push_back(lockSite);
180 while (!worklist.empty())
181 {
182 const ICFGNode *I = worklist.back();
183 worklist.pop_back();
184 const ICFGNode* exitInst = svfFun->getExitBB()->back();
185 if(exitInst == I)
186 return false;
187
188 // Skip the visited Instructions.
189 if (forwardInsts.find(I)!=forwardInsts.end())
190 continue;
191 forwardInsts.insert(I);
192
193 if (isTDRelease(I) && isAliasedLocks(lockSite, I))
194 {
195 unlockSet.insert(I);
196 DBOUT(DMTA, outs() << "LockAnalysis ci lock -- " << lockSite->getSourceLoc()<<"\n");
197 DBOUT(DMTA, outs() << "LockAnalysis ci unlock -- " << I->getSourceLoc()<<"\n");
198 continue;
199 }
200
201 for(const ICFGEdge* outEdge : I->getOutEdges())
202 {
203 if(outEdge->getDstNode()->getFun() == I->getFun())
204 {
205 worklist.push_back(outEdge->getDstNode());
206 }
207 }
208 }
209
210 return true;
211}
212
213
218{
219
220 InstVec worklist;
221 for(InstSet::const_iterator it = unlockSet.begin(), eit = unlockSet.end(); it!=eit; ++it)
222 {
223 const ICFGNode* unlockSite = *it;
225 worklist.push_back(*it);
226
227 while (!worklist.empty())
228 {
229 const ICFGNode *I = worklist.back();
230 worklist.pop_back();
231
232 if(entryInst == I)
233 return false;
234
235 // Skip the visited Instructions.
236 if (backwardInsts.find(I)!=backwardInsts.end())
237 continue;
238 backwardInsts.insert(I);
239
241 {
242 DBOUT(DMTA, outs() << "LockAnalysis ci lock -- " << I->getSourceLoc()<<"\n");
243 DBOUT(DMTA, outs() << "LockAnalysis ci unlock -- " << unlockSite->getSourceLoc()<<"\n");
244 continue;
245 }
246
247 for(const ICFGEdge* inEdge : I->getInEdges())
248 {
249 if(inEdge->getSrcNode()->getFun() == I->getFun())
250 {
251 worklist.push_back(inEdge->getSrcNode());
252 }
253 }
254 }
255 }
256
257 return true;
258}
259
260
262{
263 FunSet entryFuncSet = tct->getEntryProcs();
264 for (FunSet::const_iterator it = entryFuncSet.begin(), eit = entryFuncSet.end(); it != eit; ++it)
265 {
266 if (!isLockCandidateFun(*it))
267 continue;
268 CallStrCxt cxt;
269 CxtLockProc t(cxt, *it);
271 }
272
273 while (!clpList.empty())
274 {
276 CallGraphNode* cgNode = getTCG()->getCallGraphNode(clp.getProc());
277 // lzh TODO.
278 if (!isLockCandidateFun(cgNode->getFunction()))
279 continue;
280
281 for (CallGraphNode::const_iterator nit = cgNode->OutEdgeBegin(), neit = cgNode->OutEdgeEnd(); nit != neit; nit++)
282 {
283 const CallGraphEdge* cgEdge = (*nit);
284
285 for (CallGraphEdge::CallInstSet::const_iterator cit = cgEdge->directCallsBegin(), ecit = cgEdge->directCallsEnd();
286 cit != ecit; ++cit)
287 {
288 DBOUT(DMTA,
289 outs() << "\nCollecting CxtLocks: handling direct call:" << **cit << "\t" << cgEdge->getSrcNode()->getFunction()->getName()
290 << "-->" << cgEdge->getDstNode()->getFunction()->getName() << "\n");
292 }
293 for (CallGraphEdge::CallInstSet::const_iterator ind = cgEdge->indirectCallsBegin(), eind = cgEdge->indirectCallsEnd();
294 ind != eind; ++ind)
295 {
296 DBOUT(DMTA,
297 outs() << "\nCollecting CxtLocks: handling indirect call:" << **ind << "\t"
298 << cgEdge->getSrcNode()->getFunction()->getName() << "-->" << cgEdge->getDstNode()->getFunction()->getName()
299 << "\n");
301 }
302 }
303 }
304}
305
306
311{
312
313 CallStrCxt cxt(clp.getContext());
314 const ICFGNode* curNode = cs;
315 if (isTDAcquire(curNode))
316 {
317 addCxtLock(cxt,curNode);
318 return;
319 }
320 const FunObjVar* svfcallee = cgEdge->getDstNode()->getFunction();
321 pushCxt(cxt, SVFUtil::cast<CallICFGNode>(curNode), svfcallee);
322
325 {
326 DBOUT(DMTA, outs() << "LockAnalysis Process CallRet old clp --"; clp.dump());
327 DBOUT(DMTA, outs() << "LockAnalysis Process CallRet new clp --"; newclp.dump());
328 }
329
330}
331
333{
334
335 FunSet entryFuncSet = tct->getEntryProcs();
336 for (FunSet::const_iterator it = entryFuncSet.begin(), eit = entryFuncSet.end(); it != eit; ++it)
337 {
338 if (!isLockCandidateFun(*it))
339 continue;
340 CallStrCxt cxt;
341 const ICFGNode* frontInst = (*it)->getEntryBlock()->front();
344 }
345
346 while (!cxtStmtList.empty())
347 {
349
351 const ICFGNode* curInst = cts.getStmt();
353
354 DBOUT(DMTA, outs() << "\nVisit cxtStmt: ");
355 DBOUT(DMTA, cts.dump());
356
357 DBOUT(DMTA, outs() << "\nIts cxt lock sets: ");
359
360 if (isTDFork(curInst))
361 {
363 }
364 else if (isTDAcquire(curInst))
365 {
366 assert(hasCxtLock(cts) && "context-sensitive lock not found!!");
369 }
370 else if (isTDRelease(curInst))
371 {
374 }
375 else if (isCallSite(curInst) && !isExtCall(curInst))
376 {
378 }
379 else if (SVFUtil::dyn_cast<FunExitICFGNode>(curInst))
380 {
381 handleRet(cts);
382 }
383 else
384 {
386 }
387
388 }
389
390}
391
392
397{
399 outs() << "\nlock sets size = " << lockset.size() << "\n";
400 for (CxtLockSet::const_iterator it = lockset.begin(), eit = lockset.end(); it != eit; ++it)
401 {
402 (*it).dump();
403 }
404}
405
406
407
410{
411 const CallStrCxt& curCxt = cts.getContext();
412 const CallICFGNode* call = SVFUtil::dyn_cast<CallICFGNode>(cts.getStmt());
413 if(getTCG()->hasThreadForkEdge(call))
414 {
415 for (ThreadCallGraph::ForkEdgeSet::const_iterator cgIt = getTCG()->getForkEdgeBegin(call),
416 ecgIt = getTCG()->getForkEdgeEnd(call); cgIt != ecgIt; ++cgIt)
417 {
418 const FunObjVar* svfcallee = (*cgIt)->getDstNode()->getFunction();
421 const ICFGNode* svfInst = svfcallee->getEntryBlock()->front();
424 }
425 }
427}
428
431{
432
433 const CallStrCxt& curCxt = cts.getContext();
434 const CallICFGNode* call = SVFUtil::dyn_cast<CallICFGNode>(cts.getStmt());
435 if (getTCG()->hasCallGraphEdge(call))
436 {
437 for (CallGraph::CallGraphEdgeSet::const_iterator cgIt = getTCG()->getCallEdgeBegin(call), ecgIt = getTCG()->getCallEdgeEnd(call);
438 cgIt != ecgIt; ++cgIt)
439 {
440 const FunObjVar* svfcallee = (*cgIt)->getDstNode()->getFunction();
442 continue;
444 pushCxt(newCxt, call, svfcallee);
445 const ICFGNode* svfInst = svfcallee->getEntryBlock()->front();
448 }
449 }
450}
451
454{
455
456 const ICFGNode* curInst = cts.getStmt();
457 const CallStrCxt& curCxt = cts.getContext();
458 const FunObjVar* svffun = curInst->getFun();
460
461 for (CallGraphNode::const_iterator it = curFunNode->getInEdges().begin(), eit = curFunNode->getInEdges().end(); it != eit; ++it)
462 {
464 if (SVFUtil::isa<ThreadForkEdge, ThreadJoinEdge>(edge))
465 continue;
466 for (CallGraphEdge::CallInstSet::const_iterator cit = (edge)->directCallsBegin(), ecit = (edge)->directCallsEnd(); cit != ecit;
467 ++cit)
468 {
470 const ICFGNode* inst = *cit;
471 if (matchCxt(newCxt, SVFUtil::cast<CallICFGNode>(inst), curFunNode->getFunction()))
472 {
473 for(const ICFGEdge* outEdge : curInst->getOutEdges())
474 {
475 if(outEdge->getDstNode()->getFun() == inst->getFun())
476 {
477 // Iterate over callSite's call string context and use as the successor's context
478 if (!hasCxtStmtFromInst(*cit))
479 continue;
480 for (const CxtStmt& cxtStmt: getCxtStmtsFromInst(*cit))
481 {
482 CallStrCxt callSiteCxt = cxtStmt.getContext();
483 // If new context is a suffix of the call site context
485 {
486 CxtStmt newCts(callSiteCxt, outEdge->getDstNode());
488 }
489 }
490 }
491 }
492 }
493 }
494 for (CallGraphEdge::CallInstSet::const_iterator cit = (edge)->indirectCallsBegin(), ecit = (edge)->indirectCallsEnd();
495 cit != ecit; ++cit)
496 {
498 const ICFGNode* inst = *cit;
499 if (matchCxt(newCxt, SVFUtil::cast<CallICFGNode>(inst), curFunNode->getFunction()))
500 {
501 for(const ICFGEdge* outEdge : curInst->getOutEdges())
502 {
503 if(outEdge->getDstNode()->getFun() == inst->getFun())
504 {
505 // Iterate over callSite's call string context and use as the successor's context
506 if (!hasCxtStmtFromInst(*cit))
507 continue;
508 for (const CxtStmt& cxtStmt: getCxtStmtsFromInst(*cit))
509 {
510 CallStrCxt callSiteCxt = cxtStmt.getContext();
511 // If new context is a suffix of the call site context
513 {
514 CxtStmt newCts(callSiteCxt, outEdge->getDstNode());
516 }
517 }
518 }
519 }
520 }
521 }
522 }
523}
524
527{
528
529 const ICFGNode* curInst = cts.getStmt();
530 const CallStrCxt& curCxt = cts.getContext();
531
532 for(const ICFGEdge* outEdge : curInst->getOutEdges())
533 {
534 if(outEdge->getDstNode()->getFun() == curInst->getFun())
535 {
536 CxtStmt newCts(curCxt, outEdge->getDstNode());
538 }
539 }
540}
541
543{
544 tct->pushCxt(cxt,call,callee);
545}
546
548{
549 const FunObjVar* svfcaller = call->getFun();
550 CallSiteID csId = getTCG()->getCallSiteID(call, callee);
551
552// /// handle calling context for candidate functions only
553// if (isLockCandidateFun(caller) == false)
554// return true;
555
557 if (cxt.empty())
558 return true;
559
560 if (tct->inSameCallGraphSCC(getTCG()->getCallGraphNode(svfcaller), getTCG()->getCallGraphNode(callee)) == false)
561 {
562 if (cxt.back() == csId)
563 cxt.pop_back();
564 else
565 return false;
566 DBOUT(DMTA, tct->dumpCxt(cxt));
567 }
568 return true;
569}
570
572{
573 return tct->isContextSuffix(lhs,call);
574}
575
576
593
598{
599
601 {
604 for (InstSet::const_iterator cil1 = lockset1.begin(), ecil1 = lockset1.end(); cil1!=ecil1; ++cil1)
605 {
606 for (InstSet::const_iterator cil2=lockset2.begin(), ecil2=lockset2.end(); cil2!=ecil2; ++cil2)
607 {
608 if (isAliasedLocks(*cil1, *cil2))
609 return true;
610 }
611 }
612 }
613 return false;
614}
615
627
632{
634 return false;
637 for (CxtStmtSet::const_iterator cts1 = ctsset1.begin(), ects1 = ctsset1.end(); cts1 != ects1; cts1++)
638 {
639 const CxtStmt& cxtStmt1 = *cts1;
640 for (CxtStmtSet::const_iterator cts2 = ctsset2.begin(), ects2 = ctsset2.end(); cts2 != ects2; cts2++)
641 {
642 const CxtStmt& cxtStmt2 = *cts2;
643 if(cxtStmt1==cxtStmt2) continue;
645 return false;
646 }
647 }
648 return true;
649}
650
651
656{
657 DOTIMESTAT(double queryStart = PTAStat::getClk(true));
658
659 bool sameSpan = false;
662 else
664
665 DOTIMESTAT(double queryEnd = PTAStat::getClk(true));
667 return sameSpan;
668}
669
674{
676 {
679 for (InstSet::const_iterator cil1 = lockset1.begin(), ecil1 = lockset1.end(); cil1!=ecil1; ++cil1)
680 {
681 for (InstSet::const_iterator cil2=lockset2.begin(), ecil2=lockset2.end(); cil2!=ecil2; ++cil2)
682 {
683 if (*cil1==*cil2)
684 return true;
685 }
686 }
687 }
688 return false;
689}
690
706{
708 return false;
711
712 for (CxtStmtSet::const_iterator cts1 = ctsset1.begin(), ects1 = ctsset1.end(); cts1 != ects1; cts1++)
713 {
714 const CxtStmt& cxtStmt1 = *cts1;
715 for (CxtStmtSet::const_iterator cts2 = ctsset2.begin(), ects2 = ctsset2.end(); cts2 != ects2; cts2++)
716 {
717 const CxtStmt& cxtStmt2 = *cts2;
718 if(cxtStmt1==cxtStmt2) continue;
720 return false;
721 }
722 }
723 return true;
724}
#define DBOUT(TYPE, X)
LLVM debug macros, define type of your DBUG model of each pass.
Definition SVFType.h:497
#define TIMEINTERVAL
Definition SVFType.h:525
#define DMTA
Definition SVFType.h:518
#define DGENERAL
Definition SVFType.h:503
#define DOTIMESTAT(X)
Definition SVFType.h:499
cJSON * item
Definition cJSON.h:222
const FunObjVar * getFunction() const
Get function of this call node.
Definition CallGraph.h:191
const CallGraphNode * getCallGraphNode(const std::string &name) const
Get call graph node.
CallSiteID getCallSiteID(const CallICFGNode *cs, const FunObjVar *callee) const
Get CallSiteID.
Definition CallGraph.h:377
bool push(const Data &data)
Definition WorkList.h:165
bool empty() const
Definition WorkList.h:146
virtual const FunObjVar * getFunction() const
Get containing function, or null for globals/constants.
const SVFBasicBlock * getEntryBlock() const
iterator OutEdgeEnd()
const GEdgeSetTy & getOutEdges() const
const GEdgeSetTy & getInEdges() const
iterator OutEdgeBegin()
iterators
GEdgeSetTy::const_iterator const_iterator
iterator InEdgeBegin()
iterator InEdgeEnd()
virtual const FunObjVar * getFun() const
Return the function of this ICFGNode.
Definition ICFGNode.h:74
Set< CxtLock > CxtLockSet
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()
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.
Set< CxtStmt > CxtStmtSet
bool alias(const CxtLockSet &lockset1, const CxtLockSet &lockset2)
Return true if two locksets has at least one alias lock.
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.
ThreadCallGraph * getTCG() const
ThreadCallGraph.
void handleFork(const CxtStmt &cts)
Handle fork.
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)
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.
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.
bool isTDFork(const ICFGNode *call)
Whether it is a lock site.
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 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()
void touchCxtStmt(CxtStmt &cts)
Touch this context statement.
Set< const ICFGNode * > InstSet
bool isLockCandidateFun(const FunObjVar *fun) const
Return true if it is a candidate function.
void handleCallRelation(CxtLockProc &clp, const CallGraphEdge *cgEdge, const CallICFGNode *call)
Handle call relations.
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.
CxtLockProc popFromCTPWorkList()
bool matchCxt(CallStrCxt &cxt, const CallICFGNode *call, const FunObjVar *callee)
Match context.
void handleRet(const CxtStmt &cts)
Handle return.
Set< const FunObjVar * > FunSet
const CxtStmtSet & getCxtStmtsFromInst(const ICFGNode *inst) const
bool isInSameCISpan(const ICFGNode *i1, const ICFGNode *i2) const
bool isAliasedLocks(const CxtLock &cl1, const CxtLock &cl2)
Return true it a lock matches an unlock.
InstToCxtStmtSet instToCxtStmtSet
Map a statement to all its context-sensitive statements.
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.
CxtLockProcVec clpList
Following data structures are used for collecting context-sensitive locks.
bool isTDAcquire(const ICFGNode *call)
Whether it is a lock site.
const std::vector< const ICFGNode * > & getICFGNodeList() const
const ICFGNode * back() const
const CallGraph * getCallGraph()
Get CG.
Definition SVFIR.h:178
static SVFIR * getPAG(bool buildFromFile=false)
Singleton design here to make sure we only have one instance during any analysis.
Definition SVFIR.h:114
static double getClk(bool mark=false)
Definition SVFStat.cpp:48
virtual const std::string getSourceLoc() const
Definition SVFValue.h:196
bool isContextSuffix(const CallStrCxt &lhs, const CallStrCxt &call)
If lhs is a suffix of rhs, including equal.
Definition TCT.cpp:497
Set< const CallGraphNode * > PTACGNodeSet
Definition TCT.h:163
ThreadCallGraph * getThreadCallGraph() const
Get TCG.
Definition TCT.h:190
bool inSameCallGraphSCC(const CallGraphNode *src, const CallGraphNode *dst)
Whether two functions in the same callgraph scc.
Definition TCT.h:300
void dumpCxt(CallStrCxt &cxt)
Dump calling context.
Definition TCT.cpp:517
const FunSet & getEntryProcs() const
Get marked candidate functions.
Definition TCT.h:236
void pushCxt(CallStrCxt &cxt, const CallICFGNode *call, const FunObjVar *callee)
Context helper functions.
Definition TCT.cpp:449
bool isTDRelease(const CallICFGNode *inst) const
Return true if this call release a lock.
bool isTDAcquire(const CallICFGNode *inst) const
Return true if this call acquire a lock.
ThreadAPI * getThreadAPI() const
Thread API.
bool isExtCall(const FunObjVar *fun)
Definition SVFUtil.cpp:437
std::ostream & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:52
for isBitcode
Definition BasicTypes.h:68
unsigned CallSiteID
Definition GeneralType.h:58
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74
std::vector< u32_t > CallStrCxt