Static Value-Flow Analysis
Public Member Functions | Static Public Member Functions | Protected Attributes | Private Member Functions | Private Attributes | List of all members
SVF::DCHGraph Class Reference

Dwarf based CHG. More...

#include <DCHG.h>

Inheritance diagram for SVF::DCHGraph:
SVF::CommonCHGraph SVF::GenericGraph< DCHNode, DCHEdge >

Public Member Functions

 DCHGraph (const SVFModule *svfMod)
 
virtual ~DCHGraph ()
 
virtual void buildCHG (bool extend)
 
void dump (const std::string &filename)
 
void print (void)
 
virtual bool csHasVFnsBasedonCHA (const CallICFGNode *cs) override
 
virtual const VFunSetgetCSVFsBasedonCHA (const CallICFGNode *cs) override
 
virtual bool csHasVtblsBasedonCHA (CallBase *cs)
 
virtual bool csHasVtblsBasedonCHA (const CallICFGNode *cs) override
 
virtual const VTableSetgetCSVtblsBasedonCHA (const CallICFGNode *cs) override
 
virtual void getVFnsFromVtbls (const CallICFGNode *cs, const VTableSet &vtbls, VFunSet &virtualFunctions) override
 
virtual bool isBase (const DIType *a, const DIType *b, bool firstField)
 
virtual bool isFieldOf (const DIType *f, const DIType *b)
 Returns true if f is a field of b (fields from getFieldTypes). More...
 
const DITypegetCanonicalType (const DIType *t)
 
const DITypegetFieldType (const DIType *base, unsigned idx)
 Returns the type of field number idx (flattened) in base. More...
 
const std::vector< const DIType * > & getFieldTypes (const DIType *base)
 Returns a vector of the types of all fields in base. More...
 
unsigned getNumFields (const DIType *base)
 
const Set< const DIType * > & getAggs (const DIType *base)
 Returns all the aggregates contained (transitively) in base. More...
 
bool isFirstField (const DIType *f, const DIType *b)
 
- Public Member Functions inherited from SVF::CommonCHGraph
virtual ~CommonCHGraph ()
 
CHGKind getKind (void) const
 
- Public Member Functions inherited from SVF::GenericGraph< DCHNode, DCHEdge >
 GenericGraph ()
 Constructor. More...
 
virtual ~GenericGraph ()
 Destructor. More...
 
void destroy ()
 Release memory. More...
 
iterator begin ()
 Iterators. More...
 
const_iterator begin () const
 
iterator end ()
 
const_iterator end () const
 
void addGNode (NodeID id, NodeType *node)
 Add a Node. More...
 
NodeTypegetGNode (NodeID id) const
 Get a node. More...
 
bool hasGNode (NodeID id) const
 Has a node. More...
 
void removeGNode (NodeType *node)
 Delete a node. More...
 
u32_t getTotalNodeNum () const
 Get total number of node/edge. More...
 
u32_t getTotalEdgeNum () const
 
void incNodeNum ()
 Increase number of node/edge. More...
 
void incEdgeNum ()
 

Static Public Member Functions

static const DITypestripQualifiers (const DIType *)
 Returns the DIType beneath the qualifiers. Does not strip away "DW_TAG_members". More...
 
static const DITypestripArray (const DIType *)
 Returns the DIType beneath all qualifiers and arrays. More...
 
static bool teq (const DIType *t1, const DIType *t2)
 
static std::string diTypeToStr (const DIType *)
 Returns a human-readable version of the DIType. More...
 
static bool isAgg (const DIType *t)
 
static bool classof (const CommonCHGraph *chg)
 

Protected Attributes

const SVFModulesvfModule
 SVF Module this CHG is built from. More...
 
bool extended = false
 Whether this CHG is an extended CHG (first-field). Set by buildCHG. More...
 
Map< const DIType *, DCHNode * > diTypeToNodeMap
 Maps DITypes to their nodes. More...
 
Map< const SVFGlobalValue *, const DIType * > vtblToTypeMap
 Maps VTables to the DIType associated with them. More...
 
Map< const DIType *, NodeBSchaMap
 Maps types to all children (i.e. CHA). More...
 
Map< const DIType *, NodeBSchaFFMap
 Maps types to all children but also considering first field. More...
 
Map< const DIType *, VTableSetvtblCHAMap
 Maps types to a set with their vtable and all their children's. More...
 
Map< const CallICFGNode *, VFunSetcsCHAMap
 Maps callsites to a set of potential virtual functions based on CHA. More...
 
Map< const DIType *, const DIType * > canonicalTypeMap
 Maps types to their canonical type (many-to-one). More...
 
Set< const DIType * > canonicalTypes
 Set of all possible canonical types (i.e. values of canonicalTypeMap). More...
 
Map< const DIType *, std::vector< const DIType * > > fieldTypes
 Maps types to their flattened fields' types. More...
 
Map< const DIType *, Set< const DIType * > > containingAggs
 Maps aggregate types to all the aggregate types it transitively contains. More...
 
- Protected Attributes inherited from SVF::CommonCHGraph
CHGKind kind
 
- Protected Attributes inherited from SVF::GenericGraph< DCHNode, DCHEdge >
IDToNodeMapTy IDToNodeMap
 node map More...
 

Private Member Functions

void handleDIBasicType (const DIBasicType *basicType)
 Construction helper to process DIBasicTypes. More...
 
void handleDICompositeType (const DICompositeType *compositeType)
 Construction helper to process DICompositeTypes. More...
 
void handleDIDerivedType (const DIDerivedType *derivedType)
 Construction helper to process DIDerivedTypes. More...
 
void handleDISubroutineType (const DISubroutineType *subroutineType)
 Construction helper to process DISubroutineTypes. More...
 
void buildVTables (const SVFModule &module)
 Finds all defined virtual functions and attaches them to nodes. More...
 
const NodeBScha (const DIType *type, bool firstField)
 Returns a set of all children of type (CHA). Also gradually builds chaMap. More...
 
void handleTypedef (const DIType *typedefType)
 Attaches the typedef(s) to the base node. More...
 
void flatten (const DICompositeType *type)
 Populates fieldTypes for type and all its elements. More...
 
void gatherAggs (const DICompositeType *type)
 Populates containingAggs for type and all its elements. More...
 
DCHNodegetOrCreateNode (const DIType *type)
 Creates a node from type, or returns it if it exists. More...
 
const DITypegetCSStaticType (CallBase *cs) const
 Retrieves the metadata associated with a virtual callsite. More...
 
const DITypegetCSStaticType (const CallICFGNode *cs) const
 
bool hasNode (const DIType *type)
 Checks if a node exists for type. More...
 
DCHNodegetNode (const DIType *type)
 Returns the node for type (nullptr if it doesn't exist). More...
 
DCHEdgeaddEdge (const DIType *t1, const DIType *t2, DCHEdge::GEdgeKind et)
 Creates an edge between from t1 to t2. More...
 
DCHEdgehasEdge (const DIType *t1, const DIType *t2, DCHEdge::GEdgeKind et)
 Returns the edge between t1 and t2 if it exists, returns nullptr otherwise. More...
 

Private Attributes

NodeID numTypes
 Number of types (nodes) in the graph. More...
 

Additional Inherited Members

- Public Types inherited from SVF::CommonCHGraph
enum  CHGKind { Standard , DI }
 
- Public Types inherited from SVF::GenericGraph< DCHNode, DCHEdge >
typedef DCHNode NodeType
 
typedef DCHEdge EdgeType
 
typedef OrderedMap< NodeID, NodeType * > IDToNodeMapTy
 NodeID to GenericNode map. More...
 
typedef IDToNodeMapTy::iterator iterator
 Node Iterators. More...
 
typedef IDToNodeMapTy::const_iterator const_iterator
 
- Public Attributes inherited from SVF::GenericGraph< DCHNode, DCHEdge >
u32_t edgeNum
 total num of node More...
 
u32_t nodeNum
 total num of edge More...
 

Detailed Description

Dwarf based CHG.

Definition at line 208 of file DCHG.h.

Constructor & Destructor Documentation

◆ DCHGraph()

SVF::DCHGraph::DCHGraph ( const SVFModule svfMod)
inline

Definition at line 233 of file DCHG.h.

234  : svfModule(svfMod), numTypes(0) // vfID(0), buildingCHGTime(0) {
235  {
236  this->kind = DI;
237  }
CHGKind kind
Definition: CHG.h:73
NodeID numTypes
Number of types (nodes) in the graph.
Definition: DCHG.h:449
const SVFModule * svfModule
SVF Module this CHG is built from.
Definition: DCHG.h:362

◆ ~DCHGraph()

virtual SVF::DCHGraph::~DCHGraph ( )
inlinevirtual

Definition at line 239 of file DCHG.h.

239 { };

Member Function Documentation

◆ addEdge()

DCHEdge * DCHGraph::addEdge ( const DIType t1,
const DIType t2,
DCHEdge::GEdgeKind  et 
)
private

Creates an edge between from t1 to t2.

Definition at line 433 of file DCHG.cpp.

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 }
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
DCHNode * getOrCreateNode(const DIType *type)
Creates a node from type, or returns it if it exists.
Definition: DCHG.cpp:406
bool addIncomingEdge(EdgeType *inEdge)
Add incoming and outgoing edges.
Definition: GenericGraph.h:527
bool addOutgoingEdge(EdgeType *outEdge)
Definition: GenericGraph.h:531

◆ buildCHG()

void DCHGraph::buildCHG ( bool  extend)
virtual

Builds the CHG from DWARF debug information. extend determines whether to extend the CHG with first field edges.

Definition at line 469 of file DCHG.cpp.

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 }
newitem type
Definition: cJSON.cpp:2739
@ STD_DEF
Definition: DCHG.h:38
void buildVTables(const SVFModule &module)
Finds all defined virtual functions and attaches them to nodes.
Definition: DCHG.cpp:166
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
void handleDICompositeType(const DICompositeType *compositeType)
Construction helper to process DICompositeTypes.
Definition: DCHG.cpp:27
void print(void)
Definition: DCHG.cpp:1140
void handleDISubroutineType(const DISubroutineType *subroutineType)
Construction helper to process DISubroutineTypes.
Definition: DCHG.cpp:133
void handleDIBasicType(const DIBasicType *basicType)
Construction helper to process DIBasicTypes.
Definition: DCHG.cpp:22
bool extended
Whether this CHG is an extended CHG (first-field). Set by buildCHG.
Definition: DCHG.h:364
IDToNodeMapTy::iterator iterator
Node Iterators.
Definition: GenericGraph.h:606
static LLVMModuleSet * getLLVMModuleSet()
Definition: LLVMModule.h:118
static const Option< bool > PrintDCHG
Definition: Options.h:179
llvm::DISubroutineType DISubroutineType
Definition: BasicTypes.h:240
llvm::DebugInfoFinder DebugInfoFinder
Definition: BasicTypes.h:239
llvm::DIDerivedType DIDerivedType
Definition: BasicTypes.h:238
llvm::Module Module
Definition: BasicTypes.h:84
llvm::DIType DIType
Definition: BasicTypes.h:236
llvm::DIBasicType DIBasicType
Definition: BasicTypes.h:241
llvm::DICompositeType DICompositeType
Definition: BasicTypes.h:237

◆ buildVTables()

void DCHGraph::buildVTables ( const SVFModule module)
private

Finds all defined virtual functions and attaches them to nodes.

Definition at line 166 of file DCHG.cpp.

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 }
const DIType * getCanonicalType(const DIType *t)
Definition: DCHG.cpp:722
Map< const SVFGlobalValue *, const DIType * > vtblToTypeMap
Maps VTables to the DIType associated with them.
Definition: DCHG.h:368
std::vector< const Function * > & getVfnVector(unsigned n)
Return the nth virtual function vector in the vtable.
Definition: DCHG.h:181
void setVTable(const SVFGlobalValue *vtbl)
Definition: DCHG.h:164
SVFGlobalValue * getSVFGlobalValue(const GlobalValue *g) const
Definition: LLVMModule.h:258
const std::string vtMDName
Definition: CppUtil.h:171
const ConstantStruct * getVtblStruct(const GlobalValue *vtbl)
Definition: CppUtil.cpp:323
llvm::GlobalVariable GlobalVariable
Definition: BasicTypes.h:130
llvm::ConstantStruct ConstantStruct
Definition: BasicTypes.h:106
llvm::ConstantArray ConstantArray
Definition: BasicTypes.h:123
llvm::Function Function
Definition: BasicTypes.h:85
llvm::Constant Constant
Definition: BasicTypes.h:124
llvm::ConstantExpr ConstantExpr
Definition: BasicTypes.h:120

◆ cha()

const NodeBS & DCHGraph::cha ( const DIType type,
bool  firstField 
)
private

Returns a set of all children of type (CHA). Also gradually builds chaMap.

Definition at line 223 of file DCHG.cpp.

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 }
@ FIRST_FIELD
Definition: DCHG.h:37
@ INHERITANCE
Definition: DCHG.h:35
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
Map< const DIType *, NodeBS > chaFFMap
Maps types to all children but also considering first field.
Definition: DCHG.h:372
Map< const DIType *, NodeBS > chaMap
Maps types to all children (i.e. CHA).
Definition: DCHG.h:370
const GEdgeSetTy & getInEdges() const
Definition: GenericGraph.h:434
NodeID getId() const
Get ID.
Definition: GenericGraph.h:260
u32_t NodeID
Definition: GeneralType.h:55
iter_range< typename GenericGraphTraits< GraphType >::ChildIteratorType > children(const typename GenericGraphTraits< GraphType >::NodeRef &G)
Definition: GraphTraits.h:126
std::unordered_map< Key, Value, Hash, KeyEqual, Allocator > Map
Definition: GeneralType.h:101

◆ classof()

static bool SVF::DCHGraph::classof ( const CommonCHGraph chg)
inlinestatic

Definition at line 287 of file DCHG.h.

288  {
289  return chg->getKind() == DI;
290  }

◆ csHasVFnsBasedonCHA()

virtual bool SVF::DCHGraph::csHasVFnsBasedonCHA ( const CallICFGNode cs)
inlineoverridevirtual

Implements SVF::CommonCHGraph.

Definition at line 252 of file DCHG.h.

253  {
254  return csHasVtblsBasedonCHA(cs);
255  }
virtual bool csHasVtblsBasedonCHA(CallBase *cs)
Definition: DCHG.h:259

◆ csHasVtblsBasedonCHA() [1/2]

virtual bool SVF::DCHGraph::csHasVtblsBasedonCHA ( CallBase cs)
inlinevirtual

Definition at line 259 of file DCHG.h.

260  {
261  assert(false && "not supported");
263  if (!hasNode(type))
264  {
265  return false;
266  }
267 
268  return getNode(type)->getVTable() != nullptr;
269  }
const DIType * getCSStaticType(CallBase *cs) const
Retrieves the metadata associated with a virtual callsite.
Definition: DCHG.cpp:424
bool hasNode(const DIType *type)
Checks if a node exists for type.
Definition: DCHG.h:424
DCHNode * getNode(const DIType *type)
Returns the node for type (nullptr if it doesn't exist).
Definition: DCHG.h:431
const SVFGlobalValue * getVTable() const
Definition: DCHG.h:169

◆ csHasVtblsBasedonCHA() [2/2]

virtual bool SVF::DCHGraph::csHasVtblsBasedonCHA ( const CallICFGNode cs)
inlineoverridevirtual

Implements SVF::CommonCHGraph.

Definition at line 271 of file DCHG.h.

272  {
273  assert(false && "not supported!");
274  abort();
275  }

◆ diTypeToStr()

std::string DCHGraph::diTypeToStr ( const DIType t)
static

Returns a human-readable version of the DIType.

Definition at line 967 of file DCHG.cpp.

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 }
int count
Definition: cJSON.h:216
static std::string diTypeToStr(const DIType *)
Returns a human-readable version of the DIType.
Definition: DCHG.cpp:967
llvm::DINodeArray DINodeArray
Definition: BasicTypes.h:244
llvm::DISubprogram DISubprogram
Definition: BasicTypes.h:113
llvm::DISubrange DISubrange
Definition: BasicTypes.h:242
llvm::DITypeRefArray DITypeRefArray
Definition: BasicTypes.h:245
llvm::ConstantInt ConstantInt
Definition: BasicTypes.h:125

◆ dump()

void SVF::DCHGraph::dump ( const std::string filename)
inline

Definition at line 245 of file DCHG.h.

246  {
248  }
static void WriteGraphToFile(SVF::OutStream &O, const std::string &GraphName, const GraphType &GT, bool simple=false)
Definition: GraphPrinter.h:56
std::ostream & outs()
Overwrite llvm::outs()
Definition: SVFUtil.h:50

◆ flatten()

void DCHGraph::flatten ( const DICompositeType type)
private

Populates fieldTypes for type and all its elements.

Definition at line 268 of file DCHG.cpp.

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 }
cJSON * a
Definition: cJSON.cpp:2560
const cJSON *const b
Definition: cJSON.h:255
void flatten(const DICompositeType *type)
Populates fieldTypes for type and all its elements.
Definition: DCHG.cpp:268
Map< const DIType *, std::vector< const DIType * > > fieldTypes
Maps types to their flattened fields' types.
Definition: DCHG.h:382

◆ gatherAggs()

void DCHGraph::gatherAggs ( const DICompositeType type)
private

Populates containingAggs for type and all its elements.

Definition at line 353 of file DCHG.cpp.

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 }
static const DIType * stripQualifiers(const DIType *)
Returns the DIType beneath the qualifiers. Does not strip away "DW_TAG_members".
Definition: DCHG.cpp:763
void gatherAggs(const DICompositeType *type)
Populates containingAggs for type and all its elements.
Definition: DCHG.cpp:353
static bool isAgg(const DIType *t)
Definition: DCHG.cpp:345
Map< const DIType *, Set< const DIType * > > containingAggs
Maps aggregate types to all the aggregate types it transitively contains.
Definition: DCHG.h:384

◆ getAggs()

const Set<const DIType *>& SVF::DCHGraph::getAggs ( const DIType base)
inline

Returns all the aggregates contained (transitively) in base.

Definition at line 351 of file DCHG.h.

352  {
353  base = getCanonicalType(base);
354  assert(containingAggs.find(base) != containingAggs.end() && "DCHG: aggregates not gathered for base!");
355  return containingAggs[base];
356  }

◆ getCanonicalType()

const DIType * DCHGraph::getCanonicalType ( const DIType t)

Returns the type representing all qualifier-variations of t. This should only matter in the case of DerivedTypes where qualifiers and have qualified base types cause a mess.

Definition at line 722 of file DCHG.cpp.

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 }
Map< const DIType *, const DIType * > canonicalTypeMap
Maps types to their canonical type (many-to-one).
Definition: DCHG.h:378
static bool teq(const DIType *t1, const DIType *t2)
Definition: DCHG.cpp:828
Set< const DIType * > canonicalTypes
Set of all possible canonical types (i.e. values of canonicalTypeMap).
Definition: DCHG.h:380

◆ getCSStaticType() [1/2]

const DIType * DCHGraph::getCSStaticType ( CallBase cs) const
private

Retrieves the metadata associated with a virtual callsite.

Definition at line 424 of file DCHG.cpp.

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 }
const std::string derefMDName
Definition: CppUtil.h:168
llvm::MDNode MDNode
Definition: BasicTypes.h:112

◆ getCSStaticType() [2/2]

const DIType* SVF::DCHGraph::getCSStaticType ( const CallICFGNode cs) const
inlineprivate

Definition at line 417 of file DCHG.h.

418  {
419  assert(false && "not supported!");
420  abort();
421  }

◆ getCSVFsBasedonCHA()

const VFunSet & DCHGraph::getCSVFsBasedonCHA ( const CallICFGNode cs)
overridevirtual

Implements SVF::CommonCHGraph.

Definition at line 547 of file DCHG.cpp.

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 }
Map< const CallICFGNode *, VFunSet > csCHAMap
Maps callsites to a set of potential virtual functions based on CHA.
Definition: DCHG.h:376
virtual void getVFnsFromVtbls(const CallICFGNode *cs, const VTableSet &vtbls, VFunSet &virtualFunctions) override
Definition: DCHG.cpp:592
virtual const VTableSet & getCSVtblsBasedonCHA(const CallICFGNode *cs) override
Definition: DCHG.cpp:564
Set< const SVFGlobalValue * > VTableSet
Definition: CHG.h:44
Set< const SVFFunction * > VFunSet
Definition: CHG.h:47

◆ getCSVtblsBasedonCHA()

const VTableSet & DCHGraph::getCSVtblsBasedonCHA ( const CallICFGNode cs)
overridevirtual

Implements SVF::CommonCHGraph.

Definition at line 564 of file DCHG.cpp.

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 }
cJSON * child
Definition: cJSON.cpp:2723
Map< const DIType *, VTableSet > vtblCHAMap
Maps types to a set with their vtable and all their children's.
Definition: DCHG.h:374
NodeType * getGNode(NodeID id) const
Get a node.
Definition: GenericGraph.h:653

◆ getFieldType()

const DIType* SVF::DCHGraph::getFieldType ( const DIType base,
unsigned  idx 
)
inline

Returns the type of field number idx (flattened) in base.

Definition at line 298 of file DCHG.h.

299  {
300  base = getCanonicalType(base);
301  if (base == nullptr)
302  {
303  // Conservative; the base object is untyped, sadly.
304  return nullptr;
305  }
306 
307  // For TBHC this is conservative because the union type is lower in the DCHG
308  // than its fields. TODO: make more precise.
309  if (base->getTag() == dwarf::DW_TAG_union_type)
310  {
311  return base;
312  }
313 
314  if (base->getTag() == dwarf::DW_TAG_array_type)
315  {
316  const DICompositeType* cbase =
317  SVFUtil::dyn_cast<DICompositeType>(base);
318  assert(cbase && "DCHG: bad DIComposite case");
319  return cbase->getBaseType();
320  }
321 
322  if (!(base->getTag() == dwarf::DW_TAG_class_type ||
323  base->getTag() == dwarf::DW_TAG_structure_type))
324  {
325  return nullptr;
326  }
327 
328  assert(fieldTypes.find(base) != fieldTypes.end() && "DCHG: base not flattened!");
329  std::vector<const DIType *> &fields = fieldTypes[base];
330  assert(fields.size() > idx && "DCHG: idx into struct larger than # fields!");
331  return getCanonicalType(fields[idx]);
332  }

◆ getFieldTypes()

const std::vector<const DIType *>& SVF::DCHGraph::getFieldTypes ( const DIType base)
inline

Returns a vector of the types of all fields in base.

Definition at line 335 of file DCHG.h.

336  {
337  base = getCanonicalType(base);
338  assert(fieldTypes.find(base) != fieldTypes.end() && "DCHG: base not flattened!");
339  return fieldTypes[base];
340  }

◆ getNode()

DCHNode* SVF::DCHGraph::getNode ( const DIType type)
inlineprivate

Returns the node for type (nullptr if it doesn't exist).

Definition at line 431 of file DCHG.h.

432  {
434  if (hasNode(type))
435  {
436  return diTypeToNodeMap.at(type);
437  }
438 
439  return nullptr;
440  }
Map< const DIType *, DCHNode * > diTypeToNodeMap
Maps DITypes to their nodes.
Definition: DCHG.h:366

◆ getNumFields()

unsigned SVF::DCHGraph::getNumFields ( const DIType base)
inline

Definition at line 343 of file DCHG.h.

344  {
345  base = getCanonicalType(base);
346  assert(fieldTypes.find(base) != fieldTypes.end() && "DCHG: base not flattened!");
347  return fieldTypes[base].size();
348  }

◆ getOrCreateNode()

DCHNode * DCHGraph::getOrCreateNode ( const DIType type)
private

Creates a node from type, or returns it if it exists.

Definition at line 406 of file DCHG.cpp.

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 }
void addGNode(NodeID id, NodeType *node)
Add a Node.
Definition: GenericGraph.h:646

◆ getVFnsFromVtbls()

void DCHGraph::getVFnsFromVtbls ( const CallICFGNode cs,
const VTableSet vtbls,
VFunSet virtualFunctions 
)
overridevirtual

Implements SVF::CommonCHGraph.

Definition at line 592 of file DCHG.cpp.

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 }
const char *const string
Definition: cJSON.h:172
const std::vector< std::vector< const Function * > > & getVfnVectors(void) const
Returns the vector of virtual function vectors.
Definition: DCHG.h:175
const SVFFunction * getFunction(const std::string &name)
Get the corresponding Function based on its name.
Definition: LLVMUtil.cpp:412
struct DemangledName demangle(const std::string &name)
Definition: CppUtil.cpp:195

◆ handleDIBasicType()

void DCHGraph::handleDIBasicType ( const DIBasicType basicType)
private

Construction helper to process DIBasicTypes.

Definition at line 22 of file DCHG.cpp.

23 {
24  getOrCreateNode(basicType);
25 }

◆ handleDICompositeType()

void DCHGraph::handleDICompositeType ( const DICompositeType compositeType)
private

Construction helper to process DICompositeTypes.

Definition at line 27 of file DCHG.cpp.

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 }
cJSON * n
Definition: cJSON.cpp:2558
llvm::DINode DINode
Definition: BasicTypes.h:243

◆ handleDIDerivedType()

void DCHGraph::handleDIDerivedType ( const DIDerivedType derivedType)
private

Construction helper to process DIDerivedTypes.

Definition at line 97 of file DCHG.cpp.

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 }
void setOffset(u32_t offset)
Definition: DCHG.h:54
void handleTypedef(const DIType *typedefType)
Attaches the typedef(s) to the base node.
Definition: DCHG.cpp:138

◆ handleDISubroutineType()

void DCHGraph::handleDISubroutineType ( const DISubroutineType subroutineType)
private

Construction helper to process DISubroutineTypes.

Definition at line 133 of file DCHG.cpp.

134 {
135  getOrCreateNode(subroutineType);
136 }

◆ handleTypedef()

void DCHGraph::handleTypedef ( const DIType typedefType)
private

Attaches the typedef(s) to the base node.

Definition at line 138 of file DCHG.cpp.

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 }
void addTypedef(const DIDerivedType *diTypedef)
Definition: DCHG.h:154

◆ hasEdge()

DCHEdge * DCHGraph::hasEdge ( const DIType t1,
const DIType t2,
DCHEdge::GEdgeKind  et 
)
private

Returns the edge between t1 and t2 if it exists, returns nullptr otherwise.

Definition at line 450 of file DCHG.cpp.

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 }
const GEdgeSetTy & getOutEdges() const
Definition: GenericGraph.h:430

◆ hasNode()

bool SVF::DCHGraph::hasNode ( const DIType type)
inlineprivate

Checks if a node exists for type.

Definition at line 424 of file DCHG.h.

425  {
427  return diTypeToNodeMap.find(type) != diTypeToNodeMap.end();
428  }

◆ isAgg()

bool DCHGraph::isAgg ( const DIType t)
static

Definition at line 345 of file DCHG.cpp.

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 }

◆ isBase()

bool DCHGraph::isBase ( const DIType a,
const DIType b,
bool  firstField 
)
virtual

Returns true if a is a transitive base of b. firstField determines whether to consider first-field edges.

Definition at line 675 of file DCHG.cpp.

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 }
bool test(unsigned Idx) const

◆ isFieldOf()

bool DCHGraph::isFieldOf ( const DIType f,
const DIType b 
)
virtual

Returns true if f is a field of b (fields from getFieldTypes).

Definition at line 686 of file DCHG.cpp.

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 }
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

◆ isFirstField()

bool DCHGraph::isFirstField ( const DIType f,
const DIType b 
)

Definition at line 940 of file DCHG.cpp.

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 }
bool isFirstField(const DIType *f, const DIType *b)
Definition: DCHG.cpp:940

◆ print()

void DCHGraph::print ( void  )

Definition at line 1140 of file DCHG.cpp.

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
@ INSTANCE
Definition: DCHG.h:36
const DIType * getDIType(void) const
Definition: DCHG.h:96
const Set< const DIDerivedType * > & getTypedefs(void) const
Definition: DCHG.h:159
IDToNodeMapTy::const_iterator const_iterator
Definition: GenericGraph.h:607
Set< NodeID > NodeSet
Definition: GeneralType.h:113
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

◆ stripArray()

const DIType * DCHGraph::stripArray ( const DIType t)
static

Returns the DIType beneath all qualifiers and arrays.

Definition at line 816 of file DCHG.cpp.

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 }
static const DIType * stripArray(const DIType *)
Returns the DIType beneath all qualifiers and arrays.
Definition: DCHG.cpp:816

◆ stripQualifiers()

const DIType * DCHGraph::stripQualifiers ( const DIType t)
static

Returns the DIType beneath the qualifiers. Does not strip away "DW_TAG_members".

Definition at line 763 of file DCHG.cpp.

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 }

◆ teq()

bool DCHGraph::teq ( const DIType t1,
const DIType t2 
)
static

Returns true if t1 and t2 are equivalent, ignoring qualifiers. For equality... Tags always need to be equal. DIBasicType: shallow pointer equality. DIDerivedType: base types (teq). DICompositeType: shallow pointer equality. DISubroutineType: shallow pointer equality.

Definition at line 828 of file DCHG.cpp.

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 }

Member Data Documentation

◆ canonicalTypeMap

Map<const DIType*, const DIType*> SVF::DCHGraph::canonicalTypeMap
protected

Maps types to their canonical type (many-to-one).

Definition at line 378 of file DCHG.h.

◆ canonicalTypes

Set<const DIType*> SVF::DCHGraph::canonicalTypes
protected

Set of all possible canonical types (i.e. values of canonicalTypeMap).

Definition at line 380 of file DCHG.h.

◆ chaFFMap

Map<const DIType*, NodeBS> SVF::DCHGraph::chaFFMap
protected

Maps types to all children but also considering first field.

Definition at line 372 of file DCHG.h.

◆ chaMap

Map<const DIType*, NodeBS> SVF::DCHGraph::chaMap
protected

Maps types to all children (i.e. CHA).

Definition at line 370 of file DCHG.h.

◆ containingAggs

Map<const DIType*, Set<const DIType*> > SVF::DCHGraph::containingAggs
protected

Maps aggregate types to all the aggregate types it transitively contains.

Definition at line 384 of file DCHG.h.

◆ csCHAMap

Map<const CallICFGNode*, VFunSet> SVF::DCHGraph::csCHAMap
protected

Maps callsites to a set of potential virtual functions based on CHA.

Definition at line 376 of file DCHG.h.

◆ diTypeToNodeMap

Map<const DIType*, DCHNode*> SVF::DCHGraph::diTypeToNodeMap
protected

Maps DITypes to their nodes.

Definition at line 366 of file DCHG.h.

◆ extended

bool SVF::DCHGraph::extended = false
protected

Whether this CHG is an extended CHG (first-field). Set by buildCHG.

Definition at line 364 of file DCHG.h.

◆ fieldTypes

Map<const DIType*, std::vector<const DIType*> > SVF::DCHGraph::fieldTypes
protected

Maps types to their flattened fields' types.

Definition at line 382 of file DCHG.h.

◆ numTypes

NodeID SVF::DCHGraph::numTypes
private

Number of types (nodes) in the graph.

Definition at line 449 of file DCHG.h.

◆ svfModule

const SVFModule* SVF::DCHGraph::svfModule
protected

SVF Module this CHG is built from.

Definition at line 362 of file DCHG.h.

◆ vtblCHAMap

Map<const DIType*, VTableSet> SVF::DCHGraph::vtblCHAMap
protected

Maps types to a set with their vtable and all their children's.

Definition at line 374 of file DCHG.h.

◆ vtblToTypeMap

Map<const SVFGlobalValue*, const DIType*> SVF::DCHGraph::vtblToTypeMap
protected

Maps VTables to the DIType associated with them.

Definition at line 368 of file DCHG.h.


The documentation for this class was generated from the following files: