diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile index 7a5600e321..d40c8c5c87 100644 --- a/src/apps/debugger/Jamfile +++ b/src/apps/debugger/Jamfile @@ -32,6 +32,8 @@ SourceHdrs DwarfImageDebugInfo.cpp DwarfStackFrameDebugInfo.cpp DwarfTeamDebugInfo.cpp + DwarfTypeFactory.cpp + DwarfTypes.cpp : [ FDirName $(SUBDIR) dwarf ] ; @@ -62,6 +64,8 @@ Application Debugger : DwarfImageDebugInfo.cpp DwarfStackFrameDebugInfo.cpp DwarfTeamDebugInfo.cpp + DwarfTypeFactory.cpp + DwarfTypes.cpp Function.cpp FunctionDebugInfo.cpp FunctionInstance.cpp diff --git a/src/apps/debugger/Jobs.cpp b/src/apps/debugger/Jobs.cpp index 336dfee235..a20ce0aabb 100644 --- a/src/apps/debugger/Jobs.cpp +++ b/src/apps/debugger/Jobs.cpp @@ -634,8 +634,7 @@ GetStackFrameValueJob::_GetValue() ValuePieceLocation piece = location->PieceAt(0); if (piece.type == VALUE_PIECE_LOCATION_MEMORY) { ValueLocation* dataLocation; - error = fStackFrame->DebugInfo()->ResolveObjectDataLocation( - fStackFrame, type, *location, dataLocation); + error = type->ResolveObjectDataLocation(*location, dataLocation); if (error != B_OK) return error; @@ -866,9 +865,8 @@ GetStackFrameValueJob::_ResolveTypeAndLocation(Type*& _type, // The parent's location refers to the location of the complete // object. We want to extract the location of a member. ValueLocation* location; - error = fStackFrame->DebugInfo()->ResolveBaseTypeLocation( - fStackFrame, parentType, baseType, *parentLocation, - location); + error = compoundType->ResolveBaseTypeLocation(baseType, + *parentLocation, location); if (error != B_OK) { TRACE_LOCALS("GetStackFrameValueJob::" "_ResolveTypeAndLocation(): TYPE_COMPOUND: " @@ -895,9 +893,8 @@ GetStackFrameValueJob::_ResolveTypeAndLocation(Type*& _type, // The parent's location refers to the location of the complete // object. We want to extract the location of a member. ValueLocation* location; - error = fStackFrame->DebugInfo()->ResolveDataMemberLocation( - fStackFrame, parentType, dataMember, *parentLocation, - location); + error = compoundType->ResolveDataMemberLocation(dataMember, + *parentLocation, location); if (error != B_OK) { TRACE_LOCALS("GetStackFrameValueJob::" "_ResolveTypeAndLocation(): TYPE_COMPOUND: " @@ -931,8 +928,8 @@ GetStackFrameValueJob::_ResolveTypeAndLocation(Type*& _type, // resolve the location Type* type = dynamic_cast(parentType)->BaseType(); ValueLocation* location; - error = fStackFrame->DebugInfo()->ResolveObjectDataLocation( - fStackFrame, type, parentValue.ToUInt64(), location); + error = type->ResolveObjectDataLocation(parentValue.ToUInt64(), + location); if (error != B_OK) { TRACE_LOCALS("GetStackFrameValueJob::" "_ResolveTypeAndLocation(): " @@ -967,12 +964,12 @@ GetStackFrameValueJob::_ResolveTypeAndLocation(Type*& _type, // resolve the element location ValueLocation* location; - error = fStackFrame->DebugInfo()->ResolveArrayElementLocation( - fStackFrame, arrayType, indexPath, *parentLocation, location); + error = arrayType->ResolveElementLocation(indexPath, + *parentLocation, location); if (error != B_OK) { TRACE_LOCALS("GetStackFrameValueJob::" "_ResolveTypeAndLocation(): TYPE_ARRAY: " - "ResolveArrayElementLocation() failed: %s\n", + "ResolveElementLocation() failed: %s\n", strerror(error)); return error; } diff --git a/src/apps/debugger/arch/x86/ArchitectureX86.cpp b/src/apps/debugger/arch/x86/ArchitectureX86.cpp index b545e2cbee..3b8c2ccb0b 100644 --- a/src/apps/debugger/arch/x86/ArchitectureX86.cpp +++ b/src/apps/debugger/arch/x86/ArchitectureX86.cpp @@ -322,7 +322,7 @@ ArchitectureX86::CreateStackFrame(Image* image, FunctionDebugInfo* function, // create the stack frame StackFrameDebugInfo* stackFrameDebugInfo - = new(std::nothrow) NoOpStackFrameDebugInfo(this); + = new(std::nothrow) NoOpStackFrameDebugInfo; if (stackFrameDebugInfo == NULL) return B_NO_MEMORY; Reference stackFrameDebugInfoReference( diff --git a/src/apps/debugger/debug_info/DebuggerImageDebugInfo.cpp b/src/apps/debugger/debug_info/DebuggerImageDebugInfo.cpp index 8731bf516d..d127cfb4f0 100644 --- a/src/apps/debugger/debug_info/DebuggerImageDebugInfo.cpp +++ b/src/apps/debugger/debug_info/DebuggerImageDebugInfo.cpp @@ -79,7 +79,7 @@ DebuggerImageDebugInfo::GetFunctions(BObjectList& functions) status_t -DebuggerImageDebugInfo::GetType(GlobalTypeLookupContext* context, +DebuggerImageDebugInfo::GetType(GlobalTypeCache* cache, const BString& name, Type*& _type) { return B_UNSUPPORTED; diff --git a/src/apps/debugger/debug_info/DebuggerImageDebugInfo.h b/src/apps/debugger/debug_info/DebuggerImageDebugInfo.h index a67057350d..b94872c4d2 100644 --- a/src/apps/debugger/debug_info/DebuggerImageDebugInfo.h +++ b/src/apps/debugger/debug_info/DebuggerImageDebugInfo.h @@ -27,7 +27,7 @@ public: virtual status_t GetFunctions( BObjectList& functions); - virtual status_t GetType(GlobalTypeLookupContext* context, + virtual status_t GetType(GlobalTypeCache* cache, const BString& name, Type*& _type); virtual status_t CreateFrame(Image* image, FunctionInstance* functionInstance, diff --git a/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp b/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp index 6ef0929d3b..0f68e345a4 100644 --- a/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp +++ b/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp @@ -27,6 +27,8 @@ #include "DwarfFunctionDebugInfo.h" #include "DwarfStackFrameDebugInfo.h" #include "DwarfTargetInterface.h" +#include "DwarfTypeFactory.h" +#include "DwarfTypes.h" #include "DwarfUtils.h" #include "ElfFile.h" #include "FileManager.h" @@ -201,7 +203,8 @@ struct DwarfImageDebugInfo::EntryListWrapper { DwarfImageDebugInfo::DwarfImageDebugInfo(const ImageInfo& imageInfo, Architecture* architecture, TeamMemory* teamMemory, - FileManager* fileManager, GlobalTypeLookup* typeLookup, DwarfFile* file) + FileManager* fileManager, GlobalTypeLookup* typeLookup, + GlobalTypeCache* typeCache, DwarfFile* file) : fLock("dwarf image debug info"), fImageInfo(imageInfo), @@ -209,15 +212,20 @@ DwarfImageDebugInfo::DwarfImageDebugInfo(const ImageInfo& imageInfo, fTeamMemory(teamMemory), fFileManager(fileManager), fTypeLookup(typeLookup), + fTypeCache(typeCache), fFile(file), fTextSegment(NULL), fRelocationDelta(0) { + fFile->AcquireReference(); + fTypeCache->AcquireReference(); } DwarfImageDebugInfo::~DwarfImageDebugInfo() { + fFile->ReleaseReference(); + fTypeCache->ReleaseReference(); } @@ -354,7 +362,7 @@ DwarfImageDebugInfo::GetFunctions(BObjectList& functions) status_t -DwarfImageDebugInfo::GetType(GlobalTypeLookupContext* context, +DwarfImageDebugInfo::GetType(GlobalTypeCache* cache, const BString& name, Type*& _type) { int32 registerCount = fArchitecture->CountRegisters(); @@ -374,8 +382,8 @@ DwarfImageDebugInfo::GetType(GlobalTypeLookupContext* context, // iterate through all compilation units for (int32 i = 0; CompilationUnit* unit = fFile->CompilationUnitAt(i); i++) { - DwarfStackFrameDebugInfo* stackFrameDebugInfo = NULL; - Reference stackFrameDebugInfoReference; + DwarfTypeContext* typeContext = NULL; + Reference typeContextReference; // iterate through all types of the compilation unit for (DebugInfoEntryList::ConstIterator it @@ -390,23 +398,20 @@ DwarfImageDebugInfo::GetType(GlobalTypeLookupContext* context, continue; // The name matches and the entry is not just a declaration -- - // create the type. First create the StackFrameDebugInfo lazily. - if (stackFrameDebugInfo == NULL) { - stackFrameDebugInfo = new(std::nothrow) - DwarfStackFrameDebugInfo(fArchitecture, fFile, unit, NULL, - fTypeLookup, context, 0, 0, &inputInterface, fromDwarfMap); - if (stackFrameDebugInfo == NULL) + // create the type. First create the type context lazily. + if (typeContext == NULL) { + typeContext = new(std::nothrow) + DwarfTypeContext(fArchitecture, fImageInfo.ImageID(), fFile, + unit, NULL, 0, 0, &inputInterface, fromDwarfMap); + if (typeContext == NULL) return B_NO_MEMORY; - stackFrameDebugInfoReference.SetTo(stackFrameDebugInfo, true); - - error = stackFrameDebugInfo->Init(); - if (error != B_OK) - return error; + typeContextReference.SetTo(typeContext, true); } // create the type - Type* type; - error = stackFrameDebugInfo->CreateType(typeEntry, type); + DwarfType* type; + DwarfTypeFactory typeFactory(typeContext, fTypeLookup, cache); + error = typeFactory.CreateType(typeEntry, type); if (error != B_OK) continue; @@ -492,24 +497,13 @@ DwarfImageDebugInfo::CreateFrame(Image* image, } ) - // create a type lookup context - GlobalTypeLookupContext* typeLookupContext - = new(std::nothrow) GlobalTypeLookupContext; - if (typeLookupContext == NULL) - return B_NO_MEMORY; - Reference typeLookupContextReference( - typeLookupContext, true); - - error = typeLookupContext->Init(); - if (error != B_OK) - return error; - // create the stack frame debug info DIESubprogram* subprogramEntry = function->SubprogramEntry(); DwarfStackFrameDebugInfo* stackFrameDebugInfo - = new(std::nothrow) DwarfStackFrameDebugInfo(fArchitecture, fFile, unit, - subprogramEntry, fTypeLookup, typeLookupContext, instructionPointer, - framePointer, inputInterface, fromDwarfMap); + = new(std::nothrow) DwarfStackFrameDebugInfo(fArchitecture, + fImageInfo.ImageID(), fFile, unit, subprogramEntry, fTypeLookup, + fTypeCache, instructionPointer, framePointer, inputInterface, + fromDwarfMap); if (stackFrameDebugInfo == NULL) return B_NO_MEMORY; Reference stackFrameDebugInfoReference( diff --git a/src/apps/debugger/debug_info/DwarfImageDebugInfo.h b/src/apps/debugger/debug_info/DwarfImageDebugInfo.h index e486152f08..158359f0b3 100644 --- a/src/apps/debugger/debug_info/DwarfImageDebugInfo.h +++ b/src/apps/debugger/debug_info/DwarfImageDebugInfo.h @@ -23,6 +23,7 @@ class ElfSegment; class FileManager; class FileSourceCode; class FunctionID; +class GlobalTypeCache; class GlobalTypeLookup; class LocatableFile; class SourceCode; @@ -36,6 +37,7 @@ public: TeamMemory* teamMemory, FileManager* fileManager, GlobalTypeLookup* typeLookup, + GlobalTypeCache* typeCache, DwarfFile* file); virtual ~DwarfImageDebugInfo(); @@ -46,7 +48,7 @@ public: virtual status_t GetFunctions( BObjectList& functions); - virtual status_t GetType(GlobalTypeLookupContext* context, + virtual status_t GetType(GlobalTypeCache* cache, const BString& name, Type*& _type); virtual status_t CreateFrame(Image* image, FunctionInstance* functionInstance, @@ -97,6 +99,7 @@ private: TeamMemory* fTeamMemory; FileManager* fFileManager; GlobalTypeLookup* fTypeLookup; + GlobalTypeCache* fTypeCache; DwarfFile* fFile; ElfSegment* fTextSegment; target_addr_t fRelocationDelta; diff --git a/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.cpp b/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.cpp index e06f574d12..0f9f39ca40 100644 --- a/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.cpp +++ b/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.cpp @@ -6,186 +6,29 @@ #include "DwarfStackFrameDebugInfo.h" -#include #include -#include -#include - -#include "ArrayIndexPath.h" #include "Architecture.h" #include "CompilationUnit.h" #include "DebugInfoEntries.h" #include "Dwarf.h" #include "DwarfFile.h" +#include "DwarfTargetInterface.h" +#include "DwarfTypeFactory.h" #include "DwarfUtils.h" +#include "DwarfTypes.h" #include "FunctionID.h" #include "FunctionParameterID.h" #include "GlobalTypeLookup.h" #include "LocalVariableID.h" #include "Register.h" #include "RegisterMap.h" -#include "SourceLanguageInfo.h" #include "StringUtils.h" #include "Tracing.h" #include "ValueLocation.h" #include "Variable.h" -namespace { - - -// #pragma mark - HasTypePredicate - - -template -struct HasTypePredicate { - inline bool operator()(EntryType* entry) const - { - return entry->GetType() != NULL; - } -}; - - -// #pragma mark - HasReturnTypePredicate - - -template -struct HasReturnTypePredicate { - inline bool operator()(EntryType* entry) const - { - return entry->ReturnType() != NULL; - } -}; - - -// #pragma mark - HasEnumeratorsPredicate - - -struct HasEnumeratorsPredicate { - inline bool operator()(DIEEnumerationType* entry) const - { - return !entry->Enumerators().IsEmpty(); - } -}; - - -// #pragma mark - HasDimensionsPredicate - - -struct HasDimensionsPredicate { - inline bool operator()(DIEArrayType* entry) const - { - return !entry->Dimensions().IsEmpty(); - } -}; - - -// #pragma mark - HasMembersPredicate - - -struct HasMembersPredicate { - inline bool operator()(DIECompoundType* entry) const - { - return !entry->DataMembers().IsEmpty(); - } -}; - - -// #pragma mark - HasBaseTypesPredicate - - -struct HasBaseTypesPredicate { - inline bool operator()(DIEClassBaseType* entry) const - { - return !entry->BaseTypes().IsEmpty(); - } -}; - - -// #pragma mark - HasParametersPredicate - - -template -struct HasParametersPredicate { - inline bool operator()(EntryType* entry) const - { - return !entry->Parameters().IsEmpty(); - } -}; - - -// #pragma mark - HasLowerBoundPredicate - - -struct HasLowerBoundPredicate { - inline bool operator()(DIESubrangeType* entry) const - { - return entry->LowerBound()->IsValid(); - } -}; - - -// #pragma mark - HasUpperBoundPredicate - - -struct HasUpperBoundPredicate { - inline bool operator()(DIESubrangeType* entry) const - { - return entry->UpperBound()->IsValid(); - } -}; - - -// #pragma mark - HasCountPredicate - - -struct HasCountPredicate { - inline bool operator()(DIESubrangeType* entry) const - { - return entry->Count()->IsValid(); - } -}; - - -// #pragma mark - HasBitStridePredicate - - -template -struct HasBitStridePredicate { - inline bool operator()(EntryType* entry) const - { - return entry->BitStride()->IsValid(); - } -}; - - -// #pragma mark - HasByteStridePredicate - - -template -struct HasByteStridePredicate { - inline bool operator()(EntryType* entry) const - { - return entry->ByteStride()->IsValid(); - } -}; - - -// #pragma mark - HasContainingTypePredicate - - -struct HasContainingTypePredicate { - inline bool operator()(DIEPointerToMemberType* entry) const - { - return entry->ContainingType() != NULL; - } -}; - - -} // unnamed namespace - - // #pragma mark - DwarfFunctionParameterID @@ -274,1200 +117,59 @@ private: }; -// #pragma mark - DwarfType - - -struct DwarfStackFrameDebugInfo::DwarfType : virtual Type { -public: - DwarfType(const BString& name) - : - fName(name), - fByteSize(0) - { - } - - virtual const char* Name() const - { - return fName.Length() > 0 ? fName.String() : NULL; - } - - virtual target_size_t ByteSize() const - { - return fByteSize; - } - - void SetByteSize(target_size_t size) - { - fByteSize = size; - } - - virtual DIEType* GetDIEType() const = 0; - -private: - BString fName; - target_size_t fByteSize; -}; - - -// #pragma mark - DwarfInheritance - - -struct DwarfStackFrameDebugInfo::DwarfInheritance : BaseType { -public: - DwarfInheritance(DIEInheritance* entry, DwarfType* type) - : - fEntry(entry), - fType(type) - { - fType->AcquireReference(); - } - - ~DwarfInheritance() - { - fType->ReleaseReference(); - } - - virtual Type* GetType() const - { - return fType; - } - - DIEInheritance* Entry() const - { - return fEntry; - } - -private: - DIEInheritance* fEntry; - DwarfType* fType; - -}; - - -// #pragma mark - DwarfDataMember - - -struct DwarfStackFrameDebugInfo::DwarfDataMember : DataMember { -public: - DwarfDataMember(DIEMember* entry, const BString& name, DwarfType* type) - : - fEntry(entry), - fName(name), - fType(type) - { - fType->AcquireReference(); - } - - ~DwarfDataMember() - { - fType->ReleaseReference(); - } - - virtual const char* Name() const - { - return fName.Length() > 0 ? fName.String() : NULL; - } - - virtual Type* GetType() const - { - return fType; - } - - DIEMember* Entry() const - { - return fEntry; - } - -private: - DIEMember* fEntry; - BString fName; - DwarfType* fType; - -}; - - -// #pragma mark - DwarfEnumerationValue - - -struct DwarfStackFrameDebugInfo::DwarfEnumerationValue : EnumerationValue { -public: - DwarfEnumerationValue(DIEEnumerator* entry, const BString& name, - const BVariant& value) - : - fEntry(entry), - fName(name), - fValue(value) - { - } - - ~DwarfEnumerationValue() - { - } - - virtual const char* Name() const - { - return fName.Length() > 0 ? fName.String() : NULL; - } - - DIEEnumerator* Entry() const - { - return fEntry; - } - - virtual BVariant Value() const - { - return fValue; - } - -private: - DIEEnumerator* fEntry; - BString fName; - BVariant fValue; - -}; - - -// #pragma mark - DwarfArrayDimension - - -struct DwarfStackFrameDebugInfo::DwarfArrayDimension : ArrayDimension { -public: - DwarfArrayDimension(DwarfType* type) - : - fType(type) - { - fType->AcquireReference(); - } - - ~DwarfArrayDimension() - { - fType->ReleaseReference(); - } - - virtual Type* GetType() const - { - return fType; - } - - DwarfType* GetDwarfType() const - { - return fType; - } - -private: - DwarfType* fType; - -}; - - -// #pragma mark - DwarfFunctionParameter - - -struct DwarfStackFrameDebugInfo::DwarfFunctionParameter : FunctionParameter { -public: - DwarfFunctionParameter(DIEFormalParameter* entry, const BString& name, - DwarfType* type) - : - fEntry(entry), - fName(name), - fType(type) - { - fType->AcquireReference(); - } - - ~DwarfFunctionParameter() - { - fType->ReleaseReference(); - } - - virtual const char* Name() const - { - return fName.Length() > 0 ? fName.String() : NULL; - } - - virtual Type* GetType() const - { - return fType; - } - - DIEFormalParameter* Entry() const - { - return fEntry; - } - -private: - DIEFormalParameter* fEntry; - BString fName; - DwarfType* fType; - -}; - - -// #pragma mark - DwarfPrimitiveType - - -struct DwarfStackFrameDebugInfo::DwarfPrimitiveType : PrimitiveType, DwarfType { -public: - DwarfPrimitiveType(const BString& name, DIEBaseType* entry, - uint32 typeConstant) - : - DwarfType(name), - fEntry(entry), - fTypeConstant(typeConstant) - { - } - - virtual DIEType* GetDIEType() const - { - return fEntry; - } - - DIEBaseType* Entry() const - { - return fEntry; - } - - virtual uint32 TypeConstant() const - { - return fTypeConstant; - } - -private: - DIEBaseType* fEntry; - uint32 fTypeConstant; -}; - - -// #pragma mark - DwarfCompoundType - - -struct DwarfStackFrameDebugInfo::DwarfCompoundType : CompoundType, DwarfType { -public: - DwarfCompoundType(const BString& name, DIECompoundType* entry) - : - DwarfType(name), - fEntry(entry) - { - } - - ~DwarfCompoundType() - { - for (int32 i = 0; - DwarfInheritance* inheritance = fInheritances.ItemAt(i); i++) { - inheritance->ReleaseReference(); - } - for (int32 i = 0; DwarfDataMember* member = fDataMembers.ItemAt(i); i++) - member->ReleaseReference(); - } - - virtual int32 CountBaseTypes() const - { - return fInheritances.CountItems(); - } - - virtual BaseType* BaseTypeAt(int32 index) const - { - return fInheritances.ItemAt(index); - } - - virtual int32 CountDataMembers() const - { - return fDataMembers.CountItems(); - } - - virtual DataMember* DataMemberAt(int32 index) const - { - return fDataMembers.ItemAt(index); - } - - virtual DIEType* GetDIEType() const - { - return fEntry; - } - - DIECompoundType* Entry() const - { - return fEntry; - } - - bool AddInheritance(DwarfInheritance* inheritance) - { - if (!fInheritances.AddItem(inheritance)) - return false; - - inheritance->AcquireReference(); - return true; - } - - bool AddDataMember(DwarfDataMember* member) - { - if (!fDataMembers.AddItem(member)) - return false; - - member->AcquireReference(); - return true; - } - -private: - typedef BObjectList DataMemberList; - typedef BObjectList InheritanceList; - -private: - DIECompoundType* fEntry; - InheritanceList fInheritances; - DataMemberList fDataMembers; -}; - - -// #pragma mark - DwarfModifiedType - - -struct DwarfStackFrameDebugInfo::DwarfModifiedType : ModifiedType, DwarfType { -public: - DwarfModifiedType(const BString& name, DIEModifiedType* entry, - uint32 modifiers, DwarfType* baseType) - : - DwarfType(name), - fEntry(entry), - fModifiers(modifiers), - fBaseType(baseType) - { - fBaseType->AcquireReference(); - } - - ~DwarfModifiedType() - { - fBaseType->ReleaseReference(); - } - - virtual uint32 Modifiers() const - { - return fModifiers; - } - - virtual Type* BaseType() const - { - return fBaseType; - } - - virtual DIEType* GetDIEType() const - { - return fEntry; - } - - DIEModifiedType* Entry() const - { - return fEntry; - } - -private: - DIEModifiedType* fEntry; - uint32 fModifiers; - DwarfType* fBaseType; -}; - - -// #pragma mark - DwarfTypedefType - - -struct DwarfStackFrameDebugInfo::DwarfTypedefType : TypedefType, DwarfType { -public: - DwarfTypedefType(const BString& name, DIETypedef* entry, - DwarfType* baseType) - : - DwarfType(name), - fEntry(entry), - fBaseType(baseType) - { - fBaseType->AcquireReference(); - } - - ~DwarfTypedefType() - { - fBaseType->ReleaseReference(); - } - - virtual Type* BaseType() const - { - return fBaseType; - } - - virtual DIEType* GetDIEType() const - { - return fEntry; - } - - DIETypedef* Entry() const - { - return fEntry; - } - -private: - DIETypedef* fEntry; - DwarfType* fBaseType; -}; - - -// #pragma mark - DwarfAddressType - - -struct DwarfStackFrameDebugInfo::DwarfAddressType : AddressType, DwarfType { -public: - DwarfAddressType(const BString& name, DIEAddressingType* entry, - address_type_kind addressKind, DwarfType* baseType) - : - DwarfType(name), - fEntry(entry), - fAddressKind(addressKind), - fBaseType(baseType) - { - fBaseType->AcquireReference(); - } - - ~DwarfAddressType() - { - fBaseType->ReleaseReference(); - } - - virtual address_type_kind AddressKind() const - { - return fAddressKind; - } - - virtual Type* BaseType() const - { - return fBaseType; - } - - virtual DIEType* GetDIEType() const - { - return fEntry; - } - - DIEAddressingType* Entry() const - { - return fEntry; - } - -private: - DIEAddressingType* fEntry; - address_type_kind fAddressKind; - DwarfType* fBaseType; -}; - - -// #pragma mark - DwarfEnumerationType - - -struct DwarfStackFrameDebugInfo::DwarfEnumerationType : EnumerationType, - DwarfType { -public: - DwarfEnumerationType(const BString& name, DIEEnumerationType* entry, - DwarfType* baseType) - : - DwarfType(name), - fEntry(entry), - fBaseType(baseType) - { - if (fBaseType != NULL) - fBaseType->AcquireReference(); - } - - ~DwarfEnumerationType() - { - for (int32 i = 0; DwarfEnumerationValue* value = fValues.ItemAt(i); i++) - value->ReleaseReference(); - - if (fBaseType != NULL) - fBaseType->ReleaseReference(); - } - - virtual Type* BaseType() const - { - return fBaseType; - } - - virtual int32 CountValues() const - { - return fValues.CountItems(); - } - - virtual EnumerationValue* ValueAt(int32 index) const - { - return fValues.ItemAt(index); - } - - virtual DIEType* GetDIEType() const - { - return fEntry; - } - - DIEEnumerationType* Entry() const - { - return fEntry; - } - - bool AddValue(DwarfEnumerationValue* value) - { - if (!fValues.AddItem(value)) - return false; - - value->AcquireReference(); - return true; - } - -private: - typedef BObjectList ValueList; - -private: - DIEEnumerationType* fEntry; - DwarfType* fBaseType; - ValueList fValues; -}; - - -// #pragma mark - DwarfSubrangeType - - -struct DwarfStackFrameDebugInfo::DwarfSubrangeType : SubrangeType, DwarfType { -public: - DwarfSubrangeType(const BString& name, DIESubrangeType* entry, - DwarfType* baseType, const BVariant& lowerBound, - const BVariant& upperBound) - : - DwarfType(name), - fEntry(entry), - fBaseType(baseType), - fLowerBound(lowerBound), - fUpperBound(upperBound) - { - fBaseType->AcquireReference(); - } - - ~DwarfSubrangeType() - { - fBaseType->ReleaseReference(); - } - - virtual Type* BaseType() const - { - return fBaseType; - } - - virtual DIEType* GetDIEType() const - { - return fEntry; - } - - virtual BVariant LowerBound() const - { - return fLowerBound; - } - - virtual BVariant UpperBound() const - { - return fUpperBound; - } - - DIESubrangeType* Entry() const - { - return fEntry; - } - -private: - DIESubrangeType* fEntry; - DwarfType* fBaseType; - BVariant fLowerBound; - BVariant fUpperBound; -}; - - -// #pragma mark - DwarfArrayType - - -struct DwarfStackFrameDebugInfo::DwarfArrayType : ArrayType, DwarfType { - DwarfArrayType(const BString& name, DIEArrayType* entry, - DwarfType* baseType) - : - DwarfType(name), - fEntry(entry), - fBaseType(baseType) - { - fBaseType->AcquireReference(); - } - - ~DwarfArrayType() - { - for (int32 i = 0; - DwarfArrayDimension* dimension = fDimensions.ItemAt(i); i++) { - dimension->ReleaseReference(); - } - - fBaseType->ReleaseReference(); - } - - virtual Type* BaseType() const - { - return fBaseType; - } - - virtual int32 CountDimensions() const - { - return fDimensions.CountItems(); - } - - virtual ArrayDimension* DimensionAt(int32 index) const - { - return fDimensions.ItemAt(index); - } - - DwarfArrayDimension* DwarfDimensionAt(int32 index) const - { - return fDimensions.ItemAt(index); - } - - virtual DIEType* GetDIEType() const - { - return fEntry; - } - - DIEArrayType* Entry() const - { - return fEntry; - } - - bool AddDimension(DwarfArrayDimension* dimension) - { - if (!fDimensions.AddItem(dimension)) - return false; - - dimension->AcquireReference(); - return true; - } - -private: - typedef BObjectList DimensionList; - -private: - DIEArrayType* fEntry; - DwarfType* fBaseType; - DimensionList fDimensions; -}; - - -// #pragma mark - DwarfUnspecifiedType - - -struct DwarfStackFrameDebugInfo::DwarfUnspecifiedType : UnspecifiedType, - DwarfType { -public: - // NOTE: The entry may be NULL. - DwarfUnspecifiedType(const BString& name, DIEUnspecifiedType* entry) - : - DwarfType(name), - fEntry(entry) - { - } - - ~DwarfUnspecifiedType() - { - } - - virtual DIEType* GetDIEType() const - { - return fEntry; - } - - DIEUnspecifiedType* Entry() const - { - return fEntry; - } - -private: - DIEUnspecifiedType* fEntry; -}; - - -// #pragma mark - DwarfFunctionType - - -struct DwarfStackFrameDebugInfo::DwarfFunctionType : FunctionType, DwarfType { - DwarfFunctionType(const BString& name, DIESubroutineType* entry, - DwarfType* returnType) - : - DwarfType(name), - fEntry(entry), - fReturnType(returnType), - fHasVariableArguments(false) - { - if (fReturnType != NULL) - fReturnType->AcquireReference(); - } - - ~DwarfFunctionType() - { - for (int32 i = 0; - DwarfFunctionParameter* parameter = fParameters.ItemAt(i); i++) { - parameter->ReleaseReference(); - } - - if (fReturnType != NULL) - fReturnType->ReleaseReference(); - } - - virtual Type* ReturnType() const - { - return fReturnType; - } - - virtual int32 CountParameters() const - { - return fParameters.CountItems(); - } - - virtual FunctionParameter* ParameterAt(int32 index) const - { - return fParameters.ItemAt(index); - } - - DwarfFunctionParameter* DwarfParameterAt(int32 index) const - { - return fParameters.ItemAt(index); - } - - virtual bool HasVariableArguments() const - { - return fHasVariableArguments; - } - - void SetHasVariableArguments(bool hasVarArgs) - { - fHasVariableArguments = hasVarArgs; - } - - virtual DIEType* GetDIEType() const - { - return fEntry; - } - - DIESubroutineType* Entry() const - { - return fEntry; - } - - bool AddParameter(DwarfFunctionParameter* parameter) - { - if (!fParameters.AddItem(parameter)) - return false; - - parameter->AcquireReference(); - return true; - } - -private: - typedef BObjectList ParameterList; - -private: - DIESubroutineType* fEntry; - DwarfType* fReturnType; - ParameterList fParameters; - bool fHasVariableArguments; -}; - - -// #pragma mark - DwarfPointerToMemberType - - -struct DwarfStackFrameDebugInfo::DwarfPointerToMemberType : PointerToMemberType, - DwarfType { -public: - DwarfPointerToMemberType(const BString& name, DIEPointerToMemberType* entry, - DwarfCompoundType* containingType, DwarfType* baseType) - : - DwarfType(name), - fEntry(entry), - fContainingType(containingType), - fBaseType(baseType) - { - fContainingType->AcquireReference(); - fBaseType->AcquireReference(); - } - - ~DwarfPointerToMemberType() - { - fContainingType->ReleaseReference(); - fBaseType->ReleaseReference(); - } - - virtual CompoundType* ContainingType() const - { - return fContainingType; - } - - virtual Type* BaseType() const - { - return fBaseType; - } - - virtual DIEType* GetDIEType() const - { - return fEntry; - } - - DIEPointerToMemberType* Entry() const - { - return fEntry; - } - -private: - DIEPointerToMemberType* fEntry; - DwarfCompoundType* fContainingType; - DwarfType* fBaseType; -}; - - // #pragma mark - DwarfStackFrameDebugInfo DwarfStackFrameDebugInfo::DwarfStackFrameDebugInfo(Architecture* architecture, - DwarfFile* file, CompilationUnit* compilationUnit, + image_id imageID, DwarfFile* file, CompilationUnit* compilationUnit, DIESubprogram* subprogramEntry, GlobalTypeLookup* typeLookup, - GlobalTypeLookupContext* typeLookupContext, - target_addr_t instructionPointer, target_addr_t framePointer, - DwarfTargetInterface* targetInterface, RegisterMap* fromDwarfRegisterMap) + GlobalTypeCache* typeCache, target_addr_t instructionPointer, + target_addr_t framePointer, DwarfTargetInterface* targetInterface, + RegisterMap* fromDwarfRegisterMap) : - StackFrameDebugInfo(architecture), - fFile(file), - fCompilationUnit(compilationUnit), - fSubprogramEntry(subprogramEntry), + StackFrameDebugInfo(), + fTypeContext(new(std::nothrow) DwarfTypeContext(architecture, imageID, file, + compilationUnit, subprogramEntry, instructionPointer, framePointer, + targetInterface, fromDwarfRegisterMap)), fTypeLookup(typeLookup), - fTypeLookupContext(typeLookupContext), - fInstructionPointer(instructionPointer), - fFramePointer(framePointer), - fTargetInterface(targetInterface), - fFromDwarfRegisterMap(fromDwarfRegisterMap) + fTypeCache(typeCache) { - fTypeLookupContext->AcquireReference(); + fTypeCache->AcquireReference(); } DwarfStackFrameDebugInfo::~DwarfStackFrameDebugInfo() { - fTypeLookupContext->ReleaseReference(); + fTypeCache->ReleaseReference(); + + if (fTypeContext != NULL) + fTypeContext->ReleaseReference(); + + delete fTypeFactory; } status_t DwarfStackFrameDebugInfo::Init() { - return B_OK; -} - - -status_t -DwarfStackFrameDebugInfo::ResolveObjectDataLocation(StackFrame* stackFrame, - Type* type, const ValueLocation& objectLocation, ValueLocation*& _location) -{ - // TODO: In some source languages the object address might be a pointer to - // a descriptor, not the actual object data. - - // If the given location looks good already, just clone it. - int32 count = objectLocation.CountPieces(); - if (count == 0) - return B_BAD_VALUE; - - ValuePieceLocation piece = objectLocation.PieceAt(0); - if (count > 1 || piece.type != VALUE_PIECE_LOCATION_MEMORY - || piece.size != 0 || piece.bitSize != 0) { - ValueLocation* location - = new(std::nothrow) ValueLocation(objectLocation); - if (location == NULL || location->CountPieces() != count) { - delete location; - return B_NO_MEMORY; - } - - _location = location; - return B_OK; - } - - // The location contains just a single address piece with a zero size -- set - // the type's size. - piece.SetSize(type->ByteSize()); - // TODO: Use bit size and bit offset, if specified! - - ValueLocation* location = new(std::nothrow) ValueLocation( - objectLocation.IsBigEndian()); - if (location == NULL || !location->AddPiece(piece)) { - delete location; - return B_NO_MEMORY; - } - - _location = location; - return B_OK; -} - - -status_t -DwarfStackFrameDebugInfo::ResolveBaseTypeLocation(StackFrame* stackFrame, - Type* _type, BaseType* _baseType, const ValueLocation& parentLocation, - ValueLocation*& _location) -{ - DwarfCompoundType* type = dynamic_cast(_type); - DwarfInheritance* baseType = dynamic_cast(_baseType); - if (type == NULL || baseType == NULL) - return B_BAD_VALUE; - - return _ResolveDataMemberLocation(stackFrame, type, baseType->GetType(), - baseType->Entry()->Location(), parentLocation, _location); -} - - -status_t -DwarfStackFrameDebugInfo::ResolveDataMemberLocation(StackFrame* stackFrame, - Type* _type, DataMember* _member, const ValueLocation& parentLocation, - ValueLocation*& _location) -{ - DwarfCompoundType* type = dynamic_cast(_type); - DwarfDataMember* member = dynamic_cast(_member); - if (type == NULL || member == NULL) - return B_BAD_VALUE; - - ValueLocation* location; - status_t error = _ResolveDataMemberLocation(stackFrame, type, - member->GetType(), member->Entry()->Location(), parentLocation, - location); - if (error != B_OK) - return error; - - // If the member isn't a bit field, we're done. - DIEMember* memberEntry = member->Entry(); - if (!memberEntry->ByteSize()->IsValid() - && !memberEntry->BitOffset()->IsValid() - && !memberEntry->BitSize()->IsValid()) { - _location = location; - return B_OK; - } - - Reference locationReference(location); - - // get the byte size - target_addr_t byteSize; - if (memberEntry->ByteSize()->IsValid()) { - BVariant value; - error = fFile->EvaluateDynamicValue(fCompilationUnit, fSubprogramEntry, - memberEntry->ByteSize(), fTargetInterface, fInstructionPointer, - fFramePointer, value); - if (error != B_OK) - return error; - byteSize = value.ToUInt64(); - } else - byteSize = type->ByteSize(); - - // get the bit offset - uint64 bitOffset = 0; - if (memberEntry->BitOffset()->IsValid()) { - BVariant value; - error = fFile->EvaluateDynamicValue(fCompilationUnit, fSubprogramEntry, - memberEntry->BitOffset(), fTargetInterface, fInstructionPointer, - fFramePointer, value); - if (error != B_OK) - return error; - bitOffset = value.ToUInt64(); - } - - // get the bit size - uint64 bitSize = byteSize * 8; - if (memberEntry->BitSize()->IsValid()) { - BVariant value; - error = fFile->EvaluateDynamicValue(fCompilationUnit, fSubprogramEntry, - memberEntry->BitSize(), fTargetInterface, fInstructionPointer, - fFramePointer, value); - if (error != B_OK) - return error; - bitSize = value.ToUInt64(); - } - - TRACE_LOCALS("bit field: byte size: %llu, bit offset/size: %llu/%llu\n", - byteSize, bitOffset, bitSize); - - if (bitOffset + bitSize > byteSize * 8) - return B_BAD_VALUE; - - // create the bit field value location - ValueLocation* bitFieldLocation = new(std::nothrow) ValueLocation; - if (bitFieldLocation == NULL) - return B_NO_MEMORY; - Reference bitFieldLocationReference(bitFieldLocation, true); - - if (!bitFieldLocation->SetTo(*location, bitOffset, bitSize)) + if (fTypeContext == NULL) return B_NO_MEMORY; - _location = bitFieldLocationReference.Detach(); - return B_OK; -} - - -status_t -DwarfStackFrameDebugInfo::ResolveArrayElementLocation(StackFrame* stackFrame, - ArrayType* _type, const ArrayIndexPath& indexPath, - const ValueLocation& parentLocation, ValueLocation*& _location) -{ - DwarfArrayType* type = dynamic_cast(_type); - if (type == NULL || indexPath.CountIndices() != type->CountDimensions()) - return B_BAD_VALUE; - DIEArrayType* typeEntry = type->Entry(); - - // If the array entry has a bit stride, get it. Otherwise fall back to the - // element type size. - int64 bitStride; - if (DIEArrayType* bitStrideOwnerEntry = DwarfUtils::GetDIEByPredicate( - typeEntry, HasBitStridePredicate())) { - BVariant value; - status_t error = fFile->EvaluateDynamicValue(fCompilationUnit, - fSubprogramEntry, bitStrideOwnerEntry->BitStride(), - fTargetInterface, fInstructionPointer, fFramePointer, value); - if (error != B_OK) - return error; - if (!value.IsInteger()) - return B_BAD_VALUE; - bitStride = value.ToInt64(); - } else - bitStride = type->BaseType()->ByteSize() * 8; - - // Iterate backward through the dimensions and compute the total offset of - // the element. - int64 elementOffset = 0; - DwarfArrayDimension* previousDimension = NULL; - int64 previousDimensionStride = 0; - for (int32 dimensionIndex = type->CountDimensions() - 1; - dimensionIndex >= 0; dimensionIndex--) { - DwarfArrayDimension* dimension = type->DwarfDimensionAt(dimensionIndex); - int64 index = indexPath.IndexAt(dimensionIndex); - - // If the dimension has a special bit/byte stride, get it. - int64 dimensionStride = 0; - DwarfType* dimensionType = dimension->GetDwarfType(); - DIEArrayIndexType* dimensionTypeEntry = dimensionType != NULL - ? dynamic_cast(dimensionType->GetDIEType()) - : NULL; - if (dimensionTypeEntry != NULL) { - DIEArrayIndexType* bitStrideOwnerEntry - = DwarfUtils::GetDIEByPredicate(dimensionTypeEntry, - HasBitStridePredicate()); - if (bitStrideOwnerEntry != NULL) { - BVariant value; - status_t error = fFile->EvaluateDynamicValue(fCompilationUnit, - fSubprogramEntry, bitStrideOwnerEntry->BitStride(), - fTargetInterface, fInstructionPointer, fFramePointer, - value); - if (error != B_OK) - return error; - if (!value.IsInteger()) - return B_BAD_VALUE; - dimensionStride = value.ToInt64(); - } else { - DIEArrayIndexType* byteStrideOwnerEntry - = DwarfUtils::GetDIEByPredicate(dimensionTypeEntry, - HasByteStridePredicate()); - if (byteStrideOwnerEntry != NULL) { - BVariant value; - status_t error = fFile->EvaluateDynamicValue( - fCompilationUnit, fSubprogramEntry, - byteStrideOwnerEntry->ByteStride(), fTargetInterface, - fInstructionPointer, fFramePointer, value); - if (error != B_OK) - return error; - if (!value.IsInteger()) - return B_BAD_VALUE; - dimensionStride = value.ToInt64() * 8; - } - } - } - - // If we don't have a stride for the dimension yet, use the stride of - // the previous dimension multiplied by the size of the dimension. - if (dimensionStride == 0) { - if (previousDimension != NULL) { - dimensionStride = previousDimensionStride - * previousDimension->CountElements(); - } else { - // the last dimension -- use the element bit stride - dimensionStride = bitStride; - } - } - - // If the dimension stride is still 0 (that can happen, if the dimension - // doesn't have a stride and the previous dimension's element count is - // not known), we can only resolve the first element. - if (dimensionStride == 0 && index != 0) { - WARNING("No dimension bit stride for dimension %ld and element " - "index is not 0.\n", dimensionIndex); - return B_BAD_VALUE; - } - - elementOffset += dimensionStride * index; - - previousDimension = dimension; - previousDimensionStride = dimensionStride; - } - - TRACE_LOCALS("total element bit offset: %lld\n", elementOffset); - - // create the value location object for the element - ValueLocation* location = new(std::nothrow) ValueLocation( - parentLocation.IsBigEndian()); - if (location == NULL) + // create a type context without dependency to the stack frame + DwarfTypeContext* typeContext = new(std::nothrow) DwarfTypeContext( + fTypeContext->GetArchitecture(), fTypeContext->ImageID(), + fTypeContext->File(), fTypeContext->GetCompilationUnit(), NULL, 0, 0, + fTypeContext->TargetInterface(), fTypeContext->FromDwarfRegisterMap()); + if (typeContext == NULL) return B_NO_MEMORY; - Reference locationReference(location, true); + Reference typeContextReference(typeContext, true); - // If we have a single memory piece location for the array, we compute the - // element's location by hand -- not uncommonly the array size isn't known. - if (parentLocation.CountPieces() == 1) { - ValuePieceLocation piece = parentLocation.PieceAt(0); - if (piece.type == VALUE_PIECE_LOCATION_MEMORY) { - int64 byteOffset = elementOffset >= 0 - ? elementOffset / 8 : (elementOffset - 7) / 8; - piece.SetToMemory(piece.address + byteOffset); - piece.SetSize(type->BaseType()->ByteSize()); - // TODO: Support bit offsets correctly! - // TODO: Support bit fields (primitive types) correctly! - - if (!location->AddPiece(piece)) - return B_NO_MEMORY; - - _location = locationReference.Detach(); - return B_OK; - } - } - - // We can't deal with negative element offsets at this point. It doesn't - // make a lot of sense anyway, if the array location consists of multiple - // pieces or lives in a register. - if (elementOffset < 0) { - WARNING("Negative element offset unsupported for multiple location " - "pieces or register pieces.\n"); - return B_UNSUPPORTED; - } - - if (!location->SetTo(parentLocation, elementOffset, - type->BaseType()->ByteSize() * 8)) { + // create the type factory + fTypeFactory = new(std::nothrow) DwarfTypeFactory(typeContext, fTypeLookup, + fTypeCache); + if (fTypeFactory == NULL) return B_NO_MEMORY; - } - _location = locationReference.Detach(); - return B_OK; -} - - -status_t -DwarfStackFrameDebugInfo::CreateType(DIEType* typeEntry, Type*& _type) -{ - DwarfType* type; - status_t error = _CreateType(typeEntry, type); - if (error != B_OK) - return error; - - _type = type; return B_OK; } @@ -1512,8 +214,8 @@ DwarfStackFrameDebugInfo::CreateLocalVariable(FunctionID* functionID, int32 column = -1; const char* file; const char* directory; - DwarfUtils::GetDeclarationLocation(fFile, variableEntry, directory, file, - line, column); + DwarfUtils::GetDeclarationLocation(fTypeContext->File(), variableEntry, + directory, file, line, column); // TODO: If the declaration location is unavailable, we should probably // add a component to the ID to make it unique nonetheless (the name // might not suffice). @@ -1531,970 +233,6 @@ DwarfStackFrameDebugInfo::CreateLocalVariable(FunctionID* functionID, } -status_t -DwarfStackFrameDebugInfo::_ResolveDataMemberLocation(StackFrame* stackFrame, - DwarfCompoundType* type, Type* memberType, - const MemberLocation* memberLocation, const ValueLocation& parentLocation, - ValueLocation*& _location) -{ - // create the value location object for the member - ValueLocation* location = new(std::nothrow) ValueLocation( - parentLocation.IsBigEndian()); - if (location == NULL) - return B_NO_MEMORY; - Reference locationReference(location, true); - - switch (memberLocation->attributeClass) { - case ATTRIBUTE_CLASS_CONSTANT: - { - if (!location->SetTo(parentLocation, memberLocation->constant * 8, - memberType->ByteSize() * 8)) { - return B_NO_MEMORY; - } - - break; - } - case ATTRIBUTE_CLASS_BLOCK: - case ATTRIBUTE_CLASS_LOCLISTPTR: - { - // The attribute is a location description. Since we need to push - // the parent object value onto the stack, we require the parent - // location to be a memory location. - if (parentLocation.CountPieces() != 1) - return B_BAD_VALUE; - ValuePieceLocation piece = parentLocation.PieceAt(0); - if (piece.type != VALUE_PIECE_LOCATION_MEMORY) - return B_BAD_VALUE; - - // convert member location to location description - LocationDescription locationDescription; - if (memberLocation->attributeClass == ATTRIBUTE_CLASS_BLOCK) { - locationDescription.SetToExpression( - memberLocation->expression.data, - memberLocation->expression.length); - } else { - locationDescription.SetToLocationList( - memberLocation->listOffset); - } - - // evaluate the location description - status_t error = _ResolveLocation(&locationDescription, - piece.address, memberType, *location); - if (error != B_OK) - return error; - - break; - } - default: - { - // for unions the member location can be omitted -- all members - // start at the beginning of the parent object - if (type->GetDIEType()->Tag() != DW_TAG_union_type) - return B_BAD_VALUE; - - if (!location->SetTo(parentLocation, 0, memberType->ByteSize() * 8)) - return B_NO_MEMORY; - - break; - } - } - - _location = locationReference.Detach(); - return B_OK; -} - - -status_t -DwarfStackFrameDebugInfo::_CreateType(DIEType* typeEntry, DwarfType*& _type) -{ - // try the type cache first - BString name; - DwarfUtils::GetFullyQualifiedDIEName(typeEntry, name); -// TODO: The DIE may not have a name (e.g. pointer and reference types don't). - - AutoLocker contextLocker(fTypeLookupContext); - Type* globalType = name.Length() > 0 - ? fTypeLookupContext->CachedType(name) : NULL; - if (globalType != NULL) { - DwarfType* globalDwarfType = dynamic_cast(globalType); - if (globalDwarfType != NULL) { - globalDwarfType->AcquireReference(); - _type = globalDwarfType; - return B_OK; - } - } - - contextLocker.Unlock(); - - // If the type entry indicates a declaration only, we try to look the - // type up globally first. - if (typeEntry->IsDeclaration() && name.Length() > 0 - && fTypeLookup->GetType(fTypeLookupContext, name, globalType) - == B_OK) { - DwarfType* globalDwarfType - = dynamic_cast(globalType); - if (globalDwarfType != NULL) { - _type = globalDwarfType; - return B_OK; - } - - globalType->ReleaseReference(); - } - - // No luck yet -- create the type. - DwarfType* type; - status_t error = _CreateTypeInternal(name, typeEntry, type); - if (error != B_OK) - return error; - Reference typeReference(type, true); - - // Insert the type into the cache. Re-check, as the type may already - // have been inserted (e.g. in the compound type case). - if (name.Length() > 0) { - contextLocker.Lock(); - if (fTypeLookupContext->CachedType(name) == NULL) { - error = fTypeLookupContext->AddCachedType(name, type); - if (error != B_OK) - return error; - } - contextLocker.Unlock(); - } - - // try to get the type's size - uint64 size; - if (_ResolveTypeByteSize(typeEntry, size) == B_OK) - type->SetByteSize(size); - - _type = typeReference.Detach(); - return B_OK; -} - - -status_t -DwarfStackFrameDebugInfo::_CreateTypeInternal(const BString& name, - DIEType* typeEntry, DwarfType*& _type) -{ - switch (typeEntry->Tag()) { - case DW_TAG_class_type: - case DW_TAG_structure_type: - case DW_TAG_union_type: - case DW_TAG_interface_type: - return _CreateCompoundType(name, - dynamic_cast(typeEntry), _type); - - case DW_TAG_base_type: - return _CreatePrimitiveType(name, - dynamic_cast(typeEntry), _type); - - case DW_TAG_pointer_type: - return _CreateAddressType(name, - dynamic_cast(typeEntry), - DERIVED_TYPE_POINTER, _type); - case DW_TAG_reference_type: - return _CreateAddressType(name, - dynamic_cast(typeEntry), - DERIVED_TYPE_REFERENCE, _type); - - case DW_TAG_const_type: - return _CreateModifiedType(name, - dynamic_cast(typeEntry), - TYPE_MODIFIER_CONST, _type); - case DW_TAG_packed_type: - return _CreateModifiedType(name, - dynamic_cast(typeEntry), - TYPE_MODIFIER_PACKED, _type); - case DW_TAG_volatile_type: - return _CreateModifiedType(name, - dynamic_cast(typeEntry), - TYPE_MODIFIER_VOLATILE, _type); - case DW_TAG_restrict_type: - return _CreateModifiedType(name, - dynamic_cast(typeEntry), - TYPE_MODIFIER_RESTRICT, _type); - case DW_TAG_shared_type: - return _CreateModifiedType(name, - dynamic_cast(typeEntry), - TYPE_MODIFIER_SHARED, _type); - - case DW_TAG_typedef: - return _CreateTypedefType(name, - dynamic_cast(typeEntry), _type); - - case DW_TAG_array_type: - return _CreateArrayType(name, - dynamic_cast(typeEntry), _type); - - case DW_TAG_enumeration_type: - return _CreateEnumerationType(name, - dynamic_cast(typeEntry), _type); - - case DW_TAG_subrange_type: - return _CreateSubrangeType(name, - dynamic_cast(typeEntry), _type); - - case DW_TAG_unspecified_type: - return _CreateUnspecifiedType(name, - dynamic_cast(typeEntry), _type); - - case DW_TAG_subroutine_type: - return _CreateFunctionType(name, - dynamic_cast(typeEntry), _type); - - case DW_TAG_ptr_to_member_type: - return _CreatePointerToMemberType(name, - dynamic_cast(typeEntry), _type); - - case DW_TAG_string_type: - case DW_TAG_file_type: - case DW_TAG_set_type: - // TODO: Implement (not relevant for C++)! - return B_UNSUPPORTED; - } - - return B_UNSUPPORTED; -} - - -status_t -DwarfStackFrameDebugInfo::_CreateCompoundType(const BString& name, - DIECompoundType* typeEntry, DwarfType*& _type) -{ - TRACE_LOCALS("DwarfStackFrameDebugInfo::_CreateCompoundType(\"%s\", %p)\n", - name.String(), typeEntry); - - // create the type - DwarfCompoundType* type = new(std::nothrow) DwarfCompoundType(name, - typeEntry); - if (type == NULL) - return B_NO_MEMORY; - Reference typeReference(type, true); - - // Already add the type at this pointer to the cache, since otherwise - // we could run into an infinite recursion when trying to create the types - // for the data members. -// TODO: Since access to the type lookup context is multi-threaded, the -// incomplete type could become visible to other threads. Hence we keep the -// context locked, but that essentially kills multi-threading for this context. - AutoLocker contextLocker(fTypeLookupContext); - status_t error = fTypeLookupContext->AddCachedType(name, type); - if (error != B_OK) - return error; -// contextLocker.Unlock(); - - // find the abstract origin or specification that defines the data members - DIECompoundType* memberOwnerEntry = DwarfUtils::GetDIEByPredicate(typeEntry, - HasMembersPredicate()); - - // create the data member objects - if (memberOwnerEntry != NULL) { - for (DebugInfoEntryList::ConstIterator it - = memberOwnerEntry->DataMembers().GetIterator(); - DebugInfoEntry* _memberEntry = it.Next();) { - DIEMember* memberEntry = dynamic_cast(_memberEntry); - - TRACE_LOCALS(" member %p\n", memberEntry); - - // get the type - DwarfType* memberType; - if (_CreateType(memberEntry->GetType(), memberType) != B_OK) - continue; - Reference memberTypeReference(memberType, true); - - // get the name - BString memberName; - DwarfUtils::GetDIEName(memberEntry, memberName); - - // create and add the member object - DwarfDataMember* member = new(std::nothrow) DwarfDataMember( - memberEntry, memberName, memberType); - Reference memberReference(member, true); - if (member == NULL || !type->AddDataMember(member)) { - contextLocker.Lock(); - fTypeLookupContext->RemoveCachedType(name); - return B_NO_MEMORY; - } - } - } - - // If the type is a class/struct/interface type, we also need to add its - // base types. - if (DIEClassBaseType* classTypeEntry - = dynamic_cast(typeEntry)) { - // find the abstract origin or specification that defines the base types - classTypeEntry = DwarfUtils::GetDIEByPredicate(classTypeEntry, - HasBaseTypesPredicate()); - - // create the inheritance objects for the base types - if (classTypeEntry != NULL) { - for (DebugInfoEntryList::ConstIterator it - = classTypeEntry->BaseTypes().GetIterator(); - DebugInfoEntry* _inheritanceEntry = it.Next();) { - DIEInheritance* inheritanceEntry - = dynamic_cast(_inheritanceEntry); - - // get the type - DwarfType* baseType; - if (_CreateType(inheritanceEntry->GetType(), baseType) != B_OK) - continue; - Reference baseTypeReference(baseType, true); - - // create and add the inheritance object - DwarfInheritance* inheritance = new(std::nothrow) - DwarfInheritance(inheritanceEntry, baseType); - Reference inheritanceReference(inheritance, - true); - if (inheritance == NULL || !type->AddInheritance(inheritance)) { - contextLocker.Lock(); - fTypeLookupContext->RemoveCachedType(name); - return B_NO_MEMORY; - } - } - } - } - - _type = typeReference.Detach(); - return B_OK;; -} - - -status_t -DwarfStackFrameDebugInfo::_CreatePrimitiveType(const BString& name, - DIEBaseType* typeEntry, DwarfType*& _type) -{ - const DynamicAttributeValue* byteSizeValue = typeEntry->ByteSize(); -// const DynamicAttributeValue* bitOffsetValue = typeEntry->BitOffset(); - const DynamicAttributeValue* bitSizeValue = typeEntry->BitSize(); - - uint32 bitSize = 0; - if (byteSizeValue->IsValid()) { - BVariant value; - status_t error = fFile->EvaluateDynamicValue(fCompilationUnit, - fSubprogramEntry, byteSizeValue, fTargetInterface, - fInstructionPointer, fFramePointer, value); - if (error == B_OK && value.IsInteger()) - bitSize = value.ToUInt32() * 8; - } else if (bitSizeValue->IsValid()) { - BVariant value; - status_t error = fFile->EvaluateDynamicValue(fCompilationUnit, - fSubprogramEntry, bitSizeValue, fTargetInterface, - fInstructionPointer, fFramePointer, value); - if (error == B_OK && value.IsInteger()) - bitSize = value.ToUInt32(); - } - - // determine type constant - uint32 typeConstant = 0; - switch (typeEntry->Encoding()) { - case DW_ATE_boolean: - typeConstant = B_BOOL_TYPE; - break; - - case DW_ATE_float: - switch (bitSize) { - case 32: - typeConstant = B_FLOAT_TYPE; - break; - case 64: - typeConstant = B_DOUBLE_TYPE; - break; - } - break; - - case DW_ATE_signed: - case DW_ATE_signed_char: - switch (bitSize) { - case 8: - typeConstant = B_INT8_TYPE; - break; - case 16: - typeConstant = B_INT16_TYPE; - break; - case 32: - typeConstant = B_INT32_TYPE; - break; - case 64: - typeConstant = B_INT64_TYPE; - break; - } - break; - - case DW_ATE_address: - case DW_ATE_unsigned: - case DW_ATE_unsigned_char: - switch (bitSize) { - case 8: - typeConstant = B_UINT8_TYPE; - break; - case 16: - typeConstant = B_UINT16_TYPE; - break; - case 32: - typeConstant = B_UINT32_TYPE; - break; - case 64: - typeConstant = B_UINT64_TYPE; - break; - } - break; - - case DW_ATE_complex_float: - case DW_ATE_imaginary_float: - case DW_ATE_packed_decimal: - case DW_ATE_numeric_string: - case DW_ATE_edited: - case DW_ATE_signed_fixed: - case DW_ATE_unsigned_fixed: - case DW_ATE_decimal_float: - default: - break; - } - - // create the type - DwarfPrimitiveType* type = new(std::nothrow) DwarfPrimitiveType(name, - typeEntry, typeConstant); - if (type == NULL) - return B_NO_MEMORY; - - _type = type; - return B_OK; -} - - -status_t -DwarfStackFrameDebugInfo::_CreateAddressType(const BString& name, - DIEAddressingType* typeEntry, address_type_kind addressKind, - DwarfType*& _type) -{ - // get the base type entry - DIEAddressingType* baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate( - typeEntry, HasTypePredicate()); - - // create the base type - DwarfType* baseType; - if (baseTypeOwnerEntry != NULL) { - status_t error = _CreateType(baseTypeOwnerEntry->GetType(), baseType); - if (error != B_OK) - return error; - } else { - // According to the DWARF 3 specs a modified type *has* a base type. - // GCC 4 doesn't (always?) bother to add one for "void". - // TODO: We should probably search for a respective type by name. ATM - // we just create a DwarfUnspecifiedType without DIE. - TRACE_LOCALS("no base type for address type entry -- creating " - "unspecified type\n"); - baseType = new(std::nothrow) DwarfUnspecifiedType("void", NULL); - if (baseType == NULL) - return B_NO_MEMORY; - } - Reference baseTypeReference(baseType, true); - - DwarfAddressType* type = new(std::nothrow) DwarfAddressType(name, typeEntry, - addressKind, baseType); - if (type == NULL) - return B_NO_MEMORY; - - _type = type; - return B_OK; -} - - -status_t -DwarfStackFrameDebugInfo::_CreateModifiedType(const BString& name, - DIEModifiedType* typeEntry, uint32 modifiers, DwarfType*& _type) -{ - // Get the base type entry. If it is a modified type too or a typedef, - // collect all modifiers and iterate until hitting an actual base type. - DIEType* baseTypeEntry; - while (true) { - DIEModifiedType* baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate( - typeEntry, HasTypePredicate()); - if (baseTypeOwnerEntry == NULL) - return B_BAD_VALUE; - - baseTypeEntry = baseTypeOwnerEntry->GetType(); - - // resolve a typedef - if (baseTypeEntry->Tag() == DW_TAG_typedef) { - status_t error = _ResolveTypedef( - dynamic_cast(baseTypeEntry), baseTypeEntry); - if (error != B_OK) - return error; - } - - if (baseTypeEntry == NULL) - return B_BAD_VALUE; - - // If the base type is a modified type, too, resolve it. - switch (baseTypeEntry->Tag()) { - case DW_TAG_const_type: - modifiers |= TYPE_MODIFIER_CONST; - baseTypeOwnerEntry - = dynamic_cast(baseTypeEntry); - continue; - case DW_TAG_packed_type: - modifiers |= TYPE_MODIFIER_PACKED; - baseTypeOwnerEntry - = dynamic_cast(baseTypeEntry); - continue; - case DW_TAG_volatile_type: - modifiers |= TYPE_MODIFIER_VOLATILE; - baseTypeOwnerEntry - = dynamic_cast(baseTypeEntry); - continue; - case DW_TAG_restrict_type: - modifiers |= TYPE_MODIFIER_RESTRICT; - baseTypeOwnerEntry - = dynamic_cast(baseTypeEntry); - continue; - case DW_TAG_shared_type: - modifiers |= TYPE_MODIFIER_SHARED; - baseTypeOwnerEntry - = dynamic_cast(baseTypeEntry); - continue; - - default: - break; - } - - // If we get here, we've found an actual base type. - break; - } - - // create the base type - DwarfType* baseType; - status_t error = _CreateType(baseTypeEntry, baseType); - if (error != B_OK) - return error; - Reference baseTypeReference(baseType, true); - - DwarfModifiedType* type = new(std::nothrow) DwarfModifiedType(name, - typeEntry, modifiers, baseType); - if (type == NULL) - return B_NO_MEMORY; - - _type = type; - return B_OK; -} - - -status_t -DwarfStackFrameDebugInfo::_CreateTypedefType(const BString& name, - DIETypedef* typeEntry, DwarfType*& _type) -{ - // resolve the base type - DIEType* baseTypeEntry; - status_t error = _ResolveTypedef(typeEntry, baseTypeEntry); - if (error != B_OK) - return error; - - // create the base type - DwarfType* baseType; - error = _CreateType(baseTypeEntry, baseType); - if (error != B_OK) - return error; - Reference baseTypeReference(baseType, true); - - DwarfTypedefType* type = new(std::nothrow) DwarfTypedefType(name, typeEntry, - baseType); - if (type == NULL) - return B_NO_MEMORY; - - _type = type; - return B_OK; -} - - -status_t -DwarfStackFrameDebugInfo::_CreateArrayType(const BString& name, - DIEArrayType* typeEntry, DwarfType*& _type) -{ - TRACE_LOCALS("DwarfStackFrameDebugInfo::_CreateArrayType(\"%s\", %p)\n", - name.String(), typeEntry); - - // create the base type - DIEArrayType* baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate( - typeEntry, HasTypePredicate()); - if (baseTypeOwnerEntry == NULL) { - WARNING("Failed to get base type for array type \"%s\"\n", - name.String()); - return B_BAD_VALUE; - } - - DwarfType* baseType = NULL; - status_t error = _CreateType(baseTypeOwnerEntry->GetType(), baseType); - if (error != B_OK) { - WARNING("Failed to create base type for array type \"%s\": %s\n", - name.String(), strerror(error)); - return error; - } - Reference baseTypeReference(baseType, true); - - // create the array type - DwarfArrayType* type = new(std::nothrow) DwarfArrayType(name, typeEntry, - baseType); - if (type == NULL) - return B_NO_MEMORY; - Reference typeReference(type, true); - - // add the array dimensions - DIEArrayType* dimensionOwnerEntry = DwarfUtils::GetDIEByPredicate( - typeEntry, HasDimensionsPredicate()); - - if (dimensionOwnerEntry == NULL) { - WARNING("Failed to get dimensions for array type \"%s\"\n", - name.String()); - return B_BAD_VALUE; - } - - for (DebugInfoEntryList::ConstIterator it - = dimensionOwnerEntry->Dimensions().GetIterator(); - DebugInfoEntry* _dimensionEntry = it.Next();) { - DIEType* dimensionEntry = dynamic_cast(_dimensionEntry); - - // get/create the dimension type - DwarfType* dimensionType = NULL; - status_t error = _CreateType(dimensionEntry, dimensionType); - if (error != B_OK) { - WARNING("Failed to create type for array dimension: %s\n", - strerror(error)); - return error; - } - Reference dimensionTypeReference(dimensionType, true); - - // create and add the array dimension object - DwarfArrayDimension* dimension - = new(std::nothrow) DwarfArrayDimension(dimensionType); - Reference dimensionReference(dimension, true); - if (dimension == NULL || !type->AddDimension(dimension)) - return B_NO_MEMORY; - } - - _type = typeReference.Detach(); - return B_OK; -} - - -status_t -DwarfStackFrameDebugInfo::_CreateEnumerationType(const BString& name, - DIEEnumerationType* typeEntry, DwarfType*& _type) -{ - // create the base type (it's optional) - DIEEnumerationType* baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate( - typeEntry, HasTypePredicate()); - - DwarfType* baseType = NULL; - if (baseTypeOwnerEntry != NULL) { - status_t error = _CreateType(baseTypeOwnerEntry->GetType(), baseType); - if (error != B_OK) - return error; - } - Reference baseTypeReference(baseType, true); - - // create the enumeration type - DwarfEnumerationType* type = new(std::nothrow) DwarfEnumerationType(name, - typeEntry, baseType); - if (type == NULL) - return B_NO_MEMORY; - Reference typeReference(type, true); - - // get the enumeration values - DIEEnumerationType* enumeratorOwnerEntry = DwarfUtils::GetDIEByPredicate( - typeEntry, HasEnumeratorsPredicate()); - - if (enumeratorOwnerEntry != NULL) { - for (DebugInfoEntryList::ConstIterator it - = enumeratorOwnerEntry->Enumerators().GetIterator(); - DebugInfoEntry* _enumeratorEntry = it.Next();) { - DIEEnumerator* enumeratorEntry = dynamic_cast( - _enumeratorEntry); - - // evaluate the value - BVariant value; - status_t error = fFile->EvaluateConstantValue(fCompilationUnit, - fSubprogramEntry, enumeratorEntry->ConstValue(), - fTargetInterface, fInstructionPointer, fFramePointer, value); - if (error != B_OK) { - // The value is probably not stored -- just ignore the - // enumerator. - TRACE_LOCALS("Failed to get value for enum type value %s::%s\n", - name.String(), enumeratorEntry->Name()); - continue; - } - - // create and add the enumeration value object - DwarfEnumerationValue* enumValue - = new(std::nothrow) DwarfEnumerationValue(enumeratorEntry, - enumeratorEntry->Name(), value); - Reference enumValueReference(enumValue, true); - if (enumValue == NULL || !type->AddValue(enumValue)) - return B_NO_MEMORY; - } - } - - _type = typeReference.Detach(); - return B_OK; -} - - -status_t -DwarfStackFrameDebugInfo::_CreateSubrangeType(const BString& name, - DIESubrangeType* typeEntry, DwarfType*& _type) -{ - // get the base type - DIESubrangeType* baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate( - typeEntry, HasTypePredicate()); - DIEType* baseTypeEntry = baseTypeOwnerEntry != NULL - ? baseTypeOwnerEntry->GetType() : NULL; - - // get the lower bound - BVariant lowerBound; - DIESubrangeType* lowerBoundOwnerEntry = DwarfUtils::GetDIEByPredicate( - typeEntry, HasLowerBoundPredicate()); - if (lowerBoundOwnerEntry != NULL) { - // evaluate it - DIEType* valueType; - status_t error = fFile->EvaluateDynamicValue(fCompilationUnit, - fSubprogramEntry, lowerBoundOwnerEntry->LowerBound(), - fTargetInterface, fInstructionPointer, fFramePointer, lowerBound, - &valueType); - if (error != B_OK) { - WARNING(" failed to evaluate lower bound: %s\n", strerror(error)); - return error; - } - - // If we don't have a base type yet, and the lower bound attribute - // refers to an object, the type of that object is our base type. - if (baseTypeEntry == NULL) - baseTypeEntry = valueType; - } else { - // that's ok -- use the language default - lowerBound.SetTo( - fCompilationUnit->SourceLanguage()->subrangeLowerBound); - } - - // get the upper bound - BVariant upperBound; - DIESubrangeType* upperBoundOwnerEntry = DwarfUtils::GetDIEByPredicate( - typeEntry, HasUpperBoundPredicate()); - if (upperBoundOwnerEntry != NULL) { - // evaluate it - DIEType* valueType; - status_t error = fFile->EvaluateDynamicValue(fCompilationUnit, - fSubprogramEntry, upperBoundOwnerEntry->UpperBound(), - fTargetInterface, fInstructionPointer, fFramePointer, upperBound, - &valueType); - if (error != B_OK) { - WARNING(" failed to evaluate upper bound: %s\n", strerror(error)); - return error; - } - - // If we don't have a base type yet, and the upper bound attribute - // refers to an object, the type of that object is our base type. - if (baseTypeEntry == NULL) - baseTypeEntry = valueType; - } else { - // get the count instead - DIESubrangeType* countOwnerEntry = DwarfUtils::GetDIEByPredicate( - typeEntry, HasCountPredicate()); - if (countOwnerEntry != NULL) { - // evaluate it - BVariant count; - DIEType* valueType; - status_t error = fFile->EvaluateDynamicValue(fCompilationUnit, - fSubprogramEntry, countOwnerEntry->Count(), fTargetInterface, - fInstructionPointer, fFramePointer, count, &valueType); - if (error != B_OK) { - WARNING(" failed to evaluate count: %s\n", strerror(error)); - return error; - } - - // If we don't have a base type yet, and the count attribute refers - // to an object, the type of that object is our base type. - if (baseTypeEntry == NULL) - baseTypeEntry = valueType; - - // we only support integers - bool isSigned; - if (!lowerBound.IsInteger(&isSigned) || !count.IsInteger()) { - WARNING(" count given for subrange type, but lower bound or " - "count is not integer\n"); - return B_BAD_VALUE; - } - - if (isSigned) - upperBound.SetTo(lowerBound.ToInt64() + count.ToInt64() - 1); - else - upperBound.SetTo(lowerBound.ToUInt64() + count.ToUInt64() - 1); - } - } - - // If we still don't have a base type yet, the base type is supposed to be - // the a signed integer type with the same size as an address for that - // compilation unit. - if (baseTypeEntry == NULL) { - // TODO: Implement! - WARNING("Base type fallback for subrange type not implemented yet!\n"); - return B_UNSUPPORTED; - } - - // create the base type - DwarfType* baseType; - status_t error = _CreateType(baseTypeEntry, baseType); - if (error != B_OK) - return error; - Reference baseTypeReference(baseType, true); - - // TODO: Support the thread scaling attribute! - - // create the type - DwarfSubrangeType* type = new(std::nothrow) DwarfSubrangeType(name, - typeEntry, baseType, lowerBound, upperBound); - if (type == NULL) - return B_NO_MEMORY; - - _type = type; - return B_OK; -} - - -status_t -DwarfStackFrameDebugInfo::_CreateUnspecifiedType(const BString& name, - DIEUnspecifiedType* typeEntry, DwarfType*& _type) -{ - DwarfUnspecifiedType* type = new(std::nothrow) DwarfUnspecifiedType(name, - typeEntry); - if (type == NULL) - return B_NO_MEMORY; - - _type = type; - return B_OK; -} - -status_t -DwarfStackFrameDebugInfo::_CreateFunctionType(const BString& name, - DIESubroutineType* typeEntry, DwarfType*& _type) -{ - // get the return type - DIESubroutineType* returnTypeOwnerEntry = DwarfUtils::GetDIEByPredicate( - typeEntry, HasReturnTypePredicate()); - - // create the base type - DwarfType* returnType = NULL; - if (returnTypeOwnerEntry != NULL) { - status_t error = _CreateType(returnTypeOwnerEntry->ReturnType(), - returnType); - if (error != B_OK) - return error; - } - Reference returnTypeReference(returnType, true); - - DwarfFunctionType* type = new(std::nothrow) DwarfFunctionType(name, - typeEntry, returnType); - if (type == NULL) - return B_NO_MEMORY; - Reference typeReference(type, true); - - // get the parameters - DIESubroutineType* parameterOwnerEntry = DwarfUtils::GetDIEByPredicate( - typeEntry, HasParametersPredicate()); - - if (parameterOwnerEntry != NULL) { - for (DebugInfoEntryList::ConstIterator it - = parameterOwnerEntry->Parameters().GetIterator(); - DebugInfoEntry* _parameterEntry = it.Next();) { - if (_parameterEntry->Tag() == DW_TAG_unspecified_parameters) { - type->SetHasVariableArguments(true); - continue; - } - - DIEFormalParameter* parameterEntry - = dynamic_cast(_parameterEntry); - - // get the type - DIEFormalParameter* typeOwnerEntry = DwarfUtils::GetDIEByPredicate( - parameterEntry, HasTypePredicate()); - if (typeOwnerEntry == NULL) - return B_BAD_VALUE; - - DwarfType* parameterType; - status_t error = _CreateType(typeOwnerEntry->GetType(), - parameterType); - if (error != B_OK) - return error; - Reference parameterTypeReference(parameterType, true); - - // get the name - BString parameterName; - DwarfUtils::GetDIEName(parameterEntry, parameterName); - - // create and add the parameter object - DwarfFunctionParameter* parameter - = new(std::nothrow) DwarfFunctionParameter(parameterEntry, - parameterName, parameterType); - Reference parameterReference(parameter, - true); - if (parameter == NULL || !type->AddParameter(parameter)) - return B_NO_MEMORY; - } - } - - - _type = typeReference.Detach(); - return B_OK; -} - - -status_t -DwarfStackFrameDebugInfo::_CreatePointerToMemberType(const BString& name, - DIEPointerToMemberType* typeEntry, DwarfType*& _type) -{ - // get the containing and base type entries - DIEPointerToMemberType* containingTypeOwnerEntry - = DwarfUtils::GetDIEByPredicate(typeEntry, - HasContainingTypePredicate()); - DIEPointerToMemberType* baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate( - typeEntry, HasTypePredicate()); - - if (containingTypeOwnerEntry == NULL || baseTypeOwnerEntry == NULL) { - WARNING("Failed to get containing or base type for pointer to member " - "type \"%s\"\n", name.String()); - return B_BAD_VALUE; - } - - // create the containing type - DwarfType* containingType; - status_t error = _CreateType(containingTypeOwnerEntry->ContainingType(), - containingType); - if (error != B_OK) - return error; - Reference containingTypeReference(containingType, true); - - DwarfCompoundType* compoundContainingType - = dynamic_cast(containingType); - if (compoundContainingType == NULL) { - WARNING("Containing type for pointer to member type \"%s\" is not a " - "compound type.\n", name.String()); - return B_BAD_VALUE; - } - - // create the base type - DwarfType* baseType; - error = _CreateType(baseTypeOwnerEntry->GetType(), baseType); - if (error != B_OK) - return error; - Reference baseTypeReference(baseType, true); - - // create the type object - DwarfPointerToMemberType* type = new(std::nothrow) DwarfPointerToMemberType( - name, typeEntry, compoundContainingType, baseType); - if (type == NULL) - return B_NO_MEMORY; - - _type = type; - return B_OK; -} - - status_t DwarfStackFrameDebugInfo::_CreateVariable(ObjectID* id, const BString& name, DIEType* typeEntry, LocationDescription* locationDescription, @@ -2505,21 +243,21 @@ DwarfStackFrameDebugInfo::_CreateVariable(ObjectID* id, const BString& name, // create the type DwarfType* type; - status_t error = _CreateType(typeEntry, type); + status_t error = fTypeFactory->CreateType(typeEntry, type); if (error != B_OK) return error; Reference typeReference(type, true); // get the location, if possible ValueLocation* location = new(std::nothrow) ValueLocation( - fArchitecture->IsBigEndian()); + fTypeContext->GetArchitecture()->IsBigEndian()); if (location == NULL) return B_NO_MEMORY; Reference locationReference(location, true); if (locationDescription->IsValid()) { - status_t error = _ResolveLocation(locationDescription, 0, type, - *location); + status_t error = type->ResolveLocation(fTypeContext, + locationDescription, 0, *location); if (error != B_OK) return error; @@ -2536,190 +274,6 @@ DwarfStackFrameDebugInfo::_CreateVariable(ObjectID* id, const BString& name, } -status_t -DwarfStackFrameDebugInfo::_ResolveTypedef(DIETypedef* entry, - DIEType*& _baseTypeEntry) -{ - while (true) { - // resolve the base type, possibly following abstract origin or - // specification - DIETypedef* baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate( - entry, HasTypePredicate()); - if (baseTypeOwnerEntry == NULL) - return B_BAD_VALUE; - - DIEType* baseTypeEntry = baseTypeOwnerEntry->GetType(); - if (baseTypeEntry->Tag() != DW_TAG_typedef) { - _baseTypeEntry = baseTypeEntry; - return B_OK; - } - - entry = dynamic_cast(baseTypeEntry); - } -} - - -status_t -DwarfStackFrameDebugInfo::_ResolveTypeByteSize(DIEType* typeEntry, - uint64& _size) -{ - TRACE_LOCALS("DwarfStackFrameDebugInfo::_ResolveTypeByteSize(%p)\n", - typeEntry); - - // get the size attribute - const DynamicAttributeValue* sizeValue; - - while (true) { - // resolve a typedef - if (typeEntry->Tag() == DW_TAG_typedef) { - TRACE_LOCALS(" resolving typedef...\n"); - - status_t error = _ResolveTypedef( - dynamic_cast(typeEntry), typeEntry); - if (error != B_OK) - return error; - } - - sizeValue = typeEntry->ByteSize(); - if (sizeValue != NULL && sizeValue->IsValid()) - break; - - // resolve abstract origin - if (DIEType* abstractOrigin = dynamic_cast( - typeEntry->AbstractOrigin())) { - TRACE_LOCALS(" resolving abstract origin (%p)...\n", - abstractOrigin); - - typeEntry = abstractOrigin; - sizeValue = typeEntry->ByteSize(); - if (sizeValue != NULL && sizeValue->IsValid()) - break; - } - - // resolve specification - if (DIEType* specification = dynamic_cast( - typeEntry->Specification())) { - TRACE_LOCALS(" resolving specification (%p)...\n", specification); - - typeEntry = specification; - sizeValue = typeEntry->ByteSize(); - if (sizeValue != NULL && sizeValue->IsValid()) - break; - } - - // For some types we have a special handling. For modified types we - // follow the base type, for address types we know the size anyway. - TRACE_LOCALS(" nothing yet, special type handling\n"); - - switch (typeEntry->Tag()) { - case DW_TAG_const_type: - case DW_TAG_packed_type: - case DW_TAG_volatile_type: - case DW_TAG_restrict_type: - case DW_TAG_shared_type: - typeEntry = dynamic_cast(typeEntry) - ->GetType(); - - TRACE_LOCALS(" following modified type -> %p\n", typeEntry); - - if (typeEntry == NULL) - return B_ENTRY_NOT_FOUND; - break; - case DW_TAG_pointer_type: - case DW_TAG_reference_type: - case DW_TAG_ptr_to_member_type: - _size = fCompilationUnit->AddressSize(); - - TRACE_LOCALS(" pointer/reference type: size: %llu\n", _size); - - return B_OK; - default: - return B_ENTRY_NOT_FOUND; - } - } - - TRACE_LOCALS(" found attribute\n"); - - // get the actual value - BVariant size; - status_t error = fFile->EvaluateDynamicValue(fCompilationUnit, - fSubprogramEntry, sizeValue, fTargetInterface, fInstructionPointer, - fFramePointer, size); - if (error != B_OK) { - TRACE_LOCALS(" failed to resolve attribute: %s\n", strerror(error)); - return error; - } - - _size = size.ToUInt64(); - - TRACE_LOCALS(" -> size: %llu\n", _size); - - return B_OK; -} - - -status_t -DwarfStackFrameDebugInfo::_ResolveLocation( - const LocationDescription* description, target_addr_t objectAddress, - Type* type, ValueLocation& _location) -{ - status_t error = fFile->ResolveLocation(fCompilationUnit, - fSubprogramEntry, description, fTargetInterface, - fInstructionPointer, objectAddress, fFramePointer, _location); - if (error != B_OK) - return error; - - // translate the DWARF register indices and the bit offset/size semantics - const Register* registers = fArchitecture->Registers(); - bool bigEndian = fArchitecture->IsBigEndian(); - int32 count = _location.CountPieces(); - for (int32 i = 0; i < count; i++) { - ValuePieceLocation piece = _location.PieceAt(i); - if (piece.type == VALUE_PIECE_LOCATION_REGISTER) { - int32 reg = fFromDwarfRegisterMap->MapRegisterIndex(piece.reg); - if (reg >= 0) { - piece.reg = reg; - // The bit offset for registers is to the least - // significant bit, while we want the offset to the most - // significant bit. - if (registers[reg].BitSize() > piece.bitSize) { - piece.bitOffset = registers[reg].BitSize() - piece.bitSize - - piece.bitOffset; - } - } else - piece.SetToUnknown(); - } else if (piece.type == VALUE_PIECE_LOCATION_MEMORY) { - // Whether the bit offset is to the least or most significant bit - // is target architecture and source language specific. - // TODO: Check whether this is correct! - // TODO: Source language! - if (!bigEndian && piece.size * 8 > piece.bitSize) { - piece.bitOffset = piece.size * 8 - piece.bitSize - - piece.bitOffset; - } - } - - piece.Normalize(bigEndian); - _location.SetPieceAt(i, piece); - } - - // If we only have one piece and that doesn't have a size, try to retrieve - // the size of the type. - if (count == 1) { - ValuePieceLocation piece = _location.PieceAt(0); - if (piece.IsValid() && piece.size == 0 && piece.bitSize == 0) { - piece.SetSize(type->ByteSize()); - // TODO: Use bit size and bit offset, if specified! - _location.SetPieceAt(0, piece); - - TRACE_LOCALS(" set single piece size to %llu\n", type->ByteSize()); - } - } - - return B_OK; -} - - template /*static*/ DIEType* DwarfStackFrameDebugInfo::_GetDIEType(EntryType* entry) diff --git a/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.h b/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.h index 64f4f27076..bcf17f468e 100644 --- a/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.h +++ b/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.h @@ -2,39 +2,29 @@ * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. * Distributed under the terms of the MIT License. */ -#ifndef DWARF_INTERFACE_FACTORY_H -#define DWARF_INTERFACE_FACTORY_H +#ifndef DWARF_STACK_FRAME_DEBUG_INFO_H +#define DWARF_STACK_FRAME_DEBUG_INFO_H +#include #include #include "StackFrameDebugInfo.h" -#include "Type.h" class CompilationUnit; -class DIEAddressingType; -class DIEArrayType; -class DIEBaseType; -class DIECompoundType; -class DIEEnumerationType; class DIEFormalParameter; -class DIEModifiedType; -class DIEPointerToMemberType; class DIESubprogram; -class DIESubrangeType; -class DIESubroutineType; class DIEType; -class DIETypedef; -class DIEUnspecifiedType; class DIEVariable; class DwarfFile; class DwarfTargetInterface; +class DwarfTypeContext; +class DwarfTypeFactory; class FunctionID; +class GlobalTypeCache; class GlobalTypeLookup; -class GlobalTypeLookupContext; class LocationDescription; -class MemberLocation; class ObjectID; class RegisterMap; class Variable; @@ -43,11 +33,12 @@ class Variable; class DwarfStackFrameDebugInfo : public StackFrameDebugInfo { public: DwarfStackFrameDebugInfo( - Architecture* architecture, DwarfFile* file, + Architecture* architecture, + image_id imageID, DwarfFile* file, CompilationUnit* compilationUnit, DIESubprogram* subprogramEntry, GlobalTypeLookup* typeLookup, - GlobalTypeLookupContext* typeLookupContext, + GlobalTypeCache* typeCache, target_addr_t instructionPointer, target_addr_t framePointer, DwarfTargetInterface* targetInterface, @@ -56,28 +47,6 @@ public: status_t Init(); - virtual status_t ResolveObjectDataLocation( - StackFrame* stackFrame, Type* type, - const ValueLocation& objectLocation, - ValueLocation*& _location); - virtual status_t ResolveBaseTypeLocation( - StackFrame* stackFrame, Type* type, - BaseType* baseType, - const ValueLocation& parentLocation, - ValueLocation*& _location); - virtual status_t ResolveDataMemberLocation( - StackFrame* stackFrame, Type* type, - DataMember* member, - const ValueLocation& parentLocation, - ValueLocation*& _location); - virtual status_t ResolveArrayElementLocation( - StackFrame* stackFrame, ArrayType* type, - const ArrayIndexPath& indexPath, - const ValueLocation& parentLocation, - ValueLocation*& _location); - - status_t CreateType(DIEType* typeEntry, Type*& _type); - // returns reference status_t CreateParameter(FunctionID* functionID, DIEFormalParameter* parameterEntry, Variable*& _parameter); @@ -90,102 +59,22 @@ public: private: struct DwarfFunctionParameterID; struct DwarfLocalVariableID; - struct DwarfType; - struct DwarfInheritance; - struct DwarfDataMember; - struct DwarfEnumerationValue; - struct DwarfArrayDimension; - struct DwarfFunctionParameter; - struct DwarfPrimitiveType; - struct DwarfCompoundType; - struct DwarfModifiedType; - struct DwarfTypedefType; - struct DwarfAddressType; - struct DwarfEnumerationType; - struct DwarfSubrangeType; - struct DwarfArrayType; - struct DwarfUnspecifiedType; - struct DwarfFunctionType; - struct DwarfPointerToMemberType; private: - status_t _ResolveDataMemberLocation( - StackFrame* stackFrame, - DwarfCompoundType* type, - Type* memberType, - const MemberLocation* memberLocation, - const ValueLocation& parentLocation, - ValueLocation*& _location); - // returns a new location - - status_t _CreateType(DIEType* typeEntry, - DwarfType*& _type); - status_t _CreateTypeInternal(const BString& name, - DIEType* typeEntry, DwarfType*& _type); - - status_t _CreateCompoundType(const BString& name, - DIECompoundType* typeEntry, - DwarfType*& _type); - status_t _CreatePrimitiveType(const BString& name, - DIEBaseType* typeEntry, - DwarfType*& _type); - status_t _CreateAddressType(const BString& name, - DIEAddressingType* typeEntry, - address_type_kind addressKind, - DwarfType*& _type); - status_t _CreateModifiedType(const BString& name, - DIEModifiedType* typeEntry, - uint32 modifiers, DwarfType*& _type); - status_t _CreateTypedefType(const BString& name, - DIETypedef* typeEntry, DwarfType*& _type); - status_t _CreateArrayType(const BString& name, - DIEArrayType* typeEntry, - DwarfType*& _type); - status_t _CreateEnumerationType(const BString& name, - DIEEnumerationType* typeEntry, - DwarfType*& _type); - status_t _CreateSubrangeType(const BString& name, - DIESubrangeType* typeEntry, - DwarfType*& _type); - status_t _CreateUnspecifiedType(const BString& name, - DIEUnspecifiedType* typeEntry, - DwarfType*& _type); - status_t _CreateFunctionType(const BString& name, - DIESubroutineType* typeEntry, - DwarfType*& _type); - status_t _CreatePointerToMemberType(const BString& name, - DIEPointerToMemberType* typeEntry, - DwarfType*& _type); - status_t _CreateVariable(ObjectID* id, const BString& name, DIEType* typeEntry, LocationDescription* locationDescription, Variable*& _variable); - status_t _ResolveTypedef(DIETypedef* entry, - DIEType*& _baseTypeEntry); - status_t _ResolveTypeByteSize(DIEType* typeEntry, - uint64& _size); - - status_t _ResolveLocation( - const LocationDescription* description, - target_addr_t objectAddress, Type* type, - ValueLocation& _location); - template static DIEType* _GetDIEType(EntryType* entry); private: - DwarfFile* fFile; - CompilationUnit* fCompilationUnit; - DIESubprogram* fSubprogramEntry; + DwarfTypeContext* fTypeContext; GlobalTypeLookup* fTypeLookup; - GlobalTypeLookupContext* fTypeLookupContext; - target_addr_t fInstructionPointer; - target_addr_t fFramePointer; - DwarfTargetInterface* fTargetInterface; - RegisterMap* fFromDwarfRegisterMap; + GlobalTypeCache* fTypeCache; + DwarfTypeFactory* fTypeFactory; }; -#endif // DWARF_INTERFACE_FACTORY_H +#endif // DWARF_STACK_FRAME_DEBUG_INFO_H diff --git a/src/apps/debugger/debug_info/DwarfTeamDebugInfo.cpp b/src/apps/debugger/debug_info/DwarfTeamDebugInfo.cpp index 0cbdc89af9..795dd91e14 100644 --- a/src/apps/debugger/debug_info/DwarfTeamDebugInfo.cpp +++ b/src/apps/debugger/debug_info/DwarfTeamDebugInfo.cpp @@ -9,26 +9,31 @@ #include +#include "DwarfFile.h" #include "DwarfImageDebugInfo.h" #include "DwarfManager.h" +#include "GlobalTypeLookup.h" #include "LocatableFile.h" DwarfTeamDebugInfo::DwarfTeamDebugInfo(Architecture* architecture, TeamMemory* teamMemory, FileManager* fileManager, - GlobalTypeLookup* typeLookup) + GlobalTypeLookup* typeLookup, GlobalTypeCache* typeCache) : fArchitecture(architecture), fTeamMemory(teamMemory), fFileManager(fileManager), fManager(NULL), - fTypeLookup(typeLookup) + fTypeLookup(typeLookup), + fTypeCache(typeCache) { + fTypeCache->AcquireReference(); } DwarfTeamDebugInfo::~DwarfTeamDebugInfo() { + fTypeCache->ReleaseReference(); delete fManager; } @@ -60,14 +65,18 @@ DwarfTeamDebugInfo::CreateImageDebugInfo(const ImageInfo& imageInfo, // try to load the DWARF file DwarfFile* file; status_t error = fManager->LoadFile(filePath, file); - if (error == B_OK) - error = fManager->FinishLoading(); + if (error != B_OK) + return error; + Reference fileReference(file, true); + + error = fManager->FinishLoading(); if (error != B_OK) return error; // create the image debug info DwarfImageDebugInfo* debugInfo = new(std::nothrow) DwarfImageDebugInfo( - imageInfo, fArchitecture, fTeamMemory, fFileManager, fTypeLookup, file); + imageInfo, fArchitecture, fTeamMemory, fFileManager, fTypeLookup, + fTypeCache, file); if (debugInfo == NULL) return B_NO_MEMORY; diff --git a/src/apps/debugger/debug_info/DwarfTeamDebugInfo.h b/src/apps/debugger/debug_info/DwarfTeamDebugInfo.h index a8d6411cff..db855a0cde 100644 --- a/src/apps/debugger/debug_info/DwarfTeamDebugInfo.h +++ b/src/apps/debugger/debug_info/DwarfTeamDebugInfo.h @@ -12,6 +12,7 @@ class Architecture; class DwarfManager; class FileManager; class ImageInfo; +class GlobalTypeCache; class GlobalTypeLookup; class TeamMemory; @@ -21,7 +22,8 @@ public: DwarfTeamDebugInfo(Architecture* architecture, TeamMemory* teamMemory, FileManager* fileManager, - GlobalTypeLookup* typeLookup); + GlobalTypeLookup* typeLookup, + GlobalTypeCache* typeCache); virtual ~DwarfTeamDebugInfo(); status_t Init(); @@ -36,6 +38,7 @@ private: FileManager* fFileManager; DwarfManager* fManager; GlobalTypeLookup* fTypeLookup; + GlobalTypeCache* fTypeCache; }; diff --git a/src/apps/debugger/debug_info/DwarfTypeFactory.cpp b/src/apps/debugger/debug_info/DwarfTypeFactory.cpp new file mode 100644 index 0000000000..de9efb6f0c --- /dev/null +++ b/src/apps/debugger/debug_info/DwarfTypeFactory.cpp @@ -0,0 +1,1209 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + + +#include "DwarfTypeFactory.h" + +#include +#include + +#include +#include + +#include "ArrayIndexPath.h" +#include "Architecture.h" +#include "CompilationUnit.h" +#include "DebugInfoEntries.h" +#include "Dwarf.h" +#include "DwarfFile.h" +#include "DwarfTargetInterface.h" +#include "DwarfUtils.h" +#include "DwarfTypes.h" +#include "GlobalTypeLookup.h" +#include "Register.h" +#include "RegisterMap.h" +#include "SourceLanguageInfo.h" +#include "StringUtils.h" +#include "Tracing.h" +#include "ValueLocation.h" + + +namespace { + + +// #pragma mark - HasTypePredicate + + +template +struct HasTypePredicate { + inline bool operator()(EntryType* entry) const + { + return entry->GetType() != NULL; + } +}; + + +// #pragma mark - HasReturnTypePredicate + + +template +struct HasReturnTypePredicate { + inline bool operator()(EntryType* entry) const + { + return entry->ReturnType() != NULL; + } +}; + + +// #pragma mark - HasEnumeratorsPredicate + + +struct HasEnumeratorsPredicate { + inline bool operator()(DIEEnumerationType* entry) const + { + return !entry->Enumerators().IsEmpty(); + } +}; + + +// #pragma mark - HasDimensionsPredicate + + +struct HasDimensionsPredicate { + inline bool operator()(DIEArrayType* entry) const + { + return !entry->Dimensions().IsEmpty(); + } +}; + + +// #pragma mark - HasMembersPredicate + + +struct HasMembersPredicate { + inline bool operator()(DIECompoundType* entry) const + { + return !entry->DataMembers().IsEmpty(); + } +}; + + +// #pragma mark - HasBaseTypesPredicate + + +struct HasBaseTypesPredicate { + inline bool operator()(DIEClassBaseType* entry) const + { + return !entry->BaseTypes().IsEmpty(); + } +}; + + +// #pragma mark - HasParametersPredicate + + +template +struct HasParametersPredicate { + inline bool operator()(EntryType* entry) const + { + return !entry->Parameters().IsEmpty(); + } +}; + + +// #pragma mark - HasLowerBoundPredicate + + +struct HasLowerBoundPredicate { + inline bool operator()(DIESubrangeType* entry) const + { + return entry->LowerBound()->IsValid(); + } +}; + + +// #pragma mark - HasUpperBoundPredicate + + +struct HasUpperBoundPredicate { + inline bool operator()(DIESubrangeType* entry) const + { + return entry->UpperBound()->IsValid(); + } +}; + + +// #pragma mark - HasCountPredicate + + +struct HasCountPredicate { + inline bool operator()(DIESubrangeType* entry) const + { + return entry->Count()->IsValid(); + } +}; + + +// #pragma mark - HasContainingTypePredicate + + +struct HasContainingTypePredicate { + inline bool operator()(DIEPointerToMemberType* entry) const + { + return entry->ContainingType() != NULL; + } +}; + + +} // unnamed namespace + + +// #pragma mark - DwarfTypeFactory + + +DwarfTypeFactory::DwarfTypeFactory(DwarfTypeContext* typeContext, + GlobalTypeLookup* typeLookup, GlobalTypeCache* typeCache) + : + fTypeContext(typeContext), + fTypeLookup(typeLookup), + fTypeCache(typeCache) +{ + fTypeContext->AcquireReference(); + fTypeCache->AcquireReference(); +} + + +DwarfTypeFactory::~DwarfTypeFactory() +{ + fTypeContext->ReleaseReference(); + fTypeCache->ReleaseReference(); +} + + +status_t +DwarfTypeFactory::CreateType(DIEType* typeEntry, DwarfType*& _type) +{ + // try the type cache first + BString name; + DwarfUtils::GetFullyQualifiedDIEName(typeEntry, name); +// TODO: The DIE may not have a name (e.g. pointer and reference types don't). + + AutoLocker cacheLocker(fTypeCache); + Type* globalType = name.Length() > 0 + ? fTypeCache->GetType(name) : NULL; + if (globalType != NULL) { + DwarfType* globalDwarfType = dynamic_cast(globalType); + if (globalDwarfType != NULL) { + globalDwarfType->AcquireReference(); + _type = globalDwarfType; + return B_OK; + } + } + + cacheLocker.Unlock(); + + // If the type entry indicates a declaration only, we try to look the + // type up globally first. + if (typeEntry->IsDeclaration() && name.Length() > 0 + && fTypeLookup->GetType(fTypeCache, name, globalType) + == B_OK) { + DwarfType* globalDwarfType + = dynamic_cast(globalType); + if (globalDwarfType != NULL) { + _type = globalDwarfType; + return B_OK; + } + + globalType->ReleaseReference(); + } + + // No luck yet -- create the type. + DwarfType* type; + status_t error = _CreateTypeInternal(name, typeEntry, type); + if (error != B_OK) + return error; + Reference typeReference(type, true); + + // Insert the type into the cache. Re-check, as the type may already + // have been inserted (e.g. in the compound type case). + if (name.Length() > 0) { + cacheLocker.Lock(); + if (fTypeCache->GetType(name) == NULL) { + error = fTypeCache->AddType(name, type); + if (error != B_OK) + return error; + } + cacheLocker.Unlock(); + } + + // try to get the type's size + uint64 size; + if (_ResolveTypeByteSize(typeEntry, size) == B_OK) + type->SetByteSize(size); + + _type = typeReference.Detach(); + return B_OK; +} + + +status_t +DwarfTypeFactory::_CreateTypeInternal(const BString& name, + DIEType* typeEntry, DwarfType*& _type) +{ + switch (typeEntry->Tag()) { + case DW_TAG_class_type: + case DW_TAG_structure_type: + case DW_TAG_union_type: + case DW_TAG_interface_type: + return _CreateCompoundType(name, + dynamic_cast(typeEntry), _type); + + case DW_TAG_base_type: + return _CreatePrimitiveType(name, + dynamic_cast(typeEntry), _type); + + case DW_TAG_pointer_type: + return _CreateAddressType(name, + dynamic_cast(typeEntry), + DERIVED_TYPE_POINTER, _type); + case DW_TAG_reference_type: + return _CreateAddressType(name, + dynamic_cast(typeEntry), + DERIVED_TYPE_REFERENCE, _type); + + case DW_TAG_const_type: + return _CreateModifiedType(name, + dynamic_cast(typeEntry), + TYPE_MODIFIER_CONST, _type); + case DW_TAG_packed_type: + return _CreateModifiedType(name, + dynamic_cast(typeEntry), + TYPE_MODIFIER_PACKED, _type); + case DW_TAG_volatile_type: + return _CreateModifiedType(name, + dynamic_cast(typeEntry), + TYPE_MODIFIER_VOLATILE, _type); + case DW_TAG_restrict_type: + return _CreateModifiedType(name, + dynamic_cast(typeEntry), + TYPE_MODIFIER_RESTRICT, _type); + case DW_TAG_shared_type: + return _CreateModifiedType(name, + dynamic_cast(typeEntry), + TYPE_MODIFIER_SHARED, _type); + + case DW_TAG_typedef: + return _CreateTypedefType(name, + dynamic_cast(typeEntry), _type); + + case DW_TAG_array_type: + return _CreateArrayType(name, + dynamic_cast(typeEntry), _type); + + case DW_TAG_enumeration_type: + return _CreateEnumerationType(name, + dynamic_cast(typeEntry), _type); + + case DW_TAG_subrange_type: + return _CreateSubrangeType(name, + dynamic_cast(typeEntry), _type); + + case DW_TAG_unspecified_type: + return _CreateUnspecifiedType(name, + dynamic_cast(typeEntry), _type); + + case DW_TAG_subroutine_type: + return _CreateFunctionType(name, + dynamic_cast(typeEntry), _type); + + case DW_TAG_ptr_to_member_type: + return _CreatePointerToMemberType(name, + dynamic_cast(typeEntry), _type); + + case DW_TAG_string_type: + case DW_TAG_file_type: + case DW_TAG_set_type: + // TODO: Implement (not relevant for C++)! + return B_UNSUPPORTED; + } + + return B_UNSUPPORTED; +} + + +status_t +DwarfTypeFactory::_CreateCompoundType(const BString& name, + DIECompoundType* typeEntry, DwarfType*& _type) +{ + TRACE_LOCALS("DwarfTypeFactory::_CreateCompoundType(\"%s\", %p)\n", + name.String(), typeEntry); + + // create the type + DwarfCompoundType* type = new(std::nothrow) DwarfCompoundType(fTypeContext, + name, typeEntry); + if (type == NULL) + return B_NO_MEMORY; + Reference typeReference(type, true); + + // Already add the type at this pointer to the cache, since otherwise + // we could run into an infinite recursion when trying to create the types + // for the data members. +// TODO: Since access to the type lookup context is multi-threaded, the +// incomplete type could become visible to other threads. Hence we keep the +// context locked, but that essentially kills multi-threading for this context. + AutoLocker cacheLocker(fTypeCache); + status_t error = fTypeCache->AddType(name, type); + if (error != B_OK) + return error; +// cacheLocker.Unlock(); + + // find the abstract origin or specification that defines the data members + DIECompoundType* memberOwnerEntry = DwarfUtils::GetDIEByPredicate(typeEntry, + HasMembersPredicate()); + + // create the data member objects + if (memberOwnerEntry != NULL) { + for (DebugInfoEntryList::ConstIterator it + = memberOwnerEntry->DataMembers().GetIterator(); + DebugInfoEntry* _memberEntry = it.Next();) { + DIEMember* memberEntry = dynamic_cast(_memberEntry); + + TRACE_LOCALS(" member %p\n", memberEntry); + + // get the type + DwarfType* memberType; + if (CreateType(memberEntry->GetType(), memberType) != B_OK) + continue; + Reference memberTypeReference(memberType, true); + + // get the name + BString memberName; + DwarfUtils::GetDIEName(memberEntry, memberName); + + // create and add the member object + DwarfDataMember* member = new(std::nothrow) DwarfDataMember( + memberEntry, memberName, memberType); + Reference memberReference(member, true); + if (member == NULL || !type->AddDataMember(member)) { + cacheLocker.Lock(); + fTypeCache->RemoveType(name); + return B_NO_MEMORY; + } + } + } + + // If the type is a class/struct/interface type, we also need to add its + // base types. + if (DIEClassBaseType* classTypeEntry + = dynamic_cast(typeEntry)) { + // find the abstract origin or specification that defines the base types + classTypeEntry = DwarfUtils::GetDIEByPredicate(classTypeEntry, + HasBaseTypesPredicate()); + + // create the inheritance objects for the base types + if (classTypeEntry != NULL) { + for (DebugInfoEntryList::ConstIterator it + = classTypeEntry->BaseTypes().GetIterator(); + DebugInfoEntry* _inheritanceEntry = it.Next();) { + DIEInheritance* inheritanceEntry + = dynamic_cast(_inheritanceEntry); + + // get the type + DwarfType* baseType; + if (CreateType(inheritanceEntry->GetType(), baseType) != B_OK) + continue; + Reference baseTypeReference(baseType, true); + + // create and add the inheritance object + DwarfInheritance* inheritance = new(std::nothrow) + DwarfInheritance(inheritanceEntry, baseType); + Reference inheritanceReference(inheritance, + true); + if (inheritance == NULL || !type->AddInheritance(inheritance)) { + cacheLocker.Lock(); + fTypeCache->RemoveType(name); + return B_NO_MEMORY; + } + } + } + } + + _type = typeReference.Detach(); + return B_OK;; +} + + +status_t +DwarfTypeFactory::_CreatePrimitiveType(const BString& name, + DIEBaseType* typeEntry, DwarfType*& _type) +{ + const DynamicAttributeValue* byteSizeValue = typeEntry->ByteSize(); +// const DynamicAttributeValue* bitOffsetValue = typeEntry->BitOffset(); + const DynamicAttributeValue* bitSizeValue = typeEntry->BitSize(); + + uint32 bitSize = 0; + if (byteSizeValue->IsValid()) { + BVariant value; + status_t error = fTypeContext->File()->EvaluateDynamicValue( + fTypeContext->GetCompilationUnit(), fTypeContext->SubprogramEntry(), + byteSizeValue, fTypeContext->TargetInterface(), + fTypeContext->InstructionPointer(), fTypeContext->FramePointer(), + value); + if (error == B_OK && value.IsInteger()) + bitSize = value.ToUInt32() * 8; + } else if (bitSizeValue->IsValid()) { + BVariant value; + status_t error = fTypeContext->File()->EvaluateDynamicValue( + fTypeContext->GetCompilationUnit(), fTypeContext->SubprogramEntry(), + bitSizeValue, fTypeContext->TargetInterface(), + fTypeContext->InstructionPointer(), fTypeContext->FramePointer(), + value); + if (error == B_OK && value.IsInteger()) + bitSize = value.ToUInt32(); + } + + // determine type constant + uint32 typeConstant = 0; + switch (typeEntry->Encoding()) { + case DW_ATE_boolean: + typeConstant = B_BOOL_TYPE; + break; + + case DW_ATE_float: + switch (bitSize) { + case 32: + typeConstant = B_FLOAT_TYPE; + break; + case 64: + typeConstant = B_DOUBLE_TYPE; + break; + } + break; + + case DW_ATE_signed: + case DW_ATE_signed_char: + switch (bitSize) { + case 8: + typeConstant = B_INT8_TYPE; + break; + case 16: + typeConstant = B_INT16_TYPE; + break; + case 32: + typeConstant = B_INT32_TYPE; + break; + case 64: + typeConstant = B_INT64_TYPE; + break; + } + break; + + case DW_ATE_address: + case DW_ATE_unsigned: + case DW_ATE_unsigned_char: + switch (bitSize) { + case 8: + typeConstant = B_UINT8_TYPE; + break; + case 16: + typeConstant = B_UINT16_TYPE; + break; + case 32: + typeConstant = B_UINT32_TYPE; + break; + case 64: + typeConstant = B_UINT64_TYPE; + break; + } + break; + + case DW_ATE_complex_float: + case DW_ATE_imaginary_float: + case DW_ATE_packed_decimal: + case DW_ATE_numeric_string: + case DW_ATE_edited: + case DW_ATE_signed_fixed: + case DW_ATE_unsigned_fixed: + case DW_ATE_decimal_float: + default: + break; + } + + // create the type + DwarfPrimitiveType* type = new(std::nothrow) DwarfPrimitiveType( + fTypeContext, name, typeEntry, typeConstant); + if (type == NULL) + return B_NO_MEMORY; + + _type = type; + return B_OK; +} + + +status_t +DwarfTypeFactory::_CreateAddressType(const BString& name, + DIEAddressingType* typeEntry, address_type_kind addressKind, + DwarfType*& _type) +{ + // get the base type entry + DIEAddressingType* baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate( + typeEntry, HasTypePredicate()); + + // create the base type + DwarfType* baseType; + if (baseTypeOwnerEntry != NULL) { + status_t error = CreateType(baseTypeOwnerEntry->GetType(), baseType); + if (error != B_OK) + return error; + } else { + // According to the DWARF 3 specs a modified type *has* a base type. + // GCC 4 doesn't (always?) bother to add one for "void". + // TODO: We should probably search for a respective type by name. ATM + // we just create a DwarfUnspecifiedType without DIE. + TRACE_LOCALS("no base type for address type entry -- creating " + "unspecified type\n"); + baseType = new(std::nothrow) DwarfUnspecifiedType(fTypeContext, "void", + NULL); + if (baseType == NULL) + return B_NO_MEMORY; + } + Reference baseTypeReference(baseType, true); + + DwarfAddressType* type = new(std::nothrow) DwarfAddressType(fTypeContext, + name, typeEntry, addressKind, baseType); + if (type == NULL) + return B_NO_MEMORY; + + _type = type; + return B_OK; +} + + +status_t +DwarfTypeFactory::_CreateModifiedType(const BString& name, + DIEModifiedType* typeEntry, uint32 modifiers, DwarfType*& _type) +{ + // Get the base type entry. If it is a modified type too or a typedef, + // collect all modifiers and iterate until hitting an actual base type. + DIEType* baseTypeEntry; + while (true) { + DIEModifiedType* baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate( + typeEntry, HasTypePredicate()); + if (baseTypeOwnerEntry == NULL) + return B_BAD_VALUE; + + baseTypeEntry = baseTypeOwnerEntry->GetType(); + + // resolve a typedef + if (baseTypeEntry->Tag() == DW_TAG_typedef) { + status_t error = _ResolveTypedef( + dynamic_cast(baseTypeEntry), baseTypeEntry); + if (error != B_OK) + return error; + } + + if (baseTypeEntry == NULL) + return B_BAD_VALUE; + + // If the base type is a modified type, too, resolve it. + switch (baseTypeEntry->Tag()) { + case DW_TAG_const_type: + modifiers |= TYPE_MODIFIER_CONST; + baseTypeOwnerEntry + = dynamic_cast(baseTypeEntry); + continue; + case DW_TAG_packed_type: + modifiers |= TYPE_MODIFIER_PACKED; + baseTypeOwnerEntry + = dynamic_cast(baseTypeEntry); + continue; + case DW_TAG_volatile_type: + modifiers |= TYPE_MODIFIER_VOLATILE; + baseTypeOwnerEntry + = dynamic_cast(baseTypeEntry); + continue; + case DW_TAG_restrict_type: + modifiers |= TYPE_MODIFIER_RESTRICT; + baseTypeOwnerEntry + = dynamic_cast(baseTypeEntry); + continue; + case DW_TAG_shared_type: + modifiers |= TYPE_MODIFIER_SHARED; + baseTypeOwnerEntry + = dynamic_cast(baseTypeEntry); + continue; + + default: + break; + } + + // If we get here, we've found an actual base type. + break; + } + + // create the base type + DwarfType* baseType; + status_t error = CreateType(baseTypeEntry, baseType); + if (error != B_OK) + return error; + Reference baseTypeReference(baseType, true); + + DwarfModifiedType* type = new(std::nothrow) DwarfModifiedType(fTypeContext, + name, typeEntry, modifiers, baseType); + if (type == NULL) + return B_NO_MEMORY; + + _type = type; + return B_OK; +} + + +status_t +DwarfTypeFactory::_CreateTypedefType(const BString& name, + DIETypedef* typeEntry, DwarfType*& _type) +{ + // resolve the base type + DIEType* baseTypeEntry; + status_t error = _ResolveTypedef(typeEntry, baseTypeEntry); + if (error != B_OK) + return error; + + // create the base type + DwarfType* baseType; + error = CreateType(baseTypeEntry, baseType); + if (error != B_OK) + return error; + Reference baseTypeReference(baseType, true); + + DwarfTypedefType* type = new(std::nothrow) DwarfTypedefType(fTypeContext, + name, typeEntry, baseType); + if (type == NULL) + return B_NO_MEMORY; + + _type = type; + return B_OK; +} + + +status_t +DwarfTypeFactory::_CreateArrayType(const BString& name, + DIEArrayType* typeEntry, DwarfType*& _type) +{ + TRACE_LOCALS("DwarfTypeFactory::_CreateArrayType(\"%s\", %p)\n", + name.String(), typeEntry); + + // create the base type + DIEArrayType* baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate( + typeEntry, HasTypePredicate()); + if (baseTypeOwnerEntry == NULL) { + WARNING("Failed to get base type for array type \"%s\"\n", + name.String()); + return B_BAD_VALUE; + } + + DwarfType* baseType = NULL; + status_t error = CreateType(baseTypeOwnerEntry->GetType(), baseType); + if (error != B_OK) { + WARNING("Failed to create base type for array type \"%s\": %s\n", + name.String(), strerror(error)); + return error; + } + Reference baseTypeReference(baseType, true); + + // create the array type + DwarfArrayType* type = new(std::nothrow) DwarfArrayType(fTypeContext, name, + typeEntry, baseType); + if (type == NULL) + return B_NO_MEMORY; + Reference typeReference(type, true); + + // add the array dimensions + DIEArrayType* dimensionOwnerEntry = DwarfUtils::GetDIEByPredicate( + typeEntry, HasDimensionsPredicate()); + + if (dimensionOwnerEntry == NULL) { + WARNING("Failed to get dimensions for array type \"%s\"\n", + name.String()); + return B_BAD_VALUE; + } + + for (DebugInfoEntryList::ConstIterator it + = dimensionOwnerEntry->Dimensions().GetIterator(); + DebugInfoEntry* _dimensionEntry = it.Next();) { + DIEType* dimensionEntry = dynamic_cast(_dimensionEntry); + + // get/create the dimension type + DwarfType* dimensionType = NULL; + status_t error = CreateType(dimensionEntry, dimensionType); + if (error != B_OK) { + WARNING("Failed to create type for array dimension: %s\n", + strerror(error)); + return error; + } + Reference dimensionTypeReference(dimensionType, true); + + // create and add the array dimension object + DwarfArrayDimension* dimension + = new(std::nothrow) DwarfArrayDimension(dimensionType); + Reference dimensionReference(dimension, true); + if (dimension == NULL || !type->AddDimension(dimension)) + return B_NO_MEMORY; + } + + _type = typeReference.Detach(); + return B_OK; +} + + +status_t +DwarfTypeFactory::_CreateEnumerationType(const BString& name, + DIEEnumerationType* typeEntry, DwarfType*& _type) +{ + // create the base type (it's optional) + DIEEnumerationType* baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate( + typeEntry, HasTypePredicate()); + + DwarfType* baseType = NULL; + if (baseTypeOwnerEntry != NULL) { + status_t error = CreateType(baseTypeOwnerEntry->GetType(), baseType); + if (error != B_OK) + return error; + } + Reference baseTypeReference(baseType, true); + + // create the enumeration type + DwarfEnumerationType* type = new(std::nothrow) DwarfEnumerationType( + fTypeContext, name, typeEntry, baseType); + if (type == NULL) + return B_NO_MEMORY; + Reference typeReference(type, true); + + // get the enumeration values + DIEEnumerationType* enumeratorOwnerEntry = DwarfUtils::GetDIEByPredicate( + typeEntry, HasEnumeratorsPredicate()); + + if (enumeratorOwnerEntry != NULL) { + for (DebugInfoEntryList::ConstIterator it + = enumeratorOwnerEntry->Enumerators().GetIterator(); + DebugInfoEntry* _enumeratorEntry = it.Next();) { + DIEEnumerator* enumeratorEntry = dynamic_cast( + _enumeratorEntry); + + // evaluate the value + BVariant value; + status_t error = fTypeContext->File()->EvaluateConstantValue( + fTypeContext->GetCompilationUnit(), + fTypeContext->SubprogramEntry(), enumeratorEntry->ConstValue(), + fTypeContext->TargetInterface(), + fTypeContext->InstructionPointer(), + fTypeContext->FramePointer(), value); + if (error != B_OK) { + // The value is probably not stored -- just ignore the + // enumerator. + TRACE_LOCALS("Failed to get value for enum type value %s::%s\n", + name.String(), enumeratorEntry->Name()); + continue; + } + + // create and add the enumeration value object + DwarfEnumerationValue* enumValue + = new(std::nothrow) DwarfEnumerationValue(enumeratorEntry, + enumeratorEntry->Name(), value); + Reference enumValueReference(enumValue, true); + if (enumValue == NULL || !type->AddValue(enumValue)) + return B_NO_MEMORY; + } + } + + _type = typeReference.Detach(); + return B_OK; +} + + +status_t +DwarfTypeFactory::_CreateSubrangeType(const BString& name, + DIESubrangeType* typeEntry, DwarfType*& _type) +{ + // get the base type + DIESubrangeType* baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate( + typeEntry, HasTypePredicate()); + DIEType* baseTypeEntry = baseTypeOwnerEntry != NULL + ? baseTypeOwnerEntry->GetType() : NULL; + + // get the lower bound + BVariant lowerBound; + DIESubrangeType* lowerBoundOwnerEntry = DwarfUtils::GetDIEByPredicate( + typeEntry, HasLowerBoundPredicate()); + if (lowerBoundOwnerEntry != NULL) { + // evaluate it + DIEType* valueType; + status_t error = fTypeContext->File()->EvaluateDynamicValue( + fTypeContext->GetCompilationUnit(), fTypeContext->SubprogramEntry(), + lowerBoundOwnerEntry->LowerBound(), fTypeContext->TargetInterface(), + fTypeContext->InstructionPointer(), fTypeContext->FramePointer(), + lowerBound, &valueType); + if (error != B_OK) { + WARNING(" failed to evaluate lower bound: %s\n", strerror(error)); + return error; + } + + // If we don't have a base type yet, and the lower bound attribute + // refers to an object, the type of that object is our base type. + if (baseTypeEntry == NULL) + baseTypeEntry = valueType; + } else { + // that's ok -- use the language default + lowerBound.SetTo(fTypeContext->GetCompilationUnit()->SourceLanguage() + ->subrangeLowerBound); + } + + // get the upper bound + BVariant upperBound; + DIESubrangeType* upperBoundOwnerEntry = DwarfUtils::GetDIEByPredicate( + typeEntry, HasUpperBoundPredicate()); + if (upperBoundOwnerEntry != NULL) { + // evaluate it + DIEType* valueType; + status_t error = fTypeContext->File()->EvaluateDynamicValue( + fTypeContext->GetCompilationUnit(), fTypeContext->SubprogramEntry(), + upperBoundOwnerEntry->UpperBound(), fTypeContext->TargetInterface(), + fTypeContext->InstructionPointer(), fTypeContext->FramePointer(), + upperBound, &valueType); + if (error != B_OK) { + WARNING(" failed to evaluate upper bound: %s\n", strerror(error)); + return error; + } + + // If we don't have a base type yet, and the upper bound attribute + // refers to an object, the type of that object is our base type. + if (baseTypeEntry == NULL) + baseTypeEntry = valueType; + } else { + // get the count instead + DIESubrangeType* countOwnerEntry = DwarfUtils::GetDIEByPredicate( + typeEntry, HasCountPredicate()); + if (countOwnerEntry != NULL) { + // evaluate it + BVariant count; + DIEType* valueType; + status_t error = fTypeContext->File()->EvaluateDynamicValue( + fTypeContext->GetCompilationUnit(), + fTypeContext->SubprogramEntry(), countOwnerEntry->Count(), + fTypeContext->TargetInterface(), + fTypeContext->InstructionPointer(), fTypeContext->FramePointer(), + count, &valueType); + if (error != B_OK) { + WARNING(" failed to evaluate count: %s\n", strerror(error)); + return error; + } + + // If we don't have a base type yet, and the count attribute refers + // to an object, the type of that object is our base type. + if (baseTypeEntry == NULL) + baseTypeEntry = valueType; + + // we only support integers + bool isSigned; + if (!lowerBound.IsInteger(&isSigned) || !count.IsInteger()) { + WARNING(" count given for subrange type, but lower bound or " + "count is not integer\n"); + return B_BAD_VALUE; + } + + if (isSigned) + upperBound.SetTo(lowerBound.ToInt64() + count.ToInt64() - 1); + else + upperBound.SetTo(lowerBound.ToUInt64() + count.ToUInt64() - 1); + } + } + + // If we still don't have a base type yet, the base type is supposed to be + // the a signed integer type with the same size as an address for that + // compilation unit. + if (baseTypeEntry == NULL) { + // TODO: Implement! + WARNING("Base type fallback for subrange type not implemented yet!\n"); + return B_UNSUPPORTED; + } + + // create the base type + DwarfType* baseType; + status_t error = CreateType(baseTypeEntry, baseType); + if (error != B_OK) + return error; + Reference baseTypeReference(baseType, true); + + // TODO: Support the thread scaling attribute! + + // create the type + DwarfSubrangeType* type = new(std::nothrow) DwarfSubrangeType(fTypeContext, + name, typeEntry, baseType, lowerBound, upperBound); + if (type == NULL) + return B_NO_MEMORY; + + _type = type; + return B_OK; +} + + +status_t +DwarfTypeFactory::_CreateUnspecifiedType(const BString& name, + DIEUnspecifiedType* typeEntry, DwarfType*& _type) +{ + DwarfUnspecifiedType* type = new(std::nothrow) DwarfUnspecifiedType( + fTypeContext, name, typeEntry); + if (type == NULL) + return B_NO_MEMORY; + + _type = type; + return B_OK; +} + +status_t +DwarfTypeFactory::_CreateFunctionType(const BString& name, + DIESubroutineType* typeEntry, DwarfType*& _type) +{ + // get the return type + DIESubroutineType* returnTypeOwnerEntry = DwarfUtils::GetDIEByPredicate( + typeEntry, HasReturnTypePredicate()); + + // create the base type + DwarfType* returnType = NULL; + if (returnTypeOwnerEntry != NULL) { + status_t error = CreateType(returnTypeOwnerEntry->ReturnType(), + returnType); + if (error != B_OK) + return error; + } + Reference returnTypeReference(returnType, true); + + DwarfFunctionType* type = new(std::nothrow) DwarfFunctionType(fTypeContext, + name, typeEntry, returnType); + if (type == NULL) + return B_NO_MEMORY; + Reference typeReference(type, true); + + // get the parameters + DIESubroutineType* parameterOwnerEntry = DwarfUtils::GetDIEByPredicate( + typeEntry, HasParametersPredicate()); + + if (parameterOwnerEntry != NULL) { + for (DebugInfoEntryList::ConstIterator it + = parameterOwnerEntry->Parameters().GetIterator(); + DebugInfoEntry* _parameterEntry = it.Next();) { + if (_parameterEntry->Tag() == DW_TAG_unspecified_parameters) { + type->SetHasVariableArguments(true); + continue; + } + + DIEFormalParameter* parameterEntry + = dynamic_cast(_parameterEntry); + + // get the type + DIEFormalParameter* typeOwnerEntry = DwarfUtils::GetDIEByPredicate( + parameterEntry, HasTypePredicate()); + if (typeOwnerEntry == NULL) + return B_BAD_VALUE; + + DwarfType* parameterType; + status_t error = CreateType(typeOwnerEntry->GetType(), + parameterType); + if (error != B_OK) + return error; + Reference parameterTypeReference(parameterType, true); + + // get the name + BString parameterName; + DwarfUtils::GetDIEName(parameterEntry, parameterName); + + // create and add the parameter object + DwarfFunctionParameter* parameter + = new(std::nothrow) DwarfFunctionParameter(parameterEntry, + parameterName, parameterType); + Reference parameterReference(parameter, + true); + if (parameter == NULL || !type->AddParameter(parameter)) + return B_NO_MEMORY; + } + } + + + _type = typeReference.Detach(); + return B_OK; +} + + +status_t +DwarfTypeFactory::_CreatePointerToMemberType(const BString& name, + DIEPointerToMemberType* typeEntry, DwarfType*& _type) +{ + // get the containing and base type entries + DIEPointerToMemberType* containingTypeOwnerEntry + = DwarfUtils::GetDIEByPredicate(typeEntry, + HasContainingTypePredicate()); + DIEPointerToMemberType* baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate( + typeEntry, HasTypePredicate()); + + if (containingTypeOwnerEntry == NULL || baseTypeOwnerEntry == NULL) { + WARNING("Failed to get containing or base type for pointer to member " + "type \"%s\"\n", name.String()); + return B_BAD_VALUE; + } + + // create the containing type + DwarfType* containingType; + status_t error = CreateType(containingTypeOwnerEntry->ContainingType(), + containingType); + if (error != B_OK) + return error; + Reference containingTypeReference(containingType, true); + + DwarfCompoundType* compoundContainingType + = dynamic_cast(containingType); + if (compoundContainingType == NULL) { + WARNING("Containing type for pointer to member type \"%s\" is not a " + "compound type.\n", name.String()); + return B_BAD_VALUE; + } + + // create the base type + DwarfType* baseType; + error = CreateType(baseTypeOwnerEntry->GetType(), baseType); + if (error != B_OK) + return error; + Reference baseTypeReference(baseType, true); + + // create the type object + DwarfPointerToMemberType* type = new(std::nothrow) DwarfPointerToMemberType( + fTypeContext, name, typeEntry, compoundContainingType, baseType); + if (type == NULL) + return B_NO_MEMORY; + + _type = type; + return B_OK; +} + + +status_t +DwarfTypeFactory::_ResolveTypedef(DIETypedef* entry, + DIEType*& _baseTypeEntry) +{ + while (true) { + // resolve the base type, possibly following abstract origin or + // specification + DIETypedef* baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate( + entry, HasTypePredicate()); + if (baseTypeOwnerEntry == NULL) + return B_BAD_VALUE; + + DIEType* baseTypeEntry = baseTypeOwnerEntry->GetType(); + if (baseTypeEntry->Tag() != DW_TAG_typedef) { + _baseTypeEntry = baseTypeEntry; + return B_OK; + } + + entry = dynamic_cast(baseTypeEntry); + } +} + + +status_t +DwarfTypeFactory::_ResolveTypeByteSize(DIEType* typeEntry, + uint64& _size) +{ + TRACE_LOCALS("DwarfTypeFactory::_ResolveTypeByteSize(%p)\n", + typeEntry); + + // get the size attribute + const DynamicAttributeValue* sizeValue; + + while (true) { + // resolve a typedef + if (typeEntry->Tag() == DW_TAG_typedef) { + TRACE_LOCALS(" resolving typedef...\n"); + + status_t error = _ResolveTypedef( + dynamic_cast(typeEntry), typeEntry); + if (error != B_OK) + return error; + } + + sizeValue = typeEntry->ByteSize(); + if (sizeValue != NULL && sizeValue->IsValid()) + break; + + // resolve abstract origin + if (DIEType* abstractOrigin = dynamic_cast( + typeEntry->AbstractOrigin())) { + TRACE_LOCALS(" resolving abstract origin (%p)...\n", + abstractOrigin); + + typeEntry = abstractOrigin; + sizeValue = typeEntry->ByteSize(); + if (sizeValue != NULL && sizeValue->IsValid()) + break; + } + + // resolve specification + if (DIEType* specification = dynamic_cast( + typeEntry->Specification())) { + TRACE_LOCALS(" resolving specification (%p)...\n", specification); + + typeEntry = specification; + sizeValue = typeEntry->ByteSize(); + if (sizeValue != NULL && sizeValue->IsValid()) + break; + } + + // For some types we have a special handling. For modified types we + // follow the base type, for address types we know the size anyway. + TRACE_LOCALS(" nothing yet, special type handling\n"); + + switch (typeEntry->Tag()) { + case DW_TAG_const_type: + case DW_TAG_packed_type: + case DW_TAG_volatile_type: + case DW_TAG_restrict_type: + case DW_TAG_shared_type: + typeEntry = dynamic_cast(typeEntry) + ->GetType(); + + TRACE_LOCALS(" following modified type -> %p\n", typeEntry); + + if (typeEntry == NULL) + return B_ENTRY_NOT_FOUND; + break; + case DW_TAG_pointer_type: + case DW_TAG_reference_type: + case DW_TAG_ptr_to_member_type: + _size = fTypeContext->GetCompilationUnit()->AddressSize(); + + TRACE_LOCALS(" pointer/reference type: size: %llu\n", _size); + + return B_OK; + default: + return B_ENTRY_NOT_FOUND; + } + } + + TRACE_LOCALS(" found attribute\n"); + + // get the actual value + BVariant size; + status_t error = fTypeContext->File()->EvaluateDynamicValue( + fTypeContext->GetCompilationUnit(), fTypeContext->SubprogramEntry(), + sizeValue, fTypeContext->TargetInterface(), + fTypeContext->InstructionPointer(), fTypeContext->FramePointer(), size); + if (error != B_OK) { + TRACE_LOCALS(" failed to resolve attribute: %s\n", strerror(error)); + return error; + } + + _size = size.ToUInt64(); + + TRACE_LOCALS(" -> size: %llu\n", _size); + + return B_OK; +} diff --git a/src/apps/debugger/debug_info/DwarfTypeFactory.h b/src/apps/debugger/debug_info/DwarfTypeFactory.h new file mode 100644 index 0000000000..d9b3c1c341 --- /dev/null +++ b/src/apps/debugger/debug_info/DwarfTypeFactory.h @@ -0,0 +1,117 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef DWARF_TYPE_FACTORY_H +#define DWARF_TYPE_FACTORY_H + + +#include + +#include "Type.h" + + +class CompilationUnit; +class DIEAddressingType; +class DIEArrayType; +class DIEBaseType; +class DIECompoundType; +class DIEEnumerationType; +class DIEFormalParameter; +class DIEModifiedType; +class DIEPointerToMemberType; +class DIESubprogram; +class DIESubrangeType; +class DIESubroutineType; +class DIEType; +class DIETypedef; +class DIEUnspecifiedType; +class DwarfAddressType; +class DwarfArrayDimension; +class DwarfArrayType; +class DwarfCompoundType; +class DwarfDataMember; +class DwarfEnumerationType; +class DwarfEnumerationValue; +class DwarfFile; +class DwarfFunctionParameter; +class DwarfFunctionType; +class DwarfInheritance; +class DwarfModifiedType; +class DwarfPointerToMemberType; +class DwarfPrimitiveType; +class DwarfSubrangeType; +class DwarfTargetInterface; +class DwarfType; +class DwarfTypeContext; +class DwarfTypedefType; +class DwarfUnspecifiedType; +class GlobalTypeCache; +class GlobalTypeLookup; +class LocationDescription; +class MemberLocation; +class RegisterMap; + + +class DwarfTypeFactory { +public: + DwarfTypeFactory(DwarfTypeContext* typeContext, + GlobalTypeLookup* typeLookup, + GlobalTypeCache* typeCache); + ~DwarfTypeFactory(); + + status_t CreateType(DIEType* typeEntry, + DwarfType*& _type); + // returns reference + +private: + status_t _CreateTypeInternal(const BString& name, + DIEType* typeEntry, DwarfType*& _type); + + status_t _CreateCompoundType(const BString& name, + DIECompoundType* typeEntry, + DwarfType*& _type); + status_t _CreatePrimitiveType(const BString& name, + DIEBaseType* typeEntry, + DwarfType*& _type); + status_t _CreateAddressType(const BString& name, + DIEAddressingType* typeEntry, + address_type_kind addressKind, + DwarfType*& _type); + status_t _CreateModifiedType(const BString& name, + DIEModifiedType* typeEntry, + uint32 modifiers, DwarfType*& _type); + status_t _CreateTypedefType(const BString& name, + DIETypedef* typeEntry, DwarfType*& _type); + status_t _CreateArrayType(const BString& name, + DIEArrayType* typeEntry, + DwarfType*& _type); + status_t _CreateEnumerationType(const BString& name, + DIEEnumerationType* typeEntry, + DwarfType*& _type); + status_t _CreateSubrangeType(const BString& name, + DIESubrangeType* typeEntry, + DwarfType*& _type); + status_t _CreateUnspecifiedType(const BString& name, + DIEUnspecifiedType* typeEntry, + DwarfType*& _type); + status_t _CreateFunctionType(const BString& name, + DIESubroutineType* typeEntry, + DwarfType*& _type); + status_t _CreatePointerToMemberType(const BString& name, + DIEPointerToMemberType* typeEntry, + DwarfType*& _type); + + status_t _ResolveTypedef(DIETypedef* entry, + DIEType*& _baseTypeEntry); + status_t _ResolveTypeByteSize(DIEType* typeEntry, + uint64& _size); + +private: + DwarfTypeContext* fTypeContext; + GlobalTypeLookup* fTypeLookup; + GlobalTypeCache* fTypeCache; +}; + + +#endif // DWARF_TYPE_FACTORY_H diff --git a/src/apps/debugger/debug_info/DwarfTypes.cpp b/src/apps/debugger/debug_info/DwarfTypes.cpp new file mode 100644 index 0000000000..9cfc0ae0e5 --- /dev/null +++ b/src/apps/debugger/debug_info/DwarfTypes.cpp @@ -0,0 +1,1287 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + + +#include "DwarfTypes.h" + +#include + +#include "Architecture.h" +#include "ArrayIndexPath.h" +#include "Dwarf.h" +#include "DwarfFile.h" +#include "DwarfTargetInterface.h" +#include "DwarfUtils.h" +#include "Register.h" +#include "RegisterMap.h" +#include "Tracing.h" +#include "ValueLocation.h" + + +namespace { + + +// #pragma mark - HasBitStridePredicate + + +template +struct HasBitStridePredicate { + inline bool operator()(EntryType* entry) const + { + return entry->BitStride()->IsValid(); + } +}; + + +// #pragma mark - HasByteStridePredicate + + +template +struct HasByteStridePredicate { + inline bool operator()(EntryType* entry) const + { + return entry->ByteStride()->IsValid(); + } +}; + + +} // unnamed namespace + + +// #pragma mark - DwarfTypeContext + + +DwarfTypeContext::DwarfTypeContext(Architecture* architecture, image_id imageID, + DwarfFile* file, CompilationUnit* compilationUnit, + DIESubprogram* subprogramEntry, target_addr_t instructionPointer, + target_addr_t framePointer, DwarfTargetInterface* targetInterface, + RegisterMap* fromDwarfRegisterMap) + : + fArchitecture(architecture), + fImageID(imageID), + fFile(file), + fCompilationUnit(compilationUnit), + fSubprogramEntry(subprogramEntry), + fInstructionPointer(instructionPointer), + fFramePointer(framePointer), + fTargetInterface(targetInterface), + fFromDwarfRegisterMap(fromDwarfRegisterMap) +{ + fArchitecture->AcquireReference(); + fFile->AcquireReference(); + fTargetInterface->AcquireReference(); +} + + +DwarfTypeContext::~DwarfTypeContext() +{ + fArchitecture->ReleaseReference(); + fFile->ReleaseReference(); +} + + +// #pragma mark - DwarfType + + +DwarfType::DwarfType(DwarfTypeContext* typeContext, const BString& name) + : + fTypeContext(typeContext), + fName(name), + fByteSize(0) +{ + fTypeContext->AcquireReference(); +} + + +DwarfType::~DwarfType() +{ + fTypeContext->ReleaseReference(); +} + + +image_id +DwarfType::ImageID() const +{ + return fTypeContext->ImageID(); +} + + +const char* +DwarfType::Name() const +{ + return fName.Length() > 0 ? fName.String() : NULL; +} + + +target_size_t +DwarfType::ByteSize() const +{ + return fByteSize; +} + + +status_t +DwarfType::ResolveObjectDataLocation(const ValueLocation& objectLocation, + ValueLocation*& _location) +{ + // TODO: In some source languages the object address might be a pointer + // to a descriptor, not the actual object data. + + // If the given location looks good already, just clone it. + int32 count = objectLocation.CountPieces(); + if (count == 0) + return B_BAD_VALUE; + + ValuePieceLocation piece = objectLocation.PieceAt(0); + if (count > 1 || piece.type != VALUE_PIECE_LOCATION_MEMORY + || piece.size != 0 || piece.bitSize != 0) { + ValueLocation* location + = new(std::nothrow) ValueLocation(objectLocation); + if (location == NULL || location->CountPieces() != count) { + delete location; + return B_NO_MEMORY; + } + + _location = location; + return B_OK; + } + + // The location contains just a single address piece with a zero size + // -- set the type's size. + piece.SetSize(ByteSize()); + // TODO: Use bit size and bit offset, if specified! + + ValueLocation* location = new(std::nothrow) ValueLocation( + objectLocation.IsBigEndian()); + if (location == NULL || !location->AddPiece(piece)) { + delete location; + return B_NO_MEMORY; + } + + _location = location; + return B_OK; +} + + +status_t +DwarfType::ResolveObjectDataLocation(target_addr_t objectAddress, + ValueLocation*& _location) +{ + ValuePieceLocation piece; + piece.SetToMemory(objectAddress); + piece.SetSize(0); + // We set the piece size to 0 as an indicator that the size has to be + // set. + // TODO: We could set the byte size from type, but that may not be + // accurate. We may want to add bit offset and size to Type. + + ValueLocation location(fTypeContext->GetArchitecture()->IsBigEndian()); + if (!location.AddPiece(piece)) + return B_NO_MEMORY; + + return ResolveObjectDataLocation(location, _location); +} + + +status_t +DwarfType::ResolveLocation(DwarfTypeContext* typeContext, + const LocationDescription* description, target_addr_t objectAddress, + ValueLocation& _location) +{ + status_t error = typeContext->File()->ResolveLocation( + typeContext->GetCompilationUnit(), typeContext->SubprogramEntry(), + description, typeContext->TargetInterface(), + typeContext->InstructionPointer(), objectAddress, + typeContext->FramePointer(), _location); + if (error != B_OK) + return error; + + // translate the DWARF register indices and the bit offset/size semantics + const Register* registers = typeContext->GetArchitecture()->Registers(); + bool bigEndian = typeContext->GetArchitecture()->IsBigEndian(); + int32 count = _location.CountPieces(); + for (int32 i = 0; i < count; i++) { + ValuePieceLocation piece = _location.PieceAt(i); + if (piece.type == VALUE_PIECE_LOCATION_REGISTER) { + int32 reg = typeContext->FromDwarfRegisterMap()->MapRegisterIndex( + piece.reg); + if (reg >= 0) { + piece.reg = reg; + // The bit offset for registers is to the least + // significant bit, while we want the offset to the most + // significant bit. + if (registers[reg].BitSize() > piece.bitSize) { + piece.bitOffset = registers[reg].BitSize() - piece.bitSize + - piece.bitOffset; + } + } else + piece.SetToUnknown(); + } else if (piece.type == VALUE_PIECE_LOCATION_MEMORY) { + // Whether the bit offset is to the least or most significant bit + // is target architecture and source language specific. + // TODO: Check whether this is correct! + // TODO: Source language! + if (!bigEndian && piece.size * 8 > piece.bitSize) { + piece.bitOffset = piece.size * 8 - piece.bitSize + - piece.bitOffset; + } + } + + piece.Normalize(bigEndian); + _location.SetPieceAt(i, piece); + } + + // If we only have one piece and that doesn't have a size, try to retrieve + // the size of the type. + if (count == 1) { + ValuePieceLocation piece = _location.PieceAt(0); + if (piece.IsValid() && piece.size == 0 && piece.bitSize == 0) { + piece.SetSize(ByteSize()); + // TODO: Use bit size and bit offset, if specified! + _location.SetPieceAt(0, piece); + + TRACE_LOCALS(" set single piece size to %llu\n", ByteSize()); + } + } + + return B_OK; +} + + +// #pragma mark - DwarfInheritance + + +DwarfInheritance::DwarfInheritance(DIEInheritance* entry, DwarfType* type) + : + fEntry(entry), + fType(type) +{ + fType->AcquireReference(); +} + + +DwarfInheritance::~DwarfInheritance() +{ + fType->ReleaseReference(); +} + + +Type* +DwarfInheritance::GetType() const +{ + return fType; +} + + +// #pragma mark - DwarfDataMember + + +DwarfDataMember::DwarfDataMember(DIEMember* entry, const BString& name, + DwarfType* type) + : + fEntry(entry), + fName(name), + fType(type) +{ + fType->AcquireReference(); +} + + +DwarfDataMember::~DwarfDataMember() +{ + fType->ReleaseReference(); +} + +const char* +DwarfDataMember::Name() const +{ + return fName.Length() > 0 ? fName.String() : NULL; +} + + +Type* +DwarfDataMember::GetType() const +{ + return fType; +} + + +// #pragma mark - DwarfEnumerationValue + + +DwarfEnumerationValue::DwarfEnumerationValue(DIEEnumerator* entry, + const BString& name, const BVariant& value) + : + fEntry(entry), + fName(name), + fValue(value) +{ +} + + +DwarfEnumerationValue::~DwarfEnumerationValue() +{ +} + +const char* +DwarfEnumerationValue::Name() const +{ + return fName.Length() > 0 ? fName.String() : NULL; +} + + +BVariant +DwarfEnumerationValue::Value() const +{ + return fValue; +} + + +// #pragma mark - DwarfArrayDimension + + +DwarfArrayDimension::DwarfArrayDimension(DwarfType* type) + : + fType(type) +{ + fType->AcquireReference(); +} + + +DwarfArrayDimension::~DwarfArrayDimension() +{ + fType->ReleaseReference(); +} + + +Type* +DwarfArrayDimension::GetType() const +{ + return fType; +} + + +// #pragma mark - DwarfFunctionParameter + + +DwarfFunctionParameter::DwarfFunctionParameter(DIEFormalParameter* entry, + const BString& name, DwarfType* type) + : + fEntry(entry), + fName(name), + fType(type) +{ + fType->AcquireReference(); +} + + +DwarfFunctionParameter::~DwarfFunctionParameter() +{ + fType->ReleaseReference(); +} + + +const char* +DwarfFunctionParameter::Name() const +{ + return fName.Length() > 0 ? fName.String() : NULL; +} + + +Type* +DwarfFunctionParameter::GetType() const +{ + return fType; +} + + +// #pragma mark - DwarfPrimitiveType + + +DwarfPrimitiveType::DwarfPrimitiveType(DwarfTypeContext* typeContext, + const BString& name, DIEBaseType* entry, uint32 typeConstant) + : + DwarfType(typeContext, name), + fEntry(entry), + fTypeConstant(typeConstant) +{ +} + + +DIEType* +DwarfPrimitiveType::GetDIEType() const +{ + return fEntry; +} + + +uint32 +DwarfPrimitiveType::TypeConstant() const +{ + return fTypeConstant; +} + + +// #pragma mark - DwarfCompoundType + + +DwarfCompoundType::DwarfCompoundType(DwarfTypeContext* typeContext, + const BString& name, DIECompoundType* entry) + : + DwarfType(typeContext, name), + fEntry(entry) +{ +} + + +DwarfCompoundType::~DwarfCompoundType() +{ + for (int32 i = 0; + DwarfInheritance* inheritance = fInheritances.ItemAt(i); i++) { + inheritance->ReleaseReference(); + } + for (int32 i = 0; DwarfDataMember* member = fDataMembers.ItemAt(i); i++) + member->ReleaseReference(); +} + + +int32 +DwarfCompoundType::CountBaseTypes() const +{ + return fInheritances.CountItems(); +} + + +BaseType* +DwarfCompoundType::BaseTypeAt(int32 index) const +{ + return fInheritances.ItemAt(index); +} + + +int32 +DwarfCompoundType::CountDataMembers() const +{ + return fDataMembers.CountItems(); +} + + +DataMember* +DwarfCompoundType::DataMemberAt(int32 index) const +{ + return fDataMembers.ItemAt(index); +} + + +status_t +DwarfCompoundType::ResolveBaseTypeLocation(BaseType* _baseType, + const ValueLocation& parentLocation, ValueLocation*& _location) +{ + DwarfInheritance* baseType = dynamic_cast(_baseType); + if (baseType == NULL) + return B_BAD_VALUE; + + return _ResolveDataMemberLocation(baseType->GetDwarfType(), + baseType->Entry()->Location(), parentLocation, _location); +} + + +status_t +DwarfCompoundType::ResolveDataMemberLocation(DataMember* _member, + const ValueLocation& parentLocation, ValueLocation*& _location) +{ + DwarfDataMember* member = dynamic_cast(_member); + if (member == NULL) + return B_BAD_VALUE; + DwarfTypeContext* typeContext = TypeContext(); + + ValueLocation* location; + status_t error = _ResolveDataMemberLocation(member->GetDwarfType(), + member->Entry()->Location(), parentLocation, location); + if (error != B_OK) + return error; + + // If the member isn't a bit field, we're done. + DIEMember* memberEntry = member->Entry(); + if (!memberEntry->ByteSize()->IsValid() + && !memberEntry->BitOffset()->IsValid() + && !memberEntry->BitSize()->IsValid()) { + _location = location; + return B_OK; + } + + Reference locationReference(location); + + // get the byte size + target_addr_t byteSize; + if (memberEntry->ByteSize()->IsValid()) { + BVariant value; + error = typeContext->File()->EvaluateDynamicValue( + typeContext->GetCompilationUnit(), typeContext->SubprogramEntry(), + memberEntry->ByteSize(), typeContext->TargetInterface(), + typeContext->InstructionPointer(), typeContext->FramePointer(), + value); + if (error != B_OK) + return error; + byteSize = value.ToUInt64(); + } else + byteSize = ByteSize(); + + // get the bit offset + uint64 bitOffset = 0; + if (memberEntry->BitOffset()->IsValid()) { + BVariant value; + error = typeContext->File()->EvaluateDynamicValue( + typeContext->GetCompilationUnit(), typeContext->SubprogramEntry(), + memberEntry->BitOffset(), typeContext->TargetInterface(), + typeContext->InstructionPointer(), typeContext->FramePointer(), + value); + if (error != B_OK) + return error; + bitOffset = value.ToUInt64(); + } + + // get the bit size + uint64 bitSize = byteSize * 8; + if (memberEntry->BitSize()->IsValid()) { + BVariant value; + error = typeContext->File()->EvaluateDynamicValue( + typeContext->GetCompilationUnit(), typeContext->SubprogramEntry(), + memberEntry->BitSize(), typeContext->TargetInterface(), + typeContext->InstructionPointer(), typeContext->FramePointer(), + value); + if (error != B_OK) + return error; + bitSize = value.ToUInt64(); + } + + TRACE_LOCALS("bit field: byte size: %llu, bit offset/size: %llu/%llu\n", + byteSize, bitOffset, bitSize); + + if (bitOffset + bitSize > byteSize * 8) + return B_BAD_VALUE; + + // create the bit field value location + ValueLocation* bitFieldLocation = new(std::nothrow) ValueLocation; + if (bitFieldLocation == NULL) + return B_NO_MEMORY; + Reference bitFieldLocationReference(bitFieldLocation, true); + + if (!bitFieldLocation->SetTo(*location, bitOffset, bitSize)) + return B_NO_MEMORY; + + _location = bitFieldLocationReference.Detach(); + return B_OK; +} + + +DIEType* +DwarfCompoundType::GetDIEType() const +{ + return fEntry; +} + + +bool +DwarfCompoundType::AddInheritance(DwarfInheritance* inheritance) +{ + if (!fInheritances.AddItem(inheritance)) + return false; + + inheritance->AcquireReference(); + return true; +} + + +bool +DwarfCompoundType::AddDataMember(DwarfDataMember* member) +{ + if (!fDataMembers.AddItem(member)) + return false; + + member->AcquireReference(); + return true; +} + + +status_t +DwarfCompoundType::_ResolveDataMemberLocation(DwarfType* memberType, + const MemberLocation* memberLocation, + const ValueLocation& parentLocation, ValueLocation*& _location) +{ + // create the value location object for the member + ValueLocation* location = new(std::nothrow) ValueLocation( + parentLocation.IsBigEndian()); + if (location == NULL) + return B_NO_MEMORY; + Reference locationReference(location, true); + + switch (memberLocation->attributeClass) { + case ATTRIBUTE_CLASS_CONSTANT: + { + if (!location->SetTo(parentLocation, memberLocation->constant * 8, + memberType->ByteSize() * 8)) { + return B_NO_MEMORY; + } + + break; + } + case ATTRIBUTE_CLASS_BLOCK: + case ATTRIBUTE_CLASS_LOCLISTPTR: + { + // The attribute is a location description. Since we need to push + // the parent object value onto the stack, we require the parent + // location to be a memory location. + if (parentLocation.CountPieces() != 1) + return B_BAD_VALUE; + ValuePieceLocation piece = parentLocation.PieceAt(0); + if (piece.type != VALUE_PIECE_LOCATION_MEMORY) + return B_BAD_VALUE; + + // convert member location to location description + LocationDescription locationDescription; + if (memberLocation->attributeClass == ATTRIBUTE_CLASS_BLOCK) { + locationDescription.SetToExpression( + memberLocation->expression.data, + memberLocation->expression.length); + } else { + locationDescription.SetToLocationList( + memberLocation->listOffset); + } + + // evaluate the location description + status_t error = memberType->ResolveLocation(TypeContext(), + &locationDescription, piece.address, *location); + if (error != B_OK) + return error; + + break; + } + default: + { + // for unions the member location can be omitted -- all members + // start at the beginning of the parent object + if (fEntry->Tag() != DW_TAG_union_type) + return B_BAD_VALUE; + + if (!location->SetTo(parentLocation, 0, memberType->ByteSize() * 8)) + return B_NO_MEMORY; + + break; + } + } + + _location = locationReference.Detach(); + return B_OK; +} + + +// #pragma mark - DwarfArrayType + + +DwarfArrayType::DwarfArrayType(DwarfTypeContext* typeContext, + const BString& name, DIEArrayType* entry, DwarfType* baseType) + : + DwarfType(typeContext, name), + fEntry(entry), + fBaseType(baseType) +{ + fBaseType->AcquireReference(); +} + + +DwarfArrayType::~DwarfArrayType() +{ + for (int32 i = 0; + DwarfArrayDimension* dimension = fDimensions.ItemAt(i); i++) { + dimension->ReleaseReference(); + } + + fBaseType->ReleaseReference(); +} + + +Type* +DwarfArrayType::BaseType() const +{ + return fBaseType; +} + + +int32 +DwarfArrayType::CountDimensions() const +{ + return fDimensions.CountItems(); +} + + +ArrayDimension* +DwarfArrayType::DimensionAt(int32 index) const +{ + return fDimensions.ItemAt(index); +} + + +status_t +DwarfArrayType::ResolveElementLocation(const ArrayIndexPath& indexPath, + const ValueLocation& parentLocation, ValueLocation*& _location) +{ + if (indexPath.CountIndices() != CountDimensions()) + return B_BAD_VALUE; + DwarfTypeContext* typeContext = TypeContext(); + + // If the array entry has a bit stride, get it. Otherwise fall back to the + // element type size. + int64 bitStride; + if (DIEArrayType* bitStrideOwnerEntry = DwarfUtils::GetDIEByPredicate( + fEntry, HasBitStridePredicate())) { + BVariant value; + status_t error = typeContext->File()->EvaluateDynamicValue( + typeContext->GetCompilationUnit(), typeContext->SubprogramEntry(), + bitStrideOwnerEntry->BitStride(), typeContext->TargetInterface(), + typeContext->InstructionPointer(), typeContext->FramePointer(), + value); + if (error != B_OK) + return error; + if (!value.IsInteger()) + return B_BAD_VALUE; + bitStride = value.ToInt64(); + } else + bitStride = BaseType()->ByteSize() * 8; + + // Iterate backward through the dimensions and compute the total offset of + // the element. + int64 elementOffset = 0; + DwarfArrayDimension* previousDimension = NULL; + int64 previousDimensionStride = 0; + for (int32 dimensionIndex = CountDimensions() - 1; + dimensionIndex >= 0; dimensionIndex--) { + DwarfArrayDimension* dimension = DwarfDimensionAt(dimensionIndex); + int64 index = indexPath.IndexAt(dimensionIndex); + + // If the dimension has a special bit/byte stride, get it. + int64 dimensionStride = 0; + DwarfType* dimensionType = dimension->GetDwarfType(); + DIEArrayIndexType* dimensionTypeEntry = dimensionType != NULL + ? dynamic_cast(dimensionType->GetDIEType()) + : NULL; + if (dimensionTypeEntry != NULL) { + DIEArrayIndexType* bitStrideOwnerEntry + = DwarfUtils::GetDIEByPredicate(dimensionTypeEntry, + HasBitStridePredicate()); + if (bitStrideOwnerEntry != NULL) { + BVariant value; + status_t error = typeContext->File()->EvaluateDynamicValue( + typeContext->GetCompilationUnit(), + typeContext->SubprogramEntry(), + bitStrideOwnerEntry->BitStride(), + typeContext->TargetInterface(), + typeContext->InstructionPointer(), + typeContext->FramePointer(), value); + if (error != B_OK) + return error; + if (!value.IsInteger()) + return B_BAD_VALUE; + dimensionStride = value.ToInt64(); + } else { + DIEArrayIndexType* byteStrideOwnerEntry + = DwarfUtils::GetDIEByPredicate(dimensionTypeEntry, + HasByteStridePredicate()); + if (byteStrideOwnerEntry != NULL) { + BVariant value; + status_t error = typeContext->File()->EvaluateDynamicValue( + typeContext->GetCompilationUnit(), + typeContext->SubprogramEntry(), + byteStrideOwnerEntry->ByteStride(), + typeContext->TargetInterface(), + typeContext->InstructionPointer(), + typeContext->FramePointer(), value); + if (error != B_OK) + return error; + if (!value.IsInteger()) + return B_BAD_VALUE; + dimensionStride = value.ToInt64() * 8; + } + } + } + + // If we don't have a stride for the dimension yet, use the stride of + // the previous dimension multiplied by the size of the dimension. + if (dimensionStride == 0) { + if (previousDimension != NULL) { + dimensionStride = previousDimensionStride + * previousDimension->CountElements(); + } else { + // the last dimension -- use the element bit stride + dimensionStride = bitStride; + } + } + + // If the dimension stride is still 0 (that can happen, if the dimension + // doesn't have a stride and the previous dimension's element count is + // not known), we can only resolve the first element. + if (dimensionStride == 0 && index != 0) { + WARNING("No dimension bit stride for dimension %ld and element " + "index is not 0.\n", dimensionIndex); + return B_BAD_VALUE; + } + + elementOffset += dimensionStride * index; + + previousDimension = dimension; + previousDimensionStride = dimensionStride; + } + + TRACE_LOCALS("total element bit offset: %lld\n", elementOffset); + + // create the value location object for the element + ValueLocation* location = new(std::nothrow) ValueLocation( + parentLocation.IsBigEndian()); + if (location == NULL) + return B_NO_MEMORY; + Reference locationReference(location, true); + + // If we have a single memory piece location for the array, we compute the + // element's location by hand -- not uncommonly the array size isn't known. + if (parentLocation.CountPieces() == 1) { + ValuePieceLocation piece = parentLocation.PieceAt(0); + if (piece.type == VALUE_PIECE_LOCATION_MEMORY) { + int64 byteOffset = elementOffset >= 0 + ? elementOffset / 8 : (elementOffset - 7) / 8; + piece.SetToMemory(piece.address + byteOffset); + piece.SetSize(BaseType()->ByteSize()); + // TODO: Support bit offsets correctly! + // TODO: Support bit fields (primitive types) correctly! + + if (!location->AddPiece(piece)) + return B_NO_MEMORY; + + _location = locationReference.Detach(); + return B_OK; + } + } + + // We can't deal with negative element offsets at this point. It doesn't + // make a lot of sense anyway, if the array location consists of multiple + // pieces or lives in a register. + if (elementOffset < 0) { + WARNING("Negative element offset unsupported for multiple location " + "pieces or register pieces.\n"); + return B_UNSUPPORTED; + } + + if (!location->SetTo(parentLocation, elementOffset, + BaseType()->ByteSize() * 8)) { + return B_NO_MEMORY; + } + + _location = locationReference.Detach(); + return B_OK; +} + + + +DIEType* +DwarfArrayType::GetDIEType() const +{ + return fEntry; +} + + +bool +DwarfArrayType::AddDimension(DwarfArrayDimension* dimension) +{ + if (!fDimensions.AddItem(dimension)) + return false; + + dimension->AcquireReference(); + return true; +} + + +// #pragma mark - DwarfModifiedType + + +DwarfModifiedType::DwarfModifiedType(DwarfTypeContext* typeContext, + const BString& name, DIEModifiedType* entry, uint32 modifiers, + DwarfType* baseType) + : + DwarfType(typeContext, name), + fEntry(entry), + fModifiers(modifiers), + fBaseType(baseType) +{ + fBaseType->AcquireReference(); +} + + +DwarfModifiedType::~DwarfModifiedType() +{ + fBaseType->ReleaseReference(); +} + + +uint32 +DwarfModifiedType::Modifiers() const +{ + return fModifiers; +} + + +Type* +DwarfModifiedType::BaseType() const +{ + return fBaseType; +} + + +DIEType* +DwarfModifiedType::GetDIEType() const +{ + return fEntry; +} + + +// #pragma mark - DwarfTypedefType + + +DwarfTypedefType::DwarfTypedefType(DwarfTypeContext* typeContext, + const BString& name, DIETypedef* entry, DwarfType* baseType) + : + DwarfType(typeContext, name), + fEntry(entry), + fBaseType(baseType) +{ + fBaseType->AcquireReference(); +} + + +DwarfTypedefType::~DwarfTypedefType() +{ + fBaseType->ReleaseReference(); +} + + +Type* +DwarfTypedefType::BaseType() const +{ + return fBaseType; +} + + +DIEType* +DwarfTypedefType::GetDIEType() const +{ + return fEntry; +} + + +// #pragma mark - DwarfAddressType + + +DwarfAddressType::DwarfAddressType(DwarfTypeContext* typeContext, + const BString& name, DIEAddressingType* entry, + address_type_kind addressKind, DwarfType* baseType) + : + DwarfType(typeContext, name), + fEntry(entry), + fAddressKind(addressKind), + fBaseType(baseType) +{ + fBaseType->AcquireReference(); +} + + +DwarfAddressType::~DwarfAddressType() +{ + fBaseType->ReleaseReference(); +} + + +address_type_kind +DwarfAddressType::AddressKind() const +{ + return fAddressKind; +} + + +Type* +DwarfAddressType::BaseType() const +{ + return fBaseType; +} + + +DIEType* +DwarfAddressType::GetDIEType() const +{ + return fEntry; +} + + +// #pragma mark - DwarfEnumerationType + + +DwarfEnumerationType::DwarfEnumerationType(DwarfTypeContext* typeContext, + const BString& name, DIEEnumerationType* entry, DwarfType* baseType) + : + DwarfType(typeContext, name), + fEntry(entry), + fBaseType(baseType) +{ + if (fBaseType != NULL) + fBaseType->AcquireReference(); +} + + +DwarfEnumerationType::~DwarfEnumerationType() +{ + for (int32 i = 0; DwarfEnumerationValue* value = fValues.ItemAt(i); i++) + value->ReleaseReference(); + + if (fBaseType != NULL) + fBaseType->ReleaseReference(); +} + + +Type* +DwarfEnumerationType::BaseType() const +{ + return fBaseType; +} + + +int32 +DwarfEnumerationType::CountValues() const +{ + return fValues.CountItems(); +} + + +EnumerationValue* +DwarfEnumerationType::ValueAt(int32 index) const +{ + return fValues.ItemAt(index); +} + + +DIEType* +DwarfEnumerationType::GetDIEType() const +{ + return fEntry; +} + + +bool +DwarfEnumerationType::AddValue(DwarfEnumerationValue* value) +{ + if (!fValues.AddItem(value)) + return false; + + value->AcquireReference(); + return true; +} + + +// #pragma mark - DwarfSubrangeType + + +DwarfSubrangeType::DwarfSubrangeType(DwarfTypeContext* typeContext, + const BString& name, DIESubrangeType* entry, DwarfType* baseType, + const BVariant& lowerBound, const BVariant& upperBound) + : + DwarfType(typeContext, name), + fEntry(entry), + fBaseType(baseType), + fLowerBound(lowerBound), + fUpperBound(upperBound) +{ + fBaseType->AcquireReference(); +} + + +DwarfSubrangeType::~DwarfSubrangeType() +{ + fBaseType->ReleaseReference(); +} + + +Type* +DwarfSubrangeType::BaseType() const +{ + return fBaseType; +} + + +DIEType* +DwarfSubrangeType::GetDIEType() const +{ + return fEntry; +} + + +BVariant +DwarfSubrangeType::LowerBound() const +{ + return fLowerBound; +} + + +BVariant +DwarfSubrangeType::UpperBound() const +{ + return fUpperBound; +} + + +// #pragma mark - DwarfUnspecifiedType + + +DwarfUnspecifiedType::DwarfUnspecifiedType(DwarfTypeContext* typeContext, + const BString& name, DIEUnspecifiedType* entry) + : + DwarfType(typeContext, name), + fEntry(entry) +{ +} + + +DwarfUnspecifiedType::~DwarfUnspecifiedType() +{ +} + + +DIEType* +DwarfUnspecifiedType::GetDIEType() const +{ + return fEntry; +} + + +// #pragma mark - DwarfFunctionType + + +DwarfFunctionType::DwarfFunctionType(DwarfTypeContext* typeContext, + const BString& name, DIESubroutineType* entry, DwarfType* returnType) + : + DwarfType(typeContext, name), + fEntry(entry), + fReturnType(returnType), + fHasVariableArguments(false) +{ + if (fReturnType != NULL) + fReturnType->AcquireReference(); +} + + +DwarfFunctionType::~DwarfFunctionType() +{ + for (int32 i = 0; + DwarfFunctionParameter* parameter = fParameters.ItemAt(i); i++) { + parameter->ReleaseReference(); + } + + if (fReturnType != NULL) + fReturnType->ReleaseReference(); +} + + +Type* +DwarfFunctionType::ReturnType() const +{ + return fReturnType; +} + + +int32 +DwarfFunctionType::CountParameters() const +{ + return fParameters.CountItems(); +} + + +FunctionParameter* +DwarfFunctionType::ParameterAt(int32 index) const +{ + return fParameters.ItemAt(index); +} + + +bool +DwarfFunctionType::HasVariableArguments() const +{ + return fHasVariableArguments; +} + + +void +DwarfFunctionType::SetHasVariableArguments(bool hasVarArgs) +{ + fHasVariableArguments = hasVarArgs; +} + + +DIEType* +DwarfFunctionType::GetDIEType() const +{ + return fEntry; +} + + +bool +DwarfFunctionType::AddParameter(DwarfFunctionParameter* parameter) +{ + if (!fParameters.AddItem(parameter)) + return false; + + parameter->AcquireReference(); + return true; +} + + +// #pragma mark - DwarfPointerToMemberType + + +DwarfPointerToMemberType::DwarfPointerToMemberType( + DwarfTypeContext* typeContext, const BString& name, + DIEPointerToMemberType* entry, DwarfCompoundType* containingType, + DwarfType* baseType) + : + DwarfType(typeContext, name), + fEntry(entry), + fContainingType(containingType), + fBaseType(baseType) +{ + fContainingType->AcquireReference(); + fBaseType->AcquireReference(); +} + + +DwarfPointerToMemberType::~DwarfPointerToMemberType() +{ + fContainingType->ReleaseReference(); + fBaseType->ReleaseReference(); +} + + +CompoundType* +DwarfPointerToMemberType::ContainingType() const +{ + return fContainingType; +} + + +Type* +DwarfPointerToMemberType::BaseType() const +{ + return fBaseType; +} + + +DIEType* +DwarfPointerToMemberType::GetDIEType() const +{ + return fEntry; +} diff --git a/src/apps/debugger/debug_info/DwarfTypes.h b/src/apps/debugger/debug_info/DwarfTypes.h new file mode 100644 index 0000000000..b6fab3faf5 --- /dev/null +++ b/src/apps/debugger/debug_info/DwarfTypes.h @@ -0,0 +1,526 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef DWARF_TYPES_H +#define DWARF_TYPES_H + + +#include + +#include +#include + +#include "Type.h" + + +class Architecture; +class CompilationUnit; +class DIEAddressingType; +class DIEArrayType; +class DIEBaseType; +class DIECompoundType; +class DIEEnumerationType; +class DIEEnumerator; +class DIEFormalParameter; +class DIEInheritance; +class DIEMember; +class DIEModifiedType; +class DIEPointerToMemberType; +class DIESubprogram; +class DIESubrangeType; +class DIESubroutineType; +class DIEType; +class DIETypedef; +class DIEUnspecifiedType; +class DwarfFile; +class DwarfTargetInterface; +struct LocationDescription; +struct MemberLocation; +class RegisterMap; +class ValueLocation; + + +class DwarfTypeContext : public BReferenceable { +public: + DwarfTypeContext(Architecture* architecture, + image_id imageID, DwarfFile* file, + CompilationUnit* compilationUnit, + DIESubprogram* subprogramEntry, + target_addr_t instructionPointer, + target_addr_t framePointer, + DwarfTargetInterface* targetInterface, + RegisterMap* fromDwarfRegisterMap); + ~DwarfTypeContext(); + + Architecture* GetArchitecture() const + { return fArchitecture; } + image_id ImageID() const + { return fImageID; } + DwarfFile* File() const + { return fFile; } + CompilationUnit* GetCompilationUnit() const + { return fCompilationUnit; } + DIESubprogram* SubprogramEntry() const + { return fSubprogramEntry; } + target_addr_t InstructionPointer() const + { return fInstructionPointer; } + target_addr_t FramePointer() const + { return fFramePointer; } + DwarfTargetInterface* TargetInterface() const + { return fTargetInterface; } + RegisterMap* FromDwarfRegisterMap() const + { return fFromDwarfRegisterMap; } + +private: + Architecture* fArchitecture; + image_id fImageID; + DwarfFile* fFile; + CompilationUnit* fCompilationUnit; + DIESubprogram* fSubprogramEntry; + target_addr_t fInstructionPointer; + target_addr_t fFramePointer; + DwarfTargetInterface* fTargetInterface; + RegisterMap* fFromDwarfRegisterMap; +}; + + +class DwarfType : public virtual Type { +public: + DwarfType(DwarfTypeContext* typeContext, + const BString& name); + ~DwarfType(); + + virtual image_id ImageID() const; + virtual const char* Name() const; + virtual target_size_t ByteSize() const; + + virtual status_t ResolveObjectDataLocation( + const ValueLocation& objectLocation, + ValueLocation*& _location); + virtual status_t ResolveObjectDataLocation( + target_addr_t objectAddress, + ValueLocation*& _location); + + DwarfTypeContext* TypeContext() const + { return fTypeContext; } + + void SetByteSize(target_size_t size) + { fByteSize = size; } + + virtual DIEType* GetDIEType() const = 0; + + status_t ResolveLocation(DwarfTypeContext* typeContext, + const LocationDescription* description, + target_addr_t objectAddress, + ValueLocation& _location); + +private: + DwarfTypeContext* fTypeContext; + BString fName; + target_size_t fByteSize; +}; + + +class DwarfInheritance : public BaseType { +public: + DwarfInheritance(DIEInheritance* entry, + DwarfType* type); + ~DwarfInheritance(); + + virtual Type* GetType() const; + + DwarfType* GetDwarfType() const + { return fType; } + DIEInheritance* Entry() const + { return fEntry; } + +private: + DIEInheritance* fEntry; + DwarfType* fType; +}; + + +class DwarfDataMember : public DataMember { +public: + DwarfDataMember(DIEMember* entry, + const BString& name, DwarfType* type); + ~DwarfDataMember(); + + virtual const char* Name() const; + virtual Type* GetType() const; + + DwarfType* GetDwarfType() const + { return fType; } + DIEMember* Entry() const + { return fEntry; } + +private: + DIEMember* fEntry; + BString fName; + DwarfType* fType; +}; + + +class DwarfEnumerationValue : public EnumerationValue { +public: + DwarfEnumerationValue(DIEEnumerator* entry, + const BString& name, const BVariant& value); + ~DwarfEnumerationValue(); + + virtual const char* Name() const; + virtual BVariant Value() const; + + DIEEnumerator* Entry() const + { return fEntry; } + +private: + DIEEnumerator* fEntry; + BString fName; + BVariant fValue; +}; + + +class DwarfArrayDimension : public ArrayDimension { +public: + DwarfArrayDimension(DwarfType* type); + ~DwarfArrayDimension(); + + virtual Type* GetType() const; + + DwarfType* GetDwarfType() const + { return fType; } + +private: + DwarfType* fType; + +}; + + +class DwarfFunctionParameter : public FunctionParameter { +public: + DwarfFunctionParameter( + DIEFormalParameter* entry, + const BString& name, DwarfType* type); + ~DwarfFunctionParameter(); + + virtual const char* Name() const; + virtual Type* GetType() const; + + DIEFormalParameter* Entry() const + { return fEntry; } + +private: + DIEFormalParameter* fEntry; + BString fName; + DwarfType* fType; + +}; + + +class DwarfPrimitiveType : public PrimitiveType, public DwarfType { +public: + DwarfPrimitiveType( + DwarfTypeContext* typeContext, + const BString& name, DIEBaseType* entry, + uint32 typeConstant); + + virtual DIEType* GetDIEType() const; + virtual uint32 TypeConstant() const; + + DIEBaseType* Entry() const + { return fEntry; } + +private: + DIEBaseType* fEntry; + uint32 fTypeConstant; +}; + + +class DwarfCompoundType : public CompoundType, public DwarfType { +public: + DwarfCompoundType(DwarfTypeContext* typeContext, + const BString& name, DIECompoundType* entry); + ~DwarfCompoundType(); + + virtual int32 CountBaseTypes() const; + virtual BaseType* BaseTypeAt(int32 index) const; + + virtual int32 CountDataMembers() const; + virtual DataMember* DataMemberAt(int32 index) const; + + virtual status_t ResolveBaseTypeLocation(BaseType* _baseType, + const ValueLocation& parentLocation, + ValueLocation*& _location); + virtual status_t ResolveDataMemberLocation(DataMember* _member, + const ValueLocation& parentLocation, + ValueLocation*& _location); + + virtual DIEType* GetDIEType() const; + + DIECompoundType* Entry() const + { return fEntry; } + + bool AddInheritance(DwarfInheritance* inheritance); + bool AddDataMember(DwarfDataMember* member); + +private: + typedef BObjectList DataMemberList; + typedef BObjectList InheritanceList; + +private: + status_t _ResolveDataMemberLocation( + DwarfType* memberType, + const MemberLocation* memberLocation, + const ValueLocation& parentLocation, + ValueLocation*& _location); + +private: + DIECompoundType* fEntry; + InheritanceList fInheritances; + DataMemberList fDataMembers; +}; + + +class DwarfArrayType : public ArrayType, public DwarfType { +public: + DwarfArrayType(DwarfTypeContext* typeContext, + const BString& name, DIEArrayType* entry, + DwarfType* baseType); + ~DwarfArrayType(); + + virtual Type* BaseType() const; + + virtual int32 CountDimensions() const; + virtual ArrayDimension* DimensionAt(int32 index) const; + + virtual status_t ResolveElementLocation( + const ArrayIndexPath& indexPath, + const ValueLocation& parentLocation, + ValueLocation*& _location); + + virtual DIEType* GetDIEType() const; + + bool AddDimension(DwarfArrayDimension* dimension); + + DwarfArrayDimension* DwarfDimensionAt(int32 index) const + { return fDimensions.ItemAt(index); } + DIEArrayType* Entry() const + { return fEntry; } + +private: + typedef BObjectList DimensionList; + +private: + DIEArrayType* fEntry; + DwarfType* fBaseType; + DimensionList fDimensions; +}; + + +class DwarfModifiedType : public ModifiedType, public DwarfType { +public: + DwarfModifiedType(DwarfTypeContext* typeContext, + const BString& name, DIEModifiedType* entry, + uint32 modifiers, DwarfType* baseType); + ~DwarfModifiedType(); + + virtual uint32 Modifiers() const; + virtual Type* BaseType() const; + + virtual DIEType* GetDIEType() const; + + DIEModifiedType* Entry() const + { return fEntry; } + +private: + DIEModifiedType* fEntry; + uint32 fModifiers; + DwarfType* fBaseType; +}; + + +class DwarfTypedefType : public TypedefType, public DwarfType { +public: + DwarfTypedefType(DwarfTypeContext* typeContext, + const BString& name, DIETypedef* entry, + DwarfType* baseType); + ~DwarfTypedefType(); + + virtual Type* BaseType() const; + + virtual DIEType* GetDIEType() const; + + DIETypedef* Entry() const + { return fEntry; } + +private: + DIETypedef* fEntry; + DwarfType* fBaseType; +}; + + +class DwarfAddressType : public AddressType, public DwarfType { +public: + DwarfAddressType(DwarfTypeContext* typeContext, + const BString& name, + DIEAddressingType* entry, + address_type_kind addressKind, + DwarfType* baseType); + ~DwarfAddressType(); + + virtual address_type_kind AddressKind() const; + virtual Type* BaseType() const; + + virtual DIEType* GetDIEType() const; + + DIEAddressingType* Entry() const + { return fEntry; } + +private: + DIEAddressingType* fEntry; + address_type_kind fAddressKind; + DwarfType* fBaseType; +}; + + +class DwarfEnumerationType : public EnumerationType, public DwarfType { +public: + DwarfEnumerationType( + DwarfTypeContext* typeContext, + const BString& name, + DIEEnumerationType* entry, + DwarfType* baseType); + ~DwarfEnumerationType(); + + virtual Type* BaseType() const; + + virtual int32 CountValues() const; + virtual EnumerationValue* ValueAt(int32 index) const; + + virtual DIEType* GetDIEType() const; + + bool AddValue(DwarfEnumerationValue* value); + + DIEEnumerationType* Entry() const + { return fEntry; } + +private: + typedef BObjectList ValueList; + +private: + DIEEnumerationType* fEntry; + DwarfType* fBaseType; + ValueList fValues; +}; + + +class DwarfSubrangeType : public SubrangeType, public DwarfType { +public: + DwarfSubrangeType(DwarfTypeContext* typeContext, + const BString& name, DIESubrangeType* entry, + DwarfType* baseType, + const BVariant& lowerBound, + const BVariant& upperBound); + ~DwarfSubrangeType(); + + virtual Type* BaseType() const; + + virtual BVariant LowerBound() const; + virtual BVariant UpperBound() const; + + virtual DIEType* GetDIEType() const; + + DIESubrangeType* Entry() const + { return fEntry; } + +private: + DIESubrangeType* fEntry; + DwarfType* fBaseType; + BVariant fLowerBound; + BVariant fUpperBound; +}; + + +struct DwarfUnspecifiedType : public UnspecifiedType, public DwarfType { +public: + DwarfUnspecifiedType( + DwarfTypeContext* typeContext, + const BString& name, + DIEUnspecifiedType* entry); + // entry may be NULL + ~DwarfUnspecifiedType(); + + virtual DIEType* GetDIEType() const; + + DIEUnspecifiedType* Entry() const + { return fEntry; } + +private: + DIEUnspecifiedType* fEntry; +}; + + +class DwarfFunctionType : public FunctionType, public DwarfType { +public: + DwarfFunctionType(DwarfTypeContext* typeContext, + const BString& name, + DIESubroutineType* entry, + DwarfType* returnType); + ~DwarfFunctionType(); + + virtual Type* ReturnType() const; + + virtual int32 CountParameters() const; + virtual FunctionParameter* ParameterAt(int32 index) const; + + virtual bool HasVariableArguments() const; + void SetHasVariableArguments(bool hasVarArgs); + + virtual DIEType* GetDIEType() const; + + bool AddParameter(DwarfFunctionParameter* parameter); + + DwarfFunctionParameter* DwarfParameterAt(int32 index) const + { return fParameters.ItemAt(index); } + + DIESubroutineType* Entry() const + { return fEntry; } + +private: + typedef BObjectList ParameterList; + +private: + DIESubroutineType* fEntry; + DwarfType* fReturnType; + ParameterList fParameters; + bool fHasVariableArguments; +}; + + +class DwarfPointerToMemberType : public PointerToMemberType, public DwarfType { +public: + DwarfPointerToMemberType( + DwarfTypeContext* typeContext, + const BString& name, + DIEPointerToMemberType* entry, + DwarfCompoundType* containingType, + DwarfType* baseType); + ~DwarfPointerToMemberType(); + + virtual CompoundType* ContainingType() const; + virtual Type* BaseType() const; + + virtual DIEType* GetDIEType() const; + + DIEPointerToMemberType* Entry() const + { return fEntry; } + +private: + DIEPointerToMemberType* fEntry; + DwarfCompoundType* fContainingType; + DwarfType* fBaseType; +}; + + +#endif // DWARF_TYPES_H diff --git a/src/apps/debugger/debug_info/GlobalTypeLookup.cpp b/src/apps/debugger/debug_info/GlobalTypeLookup.cpp index 81061fbaea..e378e14fd1 100644 --- a/src/apps/debugger/debug_info/GlobalTypeLookup.cpp +++ b/src/apps/debugger/debug_info/GlobalTypeLookup.cpp @@ -10,11 +10,13 @@ #include +#include + #include "StringUtils.h" #include "Type.h" -struct GlobalTypeLookupContext::TypeEntry { +struct GlobalTypeCache::TypeEntry { BString name; Type* type; TypeEntry* fNext; @@ -34,7 +36,7 @@ struct GlobalTypeLookupContext::TypeEntry { }; -struct GlobalTypeLookupContext::TypeEntryHashDefinition { +struct GlobalTypeCache::TypeEntryHashDefinition { typedef const BString KeyType; typedef TypeEntry ValueType; @@ -60,22 +62,22 @@ struct GlobalTypeLookupContext::TypeEntryHashDefinition { }; -// #pragma mark - GlobalTypeLookupContext +// #pragma mark - GlobalTypeCache -GlobalTypeLookupContext::GlobalTypeLookupContext() +GlobalTypeCache::GlobalTypeCache() : fLock("global type lookup"), - fCachedTypes(NULL) + fTypes(NULL) { } -GlobalTypeLookupContext::~GlobalTypeLookupContext() +GlobalTypeCache::~GlobalTypeCache() { // release all cached type references - if (fCachedTypes != NULL) { - TypeEntry* entry = fCachedTypes->Clear(true); + if (fTypes != NULL) { + TypeEntry* entry = fTypes->Clear(true); while (entry != NULL) { TypeEntry* nextEntry = entry->fNext; delete entry; @@ -86,32 +88,32 @@ GlobalTypeLookupContext::~GlobalTypeLookupContext() status_t -GlobalTypeLookupContext::Init() +GlobalTypeCache::Init() { status_t error = fLock.InitCheck(); if (error != B_OK) return error; - fCachedTypes = new(std::nothrow) TypeTable; - if (fCachedTypes == NULL) + fTypes = new(std::nothrow) TypeTable; + if (fTypes == NULL) return B_NO_MEMORY; - return fCachedTypes->Init(); + return fTypes->Init(); } Type* -GlobalTypeLookupContext::CachedType(const BString& name) const +GlobalTypeCache::GetType(const BString& name) const { - TypeEntry* typeEntry = fCachedTypes->Lookup(name); + TypeEntry* typeEntry = fTypes->Lookup(name); return typeEntry != NULL ? typeEntry->type : NULL; } status_t -GlobalTypeLookupContext::AddCachedType(const BString& name, Type* type) +GlobalTypeCache::AddType(const BString& name, Type* type) { - TypeEntry* typeEntry = fCachedTypes->Lookup(name); + TypeEntry* typeEntry = fTypes->Lookup(name); if (typeEntry != NULL) return B_BAD_VALUE; @@ -119,21 +121,36 @@ GlobalTypeLookupContext::AddCachedType(const BString& name, Type* type) if (typeEntry == NULL) return B_NO_MEMORY; - fCachedTypes->Insert(typeEntry); + fTypes->Insert(typeEntry); return B_OK; } void -GlobalTypeLookupContext::RemoveCachedType(const BString& name) +GlobalTypeCache::RemoveType(const BString& name) { - if (TypeEntry* typeEntry = fCachedTypes->Lookup(name)) { - fCachedTypes->Remove(typeEntry); + if (TypeEntry* typeEntry = fTypes->Lookup(name)) { + fTypes->Remove(typeEntry); delete typeEntry; } } +void +GlobalTypeCache::RemoveTypes(image_id imageID) +{ + AutoLocker locker(this); + + for (TypeTable::Iterator it = fTypes->GetIterator(); + TypeEntry* typeEntry = it.Next();) { + if (typeEntry->type->ImageID() == imageID) { + fTypes->RemoveUnchecked(typeEntry); + delete typeEntry; + } + } +} + + // #pragma mark - GlobalTypeLookup diff --git a/src/apps/debugger/debug_info/GlobalTypeLookup.h b/src/apps/debugger/debug_info/GlobalTypeLookup.h index 22a5f1209f..e8ca45be96 100644 --- a/src/apps/debugger/debug_info/GlobalTypeLookup.h +++ b/src/apps/debugger/debug_info/GlobalTypeLookup.h @@ -6,6 +6,7 @@ #define GLOBAL_TYPE_LOOKUP_H +#include #include #include @@ -16,20 +17,23 @@ class BString; class Type; -class GlobalTypeLookupContext : public Referenceable { +class GlobalTypeCache : public Referenceable { public: - GlobalTypeLookupContext(); - ~GlobalTypeLookupContext(); + GlobalTypeCache(); + ~GlobalTypeCache(); status_t Init(); inline bool Lock(); inline void Unlock(); - // context must be locked - Type* CachedType(const BString& name) const; - status_t AddCachedType(const BString& name, Type* type); - void RemoveCachedType(const BString& name); + // cache must be locked + Type* GetType(const BString& name) const; + status_t AddType(const BString& name, Type* type); + void RemoveType(const BString& name); + + // cache locked by method + void RemoveTypes(image_id imageID); private: struct TypeEntry; @@ -39,7 +43,7 @@ private: private: BLocker fLock; - TypeTable* fCachedTypes; + TypeTable* fTypes; }; @@ -47,21 +51,21 @@ class GlobalTypeLookup { public: virtual ~GlobalTypeLookup(); - virtual status_t GetType(GlobalTypeLookupContext* context, + virtual status_t GetType(GlobalTypeCache* cache, const BString& name, Type*& _type) = 0; // returns a reference }; bool -GlobalTypeLookupContext::Lock() +GlobalTypeCache::Lock() { return fLock.Lock(); } void -GlobalTypeLookupContext::Unlock() +GlobalTypeCache::Unlock() { fLock.Unlock(); } diff --git a/src/apps/debugger/debug_info/ImageDebugInfo.cpp b/src/apps/debugger/debug_info/ImageDebugInfo.cpp index 49ee4bceb2..b7115fc187 100644 --- a/src/apps/debugger/debug_info/ImageDebugInfo.cpp +++ b/src/apps/debugger/debug_info/ImageDebugInfo.cpp @@ -76,12 +76,12 @@ ImageDebugInfo::FinishInit() status_t -ImageDebugInfo::GetType(GlobalTypeLookupContext* context, const BString& name, +ImageDebugInfo::GetType(GlobalTypeCache* cache, const BString& name, Type*& _type) { for (int32 i = 0; SpecificImageDebugInfo* specificInfo = fSpecificInfos.ItemAt(i); i++) { - status_t error = specificInfo->GetType(context, name, _type); + status_t error = specificInfo->GetType(cache, name, _type); if (error == B_OK || error == B_NO_MEMORY) return error; } diff --git a/src/apps/debugger/debug_info/ImageDebugInfo.h b/src/apps/debugger/debug_info/ImageDebugInfo.h index 31d1b96196..c54f41623b 100644 --- a/src/apps/debugger/debug_info/ImageDebugInfo.h +++ b/src/apps/debugger/debug_info/ImageDebugInfo.h @@ -20,7 +20,7 @@ class DebuggerInterface; class FileSourceCode; class FunctionDebugInfo; class FunctionInstance; -class GlobalTypeLookupContext; +class GlobalTypeCache; class LocatableFile; class SpecificImageDebugInfo; class Type; @@ -36,7 +36,7 @@ public: bool AddSpecificInfo(SpecificImageDebugInfo* info); status_t FinishInit(); - status_t GetType(GlobalTypeLookupContext* context, + status_t GetType(GlobalTypeCache* cache, const BString& name, Type*& _type); // returns a reference diff --git a/src/apps/debugger/debug_info/NoOpStackFrameDebugInfo.cpp b/src/apps/debugger/debug_info/NoOpStackFrameDebugInfo.cpp index bc8e7df992..a730cc7c9d 100644 --- a/src/apps/debugger/debug_info/NoOpStackFrameDebugInfo.cpp +++ b/src/apps/debugger/debug_info/NoOpStackFrameDebugInfo.cpp @@ -7,9 +7,9 @@ #include "NoOpStackFrameDebugInfo.h" -NoOpStackFrameDebugInfo::NoOpStackFrameDebugInfo(Architecture* architecture) +NoOpStackFrameDebugInfo::NoOpStackFrameDebugInfo() : - StackFrameDebugInfo(architecture) + StackFrameDebugInfo() { } @@ -17,38 +17,3 @@ NoOpStackFrameDebugInfo::NoOpStackFrameDebugInfo(Architecture* architecture) NoOpStackFrameDebugInfo::~NoOpStackFrameDebugInfo() { } - - -status_t -NoOpStackFrameDebugInfo::ResolveObjectDataLocation(StackFrame* stackFrame, - Type* type, const ValueLocation& objectLocation, ValueLocation*& _location) -{ - return B_UNSUPPORTED; -} - - -status_t -NoOpStackFrameDebugInfo::ResolveBaseTypeLocation(StackFrame* stackFrame, - Type* type, BaseType* baseType, const ValueLocation& parentLocation, - ValueLocation*& _location) -{ - return B_UNSUPPORTED; -} - - -status_t -NoOpStackFrameDebugInfo::ResolveDataMemberLocation(StackFrame* stackFrame, - Type* type, DataMember* member, const ValueLocation& parentLocation, - ValueLocation*& _location) -{ - return B_UNSUPPORTED; -} - - -status_t -NoOpStackFrameDebugInfo::ResolveArrayElementLocation(StackFrame* stackFrame, - ArrayType* type, const ArrayIndexPath& indexPath, - const ValueLocation& parentLocation, ValueLocation*& _location) -{ - return B_UNSUPPORTED; -} diff --git a/src/apps/debugger/debug_info/NoOpStackFrameDebugInfo.h b/src/apps/debugger/debug_info/NoOpStackFrameDebugInfo.h index 5c639f77a6..50053f9a81 100644 --- a/src/apps/debugger/debug_info/NoOpStackFrameDebugInfo.h +++ b/src/apps/debugger/debug_info/NoOpStackFrameDebugInfo.h @@ -11,29 +11,9 @@ class NoOpStackFrameDebugInfo : public StackFrameDebugInfo { public: - NoOpStackFrameDebugInfo( - Architecture* architecture); + NoOpStackFrameDebugInfo(); virtual ~NoOpStackFrameDebugInfo(); - virtual status_t ResolveObjectDataLocation( - StackFrame* stackFrame, Type* type, - const ValueLocation& objectLocation, - ValueLocation*& _location); - virtual status_t ResolveBaseTypeLocation( - StackFrame* stackFrame, Type* type, - BaseType* baseType, - const ValueLocation& parentLocation, - ValueLocation*& _location); - virtual status_t ResolveDataMemberLocation( - StackFrame* stackFrame, Type* type, - DataMember* member, - const ValueLocation& parentLocation, - ValueLocation*& _location); - virtual status_t ResolveArrayElementLocation( - StackFrame* stackFrame, ArrayType* type, - const ArrayIndexPath& indexPath, - const ValueLocation& parentLocation, - ValueLocation*& _location); }; diff --git a/src/apps/debugger/debug_info/SpecificImageDebugInfo.h b/src/apps/debugger/debug_info/SpecificImageDebugInfo.h index 8061974ae0..54da08de92 100644 --- a/src/apps/debugger/debug_info/SpecificImageDebugInfo.h +++ b/src/apps/debugger/debug_info/SpecificImageDebugInfo.h @@ -20,7 +20,7 @@ class DebuggerInterface; class FileSourceCode; class FunctionDebugInfo; class FunctionInstance; -class GlobalTypeLookupContext; +class GlobalTypeCache; class Image; class LocatableFile; class SourceLanguage; @@ -40,7 +40,7 @@ public: = 0; // returns references - virtual status_t GetType(GlobalTypeLookupContext* context, + virtual status_t GetType(GlobalTypeCache* cache, const BString& name, Type*& _type) = 0; // returns a reference diff --git a/src/apps/debugger/debug_info/StackFrameDebugInfo.cpp b/src/apps/debugger/debug_info/StackFrameDebugInfo.cpp index 61878b986b..8fd2c51502 100644 --- a/src/apps/debugger/debug_info/StackFrameDebugInfo.cpp +++ b/src/apps/debugger/debug_info/StackFrameDebugInfo.cpp @@ -10,35 +10,11 @@ #include "ValueLocation.h" -StackFrameDebugInfo::StackFrameDebugInfo(Architecture* architecture) - : - fArchitecture(architecture) +StackFrameDebugInfo::StackFrameDebugInfo() { - fArchitecture->AcquireReference(); } StackFrameDebugInfo::~StackFrameDebugInfo() { - fArchitecture->ReleaseReference(); -} - - -status_t -StackFrameDebugInfo::ResolveObjectDataLocation(StackFrame* stackFrame, - Type* type, target_addr_t objectAddress, ValueLocation*& _location) -{ - ValuePieceLocation piece; - piece.SetToMemory(objectAddress); - piece.SetSize(0); - // We set the piece size to 0 as an indicator that the size has to be - // set. - // TODO: We could set the byte size from type, but that may not be - // accurate. We may want to add bit offset and size to Type. - - ValueLocation location(fArchitecture->IsBigEndian()); - if (!location.AddPiece(piece)) - return B_NO_MEMORY; - - return ResolveObjectDataLocation(stackFrame, type, location, _location); } diff --git a/src/apps/debugger/debug_info/StackFrameDebugInfo.h b/src/apps/debugger/debug_info/StackFrameDebugInfo.h index caead5eed1..7411a2998a 100644 --- a/src/apps/debugger/debug_info/StackFrameDebugInfo.h +++ b/src/apps/debugger/debug_info/StackFrameDebugInfo.h @@ -23,40 +23,8 @@ class ValueLocation; class StackFrameDebugInfo : public Referenceable { public: - StackFrameDebugInfo(Architecture* architecture); + StackFrameDebugInfo(); virtual ~StackFrameDebugInfo(); - - virtual status_t ResolveObjectDataLocation( - StackFrame* stackFrame, Type* type, - const ValueLocation& objectLocation, - ValueLocation*& _location) = 0; - // returns a reference - status_t ResolveObjectDataLocation( - StackFrame* stackFrame, Type* type, - target_addr_t objectAddress, - ValueLocation*& _location); - // returns a reference - virtual status_t ResolveBaseTypeLocation( - StackFrame* stackFrame, Type* type, - BaseType* baseType, - const ValueLocation& parentLocation, - ValueLocation*& _location) = 0; - // returns a reference - virtual status_t ResolveDataMemberLocation( - StackFrame* stackFrame, Type* type, - DataMember* member, - const ValueLocation& parentLocation, - ValueLocation*& _location) = 0; - // returns a reference - virtual status_t ResolveArrayElementLocation( - StackFrame* stackFrame, ArrayType* type, - const ArrayIndexPath& indexPath, - const ValueLocation& parentLocation, - ValueLocation*& _location) = 0; - // returns a reference - -protected: - Architecture* fArchitecture; }; diff --git a/src/apps/debugger/debug_info/TeamDebugInfo.cpp b/src/apps/debugger/debug_info/TeamDebugInfo.cpp index e024485972..0ff329ec7c 100644 --- a/src/apps/debugger/debug_info/TeamDebugInfo.cpp +++ b/src/apps/debugger/debug_info/TeamDebugInfo.cpp @@ -258,13 +258,17 @@ TeamDebugInfo::TeamDebugInfo(DebuggerInterface* debuggerInterface, fFileManager(fileManager), fSpecificInfos(10, true), fFunctions(NULL), - fSourceFiles(NULL) + fSourceFiles(NULL), + fTypeCache(NULL) { } TeamDebugInfo::~TeamDebugInfo() { + if (fTypeCache != NULL) + fTypeCache->ReleaseReference(); + if (fSourceFiles != NULL) { SourceFileEntry* entry = fSourceFiles->Clear(true); while (entry != NULL) { @@ -315,12 +319,21 @@ TeamDebugInfo::Init() if (error != B_OK) return error; + // create a type cache + fTypeCache = new(std::nothrow) GlobalTypeCache; + if (fTypeCache == NULL) + return B_NO_MEMORY; + + error = fTypeCache->Init(); + if (error != B_OK) + return error; + // Create specific infos for all types of debug info we support, in // descending order of expressiveness. // DWARF DwarfTeamDebugInfo* dwarfInfo = new(std::nothrow) DwarfTeamDebugInfo( - fArchitecture, fDebuggerInterface, fFileManager, this); + fArchitecture, fDebuggerInterface, fFileManager, this, fTypeCache); if (dwarfInfo == NULL || !fSpecificInfos.AddItem(dwarfInfo)) { delete dwarfInfo; return B_NO_MEMORY; @@ -348,19 +361,19 @@ TeamDebugInfo::Init() status_t -TeamDebugInfo::GetType(GlobalTypeLookupContext* context, const BString& name, +TeamDebugInfo::GetType(GlobalTypeCache* cache, const BString& name, Type*& _type) { // maybe the type is already cached - AutoLocker contextLocker(context); - Type* type = context->CachedType(name); + AutoLocker cacheLocker(cache); + Type* type = cache->GetType(name); if (type != NULL) { type->AcquireReference(); _type = type; return B_OK; } - contextLocker.Unlock(); + cacheLocker.Unlock(); // Clone the image list and get references to the images, so we can iterate // through them without locking. @@ -377,7 +390,7 @@ TeamDebugInfo::GetType(GlobalTypeLookupContext* context, const BString& name, // get the type status_t error = B_ENTRY_NOT_FOUND; for (int32 i = 0; ImageDebugInfo* imageDebugInfo = images.ItemAt(i); i++) { - error = imageDebugInfo->GetType(context, name, type); + error = imageDebugInfo->GetType(cache, name, type); if (error == B_OK) { _type = type; break; @@ -621,6 +634,9 @@ TeamDebugInfo::RemoveImageDebugInfo(ImageDebugInfo* imageDebugInfo) } } + // remove cached types from that image + fTypeCache->RemoveTypes(imageDebugInfo->GetImageInfo().ImageID()); + fImages.RemoveItem(imageDebugInfo); } diff --git a/src/apps/debugger/debug_info/TeamDebugInfo.h b/src/apps/debugger/debug_info/TeamDebugInfo.h index 639f0dc9b2..a822e79835 100644 --- a/src/apps/debugger/debug_info/TeamDebugInfo.h +++ b/src/apps/debugger/debug_info/TeamDebugInfo.h @@ -42,7 +42,7 @@ public: status_t Init(); - virtual status_t GetType(GlobalTypeLookupContext* context, + virtual status_t GetType(GlobalTypeCache* cache, const BString& name, Type*& _type); status_t LoadImageDebugInfo(const ImageInfo& imageInfo, @@ -91,6 +91,7 @@ private: ImageList fImages; FunctionTable* fFunctions; SourceFileTable* fSourceFiles; + GlobalTypeCache* fTypeCache; }; diff --git a/src/apps/debugger/dwarf/DwarfFile.h b/src/apps/debugger/dwarf/DwarfFile.h index 1b39d0b17a..ac9b724382 100644 --- a/src/apps/debugger/dwarf/DwarfFile.h +++ b/src/apps/debugger/dwarf/DwarfFile.h @@ -7,6 +7,7 @@ #include +#include #include #include "DebugInfoEntries.h" @@ -25,7 +26,8 @@ class TargetAddressRangeList; class ValueLocation; -class DwarfFile : public DoublyLinkedListLinkImpl { +class DwarfFile : public BReferenceable, + public DoublyLinkedListLinkImpl { public: DwarfFile(); ~DwarfFile(); diff --git a/src/apps/debugger/dwarf/DwarfManager.cpp b/src/apps/debugger/dwarf/DwarfManager.cpp index b79551c537..5d02dfed71 100644 --- a/src/apps/debugger/dwarf/DwarfManager.cpp +++ b/src/apps/debugger/dwarf/DwarfManager.cpp @@ -48,7 +48,9 @@ DwarfManager::LoadFile(const char* fileName, DwarfFile*& _file) } fFiles.Add(file); + // we keep the initial reference for ourselves + file->AcquireReference(); _file = file; return B_OK; } diff --git a/src/apps/debugger/dwarf/DwarfManager.h b/src/apps/debugger/dwarf/DwarfManager.h index 928d3c0af2..8da0755a49 100644 --- a/src/apps/debugger/dwarf/DwarfManager.h +++ b/src/apps/debugger/dwarf/DwarfManager.h @@ -25,6 +25,7 @@ public: status_t LoadFile(const char* fileName, DwarfFile*& _file); + // returns a reference status_t FinishLoading(); private: diff --git a/src/apps/debugger/model/Type.h b/src/apps/debugger/model/Type.h index 6178aede35..fcf4252b62 100644 --- a/src/apps/debugger/model/Type.h +++ b/src/apps/debugger/model/Type.h @@ -6,6 +6,8 @@ #define TYPE_H +#include + #include #include @@ -42,7 +44,9 @@ enum { }; +class ArrayIndexPath; class Type; +class ValueLocation; class BaseType : public Referenceable { @@ -95,11 +99,21 @@ class Type : public Referenceable { public: virtual ~Type(); + virtual image_id ImageID() const = 0; virtual const char* Name() const = 0; virtual type_kind Kind() const = 0; virtual target_size_t ByteSize() const = 0; virtual Type* ResolveRawType() const; // strips modifiers and typedefs + + virtual status_t ResolveObjectDataLocation( + const ValueLocation& objectLocation, + ValueLocation*& _location) = 0; + // returns a reference + virtual status_t ResolveObjectDataLocation( + target_addr_t objectAddress, + ValueLocation*& _location) = 0; + // returns a reference }; @@ -124,6 +138,15 @@ public: virtual int32 CountDataMembers() const = 0; virtual DataMember* DataMemberAt(int32 index) const = 0; + + virtual status_t ResolveBaseTypeLocation(BaseType* baseType, + const ValueLocation& parentLocation, + ValueLocation*& _location) = 0; + // returns a reference + virtual status_t ResolveDataMemberLocation(DataMember* member, + const ValueLocation& parentLocation, + ValueLocation*& _location) = 0; + // returns a reference }; @@ -199,6 +222,12 @@ public: virtual int32 CountDimensions() const = 0; virtual ArrayDimension* DimensionAt(int32 index) const = 0; + + virtual status_t ResolveElementLocation( + const ArrayIndexPath& indexPath, + const ValueLocation& parentLocation, + ValueLocation*& _location) = 0; + // returns a reference };