31 case dwarf::DW_TAG_array_type:
35 case dwarf::DW_TAG_class_type:
36 case dwarf::DW_TAG_structure_type:
50 if (
fm->getTag() == dwarf::DW_TAG_member && !
fm->isStaticMember())
70 case dwarf::DW_TAG_union_type:
89 case dwarf::DW_TAG_enumeration_type:
93 assert(
false &&
"DCHGraph::buildCHG: unexpected CompositeType tag.");
101 case dwarf::DW_TAG_inheritance:
103 assert(SVFUtil::isa<DIType>(
derivedType->getScope()) &&
"inheriting from non-type?");
110 case dwarf::DW_TAG_member:
111 case dwarf::DW_TAG_friend:
114 case dwarf::DW_TAG_typedef:
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:
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:
129 assert(
false &&
"DCHGraph::buildCHG: unexpected DerivedType tag.");
144 std::vector<const DIDerivedType *> typedefs;
170 for (Module::const_global_iterator
gvI =
M.global_begin();
gvI !=
M.global_end(); ++
gvI)
174 if (
gv ==
nullptr)
continue;
178 assert(
type &&
"DCHG::buildVTables: bad metadata for ctir.vt");
188 assert(
vtbl &&
"Element of vtbl struct not an array");
196 for (
unsigned cN = 0;
cN <
vtbl->getNumOperands(); ++
cN)
199 if (SVFUtil::isa<ConstantPointerNull>(
c))
206 assert(
ce &&
"non-ConstantExpr, non-ConstantPointerNull in vtable?");
207 if (
ce->getOpcode() == Instruction::BitCast)
210 const Function*
vfn = SVFUtil::dyn_cast<Function>(
ce->getOperand(0));
271 assert(
type &&
"DCHG::flatten: canon type of struct/class is not struct/class");
282 && (
type->getTag() == dwarf::DW_TAG_class_type
283 ||
type->getTag() == dwarf::DW_TAG_structure_type)
284 &&
"DCHG::flatten: expected a class/struct");
287 std::vector<const DIDerivedType *>
fields;
301 { return a->getOffsetInBits() < b->getOffsetInBits(); });
305 assert((
mt->getTag() == dwarf::DW_TAG_member ||
mt->getTag() == dwarf::DW_TAG_inheritance)
306 &&
"DCHG: expected member/inheritance");
309 if (
fieldType->getTag() == dwarf::DW_TAG_structure_type
310 ||
fieldType->getTag() == dwarf::DW_TAG_class_type)
320 else if (
fieldType->getTag() == dwarf::DW_TAG_array_type)
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;
364 if (
type->getTag() == dwarf::DW_TAG_array_type)
383 for (
unsigned i = 0;
i <
fields.size(); ++
i)
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");
459 if (node == dst && edgeType ==
et)
461 assert(SVFUtil::isa<DCHEdge>(
edge) &&
"Non-DCHEdge in DCHNode edge set.");
496 if (
basicType->getEncoding() == dwarf::DW_ATE_unsigned_char
497 ||
basicType->getEncoding() == dwarf::DW_ATE_signed_char)
518 assert(
false &&
"DCHGraph::buildCHG: unexpected DIType.");
533 if (
nodeI->second->getDIType() !=
nullptr
534 &&
nodeI->second->getOutEdges().size() == 0)
627 const std::string
suffix(
"[abi:cxx11]");
688 assert(
f &&
b &&
"DCHG::isFieldOf: given nullptr!");
692 if (
f ==
b)
return true;
694 if (
b->getTag() == dwarf::DW_TAG_array_type ||
b->getTag() == dwarf::DW_TAG_pointer_type)
701 else if (
const DIDerivedType *ptrType = SVFUtil::dyn_cast<DIDerivedType>(
b))
705 assert(
baseType &&
"DCHG::isFieldOf: baseType is neither DIComposite nor DIDerived!");
710 else if (
b->getTag() == dwarf::DW_TAG_class_type
711 ||
b->getTag() == dwarf::DW_TAG_structure_type)
769 || SVFUtil::isa<DIBasicType>(t)
770 || SVFUtil::isa<DISubroutineType>(t))
775 unsigned tag = t->getTag();
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)
785 assert(t &&
"DCHG: expected DerivedType");
786 t =
dt->getBaseType();
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)
802 else if (
tag == dwarf::DW_TAG_inheritance
803 ||
tag == dwarf::DW_TAG_friend)
805 assert(
false &&
"DCHG: unexpected tag when stripping qualifiers");
809 assert(
false &&
"DCHG: unhandled tag when stripping qualifiers");
819 if (t->getTag() == dwarf::DW_TAG_array_type)
839 if (
t1 ==
nullptr ||
t2 ==
nullptr)
847 if (SVFUtil::isa<DIBasicType>(
t1) && SVFUtil::isa<DIBasicType>(
t2))
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))
857 (
enc1 == dwarf::DW_ATE_float &&
enc2 == dwarf::DW_ATE_float)
859 ((
enc1 == dwarf::DW_ATE_signed_char ||
enc1 == dwarf::DW_ATE_unsigned_char)
861 (
enc2 == dwarf::DW_ATE_signed_char ||
enc2 == dwarf::DW_ATE_unsigned_char));
866 return t1->getSizeInBits() ==
t2->getSizeInBits()
867 &&
t1->getAlignInBits() ==
t2->getAlignInBits();
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))
886 assert(
c1 &&
"teq: bad cast for array type");
898 assert(
c2 &&
"teq: bad cast for array type");
907 if (SVFUtil::isa<DICompositeType>(
t1) && SVFUtil::isa<DICompositeType>(
t2))
912 if (
ct1->getTag() !=
ct2->getTag())
return false;
915 if (
ct1->getTag() == dwarf::DW_TAG_enumeration_type)
921 if (
ct1->getTag() == dwarf::DW_TAG_class_type)
923 return ct1->getIdentifier() ==
ct2->getIdentifier();
929 return ct1->getName() ==
ct2->getName()
930 &&
ct1->getFile() ==
ct2->getFile()
931 &&
ct1->getLine() ==
ct2->getLine();
949 if (
f ==
b)
return true;
952 assert(node &&
"DCHG::isFirstField: node not found");
959 if (
edge->getSrcNode()->getDIType() ==
b)
return true;
969 std::stringstream
ss;
976 if (
const DIBasicType *
bt = SVFUtil::dyn_cast<DIBasicType>(t))
978 ss <<
bt->getName().str();
980 else if (
const DIDerivedType *
dt = SVFUtil::dyn_cast<DIDerivedType>(t))
982 if (
dt->getName() ==
"__vtbl_ptr_type")
984 ss <<
"(vtbl * =) __vtbl_ptr_type";
986 else if (
dt->getTag() == dwarf::DW_TAG_const_type)
990 else if (
dt->getTag() == dwarf::DW_TAG_volatile_type)
994 else if (
dt->getTag() == dwarf::DW_TAG_restrict_type)
998 else if (
dt->getTag() == dwarf::DW_TAG_atomic_type)
1002 else if (
dt->getTag() == dwarf::DW_TAG_pointer_type)
1006 else if (
dt->getTag() == dwarf::DW_TAG_ptr_to_member_type)
1009 <<
" " <<
diTypeToStr(SVFUtil::dyn_cast<DIType>(
dt->getExtraData())) <<
"::*";
1011 else if (
dt->getTag() == dwarf::DW_TAG_reference_type)
1015 else if (
dt->getTag() == dwarf::DW_TAG_rvalue_reference_type)
1019 else if (
dt->getTag() == dwarf::DW_TAG_typedef)
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)
1031 if (
ct->getTag() == dwarf::DW_TAG_class_type)
1035 else if (
ct->getTag() == dwarf::DW_TAG_structure_type)
1039 else if (
ct->getTag() == dwarf::DW_TAG_union_type)
1046 if (
ct->getName() !=
"")
1048 ss <<
ct->getName().str();
1056 for (
unsigned i = 0;
i <
fields.size(); ++
i)
1062 ss <<
sp->getName().str();
1066 assert(
mt->getTag() == dwarf::DW_TAG_member &&
"DCHG: expected member");
1079 else if (
ct->getTag() == dwarf::DW_TAG_array_type)
1083 for (
unsigned i = 0;
i <
sizes.size(); ++
i)
1086 assert(
sr !=
nullptr &&
"DCHG: non-subrange as array element?");
1096 else if (
ct->getTag() == dwarf::DW_TAG_enumeration_type)
1100 else if (
ct->getTag() == dwarf::DW_TAG_union_type)
1110 if (
types.size() == 1)
1116 for (
unsigned i = 1;
i <
types.size(); ++
i)
1119 if (
i + 1 !=
types.size())
1129 ss <<
st->getName().str();
1137 return std::string(
n,
' ');
1142 static const std::string
line =
"-------------------------------------\n";
1143 static const std::string
thickLine =
"=====================================\n";
1158 if (*
nodes.begin() != id)
1167 && (node->
getDIType()->getTag() == dwarf::DW_TAG_class_type
1169 node->
getDIType()->getTag() == dwarf::DW_TAG_structure_type))
1179 const std::vector<std::vector<const Function* >> &vfnVectors = node->
getVfnVectors();
1180 for (
unsigned i = 0;
i < vfnVectors.size(); ++
i)
1184 for (
unsigned j = 0;
j < vfnVectors[
i].size(); ++
j)
1188 <<
dname.className <<
"::" <<
dname.funcName <<
"\n";
1195 if (vfnVectors.size() == 0)
1209 arrow =
"--inheritance-->";
1213 arrow =
"--first-field-->";
1217 arrow =
"---instance---->";
1221 arrow =
"---standard---->";
1225 arrow =
"----unknown---->";
1247 if (
tdef !=
nullptr)
1255 if (typedefs.size() == 0)
static std::string indent(size_t n)
s32_t getFunIdxInVtable() const
const std::string & getFunNameOfVirtualCall() const
const DIType * getCSStaticType(CallBase *cs) const
Retrieves the metadata associated with a virtual callsite.
const DIType * getCanonicalType(const DIType *t)
const NodeBS & cha(const DIType *type, bool firstField)
Returns a set of all children of type (CHA). Also gradually builds chaMap.
void buildVTables(const SVFModule &module)
Finds all defined virtual functions and attaches them to nodes.
static const DIType * stripQualifiers(const DIType *)
Returns the DIType beneath the qualifiers. Does not strip away "DW_TAG_members".
void handleDIDerivedType(const DIDerivedType *derivedType)
Construction helper to process DIDerivedTypes.
DCHEdge * addEdge(const DIType *t1, const DIType *t2, DCHEdge::GEdgeKind et)
Creates an edge between from t1 to t2.
bool isFirstField(const DIType *f, const DIType *b)
static std::string diTypeToStr(const DIType *)
Returns a human-readable version of the DIType.
void handleDICompositeType(const DICompositeType *compositeType)
Construction helper to process DICompositeTypes.
Map< const CallICFGNode *, VFunSet > csCHAMap
Maps callsites to a set of potential virtual functions based on CHA.
bool hasNode(const DIType *type)
Checks if a node exists for type.
Map< const DIType *, NodeBS > chaFFMap
Maps types to all children but also considering first field.
DCHNode * getNode(const DIType *type)
Returns the node for type (nullptr if it doesn't exist).
Map< const DIType *, const DIType * > canonicalTypeMap
Maps types to their canonical type (many-to-one).
void handleDISubroutineType(const DISubroutineType *subroutineType)
Construction helper to process DISubroutineTypes.
virtual void getVFnsFromVtbls(const CallICFGNode *cs, const VTableSet &vtbls, VFunSet &virtualFunctions) override
static const DIType * stripArray(const DIType *)
Returns the DIType beneath all qualifiers and arrays.
void handleTypedef(const DIType *typedefType)
Attaches the typedef(s) to the base node.
virtual void buildCHG(bool extend)
DCHEdge * hasEdge(const DIType *t1, const DIType *t2, DCHEdge::GEdgeKind et)
Returns the edge between t1 and t2 if it exists, returns nullptr otherwise.
NodeID numTypes
Number of types (nodes) in the graph.
void handleDIBasicType(const DIBasicType *basicType)
Construction helper to process DIBasicTypes.
virtual const VTableSet & getCSVtblsBasedonCHA(const CallICFGNode *cs) override
void gatherAggs(const DICompositeType *type)
Populates containingAggs for type and all its elements.
static bool isAgg(const DIType *t)
DCHNode * getOrCreateNode(const DIType *type)
Creates a node from type, or returns it if it exists.
Map< const DIType *, VTableSet > vtblCHAMap
Maps types to a set with their vtable and all their children's.
bool extended
Whether this CHG is an extended CHG (first-field). Set by buildCHG.
const std::vector< const DIType * > & getFieldTypes(const DIType *base)
Returns a vector of the types of all fields in base.
Map< const DIType *, Set< const DIType * > > containingAggs
Maps aggregate types to all the aggregate types it transitively contains.
virtual bool isBase(const DIType *a, const DIType *b, bool firstField)
void flatten(const DICompositeType *type)
Populates fieldTypes for type and all its elements.
virtual const VFunSet & getCSVFsBasedonCHA(const CallICFGNode *cs) override
static bool teq(const DIType *t1, const DIType *t2)
Map< const DIType *, std::vector< const DIType * > > fieldTypes
Maps types to their flattened fields' types.
Map< const DIType *, NodeBS > chaMap
Maps types to all children (i.e. CHA).
Map< const DIType *, DCHNode * > diTypeToNodeMap
Maps DITypes to their nodes.
virtual bool isFieldOf(const DIType *f, const DIType *b)
Returns true if f is a field of b (fields from getFieldTypes).
Map< const SVFGlobalValue *, const DIType * > vtblToTypeMap
Maps VTables to the DIType associated with them.
Set< const DIType * > canonicalTypes
Set of all possible canonical types (i.e. values of canonicalTypeMap).
const std::vector< std::vector< const Function * > > & getVfnVectors(void) const
Returns the vector of virtual function vectors.
std::vector< const Function * > & getVfnVector(unsigned n)
Return the nth virtual function vector in the vtable.
const DIType * getDIType(void) const
void setVTable(const SVFGlobalValue *vtbl)
const Set< const DIDerivedType * > & getTypedefs(void) const
void addGNode(NodeID id, NodeType *node)
Add a Node.
iterator begin()
Iterators.
IDToNodeMapTy::const_iterator const_iterator
IDToNodeMapTy::iterator iterator
Node Iterators.
NodeType * getGNode(NodeID id) const
Get a node.
const GEdgeSetTy & getOutEdges() const
const GEdgeSetTy & getInEdges() const
bool addIncomingEdge(EdgeType *inEdge)
Add incoming and outgoing edges.
bool addOutgoingEdge(EdgeType *outEdge)
static LLVMModuleSet * getLLVMModuleSet()
const std::vector< std::reference_wrapper< Module > > & getLLVMModules() const
SVFGlobalValue * getSVFGlobalValue(const GlobalValue *g) const
static const Option< bool > PrintDCHG
NodeID getId() const
Get ID.
std::pair< s64_t, u64_t > getIntegerValue(const ConstantInt *intValue)
const SVFFunction * getFunction(const std::string &name)
Get the corresponding Function based on its name.
std::ostream & outs()
Overwrite llvm::outs()
const std::string derefMDName
const std::string vtMDName
struct DemangledName demangle(const std::string &name)
const ConstantStruct * getVtblStruct(const GlobalValue *vtbl)
llvm::DISubroutineType DISubroutineType
llvm::GlobalVariable GlobalVariable
llvm::DINodeArray DINodeArray
llvm::ConstantStruct ConstantStruct
Set< const SVFGlobalValue * > VTableSet
llvm::ConstantArray ConstantArray
llvm::DebugInfoFinder DebugInfoFinder
llvm::DIDerivedType DIDerivedType
llvm::DISubprogram DISubprogram
llvm::ConstantExpr ConstantExpr
llvm::IRBuilder IRBuilder
llvm::DISubrange DISubrange
llvm::DITypeRefArray DITypeRefArray
iter_range< typename GenericGraphTraits< GraphType >::nodes_iterator > nodes(const GraphType &G)
iter_range< typename GenericGraphTraits< GraphType >::ChildIteratorType > children(const typename GenericGraphTraits< GraphType >::NodeRef &G)
Set< const SVFFunction * > VFunSet
llvm::DIBasicType DIBasicType
llvm::DICompositeType DICompositeType
llvm::ConstantInt ConstantInt