Static Value-Flow Analysis
Loading...
Searching...
No Matches
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).
 
const DITypegetCanonicalType (const DIType *t)
 
const DITypegetFieldType (const DIType *base, unsigned idx)
 Returns the type of field number idx (flattened) in base.
 
const std::vector< const DIType * > & getFieldTypes (const DIType *base)
 Returns a vector of the types of all fields in base.
 
unsigned getNumFields (const DIType *base)
 
const Set< const DIType * > & getAggs (const DIType *base)
 Returns all the aggregates contained (transitively) in base.
 
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.
 
virtual ~GenericGraph ()
 Destructor.
 
void destroy ()
 Release memory.
 
iterator begin ()
 Iterators.
 
const_iterator begin () const
 
iterator end ()
 
const_iterator end () const
 
void addGNode (NodeID id, NodeType *node)
 Add a Node.
 
NodeTypegetGNode (NodeID id) const
 Get a node.
 
bool hasGNode (NodeID id) const
 Has a node.
 
void removeGNode (NodeType *node)
 Delete a node.
 
u32_t getTotalNodeNum () const
 Get total number of node/edge.
 
u32_t getTotalEdgeNum () const
 
void incNodeNum ()
 Increase number of node/edge.
 
void incEdgeNum ()
 

Static Public Member Functions

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

Protected Attributes

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

Private Member Functions

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

Private Attributes

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

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.
 
typedef IDToNodeMapTy::iterator iterator
 Node Iterators.
 
typedef IDToNodeMapTy::const_iterator const_iterator
 
- Public Attributes inherited from SVF::GenericGraph< DCHNode, DCHEdge >
u32_t edgeNum
 total num of node
 
u32_t nodeNum
 total num of edge
 

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.
bool addOutgoingEdge(EdgeType *outEdge)
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74

◆ 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{
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
503 }
504 else if (const DICompositeType *compositeType = SVFUtil::dyn_cast<DICompositeType>(type))
505 {
507 }
508 else if (const DIDerivedType *derivedType = SVFUtil::dyn_cast<DIDerivedType>(type))
509 {
511 }
512 else if (const DISubroutineType *subroutineType = SVFUtil::dyn_cast<DISubroutineType>(type))
513 {
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
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.
static LLVMModuleSet * getLLVMModuleSet()
Definition LLVMModule.h:122
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");
181 node->setVTable(svfgv);
183
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:288
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{
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
NodeID getId() const
Get ID.
u32_t NodeID
Definition GeneralType.h:55
iter_range< typename GenericGraphTraits< GraphType >::ChildIteratorType > children(const typename GenericGraphTraits< GraphType >::NodeRef &G)

◆ 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)
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.
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 {
336 }
337 }
338 else
339 {
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();
368
369 if (isAgg(bt))
370 {
371 const DICompositeType *cbt = SVFUtil::dyn_cast<DICompositeType>(bt);
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();
390
391 if (isAgg(ft))
392 {
393 const DICompositeType *cft = SVFUtil::dyn_cast<DICompositeType>(ft);
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.
730 {
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 {
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.
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
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:46
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
574 const NodeBS &children = cha(type, false);
575 for (NodeID childId : children)
576 {
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.

◆ 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.

◆ 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 {
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 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:411
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{
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:
34 break;
35 case dwarf::DW_TAG_class_type:
36 case dwarf::DW_TAG_structure_type:
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 {
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.
62 }
63 }
64 }
65
68
69 break;
70 case dwarf::DW_TAG_union_type:
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");
82 }
83 }
84
85 // flatten(compositeType);
87
88 break;
89 case dwarf::DW_TAG_enumeration_type:
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:
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:
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 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.

◆ 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;
158
159 for (const DIDerivedType *tdef : typedefs)
160 {
161 // Base type needs to hold its typedefs.
162 baseTypeNode->addTypedef(tdef);
163 }
164}

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

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

◆ 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
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
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.
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;
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();
1174 }
1175
1177 SVFUtil::outs() << indent(currIndent) << "Virtual functions\n";
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";
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
1192 }
1193
1194 // Nothing was printed.
1195 if (vfnVectors.size() == 0)
1196 {
1197 SVFUtil::outs() << indent(currIndent) << "(none)\n";
1198 }
1199
1201
1202 SVFUtil::outs() << indent(currIndent) << "Bases\n";
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
1238
1239 SVFUtil::outs() << indent(currIndent) << "Typedefs\n";
1240
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
1261
1263 }
1264
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";
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
const GEdgeSetTy & getOutEdges() const
Set< NodeID > NodeSet
iter_range< typename GenericGraphTraits< GraphType >::nodes_iterator > nodes(const GraphType &G)

◆ 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{
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: