Static Value-Flow Analysis
PCG.cpp
Go to the documentation of this file.
1 //===- PCG.cpp -- Procedure creation graph-------------//
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  * PCG.cpp
25  *
26  * Created on: Jun 24, 2015
27  * Author: Yulei Sui, Peng Di
28  */
29 
30 #include "Util/CommandLine.h"
31 #include "Util/Options.h"
32 #include "MTA/PCG.h"
33 #include "Util/SVFUtil.h"
34 
35 using namespace SVF;
36 using namespace SVFUtil;
37 
38 //=====================================================//
43 //static Option<bool> TDPrint(
44 // "print-td",
45 // true,
46 // "Print Thread Analysis Results"
47 //);
48 
50 {
51 
52  //callgraph = new PTACallGraph(mod);
53 
54  DBOUT(DMTA, outs() << pasMsg("Starting MHP analysis\n"));
55 
56  initFromThreadAPI(mod);
57 
58  inferFromCallGraph();
59 
60  //interferenceAnalysis();
61 
62  //if (Options::TDPrint()) {
63  //printResults();
64  //tdAPI->performAPIStat(mod);
65  //}
66  return false;
67 }
68 
70 {
71  // if neither of functions are spawnees, then they won't happen in parallel
72  if (isSpawneeFun(fun1) == false && isSpawneeFun(fun2) == false)
73  return false;
74  // if there exit one of the function are not spawner, spawnee or follower, then they won't happen in parallel
75  if (isSpawnerFun(fun1) == false && isSpawneeFun(fun1) == false && isFollowerFun(fun1) == false)
76  return false;
77  if (isSpawnerFun(fun2) == false && isSpawneeFun(fun2) == false && isFollowerFun(fun2) == false)
78  return false;
79 
80  return true;
81 }
82 
83 bool PCG::mayHappenInParallel(const SVFInstruction* i1, const SVFInstruction* i2) const
84 {
85  const SVFFunction* fun1 = i1->getFunction();
86  const SVFFunction* fun2 = i2->getFunction();
87  return mayHappenInParallelBetweenFunctions(fun1, fun2);
88 }
89 
90 
97 {
98  for (const SVFFunction* fun : module->getFunctionSet())
99  {
100  for (const SVFBasicBlock* svfbb : fun->getBasicBlockList())
101  {
102  for (const SVFInstruction* inst : svfbb->getInstructionList())
103  {
104  if (tdAPI->isTDFork(inst))
105  {
106  const SVFValue* forkVal = tdAPI->getForkedFun(inst);
107  if (const SVFFunction* svForkfun = SVFUtil::dyn_cast<SVFFunction>(forkVal))
108  {
109  addSpawnsite(inst);
110  spawners.insert(fun);
111  spawnees.insert(svForkfun);
112  }
114  else
115  {
116  writeWrnMsg("pthread create");
117  outs() << inst->toString() << "\n";
118  writeWrnMsg("invoke spawnee indirectly");
119  }
120  }
121  }
122  }
123  }
124 }
125 
134 {
135 
136  collectSpawners();
137 
138  collectSpawnees();
139 
140  collectFollowers();
141 }
142 
147 {
148 
150  FunWorkList worklist;
151  for (FunSet::iterator it = spawners.begin(), eit = spawners.end(); it != eit; ++it)
152  {
153  worklist.push(*it);
154  }
155  while (!worklist.empty())
156  {
157  const SVFFunction* svffun = worklist.pop();
158  PTACallGraphNode* funNode = callgraph->getCallGraphNode(svffun);
159  for (PTACallGraphNode::const_iterator it = funNode->InEdgeBegin(), eit = funNode->InEdgeEnd(); it != eit;
160  ++it)
161  {
162  PTACallGraphEdge* callEdge = (*it);
163  const SVFFunction* caller = callEdge->getSrcNode()->getFunction();
164  if (isSpawnerFun(caller) == false)
165  {
166  worklist.push(caller);
167  addSpawnerFun(caller);
168  }
170  for (PTACallGraphEdge::CallInstSet::const_iterator dit = callEdge->directCallsBegin(), deit =
171  callEdge->directCallsEnd(); dit != deit; ++dit)
172  {
173  addSpawnsite((*dit)->getCallSite());
174  }
175  for (PTACallGraphEdge::CallInstSet::const_iterator dit = callEdge->indirectCallsBegin(), deit =
176  callEdge->indirectCallsEnd(); dit != deit; ++dit)
177  {
178  addSpawnsite((*dit)->getCallSite());
179  }
180  }
181  }
182 }
183 
188 {
189 
191  FunWorkList worklist;
192  for (FunSet::iterator it = spawnees.begin(), eit = spawnees.end(); it != eit; ++it)
193  {
194  worklist.push(*it);
195  }
196  while (!worklist.empty())
197  {
198  const SVFFunction* svffun = worklist.pop();
199  PTACallGraphNode* funNode = callgraph->getCallGraphNode(svffun);
200  for (PTACallGraphNode::const_iterator it = funNode->OutEdgeBegin(), eit = funNode->OutEdgeEnd(); it != eit;
201  ++it)
202  {
203  const SVFFunction* caller = (*it)->getDstNode()->getFunction();
204  if (isSpawneeFun(caller) == false)
205  {
206  worklist.push(caller);
207  addSpawneeFun(caller);
208  }
209  }
210  }
211 }
212 
218 {
219 
220  for (CallInstSet::const_iterator sit = spawnSitesBegin(), esit = spawnSitesEnd(); sit != esit; ++sit)
221  {
222  const SVFInstruction* inst = *sit;
223  BBWorkList bb_worklist;
224  Set<const SVFBasicBlock*> visitedBBs;
225  bb_worklist.push(inst->getParent());
226  while (!bb_worklist.empty())
227  {
228  const SVFBasicBlock* bb = bb_worklist.pop();
229  for (SVFBasicBlock::const_iterator it = bb->begin(), eit = bb->end(); it != eit; ++it)
230  {
231  const SVFInstruction* inst = *it;
232  // mark the callee of this callsite as follower
233  // if this is an call/invoke instruction but not a spawn site
234  if ((SVFUtil::isCallSite(inst)) && !isSpawnsite(inst) && !SVFUtil::isIntrinsicInst(inst))
235  {
236  CallICFGNode* cbn = getCallICFGNode(inst);
237  if (callgraph->hasCallGraphEdge(cbn))
238  {
239  for (PTACallGraph::CallGraphEdgeSet::const_iterator cgIt = callgraph->getCallEdgeBegin(cbn),
240  ecgIt = callgraph->getCallEdgeEnd(cbn); cgIt != ecgIt; ++cgIt)
241  {
242  const PTACallGraphEdge* edge = *cgIt;
243  addFollowerFun(edge->getDstNode()->getFunction());
244  }
245  }
246  }
247  }
248  for (const SVFBasicBlock* svf_scc_bb : bb->getSuccessors())
249  {
250  if (visitedBBs.count(svf_scc_bb) == 0)
251  {
252  visitedBBs.insert(svf_scc_bb);
253  bb_worklist.push(svf_scc_bb);
254  }
255  }
256  }
257  }
258 
259 }
260 
266 {
267 
269  identifyFollowers();
270 
272  FunWorkList worklist;
273  for (FunSet::iterator it = followers.begin(), eit = followers.end(); it != eit; ++it)
274  {
275  worklist.push(*it);
276  }
277  while (!worklist.empty())
278  {
279  const SVFFunction* svffun = worklist.pop();
280  PTACallGraphNode* funNode = callgraph->getCallGraphNode(svffun);
281  for (PTACallGraphNode::const_iterator it = funNode->OutEdgeBegin(), eit = funNode->OutEdgeEnd(); it != eit;
282  ++it)
283  {
284  const SVFFunction* caller = (*it)->getDstNode()->getFunction();
285  if (isFollowerFun(caller) == false)
286  {
287  worklist.push(caller);
288  addFollowerFun(caller);
289  }
290  }
291  }
292 }
293 
303 {
304 
305 // DBOUT(DMTA, outs() << pasMsg("Starting Race Detection\n"));
306 
307  PCG::FunVec worklist;
308  for (SVFModule::const_iterator F = mod->begin(), E = mod->end(); F != E; ++F)
309  {
310  const SVFFunction* fun = *F;
311  if (isExtCall(fun))
312  continue;
313  worklist.push_back(fun);
314  }
315 
316  while (!worklist.empty())
317  {
318  const SVFFunction* fun1 = worklist.back();
319  worklist.pop_back();
320 
321  bool ismhpfun = false;
322  for (PCG::FunVec::iterator it = worklist.begin(), eit = worklist.end(); it != eit; ++it)
323  {
324  const SVFFunction* fun2 = *it;
325  if (mayHappenInParallelBetweenFunctions(fun1, fun2))
326  {
327  ismhpfun = true;
328  mhpfuns.insert(fun2);
329  }
330  }
331  if (ismhpfun)
332  {
333  mhpfuns.insert(fun1);
334  }
335  }
336 }
337 
342 {
343 
344  printTDFuns();
345 }
346 
351 {
352 
353  for (SVFModule::const_iterator fi = mod->begin(), efi = mod->end(); fi != efi; ++fi)
354  {
355  const SVFFunction* fun = (*fi);
356  if (fun->isDeclaration())
357  continue;
358 
359  std::string isSpawner = isSpawnerFun(fun) ? " SPAWNER " : "";
360  std::string isSpawnee = isSpawneeFun(fun) ? " CHILDREN " : "";
361  std::string isFollower = isFollowerFun(fun) ? " FOLLOWER " : "";
362  outs() << fun->getName() << " [" << isSpawner << isSpawnee << isFollower << "]\n";
363  }
364 }
#define F(f)
#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
const char *const string
Definition: cJSON.h:172
bool push(const Data &data)
Definition: WorkList.h:165
bool empty() const
Definition: WorkList.h:146
NodeType * getSrcNode() const
Definition: GenericGraph.h:97
NodeType * getDstNode() const
Definition: GenericGraph.h:101
iterator OutEdgeEnd()
Definition: GenericGraph.h:221
iterator OutEdgeBegin()
iterators
Definition: GenericGraph.h:217
iterator InEdgeBegin()
Definition: GenericGraph.h:225
iterator InEdgeEnd()
Definition: GenericGraph.h:229
void interferenceAnalysis()
Thread interferenceAnalysis.
Definition: PCG.cpp:302
void collectFollowers()
Definition: PCG.cpp:265
virtual bool mayHappenInParallel(const SVFInstruction *i1, const SVFInstruction *i2) const
Interface to query whether two function may happen-in-parallel.
Definition: PCG.cpp:83
std::vector< const SVFFunction * > FunVec
Definition: PCG.h:55
void initFromThreadAPI(SVFModule *module)
Initialize spawner and spawnee sets with threadAPI.
Definition: PCG.cpp:96
virtual bool analyze()
We start the pass here.
Definition: PCG.cpp:49
void collectSpawnees()
Definition: PCG.cpp:187
void printResults()
Print analysis results.
Definition: PCG.cpp:341
void inferFromCallGraph()
Infer spawner spawnee and followers sets by traversing on callGraph.
Definition: PCG.cpp:133
void identifyFollowers()
Definition: PCG.cpp:217
void collectSpawners()
Definition: PCG.cpp:146
bool mayHappenInParallelBetweenFunctions(const SVFFunction *fun1, const SVFFunction *fun2) const
Definition: PCG.cpp:69
void printTDFuns()
Definition: PCG.cpp:350
CallInstSet::const_iterator indirectCallsEnd() const
Definition: PTACallGraph.h:135
CallInstSet::const_iterator directCallsBegin() const
Iterators for direct and indirect callsites.
Definition: PTACallGraph.h:122
CallInstSet::const_iterator directCallsEnd() const
Definition: PTACallGraph.h:126
CallInstSet::const_iterator indirectCallsBegin() const
Definition: PTACallGraph.h:131
PTACallGraphEdge::CallGraphEdgeSet::const_iterator const_iterator
Definition: PTACallGraph.h:180
const std::vector< const SVFBasicBlock * > & getSuccessors() const
Definition: SVFValue.h:612
std::vector< const SVFInstruction * >::const_iterator const_iterator
Definition: SVFValue.h:536
const_iterator end() const
Definition: SVFValue.h:583
const_iterator begin() const
Definition: SVFValue.h:578
const SVFBasicBlock * back() const
Definition: SVFValue.h:427
bool isDeclaration() const
Definition: SVFValue.h:367
const SVFBasicBlock * getParent() const
Definition: SVFValue.h:658
const SVFFunction * getFunction() const
Definition: SVFValue.h:683
const FunctionSetType & getFunctionSet() const
Definition: SVFModule.h:216
FunctionSetType::const_iterator const_iterator
Definition: SVFModule.h:54
const std::string & getName() const
Definition: SVFValue.h:243
bool isExtCall(const SVFFunction *fun)
Definition: SVFUtil.h:309
std::string pasMsg(const std::string &msg)
Print each pass/phase message by converting a string into blue string output.
Definition: SVFUtil.cpp:99
void writeWrnMsg(const std::string &msg)
Writes a message run through wrnMsg.
Definition: SVFUtil.cpp:66
bool isIntrinsicInst(const SVFInstruction *inst)
Return true if it is an llvm intrinsic instruction.
Definition: SVFUtil.cpp:247
std::ostream & outs()
Overwrite llvm::outs()
Definition: SVFUtil.h:50
bool isCallSite(const SVFInstruction *inst)
Whether an instruction is a call or invoke instruction.
Definition: SVFUtil.h:174
for isBitcode
Definition: BasicTypes.h:68
std::unordered_set< Key, Hash, KeyEqual, Allocator > Set
Definition: GeneralType.h:96