Static Value-Flow Analysis
Loading...
Searching...
No Matches
ThreadCallGraph.cpp
Go to the documentation of this file.
1//===- ThreadCallGraph.cpp -- Call graph considering thread fork/join---------//
2//
3// SVF: Static Value-Flow Analysis
4//
5// Copyright (C) <2013-2017> <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 * ThreadCallGraph.cpp
25 *
26 * Created on: Jul 12, 2014
27 * Author: Yulei Sui, Peng Di, Ding Ye
28 */
29
30#include "SVFIR/SVFModule.h"
32#include "Util/ThreadAPI.h"
33#include "SVFIR/SVFIR.h"
35#include "Graphs/CallGraph.h"
36
37using namespace SVF;
38using namespace SVFUtil;
39
44 PTACallGraph(cg), tdAPI(ThreadAPI::getThreadAPI())
45{
47 DBOUT(DGENERAL, outs() << SVFUtil::pasMsg("Building ThreadCallGraph\n"));
48}
49
50
51/*
52 * Update call graph using pointer analysis results
53 * (1) resolve function pointers for non-fork calls
54 * (2) resolve function pointers for fork sites
55 * (3) resolve function pointers for parallel_for sites
56 */
58{
59
60 PointerAnalysis::CallEdgeMap::const_iterator iter = pta->getIndCallMap().begin();
61 PointerAnalysis::CallEdgeMap::const_iterator eiter = pta->getIndCallMap().end();
62 for (; iter != eiter; iter++)
63 {
64 const CallICFGNode* cs = iter->first;
66 for (PTACallGraph::FunctionSet::const_iterator func_iter =
67 functions.begin(); func_iter != functions.end(); func_iter++)
68 {
71 }
72 }
73
74 // Fork sites
75 for (CallSiteSet::const_iterator it = forksitesBegin(), eit = forksitesEnd(); it != eit; ++it)
76 {
78 if(SVFUtil::dyn_cast<FunValVar>(forkedval)==nullptr)
79 {
80 SVFIR* pag = pta->getPAG();
81 const NodeBS targets = pta->getPts(forkedval->getId()).toNodeBS();
82 for (NodeBS::iterator ii = targets.begin(), ie = targets.end(); ii != ie; ii++)
83 {
84 if(ObjVar* objPN = SVFUtil::dyn_cast<ObjVar>(pag->getGNode(*ii)))
85 {
86 const MemObj* obj = pag->getObject(objPN);
87 if(obj->isFunction())
88 {
89 const SVFFunction* svfCallee = SVFUtil::cast<CallGraphNode>(obj->getGNode())->getFunction();
91 }
92 }
93 }
94 }
95 }
96}
97
98
103{
104
105 for (CallSiteSet::const_iterator it = joinsitesBegin(), eit = joinsitesEnd(); it != eit; ++it)
106 {
108 // find its corresponding fork sites first
110 for (CallSiteSet::const_iterator it = forksitesBegin(), eit = forksitesEnd(); it != eit; ++it)
111 {
113 if (pta->alias(jointhread->getId(), forkthread->getId()))
114 {
115 forkset.insert(*it);
116 }
117 }
118 assert(!forkset.empty() && "Can't find a forksite for this join!!");
120 }
121}
122
127{
128
130 const SVFFunction* forkee = SVFUtil::dyn_cast<FunValVar>(tdAPI->getForkedFun(cs))
132 assert(forkee && "callee does not exist");
133 PTACallGraphNode* callee = getCallGraphNode(forkee->getDefFunForMultipleModule());
134 CallSiteID csId = addCallSite(cs, callee->getFunction());
135
137 {
138 assert(cs->getCaller() == caller->getFunction() && "callee instruction not inside caller??");
139
141 edge->addDirectCallSite(cs);
142
143 addEdge(edge);
145 return true;
146 }
147 else
148 return false;
149}
150
155{
158
159 CallSiteID csId = addCallSite(cs, callee->getFunction());
160
162 {
163 assert(cs->getCaller() == caller->getFunction() && "callee instruction not inside caller??");
164
166 edge->addInDirectCallSite(cs);
167
168 addEdge(edge);
170 return true;
171 }
172 else
173 return false;
174}
175
183{
184
186
187 for (CallSiteSet::const_iterator it = forkset.begin(), eit = forkset.end(); it != eit; ++it)
188 {
189
191 SVFUtil::dyn_cast<FunValVar>(tdAPI->getForkedFun(*it))
193 ->getFunction();
194 assert(threadRoutineFun && "thread routine function does not exist");
197
199 {
200 assert(cs->getCaller() == joinFunNode->getFunction() && "callee instruction not inside caller??");
202 edge->addDirectCallSite(cs);
203
205 }
206 }
207}
#define DBOUT(TYPE, X)
LLVM debug macros, define type of your DBUG model of each pass.
Definition SVFType.h:484
#define DGENERAL
Definition SVFType.h:490
const SVFFunction * getFunction() const
Get function of this call node.
Definition CallGraph.h:131
const SVFFunction * getCaller() const
Return callsite.
Definition ICFGNode.h:470
NodeType * getGNode(NodeID id) const
Get a node.
void addEdge(PTACallGraphEdge *edge)
Add call graph edge.
void addIndirectCallGraphEdge(const CallICFGNode *cs, const SVFFunction *callerFun, const SVFFunction *calleeFun)
Add indirect call edges.
Set< const SVFFunction * > FunctionSet
PTACallGraphEdge * hasGraphEdge(PTACallGraphNode *src, PTACallGraphNode *dst, PTACallGraphEdge::CEDGEK kind, CallSiteID csId) const
Whether we have already created this call graph edge.
CallSiteID addCallSite(const CallICFGNode *cs, const SVFFunction *callee)
Add CallSiteID.
PTACallGraphNode * getCallGraphNode(NodeID id) const
Get call graph node.
virtual const PointsTo & getPts(NodeID ptr)=0
Get points-to targets of a pointer. It needs to be implemented in child class.
SVFIR * getPAG() const
CallEdgeMap & getIndCallMap()
Get callees from an indirect callsite.
virtual AliasResult alias(const SVFValue *V1, const SVFValue *V2)=0
Interface exposed to users of our pointer analysis, given Value infos.
NodeBS toNodeBS() const
Returns this points-to set as a NodeBS.
Definition PointsTo.cpp:313
const CallGraphNode * getCallGraphNode() const
Definition SVFValue.h:363
const MemObj * getObject(NodeID id) const
Definition SVFIR.h:396
const ValVar * getForkedFun(const CallICFGNode *inst) const
const ValVar * getForkedThread(const CallICFGNode *inst) const
Return arguments/attributes of pthread_create / hare_parallel_for.
const SVFVar * getJoinedThread(const CallICFGNode *inst) const
Return arguments/attributes of pthread_join.
CallSiteSet::const_iterator forksitesEnd() const
bool addIndirectForkEdge(const CallICFGNode *cs, const SVFFunction *callee)
bool addDirectForkEdge(const CallICFGNode *cs)
Add direct/indirect thread fork edges.
CallSiteSet::const_iterator forksitesBegin() const
Fork sites iterators.
void updateJoinEdge(PointerAnalysis *pta)
Update join edge using pointer analysis results.
CallSiteSet::const_iterator joinsitesEnd() const
bool hasThreadJoinEdge(const CallICFGNode *cs) const
Get call graph edge via call instruction.
void addThreadJoinEdgeSetMap(const CallICFGNode *cs, ThreadJoinEdge *edge)
map call instruction to its PTACallGraphEdge map
void addDirectJoinEdge(const CallICFGNode *cs, const CallSiteSet &forksite)
Add thread join edges.
CallSiteSet::const_iterator joinsitesBegin() const
Join sites iterators.
void addThreadForkEdgeSetMap(const CallICFGNode *cs, ThreadForkEdge *edge)
map call instruction to its PTACallGraphEdge map
void updateCallGraph(PointerAnalysis *pta)
Update call graph using pointer results.
ThreadCallGraph(const CallGraph &cg)
Constructor.
ThreadAPI * tdAPI
Thread API.
std::string pasMsg(const std::string &msg)
Print each pass/phase message by converting a string into blue string output.
Definition SVFUtil.cpp:100
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