Static Value-Flow Analysis
Loading...
Searching...
No Matches
TCT.cpp
Go to the documentation of this file.
1//===- TCT.cpp -- Thread creation tree-------------//
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/*
25 * TCT.cpp
26 *
27 * Created on: Jun 24, 2015
28 * Author: Yulei Sui, Peng Di
29 */
30
31#include "Util/Options.h"
32#include "MTA/TCT.h"
33#include "MTA/MTA.h"
34#include "Graphs/CallGraph.h"
35
36#include <string>
37
38using namespace SVF;
39using namespace SVFUtil;
40
47{
48 assert(inst && "null value instruction!!");
49
52 worklist.push(inst);
53
54 while(!worklist.empty())
55 {
56 const ICFGNode* inst = worklist.pop();
57 insts.insert(inst);
59 for(PTACallGraphNode::const_iterator nit = cgnode->InEdgeBegin(), neit = cgnode->InEdgeEnd(); nit!=neit; nit++)
60 {
61 for(PTACallGraphEdge::CallInstSet::const_iterator cit = (*nit)->directCallsBegin(),
62 ecit = (*nit)->directCallsEnd(); cit!=ecit; ++cit)
63 {
64 if(insts.insert(*cit).second)
65 worklist.push(*cit);
66 }
67 for(PTACallGraphEdge::CallInstSet::const_iterator cit = (*nit)->indirectCallsBegin(),
68 ecit = (*nit)->indirectCallsEnd(); cit!=ecit; ++cit)
69 {
70 if(insts.insert(*cit).second)
71 worklist.push(*cit);
72 }
73 }
74 }
75
76 for(const ICFGNode* i : insts)
77 {
78 if(i->getFun()->hasLoopInfo(i->getBB()))
79 return true;
80 }
81
82
83 return false;
84}
85
91bool TCT::isInRecursion(const ICFGNode* inst) const
92{
93 const SVFFunction* f = inst->getFun();
96 worklist.push(f);
97
98 while(!worklist.empty())
99 {
100 const SVFFunction* svffun = worklist.pop();
101 visits.insert(svffun);
102 if(tcgSCC->isInCycle(tcg->getCallGraphNode(svffun)->getId()))
103 return true;
104
106
107 for(PTACallGraphNode::const_iterator nit = cgnode->InEdgeBegin(), neit = cgnode->InEdgeEnd(); nit!=neit; nit++)
108 {
109 for(PTACallGraphEdge::CallInstSet::const_iterator cit = (*nit)->directCallsBegin(),
110 ecit = (*nit)->directCallsEnd(); cit!=ecit; ++cit)
111 {
112 const SVFFunction* caller = (*cit)->getFun();
113 if(visits.find(caller)==visits.end())
114 worklist.push(caller);
115 }
116 for(PTACallGraphEdge::CallInstSet::const_iterator cit = (*nit)->indirectCallsBegin(),
117 ecit = (*nit)->indirectCallsEnd(); cit!=ecit; ++cit)
118 {
119 const SVFFunction* caller = (*cit)->getFun();
120 if(visits.find(caller)==visits.end())
121 worklist.push(caller);
122 }
123 }
124 }
125
126 return false;
127
128}
129
134{
135 for (ThreadCallGraph::CallSiteSet::const_iterator it = tcg->forksitesBegin(), eit = tcg->forksitesEnd(); it != eit; ++it)
136 {
137 const SVFFunction* svfun = (*it)->getParent()->getParent();
139
140 for(ThreadCallGraph::ForkEdgeSet::const_iterator nit = tcg->getForkEdgeBegin(*it), neit = tcg->getForkEdgeEnd(*it); nit!=neit; nit++)
141 {
142 const PTACallGraphNode* forkeeNode = (*nit)->getDstNode();
143 candidateFuncSet.insert(forkeeNode->getFunction());
144 }
145
146 }
147
148 for (ThreadCallGraph::CallSiteSet::const_iterator it = tcg->joinsitesBegin(), eit = tcg->joinsitesEnd(); it != eit; ++it)
149 {
150 const SVFFunction* svfun = (*it)->getParent()->getParent();
152 }
153
154 if(candidateFuncSet.empty())
155 writeWrnMsg("We didn't recognize any fork site, this is single thread program?");
156}
157
162{
165 PTACGNodeSet visited;
166 worklist.push(cgnode);
167 visited.insert(cgnode);
168 while(!worklist.empty())
169 {
170 const PTACallGraphNode* node = worklist.pop();
171 candidateFuncSet.insert(node->getFunction());
173 {
174 const PTACallGraphNode* srcNode = (*nit)->getSrcNode();
175 if(visited.find(srcNode)==visited.end())
176 {
177 visited.insert(srcNode);
178 worklist.push(srcNode);
179 }
180 }
181 }
182}
183
188{
190 for (const auto& item: *svfirCallGraph)
191 {
192 const SVFFunction* fun = item.second->getFunction();
193 if (SVFUtil::isExtCall(fun))
194 continue;
196 if (!node->hasIncomingEdge())
197 {
198 entryFuncSet.insert(fun);
199 }
200 }
201 assert(!entryFuncSet.empty() && "Can't find any function in module!");
202}
203
208{
209 if (this->nodeNum == 0 )
210 return;
211
212 FIFOWorkList<TCTNode*> worklist;
213 worklist.push(getTCTNode(0));
214
215 while(!worklist.empty())
216 {
217 TCTNode* node = worklist.pop();
218 const CxtThread &ct = node->getCxtThread();
219
220 if(ct.isIncycle() || ct.isInloop())
221 {
222 node->setMultiforked(true);
223 }
224 else
225 {
226 for (TCT::ThreadCreateEdgeSet::const_iterator it = node->getInEdges().begin(), eit = node->getInEdges().end(); it != eit;
227 ++it)
228 {
229 if ((*it)->getSrcNode()->isMultiforked())
230 node->setMultiforked(true);
231 }
232 }
233 for (TCT::ThreadCreateEdgeSet::const_iterator it = node->getOutEdges().begin(), eit = node->getOutEdges().end(); it != eit;
234 ++it)
235 {
236 worklist.push((*it)->getDstNode());
237 }
238 }
239}
240
241
246{
247 const SVFFunction* callee = cgEdge->getDstNode()->getFunction();
248
249 CallStrCxt cxt(ctp.getContext());
250 CallStrCxt oldCxt = cxt;
251 const CallICFGNode* callNode = cs;
253
254 if(cgEdge->getEdgeKind() == PTACallGraphEdge::CallRetEdge)
255 {
256 CxtThreadProc newctp(ctp.getTid(),cxt,callee);
258 {
259 DBOUT(DMTA,outs() << "TCT Process CallRet old ctp --"; ctp.dump());
260 DBOUT(DMTA,outs() << "TCT Process CallRet new ctp --"; newctp.dump());
261 }
262 }
263
264 else if(cgEdge->getEdgeKind() == PTACallGraphEdge::TDForkEdge)
265 {
269
271 {
273 if(addTCTEdge(this->getGNode(ctp.getTid()), spawneeNode))
274 {
275 DBOUT(DMTA,outs() << "Add TCT Edge from thread " << ctp.getTid() << " ";
276 this->getGNode(ctp.getTid())->getCxtThread().dump();
277 outs() << " to thread " << spawneeNode->getId() << " ";
278 spawneeNode->getCxtThread().dump();
279 outs() << "\n" );
280 }
281 DBOUT(DMTA,outs() << "TCT Process Fork old ctp --"; ctp.dump());
282 DBOUT(DMTA,outs() << "TCT Process Fork new ctp --"; newctp.dump());
283 }
284 }
285}
286
292{
293 assert(!lp.empty() && "this is not a loop, empty basic block");
294 const SVFFunction* svffun = join->getFun();
295 const SVFBasicBlock* loopheadbb = svffun->getLoopHeader(lp);
296 const SVFBasicBlock* joinbb = join->getBB();
297 assert(loopheadbb->getParent()==joinbb->getParent() && "should inside same function");
298
299 for (const SVFBasicBlock* svf_scc_bb : loopheadbb->getSuccessors())
300 {
301 if(svffun->loopContainsBB(lp,svf_scc_bb))
302 {
303 if(svffun->dominate(joinbb,svf_scc_bb)==false)
304 return false;
305 }
306 }
307
308 return true;
309}
310
316{
317 for(ThreadCallGraph::CallSiteSet::const_iterator it = tcg->joinsitesBegin(), eit = tcg->joinsitesEnd(); it!=eit; ++it)
318 {
319 const ICFGNode* join = *it;
320 const SVFFunction* svffun = join->getFun();
321 const SVFBasicBlock* svfbb = join->getBB();
322
323 if(svffun->hasLoopInfo(svfbb))
324 {
325 const LoopBBs& lp = svffun->getLoopInfo(svfbb);
326 if(!lp.empty() && isJoinMustExecutedInLoop(lp,join))
327 {
329 }
330 }
331
333 inRecurJoinSites.insert(join);
334 }
335}
336
341{
342 for(InstToLoopMap::const_iterator it = joinSiteToLoopMap.begin(), eit = joinSiteToLoopMap.end(); it!=eit; ++it)
343 {
344 if(bb->getParent()->getLoopHeader(it->second) == bb)
345 return true;
346 }
347
348 return false;
349}
350
355{
356 for(InstToLoopMap::const_iterator it = joinSiteToLoopMap.begin(), eit = joinSiteToLoopMap.end(); it!=eit; ++it)
357 {
358 std::vector<const SVFBasicBlock*> exitbbs;
359 it->first->getFun()->getExitBlocksOfLoop(it->first->getBB(),exitbbs);
360 while(!exitbbs.empty())
361 {
362 const SVFBasicBlock* eb = exitbbs.back();
363 exitbbs.pop_back();
364 if(eb == bb)
365 return true;
366 }
367 }
368
369 return false;
370}
371
376{
377 const SVFFunction* fun = bb->getParent();
378 return fun->getLoopInfo(bb);
379}
380
385{
386
387 markRelProcs();
388
390
391 // the fork site of main function is initialized with nullptr.
392 // the context of main is initialized with empty
393 // start routine is empty
394
396 for (FunSet::iterator it=entryFuncSet.begin(), eit=entryFuncSet.end(); it!=eit; ++it)
397 {
398 if (!isCandidateFun(*it))
399 continue;
400 CallStrCxt cxt;
401 TCTNode* mainTCTNode = getOrCreateTCTNode(cxt, nullptr, cxt, *it);
402 CxtThreadProc t(mainTCTNode->getId(), cxt, *it);
404 }
405
406 while(!ctpList.empty())
407 {
410 if(isCandidateFun(cgNode->getFunction()) == false)
411 continue;
412
413 for(PTACallGraphNode::const_iterator nit = cgNode->OutEdgeBegin(), neit = cgNode->OutEdgeEnd(); nit!=neit; nit++)
414 {
415 const PTACallGraphEdge* cgEdge = (*nit);
416
417 for(PTACallGraphEdge::CallInstSet::const_iterator cit = cgEdge->directCallsBegin(),
418 ecit = cgEdge->directCallsEnd(); cit!=ecit; ++cit)
419 {
420 DBOUT(DMTA,outs() << "\nTCT handling direct call:" << **cit << "\t" << cgEdge->getSrcNode()->getFunction()->getName() << "-->" << cgEdge->getDstNode()->getFunction()->getName() << "\n");
422 }
423 for(PTACallGraphEdge::CallInstSet::const_iterator ind = cgEdge->indirectCallsBegin(),
424 eind = cgEdge->indirectCallsEnd(); ind!=eind; ++ind)
425 {
426 DBOUT(DMTA,outs() << "\nTCT handling indirect call:" << **ind << "\t" << cgEdge->getSrcNode()->getFunction()->getName() << "-->" << cgEdge->getDstNode()->getFunction()->getName() << "\n");
428 }
429 }
430 }
431
433
435 {
436 print();
437 dump("tct");
438 }
439
440}
441
446{
447
448 const SVFFunction* caller = call->getFun();
449 CallSiteID csId = tcg->getCallSiteID(call, callee);
450
452 if(isCandidateFun(caller) == false)
453 return;
454
456 {
457 pushCxt(cxt,csId);
458 DBOUT(DMTA,dumpCxt(cxt));
459 }
460}
461
462
467{
468
469 const SVFFunction* caller = call->getFun();
470 CallSiteID csId = tcg->getCallSiteID(call, callee);
471
473 if(isCandidateFun(caller) == false)
474 return true;
475
477 if(cxt.empty())
478 return true;
479
481 {
482 if(cxt.back() == csId)
483 cxt.pop_back();
484 else
485 return false;
486 DBOUT(DMTA,dumpCxt(cxt));
487 }
488
489 return true;
490}
491
492
497{
498 std::string str;
499 std::stringstream rawstr(str);
500 rawstr << "[:";
501 for(CallStrCxt::const_iterator it = cxt.begin(), eit = cxt.end(); it!=eit; ++it)
502 {
503 rawstr << " ' "<< *it << " ' ";
504 rawstr << (tcg->getCallSite(*it))->valueOnlyToString();
505 rawstr << " call " << tcg->getCallSite(*it)->getCaller()->getName() << "-->" << tcg->getCalleeOfCallSite(*it)->getName() << ", \n";
506 }
507 rawstr << " ]";
508 outs() << "max cxt = " << cxt.size() << rawstr.str() << "\n";
509}
510
514void TCT::dump(const std::string& filename)
515{
518}
519
523void TCT::print() const
524{
525 for(TCT::const_iterator it = this->begin(), eit = this->end(); it!=eit; ++it)
526 {
527 outs() << "TID " << it->first << "\t";
528 it->second->getCxtThread().dump();
529 }
530}
531
536{
537 TCTEdge edge(src, dst, kind);
540 if (outEdge && inEdge)
541 {
542 assert(outEdge == inEdge && "edges not match");
543 return outEdge;
544 }
545 else
546 return nullptr;
547}
548
553{
554 for (TCTEdge::ThreadCreateEdgeSet::const_iterator iter = src->OutEdgeBegin(); iter != src->OutEdgeEnd(); ++iter)
555 {
556 TCTEdge* edge = (*iter);
557 if (edge->getEdgeKind() == kind && edge->getDstID() == dst->getId())
558 return edge;
559 }
560 return nullptr;
561}
562namespace SVF
563{
564
568template<>
570{
571
574 DOTGraphTraits(bool isSimple = false) :
575 DefaultDOTGraphTraits(isSimple)
576 {
577 }
578
580 static std::string getGraphName(TCT *graph)
581 {
582 return "Thread Create Tree";
583 }
585 static std::string getNodeLabel(TCTNode *node, TCT *graph)
586 {
587 return std::to_string(node->getId());
588 }
589
590 static std::string getNodeAttributes(TCTNode *node, TCT *tct)
591 {
592 std::string attr;
593 if (node->isInloop())
594 {
595 attr.append(" style=filled fillcolor=red");
596 }
597 else if (node->isIncycle())
598 {
599 attr.append(" style=filled fillcolor=yellow");
600 }
601 return attr;
602 }
603
604 template<class EdgeIter>
606 {
607
608 TCTEdge* edge = csThreadTree->getGraphEdge(node, *EI, TCTEdge::ThreadCreateEdge);
609 (void)edge; // Suppress warning of unused variable under release build
610 assert(edge && "No edge found!!");
612 return "color=black";
613 }
614};
615} // End namespace llvm
616
#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
cJSON * item
Definition cJSON.h:222
const SVFFunction * getCaller() const
Return callsite.
Definition ICFGNode.h:470
NodeID getTid() const
Return current thread id.
Definition CxtStmt.h:412
bool push(const Data &data)
Definition WorkList.h:165
bool empty() const
Definition WorkList.h:146
iterator begin()
Iterators.
u32_t nodeNum
total num of edge
IDToNodeMapTy::const_iterator const_iterator
NodeType * getGNode(NodeID id) const
Get a node.
bool hasIncomingEdge() const
Has incoming/outgoing edge set.
bool hasOutgoingEdge() const
iterator OutEdgeEnd()
GEdgeSetTy::iterator iterator
const GEdgeSetTy & getOutEdges() const
const GEdgeSetTy & getInEdges() const
iterator OutEdgeBegin()
iterators
GEdgeSetTy::const_iterator const_iterator
iterator InEdgeBegin()
iterator InEdgeEnd()
static void WriteGraphToFile(SVF::OutStream &O, const std::string &GraphName, const GraphType &GT, bool simple=false)
virtual const SVFFunction * getFun() const
Return the function of this ICFGNode.
Definition ICFGNode.h:76
static const Option< bool > TCTDotGraph
Definition Options.h:166
const SVFFunction * getFunction() const
Get function of this call node.
const CallICFGNode * getCallSite(CallSiteID id) const
CallSiteID getCallSiteID(const CallICFGNode *cs, const SVFFunction *callee) const
Get CallSiteID.
const SVFFunction * getCalleeOfCallSite(CallSiteID id) const
PTACallGraphNode * getCallGraphNode(NodeID id) const
Get call graph node.
NodeID getId() const
Get ID.
const SVFFunction * getParent() const
Definition SVFValue.h:595
const ICFGNode * back() const
Definition SVFValue.h:611
const LoopBBs & getLoopInfo(const SVFBasicBlock *bb) const
Definition SVFValue.h:486
const SVFBasicBlock * getLoopHeader(const BBList &lp) const
Definition SVFValue.h:491
CallGraph * getCallGraph()
Definition SVFIR.h:193
static SVFIR * getPAG(bool buildFromFile=false)
Singleton design here to make sure we only have one instance during any analysis.
Definition SVFIR.h:116
const std::string & getName() const
Definition SVFValue.h:243
@ ThreadCreateEdge
Definition TCT.h:55
const CxtThread & getCxtThread() const
Get CxtThread.
Definition TCT.h:101
void setMultiforked(bool value)
Definition TCT.h:116
bool isIncycle() const
Definition TCT.h:112
bool isInloop() const
inloop, incycle attributes
Definition TCT.h:108
bool pushToCTPWorkList(const CxtThreadProc &ctp)
WorkList helper functions.
Definition TCT.h:561
bool isInRecursion(const ICFGNode *inst) const
Whether an instruction is in a recursion.
Definition TCT.cpp:91
TCTNode * getTCTNode(NodeID id) const
Get TCT node.
Definition TCT.h:206
FunSet entryFuncSet
Definition TCT.h:588
void collectLoopInfoForJoin()
Handle join site in loop.
Definition TCT.cpp:315
ThreadCallGraphSCC * tcgSCC
Procedures we care about during call graph traversing when creating TCT.
Definition TCT.h:590
void collectEntryFunInCallGraph()
Get entry functions that are neither called by other functions nor extern functions.
Definition TCT.cpp:187
void pushCxt(CallStrCxt &cxt, const CallICFGNode *call, const SVFFunction *callee)
Push calling context.
Definition TCT.cpp:445
InstToLoopMap joinSiteToLoopMap
Map a CxtThread to its start routine function.
Definition TCT.h:596
void dump(const std::string &filename)
Dump the graph.
Definition TCT.cpp:514
FunSet candidateFuncSet
Procedures that are neither called by other functions nor extern functions.
Definition TCT.h:589
TCTEdge * getGraphEdge(TCTNode *src, TCTNode *dst, TCTEdge::CEDGEK kind)
Get call graph edge via nodes.
Definition TCT.cpp:552
CxtThreadProcVec ctpList
Thread call graph SCC.
Definition TCT.h:591
bool isInLoopInstruction(const ICFGNode *inst)
Multi-forked threads.
Definition TCT.cpp:46
bool isJoinMustExecutedInLoop(const LoopBBs &lp, const ICFGNode *join)
Return true if a join instruction must be executed inside a loop.
Definition TCT.cpp:291
void markRelProcs()
Mark relevant procedures that are backward reachable from any fork/join site.
Definition TCT.cpp:133
Set< const ICFGNode * > inRecurJoinSites
Fork or Join sites in recursions.
Definition TCT.h:597
void handleCallRelation(CxtThreadProc &ctp, const PTACallGraphEdge *cgEdge, const CallICFGNode *call)
Handle call relations.
Definition TCT.cpp:245
bool inSameCallGraphSCC(const PTACallGraphNode *src, const PTACallGraphNode *dst)
Whether two functions in the same callgraph scc.
Definition TCT.h:306
TCTNode * getOrCreateTCTNode(const CallStrCxt &cxt, const ICFGNode *fork, const CallStrCxt &oldCxt, const SVFFunction *routine)
Get or create a tct node based on CxtThread.
Definition TCT.h:513
bool matchCxt(CallStrCxt &cxt, const CallICFGNode *call, const SVFFunction *callee)
Match context.
Definition TCT.cpp:466
bool isCandidateFun(const PTACallGraph::FunctionSet &callees) const
Whether it is a candidate function for indirect call.
Definition TCT.h:291
void dumpCxt(CallStrCxt &cxt)
Dump calling context.
Definition TCT.cpp:496
bool addTCTEdge(TCTNode *src, TCTNode *dst)
Add TCT edge.
Definition TCT.h:461
bool isLoopHeaderOfJoinLoop(const SVFBasicBlock *bb)
Whether a given bb is a loop head of a inloop join site.
Definition TCT.cpp:340
void build()
Build TCT.
Definition TCT.cpp:384
void print() const
Print TCT information.
Definition TCT.cpp:523
ThreadCallGraph * tcg
Definition TCT.h:443
void collectMultiForkedThreads()
Definition TCT.cpp:207
CxtThreadProc popFromCTPWorkList()
Definition TCT.h:570
TCTEdge * hasGraphEdge(TCTNode *src, TCTNode *dst, TCTEdge::CEDGEK kind) const
Whether we have already created this call graph edge.
Definition TCT.cpp:535
bool isLoopExitOfJoinLoop(const SVFBasicBlock *bb)
Whether a given bb is an exit of a inloop join site.
Definition TCT.cpp:354
SVFLoopAndDomInfo::LoopBBs LoopBBs
Definition TCT.h:157
const LoopBBs & getLoop(const ICFGNode *inst)
Get loop for an instruction.
Set< const PTACallGraphNode * > PTACGNodeSet
Definition TCT.h:163
CallSiteSet::const_iterator forksitesEnd() const
CallSiteSet::const_iterator forksitesBegin() const
Fork sites iterators.
CallSiteSet::const_iterator joinsitesEnd() const
ForkEdgeSet::const_iterator getForkEdgeEnd(const CallICFGNode *cs) const
ForkEdgeSet::const_iterator getForkEdgeBegin(const CallICFGNode *cs) const
CallSiteSet::const_iterator joinsitesBegin() const
Join sites iterators.
bool isExtCall(const SVFFunction *fun)
Definition SVFUtil.h:278
void writeWrnMsg(const std::string &msg)
Writes a message run through wrnMsg.
Definition SVFUtil.cpp:67
std::ostream & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:50
for isBitcode
Definition BasicTypes.h:68
unsigned CallSiteID
Definition GeneralType.h:58
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74
std::vector< u32_t > CallStrCxt
static std::string getEdgeAttributes(TCTNode *node, EdgeIter EI, TCT *csThreadTree)
Definition TCT.cpp:605
NodeType::iterator ChildIteratorType
Definition TCT.cpp:573
static std::string getGraphName(TCT *graph)
Return name of the graph.
Definition TCT.cpp:580
static std::string getNodeAttributes(TCTNode *node, TCT *tct)
Definition TCT.cpp:590
static std::string getNodeLabel(TCTNode *node, TCT *graph)
Return function name;.
Definition TCT.cpp:585
DOTGraphTraits(bool isSimple=false)
Definition TCT.cpp:574