Static Value-Flow Analysis
DCHG.cpp
Go to the documentation of this file.
1 //===----- DCHG.cpp CHG using DWARF debug info ------------------------//
2 //
3 /*
4  * DCHG.cpp
5  *
6  * Created on: Aug 24, 2019
7  * Author: Mohamad Barbar
8  */
9 
10 #include <sstream>
11 
12 #include "Util/Options.h"
13 #include "SVF-LLVM/DCHG.h"
14 #include "SVF-LLVM/CppUtil.h"
15 #include "Util/SVFUtil.h"
16 #include "SVF-LLVM/LLVMUtil.h"
17 #include "SVF-LLVM/LLVMModule.h"
18 
19 using namespace SVF;
20 
21 
23 {
24  getOrCreateNode(basicType);
25 }
26 
28 {
29  switch (compositeType->getTag())
30  {
31  case dwarf::DW_TAG_array_type:
32  if (extended) getOrCreateNode(compositeType);
33  gatherAggs(compositeType);
34  break;
35  case dwarf::DW_TAG_class_type:
36  case dwarf::DW_TAG_structure_type:
37  getOrCreateNode(compositeType);
38  // If we're extending, we need to add the first-field relation.
39  if (extended)
40  {
41  DINodeArray fields = compositeType->getElements();
42  if (!fields.empty())
43  {
44  // We want the first non-static, non-function member; it may not exist.
45  DIDerivedType *firstMember = nullptr;
46  for (DINode *n : fields)
47  {
48  if (DIDerivedType *fm = SVFUtil::dyn_cast<DIDerivedType>(n))
49  {
50  if (fm->getTag() == dwarf::DW_TAG_member && !fm->isStaticMember())
51  {
52  firstMember = fm;
53  break;
54  }
55  }
56  }
57 
58  if (firstMember != nullptr)
59  {
60  // firstMember is a DW_TAG_member, we want the base type beneath it.
61  addEdge(compositeType, firstMember->getBaseType(), DCHEdge::FIRST_FIELD);
62  }
63  }
64  }
65 
66  flatten(compositeType);
67  gatherAggs(compositeType);
68 
69  break;
70  case dwarf::DW_TAG_union_type:
71  getOrCreateNode(compositeType);
72  // All fields are first fields.
73  if (extended)
74  {
75  DINodeArray fields = compositeType->getElements();
76  for (DINode *field : fields)
77  {
78  // fields[0] gives a type which is DW_TAG_member, we want the member's type (getBaseType).
79  DIDerivedType *firstMember = SVFUtil::dyn_cast<DIDerivedType>(field);
80  assert(firstMember != nullptr && "DCHG: expected member type");
81  addEdge(compositeType, firstMember->getBaseType(), DCHEdge::FIRST_FIELD);
82  }
83  }
84 
85  // flatten(compositeType);
86  gatherAggs(compositeType);
87 
88  break;
89  case dwarf::DW_TAG_enumeration_type:
90  getOrCreateNode(compositeType);
91  break;
92  default:
93  assert(false && "DCHGraph::buildCHG: unexpected CompositeType tag.");
94  }
95 }
96 
98 {
99  switch (derivedType->getTag())
100  {
101  case dwarf::DW_TAG_inheritance:
102  {
103  assert(SVFUtil::isa<DIType>(derivedType->getScope()) && "inheriting from non-type?");
104  DCHEdge *edge = addEdge(SVFUtil::dyn_cast<DIType>(derivedType->getScope()),
105  derivedType->getBaseType(), DCHEdge::INHERITANCE);
106  // If the offset does not exist (for primary base), getConstantFieldIdx should return 0.
107  edge->setOffset(derivedType->getOffsetInBits());
108  break;
109  }
110  case dwarf::DW_TAG_member:
111  case dwarf::DW_TAG_friend:
112  // Don't care.
113  break;
114  case dwarf::DW_TAG_typedef:
115  handleTypedef(derivedType);
116  break;
117  case dwarf::DW_TAG_pointer_type:
118  case dwarf::DW_TAG_ptr_to_member_type:
119  case dwarf::DW_TAG_reference_type:
120  case dwarf::DW_TAG_rvalue_reference_type:
121  if (extended) getOrCreateNode(derivedType);
122  break;
123  case dwarf::DW_TAG_const_type:
124  case dwarf::DW_TAG_atomic_type:
125  case dwarf::DW_TAG_volatile_type:
126  case dwarf::DW_TAG_restrict_type:
127  break;
128  default:
129  assert(false && "DCHGraph::buildCHG: unexpected DerivedType tag.");
130  }
131 }
132 
134 {
135  getOrCreateNode(subroutineType);
136 }
137 
138 void DCHGraph::handleTypedef(const DIType *typedefType)
139 {
140  assert(typedefType && typedefType->getTag() == dwarf::DW_TAG_typedef);
141 
142  // Need to gather them in a set first because we don't know the base type till
143  // we get to the bottom of the (potentially many) typedefs.
144  std::vector<const DIDerivedType *> typedefs;
145  // Check for nullptr because you can typedef void.
146  while (typedefType != nullptr && typedefType->getTag() == dwarf::DW_TAG_typedef)
147  {
148  const DIDerivedType *typedefDerivedType = SVFUtil::dyn_cast<DIDerivedType>(typedefType);
149  // The typedef itself.
150  typedefs.push_back(typedefDerivedType);
151 
152  // Next in the typedef line.
153  typedefType = typedefDerivedType->getBaseType();
154  }
155 
156  const DIType *baseType = typedefType;
157  DCHNode *baseTypeNode = getOrCreateNode(baseType);
158 
159  for (const DIDerivedType *tdef : typedefs)
160  {
161  // Base type needs to hold its typedefs.
162  baseTypeNode->addTypedef(tdef);
163  }
164 }
165 
167 {
168  for (Module &M : LLVMModuleSet::getLLVMModuleSet()->getLLVMModules())
169  {
170  for (Module::const_global_iterator gvI = M.global_begin(); gvI != M.global_end(); ++gvI)
171  {
172  // Though this will return more than GlobalVariables, we only care about GlobalVariables (for the vtbls).
173  const GlobalVariable *gv = SVFUtil::dyn_cast<const GlobalVariable>(&*gvI);
174  if (gv == nullptr) continue;
175  if (gv->hasMetadata(cppUtil::ctir::vtMDName) && gv->getNumOperands() > 0)
176  {
177  DIType *type = SVFUtil::dyn_cast<DIType>(gv->getMetadata(cppUtil::ctir::vtMDName));
178  assert(type && "DCHG::buildVTables: bad metadata for ctir.vt");
179  DCHNode *node = getOrCreateNode(type);
181  node->setVTable(svfgv);
183 
184  const ConstantStruct *vtbls = cppUtil::getVtblStruct(gv);
185  for (unsigned nthVtbl = 0; nthVtbl < vtbls->getNumOperands(); ++nthVtbl)
186  {
187  const ConstantArray *vtbl = SVFUtil::dyn_cast<ConstantArray>(vtbls->getOperand(nthVtbl));
188  assert(vtbl && "Element of vtbl struct not an array");
189 
190  std::vector<const Function* > &vfns = node->getVfnVector(nthVtbl);
191 
192  // Iterating over the vtbl, we will run into:
193  // 1. i8* null (don't care for now).
194  // 2. i8* inttoptr ... (don't care for now).
195  // 3. i8* bitcast ... (we only care when a function pointer is being bitcasted).
196  for (unsigned cN = 0; cN < vtbl->getNumOperands(); ++cN)
197  {
198  Constant *c = vtbl->getOperand(cN);
199  if (SVFUtil::isa<ConstantPointerNull>(c))
200  {
201  // Don't care for now.
202  continue;
203  }
204 
205  ConstantExpr *ce = SVFUtil::dyn_cast<ConstantExpr>(c);
206  assert(ce && "non-ConstantExpr, non-ConstantPointerNull in vtable?");
207  if (ce->getOpcode() == Instruction::BitCast)
208  {
209  // Could be a GlobalAlias which we don't care about, or a virtual/thunk function.
210  const Function* vfn = SVFUtil::dyn_cast<Function>(ce->getOperand(0));
211  if (vfn != nullptr)
212  {
213  vfns.push_back(vfn);
214  }
215  }
216  }
217  }
218  }
219  }
220  }
221 }
222 
223 const NodeBS &DCHGraph::cha(const DIType *type, bool firstField)
224 {
226  Map<const DIType *, NodeBS> &cacheMap = firstField ? chaFFMap : chaMap;
227 
228  // Check if we've already computed.
229  if (cacheMap.find(type) != cacheMap.end())
230  {
231  return cacheMap[type];
232  }
233 
235  const DCHNode *node = getOrCreateNode(type);
236  // Consider oneself a child, otherwise the recursion will just come up with nothing.
237  children.set(node->getId());
238  for (const DCHEdge *edge : node->getInEdges())
239  {
240  // Don't care about anything but inheritance, first-field, and standard def. edges.
241  if ( edge->getEdgeKind() != DCHEdge::INHERITANCE
242  && edge->getEdgeKind() != DCHEdge::FIRST_FIELD
243  && edge->getEdgeKind() != DCHEdge::STD_DEF)
244  {
245  continue;
246  }
247 
248  // We only care about first-field edges if the flag is on.
249  if (!firstField && edge->getEdgeKind() == DCHEdge::FIRST_FIELD)
250  {
251  continue;
252  }
253 
254  const NodeBS &cchildren = cha(edge->getSrcNode()->getDIType(), firstField);
255  // Children's children are my children.
256  for (NodeID cchild : cchildren)
257  {
258  children.set(cchild);
259  }
260  }
261 
262  // Cache results.
263  cacheMap.insert({type, children});
264  // Return the permanent object; we're returning a reference.
265  return cacheMap[type];
266 }
267 
269 {
270  type = SVFUtil::dyn_cast<DICompositeType>(getCanonicalType(type));
271  assert(type && "DCHG::flatten: canon type of struct/class is not struct/class");
272  if (fieldTypes.find(type) != fieldTypes.end())
273  {
274  // Already done (necessary because of the recursion).
275  return;
276  }
277 
278  // Create empty vector.
279  fieldTypes[type];
280 
281  assert(type != nullptr
282  && (type->getTag() == dwarf::DW_TAG_class_type
283  || type->getTag() == dwarf::DW_TAG_structure_type)
284  && "DCHG::flatten: expected a class/struct");
285 
286  // Sort the fields from getElements. Especially a problem for classes; it's all jumbled up.
287  std::vector<const DIDerivedType *> fields;
288  DINodeArray fieldsDINA = type->getElements();
289  for (unsigned i = 0; i < fieldsDINA.size(); ++i)
290  {
291  if (const DIDerivedType *dt = SVFUtil::dyn_cast<DIDerivedType>(fieldsDINA[i]))
292  {
293  // Don't care about subprograms, only member/inheritance.
294  fields.push_back(dt);
295  }
296  }
297 
298  // TODO: virtual inheritance is not handled at all!
299  std::sort(fields.begin(), fields.end(),
300  [](const DIDerivedType *&a, const DIDerivedType *&b) -> bool
301  { return a->getOffsetInBits() < b->getOffsetInBits(); });
302 
303  for (const DIDerivedType *mt : fields)
304  {
305  assert((mt->getTag() == dwarf::DW_TAG_member || mt->getTag() == dwarf::DW_TAG_inheritance)
306  && "DCHG: expected member/inheritance");
307  // Either we have a class, struct, array, or something not in need of flattening.
308  const DIType *fieldType = mt->getBaseType();
309  if (fieldType->getTag() == dwarf::DW_TAG_structure_type
310  || fieldType->getTag() == dwarf::DW_TAG_class_type)
311  {
312  flatten(SVFUtil::dyn_cast<DICompositeType>(fieldType));
313  for (const DIType *ft : fieldTypes[fieldType])
314  {
315  // ft is already a canonical type because the "root" additions insert
316  // canonical types.
317  fieldTypes[type].push_back(ft);
318  }
319  }
320  else if (fieldType->getTag() == dwarf::DW_TAG_array_type)
321  {
322  const DICompositeType *arrayType = SVFUtil::dyn_cast<DICompositeType>(fieldType);
323  const DIType *baseType = arrayType->getBaseType();
324  if (const DICompositeType *cbt = SVFUtil::dyn_cast<DICompositeType>(baseType))
325  {
326  flatten(cbt);
327  for (const DIType *ft : fieldTypes[cbt])
328  {
329  // ft is already a canonical type like above.
330  fieldTypes[type].push_back(ft);
331  }
332  }
333  else
334  {
335  fieldTypes[type].push_back(getCanonicalType(baseType));
336  }
337  }
338  else
339  {
340  fieldTypes[type].push_back(getCanonicalType(fieldType));
341  }
342  }
343 }
344 
345 bool DCHGraph::isAgg(const DIType *t)
346 {
347  if (t == nullptr) return false;
348  return t->getTag() == dwarf::DW_TAG_array_type
349  || t->getTag() == dwarf::DW_TAG_structure_type
350  || t->getTag() == dwarf::DW_TAG_class_type;
351 }
352 
354 {
356  {
357  return;
358  }
359 
360  // Initialise an empty set. We want all aggregates to have a value in
361  // this map, even if empty (e.g. struct has no aggs, only scalars).
363 
364  if (type->getTag() == dwarf::DW_TAG_array_type)
365  {
366  const DIType *bt = type->getBaseType();
367  bt = stripQualifiers(bt);
368 
369  if (isAgg(bt))
370  {
371  const DICompositeType *cbt = SVFUtil::dyn_cast<DICompositeType>(bt);
373  gatherAggs(cbt);
374  // These must be canonical already because of aggs.insert above/below.
378  }
379  }
380  else
381  {
382  DINodeArray fields = type->getElements();
383  for (unsigned i = 0; i < fields.size(); ++i)
384  {
385  // Unwrap the member (could be a subprogram, not type, so guard needed).
386  if (const DIDerivedType *mt = SVFUtil::dyn_cast<DIDerivedType>(fields[i]))
387  {
388  const DIType *ft = mt->getBaseType();
389  ft = stripQualifiers(ft);
390 
391  if (isAgg(ft))
392  {
393  const DICompositeType *cft = SVFUtil::dyn_cast<DICompositeType>(ft);
395  gatherAggs(cft);
396  // These must be canonical already because of aggs.insert above.
400  }
401  }
402  }
403  }
404 }
405 
407 {
409 
410  // Check, does the node for type exist?
411  if (diTypeToNodeMap[type] != nullptr)
412  {
413  return diTypeToNodeMap[type];
414  }
415 
416  DCHNode *node = new DCHNode(type, numTypes++);
417  addGNode(node->getId(), node);
418  diTypeToNodeMap[type] = node;
419  // TODO: handle templates.
420 
421  return node;
422 }
423 
425 {
426  MDNode *md = cs->getMetadata(cppUtil::ctir::derefMDName);
427  assert(md != nullptr && "Missing type metadata at virtual callsite");
428  DIType *diType = SVFUtil::dyn_cast<DIType>(md);
429  assert(diType != nullptr && "Incorrect metadata type at virtual callsite");
430  return diType;
431 }
432 
434 {
435  DCHNode *src = getOrCreateNode(t1);
436  DCHNode *dst = getOrCreateNode(t2);
437 
438  DCHEdge *edge = hasEdge(t1, t2, et);
439  if (edge == nullptr)
440  {
441  // Create a new edge.
442  edge = new DCHEdge(src, dst, et);
443  src->addOutgoingEdge(edge);
444  dst->addIncomingEdge(edge);
445  }
446 
447  return edge;
448 }
449 
451 {
452  DCHNode *src = getOrCreateNode(t1);
453  DCHNode *dst = getOrCreateNode(t2);
454 
455  for (DCHEdge *edge : src->getOutEdges())
456  {
457  DCHNode *node = edge->getDstNode();
458  DCHEdge::GEdgeKind edgeType = edge->getEdgeKind();
459  if (node == dst && edgeType == et)
460  {
461  assert(SVFUtil::isa<DCHEdge>(edge) && "Non-DCHEdge in DCHNode edge set.");
462  return edge;
463  }
464  }
465 
466  return nullptr;
467 }
468 
469 void DCHGraph::buildCHG(bool extend)
470 {
471  extended = extend;
472  DebugInfoFinder finder;
473  for (Module &M : LLVMModuleSet::getLLVMModuleSet()->getLLVMModules())
474  {
475  finder.processModule(M);
476  }
477 
478  // Create the void node regardless of whether it appears.
479  getOrCreateNode(nullptr);
480  // Find any char type.
481  const DIType *charType = nullptr;
482  /*
483  * We want void at the top, char as a child, and everything is a child of char:
484  * void
485  * |
486  * char
487  * / | \
488  * x y z
489  */
490 
491 
492  for (const DIType *type : finder.types())
493  {
494  if (const DIBasicType *basicType = SVFUtil::dyn_cast<DIBasicType>(type))
495  {
496  if (basicType->getEncoding() == dwarf::DW_ATE_unsigned_char
497  || basicType->getEncoding() == dwarf::DW_ATE_signed_char)
498  {
499  charType = type;
500  }
501 
502  handleDIBasicType(basicType);
503  }
504  else if (const DICompositeType *compositeType = SVFUtil::dyn_cast<DICompositeType>(type))
505  {
506  handleDICompositeType(compositeType);
507  }
508  else if (const DIDerivedType *derivedType = SVFUtil::dyn_cast<DIDerivedType>(type))
509  {
510  handleDIDerivedType(derivedType);
511  }
512  else if (const DISubroutineType *subroutineType = SVFUtil::dyn_cast<DISubroutineType>(type))
513  {
514  handleDISubroutineType(subroutineType);
515  }
516  else
517  {
518  assert(false && "DCHGraph::buildCHG: unexpected DIType.");
519  }
520  }
521 
522  buildVTables(*(LLVMModuleSet::getLLVMModuleSet()->getSVFModule()));
523 
524  // Build the void/char/everything else relation.
525  if (extended && charType != nullptr)
526  {
527  // void <-- char
528  addEdge(charType, nullptr, DCHEdge::STD_DEF);
529  // char <-- x, char <-- y, ...
530  for (iterator nodeI = begin(); nodeI != end(); ++nodeI)
531  {
532  // Everything without a parent gets char as a parent.
533  if (nodeI->second->getDIType() != nullptr
534  && nodeI->second->getOutEdges().size() == 0)
535  {
536  addEdge(nodeI->second->getDIType(), charType, DCHEdge::STD_DEF);
537  }
538  }
539  }
540 
541  if (Options::PrintDCHG())
542  {
543  print();
544  }
545 }
546 
548 {
549  if (csCHAMap.find(cs) != csCHAMap.end())
550  {
551  return csCHAMap[cs];
552  }
553 
554  VFunSet vfns;
555  const VTableSet &vtbls = getCSVtblsBasedonCHA(cs);
556  getVFnsFromVtbls(cs, vtbls, vfns);
557 
558  // Cache.
559  csCHAMap.insert({cs, vfns});
560  // Return cached object, not the stack object.
561  return csCHAMap[cs];
562 }
563 
565 {
567  // Check if we've already computed.
568  if (vtblCHAMap.find(type) != vtblCHAMap.end())
569  {
570  return vtblCHAMap[type];
571  }
572 
573  VTableSet vtblSet;
574  const NodeBS &children = cha(type, false);
575  for (NodeID childId : children)
576  {
577  DCHNode *child = getGNode(childId);
578  const SVFGlobalValue *vtbl = child->getVTable();
579  // TODO: what if it is null?
580  if (vtbl != nullptr)
581  {
582  vtblSet.insert(vtbl);
583  }
584  }
585 
586  // Cache.
587  vtblCHAMap.insert({type, vtblSet});
588  // Return cached version - not the stack object.
589  return vtblCHAMap[type];
590 }
591 
592 void DCHGraph::getVFnsFromVtbls(const CallICFGNode* callsite, const VTableSet &vtbls, VFunSet &virtualFunctions)
593 {
594  size_t idx = callsite->getFunIdxInVtable();
595  std::string funName = callsite->getFunNameOfVirtualCall();
596  for (const SVFGlobalValue *vtbl : vtbls)
597  {
598  assert(vtblToTypeMap.find(vtbl) != vtblToTypeMap.end() && "floating vtbl");
599  const DIType *type = vtblToTypeMap[vtbl];
600  assert(hasNode(type) && "trying to get vtbl for type not in graph");
601  const DCHNode *node = getNode(type);
602  std::vector<std::vector<const Function* >> allVfns = node->getVfnVectors();
603  for (std::vector<const Function* > vfnV : allVfns)
604  {
605  // We only care about any virtual function corresponding to idx.
606  if (idx >= vfnV.size())
607  {
608  continue;
609  }
610 
611  const Function* callee = vfnV[idx];
612  // Practically a copy of that in lib/MemoryModel/CHA.cpp
613  if (callsite->arg_size() == callee->arg_size() || (callsite->isVarArg() && callee->isVarArg()))
614  {
615  cppUtil::DemangledName dname = cppUtil::demangle(callee->getName().str());
616  std::string calleeName = dname.funcName;
617 
618  /*
619  * The compiler will add some special suffix (e.g.,
620  * "[abi:cxx11]") to the end of some virtual function:
621  * In dealII
622  * function: FE_Q<3>::get_name
623  * will be mangled as: _ZNK4FE_QILi3EE8get_nameB5cxx11Ev
624  * after demangling: FE_Q<3>::get_name[abi:cxx11]
625  * The special suffix ("[abi:cxx11]") needs to be removed
626  */
627  const std::string suffix("[abi:cxx11]");
628  size_t suffixPos = calleeName.rfind(suffix);
629  if (suffixPos != std::string::npos)
630  {
631  calleeName.erase(suffixPos, suffix.size());
632  }
633 
634  /*
635  * if we can't get the function name of a virtual callsite, all virtual
636  * functions corresponding to idx will be valid
637  */
638  if (funName.size() == 0)
639  {
640  virtualFunctions.insert(LLVMUtil::getFunction(callee->getName().str()));
641  }
642  else if (funName[0] == '~')
643  {
644  /*
645  * if the virtual callsite is calling a destructor, then all
646  * destructors in the ch will be valid
647  * class A { virtual ~A(){} };
648  * class B: public A { virtual ~B(){} };
649  * int main() {
650  * A *a = new B;
651  * delete a; /// the function name of this virtual callsite is ~A()
652  * }
653  */
654  if (calleeName[0] == '~')
655  {
656  virtualFunctions.insert(LLVMUtil::getFunction(callee->getName().str()));
657  }
658  }
659  else
660  {
661  /*
662  * For other virtual function calls, the function name of the callsite
663  * and the function name of the target callee should match exactly
664  */
665  if (funName.compare(calleeName) == 0)
666  {
667  virtualFunctions.insert(LLVMUtil::getFunction(callee->getName().str()));
668  }
669  }
670  }
671  }
672  }
673 }
674 
675 bool DCHGraph::isBase(const DIType *a, const DIType *b, bool firstField)
676 {
677  a = getCanonicalType(a);
678  b = getCanonicalType(b);
679  assert(hasNode(a) && hasNode(b) && "DCHG: isBase query for non-existent node!");
680  const DCHNode *bNode = getNode(b);
681 
682  const NodeBS &aChildren = cha(a, firstField);
683  return aChildren.test(bNode->getId());
684 }
685 
686 bool DCHGraph::isFieldOf(const DIType *f, const DIType *b)
687 {
688  assert(f && b && "DCHG::isFieldOf: given nullptr!");
689 
690  f = getCanonicalType(f);
691  b = getCanonicalType(b);
692  if (f == b) return true;
693 
694  if (b->getTag() == dwarf::DW_TAG_array_type || b->getTag() == dwarf::DW_TAG_pointer_type)
695  {
696  const DIType *baseType = nullptr;
697  if (const DICompositeType *arrayType = SVFUtil::dyn_cast<DICompositeType>(b))
698  {
699  baseType = arrayType->getBaseType();
700  }
701  else if (const DIDerivedType *ptrType = SVFUtil::dyn_cast<DIDerivedType>(b))
702  {
703  baseType = ptrType->getBaseType();
704  }
705  assert(baseType && "DCHG::isFieldOf: baseType is neither DIComposite nor DIDerived!");
706 
707  baseType = getCanonicalType(baseType);
708  return f == baseType || (baseType != nullptr && isFieldOf(f, baseType));
709  }
710  else if (b->getTag() == dwarf::DW_TAG_class_type
711  || b->getTag() == dwarf::DW_TAG_structure_type)
712  {
713  const std::vector<const DIType *> &fields = getFieldTypes(b);
714  return std::find(fields.begin(), fields.end(), f) != fields.end();
715  }
716  else
717  {
718  return false;
719  }
720 }
721 
723 {
724  // We want stripped types to be canonical.
725  const DIType *unstrippedT = t;
726  t = stripQualifiers(t);
727 
728  // Is there a mapping for the unstripped type? Yes - return it.
729  if (canonicalTypeMap.find(unstrippedT) != canonicalTypeMap.end())
730  {
731  return canonicalTypeMap[unstrippedT];
732  }
733 
734  // There is no mapping for unstripped type (^), is there one for the stripped
735  // type? Yes - map the unstripped type to the same thing.
736  if (unstrippedT != t)
737  {
738  if (canonicalTypeMap.find(t) != canonicalTypeMap.end())
739  {
740  canonicalTypeMap[unstrippedT] = canonicalTypeMap[t];
741  return canonicalTypeMap[unstrippedT];
742  }
743  }
744 
745  // Canonical type for t is not cached, find one for it.
746  for (const DIType *canonType : canonicalTypes)
747  {
748  if (teq(t, canonType))
749  {
750  // Found a canonical type.
751  canonicalTypeMap[t] = canonType;
752  return canonicalTypeMap[t];
753  }
754  }
755 
756  // No canonical type found, so t will be a canonical type.
757  canonicalTypes.insert(t);
758  canonicalTypeMap.insert({t, t});
759 
760  return canonicalTypeMap[t];
761 }
762 
764 {
765  while (true)
766  {
767  // nullptr means void.
768  if (t == nullptr
769  || SVFUtil::isa<DIBasicType>(t)
770  || SVFUtil::isa<DISubroutineType>(t))
771  {
772  break;
773  }
774 
775  unsigned tag = t->getTag();
776  // Verbose for clarity.
777  if ( tag == dwarf::DW_TAG_const_type
778  || tag == dwarf::DW_TAG_atomic_type
779  || tag == dwarf::DW_TAG_volatile_type
780  || tag == dwarf::DW_TAG_restrict_type
781  || tag == dwarf::DW_TAG_typedef)
782  {
783  // Qualifier - get underlying type.
784  const DIDerivedType *dt = SVFUtil::dyn_cast<DIDerivedType>(t);
785  assert(t && "DCHG: expected DerivedType");
786  t = dt->getBaseType();
787  }
788  else if ( tag == dwarf::DW_TAG_array_type
789  || tag == dwarf::DW_TAG_class_type
790  || tag == dwarf::DW_TAG_structure_type
791  || tag == dwarf::DW_TAG_union_type
792  || tag == dwarf::DW_TAG_enumeration_type
793  || tag == dwarf::DW_TAG_member
794  || tag == dwarf::DW_TAG_pointer_type
795  || tag == dwarf::DW_TAG_ptr_to_member_type
796  || tag == dwarf::DW_TAG_reference_type
797  || tag == dwarf::DW_TAG_rvalue_reference_type)
798  {
799  // Hit a non-qualifier.
800  break;
801  }
802  else if ( tag == dwarf::DW_TAG_inheritance
803  || tag == dwarf::DW_TAG_friend)
804  {
805  assert(false && "DCHG: unexpected tag when stripping qualifiers");
806  }
807  else
808  {
809  assert(false && "DCHG: unhandled tag when stripping qualifiers");
810  }
811  }
812 
813  return t;
814 }
815 
817 {
818  t = stripQualifiers(t);
819  if (t->getTag() == dwarf::DW_TAG_array_type)
820  {
821  const DICompositeType *at = SVFUtil::dyn_cast<DICompositeType>(t);
822  return stripArray(at->getBaseType());
823  }
824 
825  return t;
826 }
827 
828 bool DCHGraph::teq(const DIType *t1, const DIType *t2)
829 {
830  t1 = stripQualifiers(t1);
831  t2 = stripQualifiers(t2);
832 
833  if (t1 == t2)
834  {
835  // Trivial case. Handles SubRoutineTypes too.
836  return true;
837  }
838 
839  if (t1 == nullptr || t2 == nullptr)
840  {
841  // Since t1 != t2 and one of them is null, it is
842  // impossible for them to be equal.
843  return false;
844  }
845 
846  // Check if we need base type comparisons.
847  if (SVFUtil::isa<DIBasicType>(t1) && SVFUtil::isa<DIBasicType>(t2))
848  {
849  const DIBasicType *b1 = SVFUtil::dyn_cast<DIBasicType>(t1);
850  const DIBasicType *b2 = SVFUtil::dyn_cast<DIBasicType>(t2);
851 
852  unsigned enc1 = b1->getEncoding();
853  unsigned enc2 = b2->getEncoding();
854  bool okayEnc = ((enc1 == dwarf::DW_ATE_signed || enc1 == dwarf::DW_ATE_unsigned || enc1 == dwarf::DW_ATE_boolean)
855  && (enc2 == dwarf::DW_ATE_signed || enc2 == dwarf::DW_ATE_unsigned || enc2 == dwarf::DW_ATE_boolean))
856  ||
857  (enc1 == dwarf::DW_ATE_float && enc2 == dwarf::DW_ATE_float)
858  ||
859  ((enc1 == dwarf::DW_ATE_signed_char || enc1 == dwarf::DW_ATE_unsigned_char)
860  &&
861  (enc2 == dwarf::DW_ATE_signed_char || enc2 == dwarf::DW_ATE_unsigned_char));
862 
863  if (!okayEnc) return false;
864  // Now we have split integers, floats, and chars, ignoring signedness.
865 
866  return t1->getSizeInBits() == t2->getSizeInBits()
867  && t1->getAlignInBits() == t2->getAlignInBits();
868  }
869 
870  // Check, do we need to compare base types?
871  // This makes pointers, references, and arrays equivalent.
872  // Will handle member types.
873  if ((SVFUtil::isa<DIDerivedType>(t1) || t1->getTag() == dwarf::DW_TAG_array_type)
874  && (SVFUtil::isa<DIDerivedType>(t2) || t2->getTag() == dwarf::DW_TAG_array_type))
875  {
876  const DIType *base1, *base2;
877 
878  // Set base1.
879  if (const DIDerivedType *d1 = SVFUtil::dyn_cast<DIDerivedType>(t1))
880  {
881  base1 = d1->getBaseType();
882  }
883  else
884  {
885  const DICompositeType *c1 = SVFUtil::dyn_cast<DICompositeType>(t1);
886  assert(c1 && "teq: bad cast for array type");
887  base1 = c1->getBaseType();
888  }
889 
890  // Set base2.
891  if (const DIDerivedType *d2 = SVFUtil::dyn_cast<DIDerivedType>(t2))
892  {
893  base2 = d2->getBaseType();
894  }
895  else
896  {
897  const DICompositeType *c2 = SVFUtil::dyn_cast<DICompositeType>(t2);
898  assert(c2 && "teq: bad cast for array type");
899  base2 = c2->getBaseType();
900  }
901 
902  // For ptr-to-member, there is some imprecision (but soundness) in
903  // that we don't check the class type.
904  return teq(base1, base2);
905  }
906 
907  if (SVFUtil::isa<DICompositeType>(t1) && SVFUtil::isa<DICompositeType>(t2))
908  {
909  const DICompositeType *ct1 = SVFUtil::dyn_cast<DICompositeType>(t1);
910  const DICompositeType *ct2 = SVFUtil::dyn_cast<DICompositeType>(t2);
911 
912  if (ct1->getTag() != ct2->getTag()) return false;
913 
914  // Treat all enums the same.
915  if (ct1->getTag() == dwarf::DW_TAG_enumeration_type)
916  {
917  return true;
918  }
919 
920  // C++ classes? Check mangled name.
921  if (ct1->getTag() == dwarf::DW_TAG_class_type)
922  {
923  return ct1->getIdentifier() == ct2->getIdentifier();
924  }
925 
926  // Either union or struct, simply test all fields are equal.
927  // Seems like it is enough to check it was defined in the same place.
928  // The elements sometimes differ but are referring to the same fields.
929  return ct1->getName() == ct2->getName()
930  && ct1->getFile() == ct2->getFile()
931  && ct1->getLine() == ct2->getLine();
932  }
933 
934  // They were not equal base types (discounting signedness), nor were they
935  // "equal" pointers/references/arrays, nor were they the structurally equivalent,
936  // nor were they completely equal.
937  return false;
938 }
939 
940 bool DCHGraph::isFirstField(const DIType *f, const DIType *b)
941 {
942  // TODO: some improvements.
943  // - cha should be changed to accept which edge types to use,
944  // then we can call cha(..., DCHEdge::FIRST_FIELD).
945  // - If not ^, this could benefit from caching.
946  f = getCanonicalType(f);
947  b = getCanonicalType(b);
948 
949  if (f == b) return true;
950 
951  const DCHNode *node = getNode(f);
952  assert(node && "DCHG::isFirstField: node not found");
953  // Consider oneself a child, otherwise the recursion will just come up with nothing.
954  for (const DCHEdge *edge : node->getInEdges())
955  {
956  // Only care about first-field edges.
957  if (edge->getEdgeKind() == DCHEdge::FIRST_FIELD)
958  {
959  if (edge->getSrcNode()->getDIType() == b) return true;
960  if (isFirstField(edge->getSrcNode()->getDIType(), b)) return true;
961  }
962  }
963 
964  return false;
965 }
966 
968 {
969  std::stringstream ss;
970 
971  if (t == nullptr)
972  {
973  return "void";
974  }
975 
976  if (const DIBasicType *bt = SVFUtil::dyn_cast<DIBasicType>(t))
977  {
978  ss << bt->getName().str();
979  }
980  else if (const DIDerivedType *dt = SVFUtil::dyn_cast<DIDerivedType>(t))
981  {
982  if (dt->getName() == "__vtbl_ptr_type")
983  {
984  ss << "(vtbl * =) __vtbl_ptr_type";
985  }
986  else if (dt->getTag() == dwarf::DW_TAG_const_type)
987  {
988  ss << "const " << diTypeToStr(dt->getBaseType());
989  }
990  else if (dt->getTag() == dwarf::DW_TAG_volatile_type)
991  {
992  ss << "volatile " << diTypeToStr(dt->getBaseType());
993  }
994  else if (dt->getTag() == dwarf::DW_TAG_restrict_type)
995  {
996  ss << "restrict " << diTypeToStr(dt->getBaseType());
997  }
998  else if (dt->getTag() == dwarf::DW_TAG_atomic_type)
999  {
1000  ss << "atomic " << diTypeToStr(dt->getBaseType());
1001  }
1002  else if (dt->getTag() == dwarf::DW_TAG_pointer_type)
1003  {
1004  ss << diTypeToStr(dt->getBaseType()) << " *";
1005  }
1006  else if (dt->getTag() == dwarf::DW_TAG_ptr_to_member_type)
1007  {
1008  ss << diTypeToStr(dt->getBaseType())
1009  << " " << diTypeToStr(SVFUtil::dyn_cast<DIType>(dt->getExtraData())) << "::*";
1010  }
1011  else if (dt->getTag() == dwarf::DW_TAG_reference_type)
1012  {
1013  ss << diTypeToStr(dt->getBaseType()) << " &";
1014  }
1015  else if (dt->getTag() == dwarf::DW_TAG_rvalue_reference_type)
1016  {
1017  ss << diTypeToStr(dt->getBaseType()) << " &&";
1018  }
1019  else if (dt->getTag() == dwarf::DW_TAG_typedef)
1020  {
1021  ss << dt->getName().str() << "->" << diTypeToStr(dt->getBaseType());
1022  }
1023  }
1024  else if (const DICompositeType *ct = SVFUtil::dyn_cast<DICompositeType>(t))
1025  {
1026  if (ct->getTag() == dwarf::DW_TAG_class_type
1027  || ct->getTag() == dwarf::DW_TAG_structure_type
1028  || ct->getTag() == dwarf::DW_TAG_union_type)
1029  {
1030 
1031  if (ct->getTag() == dwarf::DW_TAG_class_type)
1032  {
1033  ss << "class";
1034  }
1035  else if (ct->getTag() == dwarf::DW_TAG_structure_type)
1036  {
1037  ss << "struct";
1038  }
1039  else if (ct->getTag() == dwarf::DW_TAG_union_type)
1040  {
1041  ss << "union";
1042  }
1043 
1044  ss << ".";
1045 
1046  if (ct->getName() != "")
1047  {
1048  ss << ct->getName().str();
1049  }
1050  else
1051  {
1052  // Iterate over the element types.
1053  ss << "{ ";
1054 
1055  DINodeArray fields = ct->getElements();
1056  for (unsigned i = 0; i < fields.size(); ++i)
1057  {
1058  // fields[i] gives a type which is DW_TAG_member, we want the member's type (getBaseType).
1059  // It can also give a Subprogram type if the class just had non-virtual functions.
1060  if (const DISubprogram *sp = SVFUtil::dyn_cast<DISubprogram>(fields[i]))
1061  {
1062  ss << sp->getName().str();
1063  }
1064  else if (const DIDerivedType *mt = SVFUtil::dyn_cast<DIDerivedType>(fields[i]))
1065  {
1066  assert(mt->getTag() == dwarf::DW_TAG_member && "DCHG: expected member");
1067  ss << diTypeToStr(mt->getBaseType());
1068  }
1069 
1070  if (i != fields.size() - 1)
1071  {
1072  ss << ", ";
1073  }
1074  }
1075 
1076  ss << " }";
1077  }
1078  }
1079  else if (ct->getTag() == dwarf::DW_TAG_array_type)
1080  {
1081  ss << diTypeToStr(ct->getBaseType());
1082  DINodeArray sizes = ct->getElements();
1083  for (unsigned i = 0; i < sizes.size(); ++i)
1084  {
1085  DISubrange *sr = SVFUtil::dyn_cast<DISubrange>(sizes[0]);
1086  assert(sr != nullptr && "DCHG: non-subrange as array element?");
1087  int64_t count = -1;
1088  if (const ConstantInt* ci = sr->getCount().dyn_cast<ConstantInt* >())
1089  {
1090  count = ci->getSExtValue();
1091  }
1092 
1093  ss << "[" << count << "]";
1094  }
1095  }
1096  else if (ct->getTag() == dwarf::DW_TAG_enumeration_type)
1097  {
1098  ss << "enum " << diTypeToStr(ct->getBaseType());
1099  }
1100  else if (ct->getTag() == dwarf::DW_TAG_union_type)
1101  {
1102 
1103  }
1104  }
1105  else if (const DISubroutineType *st = SVFUtil::dyn_cast<DISubroutineType>(t))
1106  {
1107  DITypeRefArray types = st->getTypeArray();
1108  // Must have one element at least (the first type).
1109  ss << diTypeToStr(types[0]) << " fn(";
1110  if (types.size() == 1)
1111  {
1112  ss << "void)";
1113  }
1114  else
1115  {
1116  for (unsigned i = 1; i < types.size(); ++i)
1117  {
1118  ss << diTypeToStr(types[i]);
1119  if (i + 1 != types.size())
1120  {
1121  // There's another type.
1122  ss << ", ";
1123  }
1124  }
1125 
1126  ss << ")";
1127  }
1128 
1129  ss << st->getName().str();
1130  }
1131 
1132  return ss.str();
1133 }
1134 
1135 static std::string indent(size_t n)
1136 {
1137  return std::string(n, ' ');
1138 }
1139 
1141 {
1142  static const std::string line = "-------------------------------------\n";
1143  static const std::string thickLine = "=====================================\n";
1144  static const size_t singleIndent = 2;
1145 
1146  size_t currIndent = 0;
1147  SVFUtil::outs() << thickLine;
1148  unsigned numStructs = 0;
1149  unsigned largestStruct = 0;
1150  NodeSet nodes;
1151  for (DCHGraph::const_iterator it = begin(); it != end(); ++it)
1152  {
1153  nodes.insert(it->first);
1154  }
1155 
1156  for (NodeID id : nodes)
1157  {
1158  if (*nodes.begin() != id)
1159  {
1160  SVFUtil::outs() << line;
1161  }
1162 
1163  const DCHNode *node = getGNode(id);
1164 
1165  SVFUtil::outs() << indent(currIndent) << id << ": " << diTypeToStr(node->getDIType()) << " [" << node->getDIType() << "]" << "\n";
1166  if (node->getDIType() != nullptr
1167  && (node->getDIType()->getTag() == dwarf::DW_TAG_class_type
1168  ||
1169  node->getDIType()->getTag() == dwarf::DW_TAG_structure_type))
1170  {
1171  ++numStructs;
1172  unsigned numFields = getFieldTypes(node->getDIType()).size();
1173  largestStruct = numFields > largestStruct ? numFields : largestStruct;
1174  }
1175 
1176  currIndent += singleIndent;
1177  SVFUtil::outs() << indent(currIndent) << "Virtual functions\n";
1178  currIndent += singleIndent;
1179  const std::vector<std::vector<const Function* >> &vfnVectors = node->getVfnVectors();
1180  for (unsigned i = 0; i < vfnVectors.size(); ++i)
1181  {
1182  SVFUtil::outs() << indent(currIndent) << "[ vtable #" << i << " ]\n";
1183  currIndent += singleIndent;
1184  for (unsigned j = 0; j < vfnVectors[i].size(); ++j)
1185  {
1186  struct cppUtil::DemangledName dname = cppUtil::demangle(vfnVectors[i][j]->getName().str());
1187  SVFUtil::outs() << indent(currIndent) << "[" << j << "] "
1188  << dname.className << "::" << dname.funcName << "\n";
1189  }
1190 
1191  currIndent -= singleIndent;
1192  }
1193 
1194  // Nothing was printed.
1195  if (vfnVectors.size() == 0)
1196  {
1197  SVFUtil::outs() << indent(currIndent) << "(none)\n";
1198  }
1199 
1200  currIndent -= singleIndent;
1201 
1202  SVFUtil::outs() << indent(currIndent) << "Bases\n";
1203  currIndent += singleIndent;
1204  for (const DCHEdge *edge : node->getOutEdges())
1205  {
1206  std::string arrow;
1207  if (edge->getEdgeKind() == DCHEdge::INHERITANCE)
1208  {
1209  arrow = "--inheritance-->";
1210  }
1211  else if (edge->getEdgeKind() == DCHEdge::FIRST_FIELD)
1212  {
1213  arrow = "--first-field-->";
1214  }
1215  else if (edge->getEdgeKind() == DCHEdge::INSTANCE)
1216  {
1217  arrow = "---instance---->";
1218  }
1219  else if (edge->getEdgeKind() == DCHEdge::STD_DEF)
1220  {
1221  arrow = "---standard---->";
1222  }
1223  else
1224  {
1225  arrow = "----unknown---->";
1226  }
1227 
1228  SVFUtil::outs() << indent(currIndent) << "[ " << diTypeToStr(node->getDIType()) << " ] "
1229  << arrow << " [ " << diTypeToStr(edge->getDstNode()->getDIType()) << " ]\n";
1230  }
1231 
1232  if (node->getOutEdges().size() == 0)
1233  {
1234  SVFUtil::outs() << indent(currIndent) << "(none)\n";
1235  }
1236 
1237  currIndent -= singleIndent;
1238 
1239  SVFUtil::outs() << indent(currIndent) << "Typedefs\n";
1240 
1241  currIndent += singleIndent;
1242 
1243  const Set<const DIDerivedType *> &typedefs = node->getTypedefs();
1244  for (const DIDerivedType *tdef : typedefs)
1245  {
1246  std::string typedefName = "void";
1247  if (tdef != nullptr)
1248  {
1249  typedefName = tdef->getName().str();
1250  }
1251 
1252  SVFUtil::outs() << indent(currIndent) << typedefName << "\n";
1253  }
1254 
1255  if (typedefs.size() == 0)
1256  {
1257  SVFUtil::outs() << indent(currIndent) << "(none)\n";
1258  }
1259 
1260  currIndent -= singleIndent;
1261 
1262  currIndent -= singleIndent;
1263  }
1264 
1265  SVFUtil::outs() << thickLine;
1266 
1267  SVFUtil::outs() << "Other stats\n";
1268  SVFUtil::outs() << line;
1269  SVFUtil::outs() << "# Canonical types : " << canonicalTypes.size() << "\n";
1270  SVFUtil::outs() << "# structs : " << numStructs << "\n";
1271  SVFUtil::outs() << "Largest struct : " << largestStruct << " fields\n";
1272  SVFUtil::outs() << thickLine;
1273 
1274  SVFUtil::outs().flush();
1275 }
static std::string indent(size_t n)
Definition: DCHG.cpp:1135
newitem type
Definition: cJSON.cpp:2739
cJSON * a
Definition: cJSON.cpp:2560
cJSON * n
Definition: cJSON.cpp:2558
cJSON * child
Definition: cJSON.cpp:2723
const cJSON *const b
Definition: cJSON.h:255
int count
Definition: cJSON.h:216
const char *const string
Definition: cJSON.h:172
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
@ FIRST_FIELD
Definition: DCHG.h:37
@ INSTANCE
Definition: DCHG.h:36
@ STD_DEF
Definition: DCHG.h:38
@ INHERITANCE
Definition: DCHG.h:35
void setOffset(u32_t offset)
Definition: DCHG.h:54
const DIType * getCSStaticType(CallBase *cs) const
Retrieves the metadata associated with a virtual callsite.
Definition: DCHG.cpp:424
const DIType * getCanonicalType(const DIType *t)
Definition: DCHG.cpp:722
const NodeBS & cha(const DIType *type, bool firstField)
Returns a set of all children of type (CHA). Also gradually builds chaMap.
Definition: DCHG.cpp:223
void buildVTables(const SVFModule &module)
Finds all defined virtual functions and attaches them to nodes.
Definition: DCHG.cpp:166
static const DIType * stripQualifiers(const DIType *)
Returns the DIType beneath the qualifiers. Does not strip away "DW_TAG_members".
Definition: DCHG.cpp:763
void handleDIDerivedType(const DIDerivedType *derivedType)
Construction helper to process DIDerivedTypes.
Definition: DCHG.cpp:97
DCHEdge * addEdge(const DIType *t1, const DIType *t2, DCHEdge::GEdgeKind et)
Creates an edge between from t1 to t2.
Definition: DCHG.cpp:433
bool isFirstField(const DIType *f, const DIType *b)
Definition: DCHG.cpp:940
static std::string diTypeToStr(const DIType *)
Returns a human-readable version of the DIType.
Definition: DCHG.cpp:967
void handleDICompositeType(const DICompositeType *compositeType)
Construction helper to process DICompositeTypes.
Definition: DCHG.cpp:27
Map< const CallICFGNode *, VFunSet > csCHAMap
Maps callsites to a set of potential virtual functions based on CHA.
Definition: DCHG.h:376
bool hasNode(const DIType *type)
Checks if a node exists for type.
Definition: DCHG.h:424
void print(void)
Definition: DCHG.cpp:1140
Map< const DIType *, NodeBS > chaFFMap
Maps types to all children but also considering first field.
Definition: DCHG.h:372
Map< const DIType *, const DIType * > canonicalTypeMap
Maps types to their canonical type (many-to-one).
Definition: DCHG.h:378
void handleDISubroutineType(const DISubroutineType *subroutineType)
Construction helper to process DISubroutineTypes.
Definition: DCHG.cpp:133
virtual void getVFnsFromVtbls(const CallICFGNode *cs, const VTableSet &vtbls, VFunSet &virtualFunctions) override
Definition: DCHG.cpp:592
static const DIType * stripArray(const DIType *)
Returns the DIType beneath all qualifiers and arrays.
Definition: DCHG.cpp:816
void handleTypedef(const DIType *typedefType)
Attaches the typedef(s) to the base node.
Definition: DCHG.cpp:138
virtual void buildCHG(bool extend)
Definition: DCHG.cpp:469
DCHEdge * hasEdge(const DIType *t1, const DIType *t2, DCHEdge::GEdgeKind et)
Returns the edge between t1 and t2 if it exists, returns nullptr otherwise.
Definition: DCHG.cpp:450
NodeID numTypes
Number of types (nodes) in the graph.
Definition: DCHG.h:449
void handleDIBasicType(const DIBasicType *basicType)
Construction helper to process DIBasicTypes.
Definition: DCHG.cpp:22
virtual const VTableSet & getCSVtblsBasedonCHA(const CallICFGNode *cs) override
Definition: DCHG.cpp:564
void gatherAggs(const DICompositeType *type)
Populates containingAggs for type and all its elements.
Definition: DCHG.cpp:353
DCHNode * getNode(const DIType *type)
Returns the node for type (nullptr if it doesn't exist).
Definition: DCHG.h:431
static bool isAgg(const DIType *t)
Definition: DCHG.cpp:345
DCHNode * getOrCreateNode(const DIType *type)
Creates a node from type, or returns it if it exists.
Definition: DCHG.cpp:406
Map< const DIType *, VTableSet > vtblCHAMap
Maps types to a set with their vtable and all their children's.
Definition: DCHG.h:374
bool extended
Whether this CHG is an extended CHG (first-field). Set by buildCHG.
Definition: DCHG.h:364
Map< const DIType *, Set< const DIType * > > containingAggs
Maps aggregate types to all the aggregate types it transitively contains.
Definition: DCHG.h:384
virtual bool isBase(const DIType *a, const DIType *b, bool firstField)
Definition: DCHG.cpp:675
void flatten(const DICompositeType *type)
Populates fieldTypes for type and all its elements.
Definition: DCHG.cpp:268
virtual const VFunSet & getCSVFsBasedonCHA(const CallICFGNode *cs) override
Definition: DCHG.cpp:547
static bool teq(const DIType *t1, const DIType *t2)
Definition: DCHG.cpp:828
Map< const DIType *, std::vector< const DIType * > > fieldTypes
Maps types to their flattened fields' types.
Definition: DCHG.h:382
Map< const DIType *, NodeBS > chaMap
Maps types to all children (i.e. CHA).
Definition: DCHG.h:370
Map< const DIType *, DCHNode * > diTypeToNodeMap
Maps DITypes to their nodes.
Definition: DCHG.h:366
const std::vector< const DIType * > & getFieldTypes(const DIType *base)
Returns a vector of the types of all fields in base.
Definition: DCHG.h:335
virtual bool isFieldOf(const DIType *f, const DIType *b)
Returns true if f is a field of b (fields from getFieldTypes).
Definition: DCHG.cpp:686
Map< const SVFGlobalValue *, const DIType * > vtblToTypeMap
Maps VTables to the DIType associated with them.
Definition: DCHG.h:368
Set< const DIType * > canonicalTypes
Set of all possible canonical types (i.e. values of canonicalTypeMap).
Definition: DCHG.h:380
const DIType * getDIType(void) const
Definition: DCHG.h:96
std::vector< const Function * > & getVfnVector(unsigned n)
Return the nth virtual function vector in the vtable.
Definition: DCHG.h:181
const std::vector< std::vector< const Function * > > & getVfnVectors(void) const
Returns the vector of virtual function vectors.
Definition: DCHG.h:175
void addTypedef(const DIDerivedType *diTypedef)
Definition: DCHG.h:154
const Set< const DIDerivedType * > & getTypedefs(void) const
Definition: DCHG.h:159
void setVTable(const SVFGlobalValue *vtbl)
Definition: DCHG.h:164
void addGNode(NodeID id, NodeType *node)
Add a Node.
Definition: GenericGraph.h:646
NodeType * getGNode(NodeID id) const
Get a node.
Definition: GenericGraph.h:653
IDToNodeMapTy::const_iterator const_iterator
Definition: GenericGraph.h:607
IDToNodeMapTy::iterator iterator
Node Iterators.
Definition: GenericGraph.h:606
const GEdgeSetTy & getOutEdges() const
Definition: GenericGraph.h:430
bool addIncomingEdge(EdgeType *inEdge)
Add incoming and outgoing edges.
Definition: GenericGraph.h:527
bool addOutgoingEdge(EdgeType *outEdge)
Definition: GenericGraph.h:531
const GEdgeSetTy & getInEdges() const
Definition: GenericGraph.h:434
SVFGlobalValue * getSVFGlobalValue(const GlobalValue *g) const
Definition: LLVMModule.h:258
static LLVMModuleSet * getLLVMModuleSet()
Definition: LLVMModule.h:118
static const Option< bool > PrintDCHG
Definition: Options.h:179
NodeID getId() const
Get ID.
Definition: GenericGraph.h:260
bool test(unsigned Idx) const
const SVFFunction * getFunction(const std::string &name)
Get the corresponding Function based on its name.
Definition: LLVMUtil.cpp:412
std::ostream & outs()
Overwrite llvm::outs()
Definition: SVFUtil.h:50
const std::string derefMDName
Definition: CppUtil.h:168
const std::string vtMDName
Definition: CppUtil.h:171
struct DemangledName demangle(const std::string &name)
Definition: CppUtil.cpp:195
const ConstantStruct * getVtblStruct(const GlobalValue *vtbl)
Definition: CppUtil.cpp:323
for isBitcode
Definition: BasicTypes.h:68
llvm::DISubroutineType DISubroutineType
Definition: BasicTypes.h:240
llvm::GlobalVariable GlobalVariable
Definition: BasicTypes.h:130
llvm::DINodeArray DINodeArray
Definition: BasicTypes.h:244
llvm::CallBase CallBase
Definition: BasicTypes.h:146
Set< NodeID > NodeSet
Definition: GeneralType.h:113
llvm::ConstantStruct ConstantStruct
Definition: BasicTypes.h:106
Set< const SVFGlobalValue * > VTableSet
Definition: CHG.h:44
u32_t NodeID
Definition: GeneralType.h:55
llvm::ConstantArray ConstantArray
Definition: BasicTypes.h:123
llvm::DebugInfoFinder DebugInfoFinder
Definition: BasicTypes.h:239
llvm::Function Function
Definition: BasicTypes.h:85
iter_range< typename GenericGraphTraits< GraphType >::ChildIteratorType > children(const typename GenericGraphTraits< GraphType >::NodeRef &G)
Definition: GraphTraits.h:126
llvm::DINode DINode
Definition: BasicTypes.h:243
llvm::Constant Constant
Definition: BasicTypes.h:124
std::unordered_map< Key, Value, Hash, KeyEqual, Allocator > Map
Definition: GeneralType.h:101
llvm::DIDerivedType DIDerivedType
Definition: BasicTypes.h:238
llvm::DISubprogram DISubprogram
Definition: BasicTypes.h:113
llvm::ConstantExpr ConstantExpr
Definition: BasicTypes.h:120
llvm::DISubrange DISubrange
Definition: BasicTypes.h:242
llvm::DITypeRefArray DITypeRefArray
Definition: BasicTypes.h:245
llvm::Module Module
Definition: BasicTypes.h:84
llvm::DIType DIType
Definition: BasicTypes.h:236
Set< const SVFFunction * > VFunSet
Definition: CHG.h:47
llvm::MDNode MDNode
Definition: BasicTypes.h:112
llvm::DIBasicType DIBasicType
Definition: BasicTypes.h:241
llvm::DICompositeType DICompositeType
Definition: BasicTypes.h:237
llvm::ConstantInt ConstantInt
Definition: BasicTypes.h:125
iter_range< typename GenericGraphTraits< GraphType >::nodes_iterator > nodes(const GraphType &G)
Definition: GraphTraits.h:111
std::unordered_set< Key, Hash, KeyEqual, Allocator > Set
Definition: GeneralType.h:96