#ifndef TYPE_INFO_H #define TYPE_INFO_H #include #include #include #include using namespace llvm; #define TypeInfoErr(M) errs() << "TypeInfo: " << M << "\n" #define FUNCTIONS_USE_HASH_TYPE_STRINGS 1 #define ROOT_TYPES_HAVE_TYPE_STRINGS 0 #define DEBUG_CAST_LOOKUPS 0 #define TYPEINFO_PERSISTENT 0x01 namespace llvm { class TypeInfo { public: TypeInfo(const SmartType *aSmartType, int persistent=0); TypeInfo(TYPECONST FunctionType *FT, int persistent=0); TypeInfo(TYPECONST PointerType *PT, int persistent=0); TypeInfo(TYPECONST ArrayType *AT, int persistent=0); TypeInfo(TYPECONST IntegerType *IT, int persistent=0); TypeInfo(TYPECONST StructType *OpaqueST, int persistent=0); void init(int persistent); const SmartType *getSmartType() const; TYPECONST Type *getType() const; unsigned getNumContainedTypes() const; unsigned getNumChildTypes() const; TypeInfo *getContainedType(unsigned i) const; std::vector getParents() const; std::string getTypeString() const; std::string getDescription() const; std::string getVerboseDescription() const; std::string getName() const; std::vector getNames() const; std::string getNamesString() const; std::vector getMemberNames() const; std::vector getValueSet() const; std::vector getCastTypes() const; unsigned getTypeID() const; unsigned getFlags() const; unsigned getBitWidth() const; bool equals(TYPECONST TypeInfo *other) const; bool hasRawTypeRepresentation() const; std::string formatMemberName(const std::string &memberName, unsigned &numAnonMembers); void setValueSet(const std::vector &valueSet); void setContainedTypes(const std::vector &containedTypes); void addParent(GlobalValue* parent); void addParents(const std::vector &parents); bool removeParent(GlobalValue* parent); bool removeAllParents(); void setPersistent(); bool splitByParentValueSet(std::vector &splitTypeInfos, std::set &globalVariablesWithAddressTaken); static unsigned getMaxNameLength(); static unsigned getMaxTypeStringLength(); static void setIntCastTypes(std::map > &intCastTypes); static void setBitCastTypes(std::map > &bitCastTypes); private: const SmartType *aSmartType; TYPECONST Type *aType; bool forceTypeDescription; mutable std::string typeDescription; std::string name; std::vector names; std::vector memberNames; std::vector valueSet; std::vector containedTypes; std::vector parents; unsigned bitWidth; unsigned typeID; unsigned numElements; unsigned flags; static unsigned maxNameLength; static unsigned maxTypeStringLength; static std::map > intCastTypes; static std::map > bitCastTypes; static std::map > typeMap; TypeInfo() {} }; inline TypeInfo::TypeInfo(const SmartType *aSmartType, int persistent) { unsigned i; assert(aSmartType); this->aSmartType = aSmartType; this->aType = aSmartType->getType(); bool rawTypeRepresentation = aSmartType->hasRawTypeRepresentation(); forceTypeDescription = aSmartType->isFunctionTy(); name = aSmartType->getEDIType()->getName(); std::vector nameRefs = aSmartType->getEDIType()->getNames(); for(i=0;i maxNameLength) { maxNameLength = nameRefs[i].size(); } names.push_back(nameRefs[i]); } if(aSmartType->isStructTy()) { if(!rawTypeRepresentation) { const EDIType* aEDIType = aSmartType->getEDIType(); unsigned numContainedTypes = aSmartType->getNumContainedTypes(); unsigned numAnonMembers = 0; if(aEDIType->isUnionTy()) { assert(numContainedTypes == 1); i=aSmartType->getUnionMemberIdx(); const DIDerivedType subDIType = aSmartType->getMember(i); memberNames.push_back(formatMemberName(subDIType.getName(), numAnonMembers)); } else { assert(aEDIType->isStructTy()); i=0; for(;igetMember(i); memberNames.push_back(formatMemberName(subDIType.getName(), numAnonMembers)); } } } else { memberNames.push_back("raw"); } } if(aSmartType->getEDIType()->isEnumTy()) { std::vector enumValues = aSmartType->getEDIType()->getEnumValues(); valueSet.push_back(enumValues.size()); //push length as the first value for(unsigned i=0;igetType()); const EDIType *aEDIType = aSmartType->getEDIType(); typeID = 0; flags = 0; if(aSmartType->isOpaqueTy()) { typeID = MAGIC_TYPE_OPAQUE; } else if(aEDIType->isVoidTy()) { typeID = MAGIC_TYPE_VOID; } else if(aSmartType->isFunctionTy()) { typeID = MAGIC_TYPE_FUNCTION; } else if(aSmartType->isStructTy()) { if(aEDIType->isUnionTy()) { typeID = MAGIC_TYPE_UNION; } else if(aEDIType->isStructTy()) { typeID = MAGIC_TYPE_STRUCT; #if MAGIC_VARSIZED_STRUCTS_SUPPORT if(!rawTypeRepresentation) { assert(this->aType->getNumContainedTypes() > 0); TYPECONST Type *lastSubType = this->aType->getContainedType(this->aType->getNumContainedTypes()-1); if(lastSubType->isArrayTy() && ((ArrayType*)lastSubType)->getNumElements() <= 1) { flags |= MAGIC_TYPE_VARSIZE; } } #endif } } else if(aSmartType->isPointerTy()) { typeID = MAGIC_TYPE_POINTER; } else if(aSmartType->isArrayTy()) { typeID = MAGIC_TYPE_ARRAY; } else if(aEDIType->isFloatingPointTy()) { typeID = MAGIC_TYPE_FLOAT; } else if(aEDIType->isIntegerTy()) { typeID = MAGIC_TYPE_INTEGER; } else if(aEDIType->isEnumTy()) { typeID = MAGIC_TYPE_ENUM; } else if(aEDIType->isVectorTy()) { typeID = MAGIC_TYPE_VECTOR; } assert(typeID); if(typeID == MAGIC_TYPE_INTEGER || typeID == MAGIC_TYPE_ENUM) { if(getNamesString().find("unsigned") != std::string::npos) { flags |= MAGIC_TYPE_UNSIGNED; } } numElements = aSmartType->getNumElements(); init(persistent); } inline TypeInfo::TypeInfo(TYPECONST FunctionType *FT, int persistent) { assert(FT); aSmartType = NULL; aType = FT; forceTypeDescription = true; bitWidth = 0; typeID = MAGIC_TYPE_FUNCTION; numElements = 0; flags = MAGIC_TYPE_EXTERNAL; init(persistent); } inline TypeInfo::TypeInfo(TYPECONST PointerType *PT, int persistent) { assert(PT); aSmartType = NULL; aType = PT; forceTypeDescription = false; bitWidth = 0; typeID = MAGIC_TYPE_POINTER; numElements = 0; flags = MAGIC_TYPE_EXTERNAL; init(persistent); } inline TypeInfo::TypeInfo(TYPECONST ArrayType *AT, int persistent) { assert(AT); aSmartType = NULL; aType = AT; forceTypeDescription = false; bitWidth = 0; typeID = MAGIC_TYPE_ARRAY; numElements = AT->getNumElements(); flags = MAGIC_TYPE_EXTERNAL; init(persistent); } inline TypeInfo::TypeInfo(TYPECONST IntegerType *IT, int persistent) { assert(IT); aSmartType = NULL; aType = IT; forceTypeDescription = true; bitWidth = IT->getBitWidth(); typeID = MAGIC_TYPE_INTEGER; numElements = 0; flags = MAGIC_TYPE_EXTERNAL; init(persistent); } inline TypeInfo::TypeInfo(TYPECONST StructType *OpaqueST, int persistent) { assert(OpaqueST); assert(TypeUtil::isOpaqueTy(OpaqueST)); aSmartType = NULL; aType = OpaqueST; forceTypeDescription = true; bitWidth = 0; typeID = MAGIC_TYPE_OPAQUE; numElements = 0; flags = MAGIC_TYPE_EXTERNAL; init(persistent); } inline void TypeInfo::init(int persistent) { std::map >::iterator intCastTypesIt; //set persistent if necessary if(persistent) { setPersistent(); } //initialize value set for pointers casted to int if(aType->isPointerTy()) { intCastTypesIt = intCastTypes.find(aType); if(intCastTypesIt != intCastTypes.end()) { std::set &pointerValues = intCastTypesIt->second; assert(pointerValues.size() > 0); flags |= MAGIC_TYPE_INT_CAST; if(pointerValues.size() > 1 || *(pointerValues.begin()) != 0) { valueSet.push_back(pointerValues.size()); //push length as the first value for(std::set::iterator it=pointerValues.begin() ; it != pointerValues.end(); it++) { assert(*it != 0); valueSet.push_back(*it); } } } } //adjust flags bool hasInnerPointers = aSmartType ? aSmartType->hasInnerPointers() : TypeUtil::hasInnerPointers(aType); if(!hasInnerPointers) { flags |= MAGIC_TYPE_NO_INNER_PTRS; } } inline const SmartType *TypeInfo::getSmartType() const { return aSmartType; } inline TYPECONST Type *TypeInfo::getType() const { return aType; } inline unsigned TypeInfo::getNumContainedTypes() const { return containedTypes.size(); } inline unsigned TypeInfo::getNumChildTypes() const { return typeID == MAGIC_TYPE_ARRAY ? numElements : containedTypes.size(); } inline TypeInfo *TypeInfo::getContainedType(unsigned i) const { assert(i TypeInfo::getParents() const { return parents; } inline std::string TypeInfo::getTypeString() const { std::string typeString = forceTypeDescription || aType->getNumContainedTypes() == 0 ? getDescription() : ""; if(MAGIC_SHRINK_TYPE_STR && typeString.size() > MAGIC_MAX_TYPE_STR_LEN) { typeString = typeString.substr(0, MAGIC_MAX_TYPE_STR_LEN-3) + "..."; } if(typeString.size() > maxTypeStringLength) { maxTypeStringLength = typeString.size(); } return typeString; } inline std::string TypeInfo::getDescription() const { if(typeDescription.size() == 0) { if(aType->isFunctionTy() && FUNCTIONS_USE_HASH_TYPE_STRINGS) { unsigned hash = TypeUtil::getHash(aType); raw_string_ostream ostream(typeDescription); ostream << "hash_" << hash; ostream.flush(); } else { typeDescription = TypeUtil::getDescription(aType); } } return typeDescription; } inline std::string TypeInfo::getVerboseDescription() const { return aSmartType ? aSmartType->getDescription() : getDescription(); } inline std::string TypeInfo::getName() const { return name; } inline std::vector TypeInfo::getNames() const { return names; } inline std::string TypeInfo::getNamesString() const { std::string string; raw_string_ostream ostream(string); for(unsigned i=0;i0) ostream << "|"; ostream << names[i]; } ostream.flush(); return string; } inline std::vector TypeInfo::getMemberNames() const { for(unsigned i=0;i maxNameLength) { maxNameLength = memberNames[i].size(); } } return memberNames; } inline std::vector TypeInfo::getValueSet() const { return valueSet; } inline std::vector TypeInfo::getCastTypes() const { std::vector castTypes; std::map >::iterator bitCastTypesIt; std::map >::iterator typeMapIt; if(!aType->isPointerTy()) { return castTypes; } //XXX to-do: match only original struct name during lookup by looking at the original bitcast instruction //the following lookups do not distinguish between struct x = {18} and struct y = {i8} //the number of false positives generated seems to be fairly small, anyway bitCastTypesIt = bitCastTypes.find(aType); if(bitCastTypesIt == bitCastTypes.end()) { return castTypes; } std::set bitCastSet = bitCastTypesIt->second; #if MAGIC_INDEX_TRANSITIVE_BIT_CASTS std::vector bitCasts; for(std::set::iterator it=bitCastSet.begin();it!=bitCastSet.end();it++) { bitCasts.push_back(*it); } while(!bitCasts.empty()) { TYPECONST Type* bcType = bitCasts.front(); bitCasts.erase(bitCasts.begin()); bitCastTypesIt = bitCastTypes.find(bcType); if(bitCastTypesIt != bitCastTypes.end()) { std::set set = bitCastTypesIt->second; for(std::set::iterator it=set.begin();it!=set.end();it++) { unsigned bitCastSetSize = bitCastSet.size(); TYPECONST Type *newBcType = *it; if(newBcType == aType) { continue; } bitCastSet.insert(newBcType); if(bitCastSet.size() != bitCastSetSize) { bitCasts.push_back(newBcType); } } } } #endif #if DEBUG_CAST_LOOKUPS if(aType->getContainedType(0)->isStructTy()) { TypeInfoErr("--- type is struct* " << getContainedType(0)->getName()); } else if(aType->getContainedType(0)->isPointerTy() && aType->getContainedType(0)->getContainedType(0)->isStructTy()) { TypeInfoErr("--- type is struct** " << getContainedType(0)->getContainedType(0)->getName()); } else { TypeInfoErr("--- type is " << getDescription()); } #endif for(std::set::iterator it=bitCastSet.begin();it!=bitCastSet.end();it++) { TYPECONST Type* type = *it; assert(type->isPointerTy()); typeMapIt = typeMap.find(type->getContainedType(0)); if(typeMapIt == typeMap.end()) { #if DEBUG_CAST_LOOKUPS TypeInfoErr("*** cast target type not found: " << TypeUtil::getDescription(type->getContainedType(0))); #endif continue; } std::set *typeInfoSet = &(typeMapIt->second); for(std::set::iterator it2=typeInfoSet->begin();it2!=typeInfoSet->end();it2++) { TypeInfo* typeInfo = *it2; assert(typeInfo->getType() != getType()->getContainedType(0)); #if DEBUG_CAST_LOOKUPS if(typeInfo->getType()->isStructTy()) { TypeInfoErr(">>> cast target type info is struct " << typeInfo->getName()); } else if(typeInfo->getType()->isPointerTy() && typeInfo->getType()->getContainedType(0)->isStructTy()) { TypeInfoErr(">>> cast target type info is struct* " << typeInfo->getContainedType(0)->getName()); } else { TypeInfoErr(">>> cast target type info is " << typeInfo->getDescription()); } #endif castTypes.push_back(typeInfo); #if MAGIC_COMPACT_COMP_TYPES /* This is safe as long as we check for compatible (LLVM) types at runtime. */ break; #endif } } if(castTypes.size() > 0) { //push delimiter castTypes.push_back(NULL); } return castTypes; } inline unsigned TypeInfo::getTypeID() const { return typeID; } inline unsigned TypeInfo::getFlags() const { return flags; } inline unsigned TypeInfo::getBitWidth() const { return bitWidth; } inline bool TypeInfo::equals(TYPECONST TypeInfo *other) const { if(aSmartType && other->getSmartType()) { return aSmartType->equals(other->getSmartType()); } return (flags & (~MAGIC_TYPE_IS_ROOT)) == (other->getFlags() & (~MAGIC_TYPE_IS_ROOT)) && !getDescription().compare(other->getDescription()); } inline bool TypeInfo::hasRawTypeRepresentation() const { return aSmartType && aSmartType->hasRawTypeRepresentation(); } inline std::string TypeInfo::formatMemberName(const std::string &memberName, unsigned &numAnonMembers) { if (memberName.compare("")) { return memberName; } std::string name(memberName); raw_string_ostream ostream(name); ostream << MAGIC_ANON_MEMBER_PREFIX << "." << (numAnonMembers+1); ostream.flush(); numAnonMembers++; return name; } inline void TypeInfo::setValueSet(const std::vector &valueSet) { this->valueSet = valueSet; } inline void TypeInfo::setContainedTypes(const std::vector &containedTypes) { this->containedTypes = containedTypes; } inline void TypeInfo::addParent(GlobalValue* parent) { assert((typeID == MAGIC_TYPE_FUNCTION && dyn_cast(parent)) || (typeID != MAGIC_TYPE_FUNCTION && dyn_cast(parent))); this->parents.push_back(parent); flags |= MAGIC_TYPE_IS_ROOT; #if ROOT_TYPES_HAVE_TYPE_STRINGS forceTypeDescription = true; #endif } inline void TypeInfo::addParents(const std::vector &parents) { for(unsigned i=0;i originalParents = this->parents; this->parents.clear(); for(unsigned i=0;iparents.push_back(originalParents[i]); } } int sizeDiff = originalParents.size() - this->parents.size(); assert(sizeDiff == 0 || sizeDiff == 1); return (sizeDiff == 1); } inline bool TypeInfo::removeAllParents() { if(this->parents.size() > 0) { this->parents.clear(); return true; } return false; } inline void TypeInfo::setPersistent() { std::map >::iterator typeMapIt; typeMapIt = typeMap.find(aType); if(typeMapIt == typeMap.end()) { std::set set; set.insert(this); typeMap.insert(std::pair >(aType, set)); } else { std::set *set; set = &(typeMapIt->second); set->insert(this); } } inline bool TypeInfo::splitByParentValueSet(std::vector &splitTypeInfos, std::set &globalVariablesWithAddressTaken) { std::map, std::vector > valueSetMap; std::map, std::vector >::iterator valueSetMapIt; std::vector valueSet; splitTypeInfos.push_back(this); if(!isa(aType)) { return false; } assert(valueSet.size() == 0); for(unsigned i=0;i(parents[i])) { bool hasAddressTaken = globalVariablesWithAddressTaken.find(GV) != globalVariablesWithAddressTaken.end(); if(hasAddressTaken) { continue; } valueSet.clear(); bool valueSetFound = MagicUtil::lookupValueSet(GV, valueSet); if(!valueSetFound) { continue; } valueSetMapIt = valueSetMap.find(valueSet); if(valueSetMapIt == valueSetMap.end()) { std::vector vector; valueSetMap.insert(std::pair, std::vector >(valueSet, vector)); valueSetMapIt = valueSetMap.find(valueSet); assert(valueSetMapIt != valueSetMap.end()); } std::vector *globalsVector = &valueSetMapIt->second; globalsVector->push_back(GV); } } if(valueSetMap.size() == 0) { return false; } for(valueSetMapIt = valueSetMap.begin(); valueSetMapIt!=valueSetMap.end(); valueSetMapIt++) { const std::vector &values = valueSetMapIt->first; const std::vector &globalVariables = valueSetMapIt->second; TypeInfo *aTypeInfo = new TypeInfo(*this); aTypeInfo->setValueSet(values); aTypeInfo->removeAllParents(); for(unsigned i=0;iremoveParent(GV); assert(parentRemoved); aTypeInfo->addParent(GV); } splitTypeInfos.push_back(aTypeInfo); } return true; } inline unsigned TypeInfo::getMaxNameLength() { return TypeInfo::maxNameLength; } inline unsigned TypeInfo::getMaxTypeStringLength() { return TypeInfo::maxTypeStringLength; } inline void TypeInfo::setIntCastTypes(std::map > &intCastTypes) { TypeInfo::intCastTypes = intCastTypes; } inline void TypeInfo::setBitCastTypes(std::map > &bitCastTypes) { TypeInfo::bitCastTypes = bitCastTypes; } } #endif