Static Value-Flow Analysis
ICFGBuilder.cpp
Go to the documentation of this file.
1 //===- ICFGBuilder.cpp ----------------------------------------------------------------//
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  * ICFGBuilder.cpp
26  *
27  * Created on:
28  * Author: yulei
29  */
30 
31 #include "SVF-LLVM/ICFGBuilder.h"
32 #include "SVF-LLVM/CppUtil.h"
33 #include "SVF-LLVM/LLVMModule.h"
34 #include "SVF-LLVM/LLVMUtil.h"
35 
36 using namespace SVF;
37 using namespace SVFUtil;
38 
39 
44 {
45  DBOUT(DGENERAL, outs() << pasMsg("\t Building ICFG ...\n"));
46  // Add the unique global ICFGNode at the entry of a program (before the main method).
47  addGlobalICFGNode();
48 
49  // Add function entry and exit
50  for (Module &M : llvmModuleSet()->getLLVMModules())
51  {
52  for (Module::const_iterator F = M.begin(), E = M.end(); F != E; ++F)
53  {
54  const Function *fun = &*F;
55  if (fun->isDeclaration())
56  continue;
57  addFunEntryBlock(fun);
58  addFunExitBlock(fun);
59  }
60 
61  }
62 
63  for (Module &M : llvmModuleSet()->getLLVMModules())
64  {
65  for (Module::const_iterator F = M.begin(), E = M.end(); F != E; ++F)
66  {
67  const Function *fun = &*F;
68  if (fun->isDeclaration())
69  continue;
70  WorkList worklist;
71  processFunEntry(fun,worklist);
72  processNoPrecessorBasicBlocks(fun, worklist);
73  processFunBody(worklist);
74  processFunExit(fun);
75 
76  checkICFGNodesVisited(fun);
77  }
78 
79  }
80  connectGlobalToProgEntry();
81  return icfg;
82 }
83 
85 {
86  for (const auto& bb: *fun)
87  {
88  for (const auto& inst: bb)
89  {
90  if(LLVMUtil::isIntrinsicInst(&inst))
91  continue;
92  assert(visited.count(&inst) && "inst never visited");
93  assert(hasICFGNode(&inst) && "icfgnode not created");
94  }
95  }
96 }
100 void ICFGBuilder::processFunEntry(const Function* fun, WorkList& worklist)
101 {
102  FunEntryICFGNode* FunEntryICFGNode = getFunEntryICFGNode(fun);
103  const Instruction* entryInst = &((fun->getEntryBlock()).front());
104 
105  InstVec insts;
106  if (LLVMUtil::isIntrinsicInst(entryInst))
107  LLVMUtil::getNextInsts(entryInst, insts);
108  else
109  insts.push_back(entryInst);
110  for (InstVec::const_iterator nit = insts.begin(), enit = insts.end();
111  nit != enit; ++nit)
112  {
113  visited.insert(*nit);
114  ICFGNode* instNode = addBlockICFGNode(*nit); //add interprocedural edge
115  worklist.push(*nit);
116  icfg->addIntraEdge(FunEntryICFGNode, instNode);
117  }
118 
119 
120 
121 }
122 
127 {
128  for (const auto& bb: *fun)
129  {
130  for (const auto& inst: bb)
131  {
132  if (LLVMUtil::isNoPrecessorBasicBlock(inst.getParent()) &&
133  !visited.count(&inst))
134  {
135  visited.insert(&inst);
136  (void)addBlockICFGNode(&inst);
137  worklist.push(&inst);
138  }
139  }
140  }
141 }
142 
147 {
149  while (!worklist.empty())
150  {
151  const Instruction* inst = worklist.pop();
152  ICFGNode* srcNode = getICFGNode(inst);
153  if (SVFUtil::isa<ReturnInst>(inst))
154  {
155  FunExitICFGNode* FunExitICFGNode = getFunExitICFGNode(inst->getFunction());
156  icfg->addIntraEdge(srcNode, FunExitICFGNode);
157  }
158  InstVec nextInsts;
159  LLVMUtil::getNextInsts(inst, nextInsts);
160  s64_t branchID = 0;
161  for (InstVec::const_iterator nit = nextInsts.begin(), enit =
162  nextInsts.end(); nit != enit; ++nit)
163  {
164  const Instruction* succ = *nit;
165  ICFGNode* dstNode;
166  if (visited.find(succ) != visited.end())
167  {
168  dstNode = getICFGNode(succ);
169  }
170  else
171  {
172  visited.insert(succ);
173  dstNode = addBlockICFGNode(succ);
174  worklist.push(succ);
175  }
176 
177 
179  {
180  RetICFGNode* retICFGNode = getRetICFGNode(inst);
181  srcNode = retICFGNode;
182  }
183 
184  if (const BranchInst* br = SVFUtil::dyn_cast<BranchInst>(inst))
185  {
186  assert(branchID <= 1 && "if/else has more than two branches?");
187  if(br->isConditional())
188  icfg->addConditionalIntraEdge(srcNode, dstNode, 1 - branchID);
189  else
190  icfg->addIntraEdge(srcNode, dstNode);
191  }
192  else if (const SwitchInst* si = SVFUtil::dyn_cast<SwitchInst>(inst))
193  {
195  const ConstantInt* condVal = const_cast<SwitchInst*>(si)->findCaseDest(const_cast<BasicBlock*>(succ->getParent()));
197  s64_t val = -1;
198  if (condVal && condVal->getBitWidth() <= 64)
199  val = condVal->getSExtValue();
200  icfg->addConditionalIntraEdge(srcNode, dstNode,val);
201  }
202  else
203  icfg->addIntraEdge(srcNode, dstNode);
204  branchID++;
205  }
206  }
207 }
208 
215 {
216  FunExitICFGNode* FunExitICFGNode = getFunExitICFGNode(f);
217 
218  for (const auto& bb : *f)
219  {
220  for (const auto& inst : bb)
221  {
222  if (SVFUtil::isa<ReturnInst>(&inst))
223  {
224  icfg->addIntraEdge(getICFGNode(&inst), FunExitICFGNode);
225  }
226  }
227  }
228 }
229 
230 
231 
232 
238 {
239  assert(LLVMUtil::isCallSite(inst) && "not a call instruction?");
240  assert(LLVMUtil::isNonInstricCallSite(inst) && "associating an intrinsic debug instruction with an ICFGNode!");
241  assert(llvmModuleSet()->getCallBlock(inst)==nullptr && "duplicate CallICFGNode");
242  const CallBase* cb = SVFUtil::dyn_cast<CallBase>(inst);
243  bool isvcall = cppUtil::isVirtualCallSite(cb);
244  SVFFunction* calledFunc = nullptr;
245  auto called_llvmval = cb->getCalledOperand()->stripPointerCasts();
246  if (const Function* called_llvmfunc = SVFUtil::dyn_cast<Function>(called_llvmval))
247  {
248  calledFunc = llvmModuleSet()->getSVFFunction(called_llvmfunc);
249  }
250  else
251  {
252  calledFunc = SVFUtil::dyn_cast<SVFFunction>(
253  llvmModuleSet()->getSVFValue(called_llvmval));
254  }
255 
256  SVFBasicBlock* bb = llvmModuleSet()->getSVFBasicBlock(inst->getParent());
257 
258  CallICFGNode* callICFGNode = icfg->addCallICFGNode(
259  bb, llvmModuleSet()->getSVFType(inst->getType()),
260  calledFunc, cb->getFunctionType()->isVarArg(), isvcall,
261  isvcall ? cppUtil::getVCallIdx(cb) : 0,
262  isvcall ? cppUtil::getFunNameOfVCallSite(cb) : "");
263  csToCallNodeMap()[inst] = callICFGNode;
264  llvmModuleSet()->setValueAttr(inst, callICFGNode);
265 
266  assert(llvmModuleSet()->getRetBlock(inst)==nullptr && "duplicate RetICFGNode");
267  RetICFGNode* retICFGNode = icfg->addRetICFGNode(callICFGNode);
268  csToRetNodeMap()[inst] = retICFGNode;
269  llvmModuleSet()->setValueAttr(inst, retICFGNode);
270 
271  addICFGInterEdges(inst, LLVMUtil::getCallee(SVFUtil::cast<CallBase>(inst))); //creating interprocedural edges
272  return callICFGNode;
273 }
274 
279 {
280 
281  CallICFGNode* callICFGNode = getCallICFGNode(cs);
282  RetICFGNode* retBlockNode = getRetICFGNode(cs);
283 
285  if(callee)
286  {
287  SVFFunction* svfFun =
288  llvmModuleSet()->getSVFFunction(callee);
290  if (SVFUtil::isExtCall(svfFun))
291  {
292  icfg->addIntraEdge(callICFGNode, retBlockNode);
293  }
295  else
296  {
297  FunEntryICFGNode* calleeEntryNode = getFunEntryICFGNode(callee);
298  FunExitICFGNode* calleeExitNode = getFunExitICFGNode(callee);
299  icfg->addCallEdge(callICFGNode, calleeEntryNode);
300  icfg->addRetEdge(calleeExitNode, retBlockNode);
301  }
302  }
304  else
305  {
306  icfg->addIntraEdge(callICFGNode, retBlockNode);
307  }
308 }
309 /*
310 * Add the global initialization statements immediately after the function entry of main
311 */
313 {
314  for (Module &M : llvmModuleSet()->getLLVMModules())
315  {
316  if (const Function* mainFunc = LLVMUtil::getProgEntryFunction(M))
317  {
318  // main function
319  FunEntryICFGNode* entryNode = getFunEntryICFGNode(mainFunc);
320  GlobalICFGNode* globalNode = getGlobalICFGNode();
321  IntraCFGEdge* intraEdge = new IntraCFGEdge(globalNode, entryNode);
322  icfg->addICFGEdge(intraEdge);
323  }
324  else
325  {
326  // not main function
327  }
328  }
329 }
330 
332 {
333  ICFGNode* node;
335  node = addInterBlockICFGNode(inst);
336  else
337  node = addIntraBlockICFGNode(inst);
338  const_cast<SVFBasicBlock*>(
339  llvmModuleSet()->getSVFBasicBlock(inst->getParent()))
340  ->addICFGNode(node);
341  return node;
342 }
343 
345 {
346  IntraICFGNode* node = llvmModuleSet()->getIntraBlock(inst);
347  assert (node==nullptr && "no IntraICFGNode for this instruction?");
348  IntraICFGNode* sNode = icfg->addIntraICFGNode(
349  llvmModuleSet()->getSVFBasicBlock(inst->getParent()), SVFUtil::isa<ReturnInst>(inst));
350  instToBlockNodeMap()[inst] = sNode;
351  llvmModuleSet()->setValueAttr(inst, sNode);
352  return sNode;
353 }
354 
356 {
357  return funToFunEntryNodeMap()[fun] =
358  icfg->addFunEntryICFGNode(llvmModuleSet()->getSVFFunction(fun));
359 }
360 
362 {
363  return funToFunExitNodeMap()[fun] =
364  icfg->addFunExitICFGNode(llvmModuleSet()->getSVFFunction(fun));
365 }
#define F(f)
#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
bool push(const Data &data)
Definition: WorkList.h:165
bool empty() const
Definition: WorkList.h:146
FunEntryICFGNode * addFunEntryBlock(const Function *fun)
void connectGlobalToProgEntry()
IntraICFGNode * addIntraBlockICFGNode(const Instruction *inst)
Add and get IntraBlock ICFGNode.
std::vector< const Instruction * > InstVec
Definition: ICFGBuilder.h:46
void processNoPrecessorBasicBlocks(const Function *fun, WorkList &worklist)
InterICFGNode * addInterBlockICFGNode(const Instruction *inst)
Add/Get an inter block ICFGNode.
void processFunBody(WorkList &worklist)
void checkICFGNodesVisited(const Function *fun)
Definition: ICFGBuilder.cpp:84
void processFunEntry(const Function *fun, WorkList &worklist)
FunExitICFGNode * addFunExitBlock(const Function *fun)
ICFGNode * addBlockICFGNode(const Instruction *inst)
Add/Get a basic block ICFGNode.
void addICFGInterEdges(const Instruction *cs, const Function *callee)
Create edges between ICFG nodes across functions.
void processFunExit(const Function *fun)
Definition: ICFG.h:48
const SVFFunctionType * getFunctionType() const
Returns the FunctionType.
Definition: SVFValue.h:382
bool isIntrinsicInst(const Instruction *inst)
Return true if it is an intrinsic instruction.
Definition: LLVMUtil.cpp:204
bool isNoPrecessorBasicBlock(const BasicBlock *bb)
Definition: LLVMUtil.h:297
bool isCallSite(const Instruction *inst)
Whether an instruction is a call or invoke instruction.
Definition: LLVMUtil.h:45
void getNextInsts(const Instruction *curInst, std::vector< const Instruction * > &instList)
Get the next instructions following control flow.
Definition: LLVMUtil.cpp:551
const Function * getProgEntryFunction(Module &module)
Get program entry function from module.
Definition: LLVMUtil.h:367
const Function * getCallee(const CallBase *cs)
Definition: LLVMUtil.h:63
bool isNonInstricCallSite(const Instruction *inst)
Whether an instruction is a callsite in the application code, excluding llvm intrinsic calls.
Definition: LLVMUtil.cpp:649
bool isExtCall(const SVFFunction *fun)
Definition: SVFUtil.h:278
std::string pasMsg(const std::string &msg)
Print each pass/phase message by converting a string into blue string output.
Definition: SVFUtil.cpp:99
std::ostream & outs()
Overwrite llvm::outs()
Definition: SVFUtil.h:50
std::string getFunNameOfVCallSite(const CallBase *cs)
Definition: CppUtil.cpp:635
s32_t getVCallIdx(const CallBase *cs)
Definition: CppUtil.cpp:646
bool isVirtualCallSite(const CallBase *cs)
Definition: CppUtil.cpp:352
for isBitcode
Definition: BasicTypes.h:68
llvm::CallBase CallBase
Definition: BasicTypes.h:146
llvm::BasicBlock BasicBlock
Definition: BasicTypes.h:86
llvm::SwitchInst SwitchInst
Definition: BasicTypes.h:155
llvm::Function Function
Definition: BasicTypes.h:85
llvm::Instruction Instruction
Definition: BasicTypes.h:87
llvm::Module Module
Definition: BasicTypes.h:84
llvm::BranchInst BranchInst
Definition: BasicTypes.h:154
signed long long s64_t
Definition: GeneralType.h:49
llvm::ConstantInt ConstantInt
Definition: BasicTypes.h:125