Static Value-Flow Analysis
CHG.cpp
Go to the documentation of this file.
1 //===----- CHG.cpp Base class of pointer analyses ---------------------------//
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  * CHG.cpp (previously CHA.cpp)
25  *
26  * Created on: Apr 13, 2016
27  * Author: Xiaokang Fan
28  */
29 
30 #include "Graphs/CHG.h"
31 #include "Util/SVFUtil.h"
32 #include "Graphs/ICFG.h"
33 #include "SVFIR/SVFIR.h"
34 
35 using namespace SVF;
36 using namespace SVFUtil;
37 using namespace std;
38 
39 static bool hasEdge(const CHNode *src, const CHNode *dst,
41 {
42  for (CHEdge::CHEdgeSetTy::const_iterator it = src->getOutEdges().begin(),
43  eit = src->getOutEdges().end(); it != eit; ++it)
44  {
45  CHNode *node = (*it)->getDstNode();
46  CHEdge::CHEDGETYPE edgeType = (*it)->getEdgeType();
47  if (node == dst && edgeType == et)
48  return true;
49  }
50  return false;
51 }
52 
53 static bool checkArgTypes(const CallICFGNode* cs, const SVFFunction* fn)
54 {
55 
56  // here we skip the first argument (i.e., this pointer)
57  u32_t arg_size = (fn->arg_size() > cs->arg_size()) ? cs->arg_size(): fn->arg_size();
58  if(arg_size > 1)
59  {
60  for (unsigned i = 1; i < arg_size; i++)
61  {
62  auto cs_arg = cs->getArgument(i);
63  auto fn_arg = fn->getArg(i);
64  if (cs_arg->getType() != fn_arg->getType())
65  {
66  return false;
67  }
68  }
69  }
70 
71  return true;
72 }
73 
75 {
76  CallNodeToVTableSetMap::const_iterator it = callNodeToCHAVtblsMap.find(cs);
77  return it != callNodeToCHAVtblsMap.end();
78 }
80 {
81  CallNodeToVFunSetMap::const_iterator it = callNodeToCHAVFnsMap.find(cs);
82  return it != callNodeToCHAVFnsMap.end();
83 }
85 {
86  CallNodeToVTableSetMap::const_iterator it = callNodeToCHAVtblsMap.find(cs);
87  assert(it != callNodeToCHAVtblsMap.end() && "cs does not have vtabls based on CHA.");
88  return it->second;
89 }
91 {
92  CallNodeToVFunSetMap::const_iterator it = callNodeToCHAVFnsMap.find(cs);
93  assert(it != callNodeToCHAVFnsMap.end() && "cs does not have vfns based on CHA.");
94  return it->second;
95 }
96 
97 void CHGraph::addEdge(const string className, const string baseClassName,
98  CHEdge::CHEDGETYPE edgeType)
99 {
100  CHNode *srcNode = getNode(className);
101  CHNode *dstNode = getNode(baseClassName);
102  assert(srcNode && dstNode && "node not found?");
103 
104  if (!hasEdge(srcNode, dstNode, edgeType))
105  {
106  CHEdge *edge = new CHEdge(srcNode, dstNode, edgeType);
107  srcNode->addOutgoingEdge(edge);
108  dstNode->addIncomingEdge(edge);
109  }
110 }
111 
112 CHNode *CHGraph::getNode(const string name) const
113 {
114  auto chNode = classNameToNodeMap.find(name);
115  if (chNode != classNameToNodeMap.end()) return chNode->second;
116  else return nullptr;
117 }
118 
119 
120 /*
121  * Get virtual functions for callsite "cs" based on vtbls (calculated
122  * based on pointsto set)
123  */
124 void CHGraph::getVFnsFromVtbls(const CallICFGNode* callsite, const VTableSet &vtbls, VFunSet &virtualFunctions)
125 {
127  size_t idx = callsite->getFunIdxInVtable();
129  string funName = callsite->getFunNameOfVirtualCall();
130  for (const SVFGlobalValue *vt : vtbls)
131  {
132  const CHNode *child = getNode(vt->getName());
133  if (child == nullptr)
134  continue;
135  CHNode::FuncVector vfns;
136  child->getVirtualFunctions(idx, vfns);
137  for (CHNode::FuncVector::const_iterator fit = vfns.begin(),
138  feit = vfns.end(); fit != feit; ++fit)
139  {
140  const SVFFunction* callee = *fit;
141  if (callsite->arg_size() == callee->arg_size() ||
142  (callsite->isVarArg() && callee->isVarArg()))
143  {
144 
145  // if argument types do not match
146  // skip this one
147  if (!checkArgTypes(callsite, callee))
148  continue;
149 
150  string calleeName = callee->getName();
151 
152  /*
153  * The compiler will add some special suffix (e.g.,
154  * "[abi:cxx11]") to the end of some virtual function:
155  * In dealII
156  * function: FE_Q<3>::get_name
157  * will be mangled as: _ZNK4FE_QILi3EE8get_nameB5cxx11Ev
158  * after demangling: FE_Q<3>::get_name[abi:cxx11]
159  * The special suffix ("[abi:cxx11]") needs to be removed
160  */
161  const std::string suffix("[abi:cxx11]");
162  size_t suffix_pos = calleeName.rfind(suffix);
163  if (suffix_pos != string::npos)
164  calleeName.erase(suffix_pos, suffix.size());
165 
166  /*
167  * if we can't get the function name of a virtual callsite, all virtual
168  * functions calculated by idx will be valid
169  */
170  if (funName.size() == 0)
171  {
172  virtualFunctions.insert(callee);
173  }
174  else if (funName[0] == '~')
175  {
176  /*
177  * if the virtual callsite is calling a destructor, then all
178  * destructors in the ch will be valid
179  * class A { virtual ~A(){} };
180  * class B: public A { virtual ~B(){} };
181  * int main() {
182  * A *a = new B;
183  * delete a; /// the function name of this virtual callsite is ~A()
184  * }
185  */
186  if (calleeName[0] == '~')
187  {
188  virtualFunctions.insert(callee);
189  }
190  }
191  else
192  {
193  /*
194  * for other virtual function calls, the function name of the callsite
195  * and the function name of the target callee should match exactly
196  */
197  if (funName.compare(calleeName) == 0)
198  {
199  virtualFunctions.insert(callee);
200  }
201  }
202  }
203  }
204  }
205 }
206 
207 
208 void CHNode::getVirtualFunctions(u32_t idx, FuncVector &virtualFunctions) const
209 {
210  for (vector<FuncVector>::const_iterator it = virtualFunctionVectors.begin(),
211  eit = virtualFunctionVectors.end(); it != eit; ++it)
212  {
213  if ((*it).size() > idx)
214  virtualFunctions.push_back((*it)[idx]);
215  }
216 }
217 
219 {
220  for (CHGraph::const_iterator it = this->begin(), eit = this->end();
221  it != eit; ++it)
222  {
223  const CHNode *node = it->second;
224  outs() << "class: " << node->getName() << "\n";
225  for (CHEdge::CHEdgeSetTy::const_iterator it = node->OutEdgeBegin();
226  it != node->OutEdgeEnd(); ++it)
227  {
228  if ((*it)->getEdgeType() == CHEdge::INHERITANCE)
229  outs() << (*it)->getDstNode()->getName() << " --inheritance--> "
230  << (*it)->getSrcNode()->getName() << "\n";
231  else
232  outs() << (*it)->getSrcNode()->getName() << " --instance--> "
233  << (*it)->getDstNode()->getName() << "\n";
234  }
235  }
236  outs() << '\n';
237 }
238 
242 void CHGraph::dump(const std::string& filename)
243 {
244  GraphPrinter::WriteGraphToFile(outs(), filename, this);
245  printCH();
246 }
247 
249 {
250  SVF::ViewGraph(this, "Class Hierarchy Graph");
251 }
252 
253 namespace SVF
254 {
255 
259 template<>
261 {
262 
263  typedef CHNode NodeType;
264  DOTGraphTraits(bool isSimple = false) :
265  DefaultDOTGraphTraits(isSimple)
266  {
267  }
268 
271  {
272  return "Class Hierarchy Graph";
273  }
276  {
277  return node->getName();
278  }
279 
281  {
282  if (node->isPureAbstract())
283  {
284  return "shape=tab";
285  }
286  else
287  return "shape=box";
288  }
289 
290  template<class EdgeIter>
291  static std::string getEdgeAttributes(CHNode*, EdgeIter EI, CHGraph*)
292  {
293 
294  CHEdge* edge = *(EI.getCurrent());
295  assert(edge && "No edge found!!");
296  if (edge->getEdgeType() == CHEdge::INHERITANCE)
297  {
298  return "style=solid";
299  }
300  else
301  {
302  return "style=dashed";
303  }
304  }
305 };
306 } // End namespace llvm
static bool hasEdge(const CHNode *src, const CHNode *dst, CHEdge::CHEDGETYPE et)
Definition: CHG.cpp:39
static bool checkArgTypes(const CallICFGNode *cs, const SVFFunction *fn)
Definition: CHG.cpp:53
unsigned u32_t
Definition: CommandLine.h:18
cJSON * child
Definition: cJSON.cpp:2723
const char *const name
Definition: cJSON.h:264
const char *const string
Definition: cJSON.h:172
CHEDGETYPE
Definition: CHG.h:85
@ INHERITANCE
Definition: CHG.h:86
CHEDGETYPE getEdgeType() const
Definition: CHG.h:98
void dump(const std::string &filename)
Definition: CHG.cpp:242
bool csHasVtblsBasedonCHA(const CallICFGNode *cs) override
Definition: CHG.cpp:74
void addEdge(const std::string className, const std::string baseClassName, CHEdge::CHEDGETYPE edgeType)
Definition: CHG.cpp:97
bool csHasVFnsBasedonCHA(const CallICFGNode *cs) override
Definition: CHG.cpp:79
const VFunSet & getCSVFsBasedonCHA(const CallICFGNode *cs) override
Definition: CHG.cpp:90
const VTableSet & getCSVtblsBasedonCHA(const CallICFGNode *cs) override
Definition: CHG.cpp:84
void getVFnsFromVtbls(const CallICFGNode *cs, const VTableSet &vtbls, VFunSet &virtualFunctions) override
Definition: CHG.cpp:124
CHNode * getNode(const std::string name) const
Definition: CHG.cpp:112
void view()
Definition: CHG.cpp:248
void printCH()
Definition: CHG.cpp:218
void getVirtualFunctions(u32_t idx, FuncVector &virtualFunctions) const
Definition: CHG.cpp:208
bool isPureAbstract() const
Definition: CHG.h:160
std::vector< const SVFFunction * > FuncVector
Definition: CHG.h:121
std::string getName() const
Definition: CHG.h:130
bool isVarArg() const
Definition: ICFGNode.h:523
const std::string & getFunNameOfVirtualCall() const
Definition: ICFGNode.h:551
s32_t getFunIdxInVtable() const
Definition: ICFGNode.h:544
u32_t arg_size() const
Definition: ICFGNode.h:505
const SVFVar * getArgument(u32_t ArgNo) const
Parameter operations.
Definition: ICFGNode.h:500
IDToNodeMapTy::const_iterator const_iterator
Definition: GenericGraph.h:607
iterator OutEdgeEnd()
Definition: GenericGraph.h:458
const GEdgeSetTy & getOutEdges() const
Definition: GenericGraph.h:430
bool addIncomingEdge(EdgeType *inEdge)
Add incoming and outgoing edges.
Definition: GenericGraph.h:527
iterator OutEdgeBegin()
iterators
Definition: GenericGraph.h:454
bool addOutgoingEdge(EdgeType *outEdge)
Definition: GenericGraph.h:531
static void WriteGraphToFile(SVF::OutStream &O, const std::string &GraphName, const GraphType &GT, bool simple=false)
Definition: GraphPrinter.h:56
const SVFArgument * getArg(u32_t idx) const
Definition: SVFValue.cpp:175
u32_t arg_size() const
Definition: SVFValue.cpp:170
bool isVarArg() const
Definition: SVFValue.cpp:181
const std::string & getName() const
Definition: SVFValue.h:243
std::ostream & outs()
Overwrite llvm::outs()
Definition: SVFUtil.h:50
for isBitcode
Definition: BasicTypes.h:68
Set< const SVFGlobalValue * > VTableSet
Definition: CHG.h:44
void ViewGraph(const GraphType &G, const std::string &name, bool ShortNames=false, GraphProgram::Name Program=GraphProgram::DOT)
Definition: GraphWriter.h:371
Set< const SVFFunction * > VFunSet
Definition: CHG.h:47
unsigned u32_t
Definition: GeneralType.h:46
DOTGraphTraits(bool isSimple=false)
Definition: CHG.cpp:264
static std::string getNodeLabel(CHNode *node, CHGraph *)
Return function name;.
Definition: CHG.cpp:275
static std::string getGraphName(CHGraph *)
Return name of the graph.
Definition: CHG.cpp:270
static std::string getNodeAttributes(CHNode *node, CHGraph *)
Definition: CHG.cpp:280
static std::string getEdgeAttributes(CHNode *, EdgeIter EI, CHGraph *)
Definition: CHG.cpp:291