Static Value-Flow Analysis
CFLAlias.cpp
Go to the documentation of this file.
1 //===----- CFLAlias.cpp -- CFL Alias Analysis Client--------------//
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  * CFLAlias.cpp
25  *
26  * Created on: June 27 , 2022
27  * Author: Pei Xu
28  */
29 
30 #include "CFL/CFLAlias.h"
31 using namespace SVF;
32 using namespace SVFUtil;
33 
40 {
41  for(CallSiteToFunPtrMap::const_iterator iter = callsites.begin(), eiter = callsites.end(); iter!=eiter; ++iter)
42  {
43  const CallICFGNode* cs = iter->first;
44 
45  if (cs->isVirtualCall())
46  {
47  const SVFVar* vtbl = cs->getVtablePtr();
48 
49  assert(vtbl != nullptr);
50  NodeID vtblId = vtbl->getId();
51  resolveCPPIndCalls(cs, getCFLPts(vtblId), newEdges);
52  }
53  else
54  resolveIndCalls(iter->first,getCFLPts(iter->second),newEdges);
55  }
56 }
57 
63 {
64  assert(F);
65 
66  DBOUT(DAndersen, outs() << "connect parameters from indirect callsite " << cs->toString() << " to callee " << *F << "\n");
67 
68  const CallICFGNode* callBlockNode = cs;
69  const RetICFGNode* retBlockNode = cs->getRetICFGNode();
70 
71  if(SVFUtil::isHeapAllocExtFunViaRet(F) && svfir->callsiteHasRet(retBlockNode))
72  {
73  heapAllocatorViaIndCall(cs);
74  }
75 
76  if (svfir->funHasRet(F) && svfir->callsiteHasRet(retBlockNode))
77  {
78  const PAGNode* cs_return = svfir->getCallSiteRet(retBlockNode);
79  const PAGNode* fun_return = svfir->getFunRet(F);
80  if (cs_return->isPointer() && fun_return->isPointer())
81  {
82  NodeID dstrec = cs_return->getId();
83  NodeID srcret = fun_return->getId();
84  addCopyEdge(srcret, dstrec);
85  }
86  else
87  {
88  DBOUT(DAndersen, outs() << "not a pointer ignored\n");
89  }
90  }
91 
92  if (svfir->hasCallSiteArgsMap(callBlockNode) && svfir->hasFunArgsList(F))
93  {
94 
95  // connect actual and formal param
96  const SVFIR::SVFVarList& csArgList = svfir->getCallSiteArgsList(callBlockNode);
97  const SVFIR::SVFVarList& funArgList = svfir->getFunArgsList(F);
98  //Go through the fixed parameters.
99  DBOUT(DPAGBuild, outs() << " args:");
100  SVFIR::SVFVarList::const_iterator funArgIt = funArgList.begin(), funArgEit = funArgList.end();
101  SVFIR::SVFVarList::const_iterator csArgIt = csArgList.begin(), csArgEit = csArgList.end();
102  for (; funArgIt != funArgEit; ++csArgIt, ++funArgIt)
103  {
104  //Some programs (e.g. Linux kernel) leave unneeded parameters empty.
105  if (csArgIt == csArgEit)
106  {
107  DBOUT(DAndersen, outs() << " !! not enough args\n");
108  break;
109  }
110  const PAGNode *cs_arg = *csArgIt ;
111  const PAGNode *fun_arg = *funArgIt;
112 
113  if (cs_arg->isPointer() && fun_arg->isPointer())
114  {
115  DBOUT(DAndersen, outs() << "process actual parm " << cs_arg->toString() << " \n");
116  NodeID srcAA = cs_arg->getId();
117  NodeID dstFA = fun_arg->getId();
118  addCopyEdge(srcAA, dstFA);
119  }
120  }
121 
122  //Any remaining actual args must be varargs.
123  if (F->isVarArg())
124  {
125  NodeID vaF = svfir->getVarargNode(F);
126  DBOUT(DPAGBuild, outs() << "\n varargs:");
127  for (; csArgIt != csArgEit; ++csArgIt)
128  {
129  const PAGNode *cs_arg = *csArgIt;
130  if (cs_arg->isPointer())
131  {
132  NodeID vnAA = cs_arg->getId();
133  addCopyEdge(vnAA,vaF);
134  }
135  }
136  }
137  if(csArgIt != csArgEit)
138  {
139  writeWrnMsg("too many args to non-vararg func.");
140  writeWrnMsg("(" + cs->getSourceLoc() + ")");
141  }
142  }
143 }
144 
146 {
147  assert(cs->getCalledFunction() == nullptr && "not an indirect callsite?");
148  const RetICFGNode* retBlockNode = cs->getRetICFGNode();
149  const PAGNode* cs_return = svfir->getCallSiteRet(retBlockNode);
150  NodeID srcret;
151  CallSite2DummyValPN::const_iterator it = callsite2DummyValPN.find(cs);
152  if(it != callsite2DummyValPN.end())
153  {
154  srcret = it->second;
155  }
156  else
157  {
158  NodeID valNode = svfir->addDummyValNode();
159  NodeID objNode = svfir->addDummyObjNode(cs->getType());
160  callsite2DummyValPN.insert(std::make_pair(cs,valNode));
161  graph->addCFLNode(valNode, new CFLNode(valNode));
162  graph->addCFLNode(objNode, new CFLNode(objNode));
163  srcret = valNode;
164  }
165 
166  NodeID dstrec = cs_return->getId();
167  addCopyEdge(srcret, dstrec);
168 }
169 
174 {
175  CallEdgeMap newEdges;
176  onTheFlyCallGraphSolve(callsites,newEdges);
177  for(CallEdgeMap::iterator it = newEdges.begin(), eit = newEdges.end(); it!=eit; ++it )
178  {
179  for(FunctionSet::iterator cit = it->second.begin(), ecit = it->second.end(); cit!=ecit; ++cit)
180  {
181  connectCaller2CalleeParams(it->first,*cit);
182  }
183  }
184 
185  return (!solver->isWorklistEmpty());
186 }
187 
189 {
190  stat = new CFLStat(this);
191 
192  // Parameter Checking
193  checkParameter();
194 
195  // Build CFL Grammar
196  buildCFLGrammar();
197 
198  // Build CFL Graph
199  buildCFLGraph();
200 
201  // Normalize CFL Grammar
202  normalizeCFLGrammar();
203 
204  // Initialize solver
205  initializeSolver();
206 }
207 
209 {
210  solver = new CFLSolver(graph, grammar);
211 }
212 
214 {
215  numOfChecks = solver->numOfChecks;
216 
217  if(Options::PrintCFL() == true)
218  {
219  if (Options::CFLGraph().empty())
220  svfir->dump("IR");
221  grammar->dump("Grammar");
222  graph->dump("CFLGraph");
223  }
224  if (Options::CFLGraph().empty())
226 }
227 
229 {
230  // Start solving
231  double start = stat->getClk(true);
232 
233  solver->solve();
234  if (Options::CFLGraph().empty())
235  {
236  while (updateCallGraph(svfir->getIndirectCallsites()))
237  {
238  numOfIteration++;
239  solver->solve();
240  }
241  } // Only cflgraph built from bc could reanalyze by update call graph
242 
243  double end = stat->getClk(true);
244  timeOfSolving += (end - start) / TIMEINTERVAL;
245 }
246 
248 {
249  solver = new POCRSolver(graph, grammar);
250 }
251 
253 {
254  solver = new POCRHybridSolver(graph, grammar);
255 }
#define F(f)
#define DBOUT(TYPE, X)
LLVM debug macros, define type of your DBUG model of each pass.
Definition: SVFType.h:484
#define TIMEINTERVAL
Definition: SVFType.h:512
#define DPAGBuild
Definition: SVFType.h:492
#define DAndersen
Definition: SVFType.h:503
virtual void finalize()
Print grammar and graph.
Definition: CFLAlias.cpp:213
virtual void onTheFlyCallGraphSolve(const CallSiteToFunPtrMap &callsites, CallEdgeMap &newEdges)
On the fly call graph construction.
Definition: CFLAlias.cpp:39
virtual void initializeSolver()
Initialize Solver.
Definition: CFLAlias.cpp:208
void connectCaller2CalleeParams(const CallICFGNode *cs, const SVFFunction *F)
Connect formal and actual parameters for indirect callsites.
Definition: CFLAlias.cpp:62
void heapAllocatorViaIndCall(const CallICFGNode *cs)
Definition: CFLAlias.cpp:145
virtual void solve()
Solving CFL Reachability.
Definition: CFLAlias.cpp:228
virtual bool updateCallGraph(const CallSiteToFunPtrMap &callsites)
Update call graph for the input indirect callsites.
Definition: CFLAlias.cpp:173
virtual void initialize()
Initialize the grammar, graph, solver.
Definition: CFLAlias.cpp:188
const SVFFunction * getCalledFunction() const
Definition: ICFGNode.h:518
const std::string toString() const override
Definition: ICFG.cpp:131
const SVFVar * getVtablePtr() const
Definition: ICFGNode.h:537
const std::string getSourceLoc() const override
Definition: ICFGNode.h:588
bool isVirtualCall() const
Definition: ICFGNode.h:527
const RetICFGNode * getRetICFGNode() const
Return callsite.
Definition: ICFGNode.h:457
static const Option< std::string > CFLGraph
Definition: Options.h:232
static const Option< bool > PrintCFL
Definition: Options.h:233
virtual void initializeSolver()
Initialize POCR Solver.
Definition: CFLAlias.cpp:247
Solver Utilize Hybrid Representation of Graph.
Definition: CFLSolver.h:295
virtual void initializeSolver()
Initialize POCRHybrid Solver.
Definition: CFLAlias.cpp:252
Solver Utilize CFLData.
Definition: CFLSolver.h:117
virtual void finalize()
Finalization of a pointer analysis, including checking alias correctness.
OrderedMap< const CallICFGNode *, FunctionSet > CallEdgeMap
SVFIR::CallSiteToFunPtrMap CallSiteToFunPtrMap
virtual const SVFType * getType() const
Definition: GenericGraph.h:271
NodeID getId() const
Get ID.
Definition: GenericGraph.h:260
std::vector< const SVFVar * > SVFVarList
Definition: SVFIR.h:59
virtual bool isPointer() const
Whether it is a pointer.
Definition: SVFVariables.h:106
virtual const std::string toString() const
bool isHeapAllocExtFunViaRet(const SVFFunction *fun)
Return true if the call is a heap allocator/reallocator.
Definition: SVFUtil.h:296
void writeWrnMsg(const std::string &msg)
Writes a message run through wrnMsg.
Definition: SVFUtil.cpp:66
std::ostream & outs()
Overwrite llvm::outs()
Definition: SVFUtil.h:50
for isBitcode
Definition: BasicTypes.h:68
u32_t NodeID
Definition: GeneralType.h:55