From 71f75cdcdee748eb5e0841f8868ab8f477c0ee75 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Wed, 7 Oct 2009 03:17:22 +0000 Subject: [PATCH] * WIP regarding non comilation unit local types: - Introduced GlobalTypeLookup interface and GlobalTypeLookupContext to look up types by name and cache them. - TeamDebugInfo implementes GlobalTypeLookup iterating through all ImageDebugInfos, which in turn iterate through all SpecificImageDebugInfos. - DwarfImageDebugInfo iterates through all compilation units, using a temporary DwarfStackFrameDebugInfo to create the type. - DwarfStackFrameDebugInfo no longer caches the types itself, but uses GlobalTypeLookupContext. It uses GlobalTypeLookup to look up types not defined in the compilation unit. - DwarfFile: Made expression evaluation more robust, so that it also works, when no subroutine entry, frame pointer, and instruction pointer are available (and not used by the expression). Basically works already, although the wrong compilation unit might be used when resolving values for global types. It's also horribly slow, when there are many types in the stack frame. * DwarfStackFrameDebugInfo::ResolveArrayElementLocation(): The element location piece size was set incorrectly (multiplied by 8, although bytes were expected). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@33477 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/apps/debugger/Jamfile | 1 + .../debug_info/DebuggerImageDebugInfo.cpp | 8 + .../debug_info/DebuggerImageDebugInfo.h | 3 + .../debug_info/DwarfImageDebugInfo.cpp | 165 +++++++++++++++--- .../debugger/debug_info/DwarfImageDebugInfo.h | 9 +- .../debug_info/DwarfStackFrameDebugInfo.cpp | 165 +++++++++--------- .../debug_info/DwarfStackFrameDebugInfo.h | 16 +- .../debug_info/DwarfTeamDebugInfo.cpp | 18 +- .../debugger/debug_info/DwarfTeamDebugInfo.h | 5 +- .../debugger/debug_info/GlobalTypeLookup.cpp | 142 +++++++++++++++ .../debugger/debug_info/GlobalTypeLookup.h | 70 ++++++++ .../debugger/debug_info/ImageDebugInfo.cpp | 15 ++ src/apps/debugger/debug_info/ImageDebugInfo.h | 7 + .../debug_info/SpecificImageDebugInfo.h | 7 + .../debugger/debug_info/TeamDebugInfo.cpp | 48 ++++- src/apps/debugger/debug_info/TeamDebugInfo.h | 6 +- src/apps/debugger/dwarf/DwarfFile.cpp | 10 +- 17 files changed, 564 insertions(+), 131 deletions(-) create mode 100644 src/apps/debugger/debug_info/GlobalTypeLookup.cpp create mode 100644 src/apps/debugger/debug_info/GlobalTypeLookup.h diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile index 710efe1450..7a5600e321 100644 --- a/src/apps/debugger/Jamfile +++ b/src/apps/debugger/Jamfile @@ -65,6 +65,7 @@ Application Debugger : Function.cpp FunctionDebugInfo.cpp FunctionInstance.cpp + GlobalTypeLookup.cpp ImageDebugInfo.cpp ImageDebugInfoProvider.cpp NoOpStackFrameDebugInfo.cpp diff --git a/src/apps/debugger/debug_info/DebuggerImageDebugInfo.cpp b/src/apps/debugger/debug_info/DebuggerImageDebugInfo.cpp index 8d0819323f..8731bf516d 100644 --- a/src/apps/debugger/debug_info/DebuggerImageDebugInfo.cpp +++ b/src/apps/debugger/debug_info/DebuggerImageDebugInfo.cpp @@ -78,6 +78,14 @@ DebuggerImageDebugInfo::GetFunctions(BObjectList& functions) } +status_t +DebuggerImageDebugInfo::GetType(GlobalTypeLookupContext* context, + const BString& name, Type*& _type) +{ + return B_UNSUPPORTED; +} + + status_t DebuggerImageDebugInfo::CreateFrame(Image* image, FunctionInstance* functionInstance, CpuState* cpuState, diff --git a/src/apps/debugger/debug_info/DebuggerImageDebugInfo.h b/src/apps/debugger/debug_info/DebuggerImageDebugInfo.h index 9c8ee1bc50..a67057350d 100644 --- a/src/apps/debugger/debug_info/DebuggerImageDebugInfo.h +++ b/src/apps/debugger/debug_info/DebuggerImageDebugInfo.h @@ -5,6 +5,7 @@ #ifndef DEBUGGER_IMAGE_DEBUG_INFO_H #define DEBUGGER_IMAGE_DEBUG_INFO_H + #include "ImageInfo.h" #include "SpecificImageDebugInfo.h" @@ -26,6 +27,8 @@ public: virtual status_t GetFunctions( BObjectList& functions); + virtual status_t GetType(GlobalTypeLookupContext* context, + const BString& name, Type*& _type); virtual status_t CreateFrame(Image* image, FunctionInstance* functionInstance, CpuState* cpuState, diff --git a/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp b/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp index 94471dde29..6ef0929d3b 100644 --- a/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp +++ b/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp @@ -33,6 +33,7 @@ #include "FileSourceCode.h" #include "FunctionID.h" #include "FunctionInstance.h" +#include "GlobalTypeLookup.h" #include "LocatableFile.h" #include "Register.h" #include "RegisterMap.h" @@ -47,32 +48,26 @@ #include "Variable.h" -// #pragma mark - UnwindTargetInterface +// #pragma mark - BasicTargetInterface -struct DwarfImageDebugInfo::UnwindTargetInterface : DwarfTargetInterface { - UnwindTargetInterface(const Register* registers, int32 registerCount, - RegisterMap* fromDwarfMap, RegisterMap* toDwarfMap, CpuState* cpuState, - Architecture* architecture, TeamMemory* teamMemory) +struct DwarfImageDebugInfo::BasicTargetInterface : DwarfTargetInterface { + BasicTargetInterface(const Register* registers, int32 registerCount, + RegisterMap* fromDwarfMap, Architecture* architecture, + TeamMemory* teamMemory) : fRegisters(registers), fRegisterCount(registerCount), fFromDwarfMap(fromDwarfMap), - fToDwarfMap(toDwarfMap), - fCpuState(cpuState), fArchitecture(architecture), fTeamMemory(teamMemory) { fFromDwarfMap->AcquireReference(); - fToDwarfMap->AcquireReference(); - fCpuState->AcquireReference(); } - ~UnwindTargetInterface() + ~BasicTargetInterface() { fFromDwarfMap->ReleaseReference(); - fToDwarfMap->ReleaseReference(); - fCpuState->ReleaseReference(); } virtual uint32 CountRegisters() const @@ -88,18 +83,12 @@ struct DwarfImageDebugInfo::UnwindTargetInterface : DwarfTargetInterface { virtual bool GetRegisterValue(uint32 index, BVariant& _value) const { - const Register* reg = _RegisterAt(index); - if (reg == NULL) - return false; - return fCpuState->GetRegisterValue(reg, _value); + return false; } virtual bool SetRegisterValue(uint32 index, const BVariant& value) { - const Register* reg = _RegisterAt(index); - if (reg == NULL) - return false; - return fCpuState->SetRegisterValue(reg, value); + return false; } virtual bool IsCalleePreservedRegister(uint32 index) const @@ -129,24 +118,67 @@ struct DwarfImageDebugInfo::UnwindTargetInterface : DwarfTargetInterface { valueType, _value) == B_OK; } -private: +protected: const Register* _RegisterAt(uint32 dwarfIndex) const { int32 index = fFromDwarfMap->MapRegisterIndex(dwarfIndex); return index >= 0 && index < fRegisterCount ? fRegisters + index : NULL; } -private: +protected: const Register* fRegisters; int32 fRegisterCount; RegisterMap* fFromDwarfMap; - RegisterMap* fToDwarfMap; - CpuState* fCpuState; Architecture* fArchitecture; TeamMemory* fTeamMemory; }; +// #pragma mark - UnwindTargetInterface + + +struct DwarfImageDebugInfo::UnwindTargetInterface : BasicTargetInterface { + UnwindTargetInterface(const Register* registers, int32 registerCount, + RegisterMap* fromDwarfMap, RegisterMap* toDwarfMap, CpuState* cpuState, + Architecture* architecture, TeamMemory* teamMemory) + : + BasicTargetInterface(registers, registerCount, fromDwarfMap, + architecture, teamMemory), + fToDwarfMap(toDwarfMap), + fCpuState(cpuState) + { + fToDwarfMap->AcquireReference(); + fCpuState->AcquireReference(); + } + + ~UnwindTargetInterface() + { + fToDwarfMap->ReleaseReference(); + fCpuState->ReleaseReference(); + } + + virtual bool GetRegisterValue(uint32 index, BVariant& _value) const + { + const Register* reg = _RegisterAt(index); + if (reg == NULL) + return false; + return fCpuState->GetRegisterValue(reg, _value); + } + + virtual bool SetRegisterValue(uint32 index, const BVariant& value) + { + const Register* reg = _RegisterAt(index); + if (reg == NULL) + return false; + return fCpuState->SetRegisterValue(reg, value); + } + +private: + RegisterMap* fToDwarfMap; + CpuState* fCpuState; +}; + + // #pragma mark - EntryListWrapper @@ -169,13 +201,14 @@ struct DwarfImageDebugInfo::EntryListWrapper { DwarfImageDebugInfo::DwarfImageDebugInfo(const ImageInfo& imageInfo, Architecture* architecture, TeamMemory* teamMemory, - FileManager* fileManager, DwarfFile* file) + FileManager* fileManager, GlobalTypeLookup* typeLookup, DwarfFile* file) : fLock("dwarf image debug info"), fImageInfo(imageInfo), fArchitecture(architecture), fTeamMemory(teamMemory), fFileManager(fileManager), + fTypeLookup(typeLookup), fFile(file), fTextSegment(NULL), fRelocationDelta(0) @@ -320,6 +353,72 @@ DwarfImageDebugInfo::GetFunctions(BObjectList& functions) } +status_t +DwarfImageDebugInfo::GetType(GlobalTypeLookupContext* context, + const BString& name, Type*& _type) +{ + int32 registerCount = fArchitecture->CountRegisters(); + const Register* registers = fArchitecture->Registers(); + + // get the DWARF -> architecture register map + RegisterMap* fromDwarfMap; + status_t error = fArchitecture->GetDwarfRegisterMaps(NULL, &fromDwarfMap); + if (error != B_OK) + return error; + Reference fromDwarfMapReference(fromDwarfMap, true); + + // create the target interface + BasicTargetInterface inputInterface(registers, registerCount, fromDwarfMap, + fArchitecture, fTeamMemory); + + // iterate through all compilation units + for (int32 i = 0; CompilationUnit* unit = fFile->CompilationUnitAt(i); + i++) { + DwarfStackFrameDebugInfo* stackFrameDebugInfo = NULL; + Reference stackFrameDebugInfoReference; + + // iterate through all types of the compilation unit + for (DebugInfoEntryList::ConstIterator it + = unit->UnitEntry()->Types().GetIterator(); + DIEType* typeEntry = dynamic_cast(it.Next());) { + if (typeEntry->IsDeclaration()) + continue; + + BString typeEntryName; + DwarfUtils::GetFullyQualifiedDIEName(typeEntry, typeEntryName); + if (typeEntryName != name) + 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) + return B_NO_MEMORY; + stackFrameDebugInfoReference.SetTo(stackFrameDebugInfo, true); + + error = stackFrameDebugInfo->Init(); + if (error != B_OK) + return error; + } + + // create the type + Type* type; + error = stackFrameDebugInfo->CreateType(typeEntry, type); + if (error != B_OK) + continue; + + _type = type; + return B_OK; + } + } + + return B_ENTRY_NOT_FOUND; +} + + status_t DwarfImageDebugInfo::CreateFrame(Image* image, FunctionInstance* functionInstance, CpuState* cpuState, @@ -393,12 +492,24 @@ 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, instructionPointer, framePointer, inputInterface, - fromDwarfMap); + subprogramEntry, fTypeLookup, typeLookupContext, 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 5af655b763..e486152f08 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 GlobalTypeLookup; class LocatableFile; class SourceCode; class TeamMemory; @@ -33,7 +34,9 @@ public: DwarfImageDebugInfo(const ImageInfo& imageInfo, Architecture* architecture, TeamMemory* teamMemory, - FileManager* fileManager, DwarfFile* file); + FileManager* fileManager, + GlobalTypeLookup* typeLookup, + DwarfFile* file); virtual ~DwarfImageDebugInfo(); status_t Init(); @@ -43,6 +46,8 @@ public: virtual status_t GetFunctions( BObjectList& functions); + virtual status_t GetType(GlobalTypeLookupContext* context, + const BString& name, Type*& _type); virtual status_t CreateFrame(Image* image, FunctionInstance* functionInstance, CpuState* cpuState, @@ -66,6 +71,7 @@ public: FileSourceCode* sourceCode); private: + struct BasicTargetInterface; struct UnwindTargetInterface; struct EntryListWrapper; @@ -90,6 +96,7 @@ private: Architecture* fArchitecture; TeamMemory* fTeamMemory; FileManager* fFileManager; + GlobalTypeLookup* fTypeLookup; 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 fe822d23e1..e06f574d12 100644 --- a/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.cpp +++ b/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include "ArrayIndexPath.h" @@ -20,6 +21,7 @@ #include "DwarfUtils.h" #include "FunctionID.h" #include "FunctionParameterID.h" +#include "GlobalTypeLookup.h" #include "LocalVariableID.h" #include "Register.h" #include "RegisterMap.h" @@ -304,9 +306,6 @@ public: private: BString fName; target_size_t fByteSize; - -public: - DwarfType* fNext; }; @@ -1127,80 +1126,41 @@ private: }; -// #pragma mark - DwarfTypeHashDefinition - - -struct DwarfStackFrameDebugInfo::DwarfTypeHashDefinition { - typedef const DIEType* KeyType; - typedef DwarfType ValueType; - - size_t HashKey(const DIEType* key) const - { - return (addr_t)key; - } - - size_t Hash(const DwarfType* value) const - { - return HashKey(value->GetDIEType()); - } - - bool Compare(const DIEType* key, const DwarfType* value) const - { - return key == value->GetDIEType(); - } - - DwarfType*& GetLink(DwarfType* value) const - { - return value->fNext; - } -}; - - // #pragma mark - DwarfStackFrameDebugInfo DwarfStackFrameDebugInfo::DwarfStackFrameDebugInfo(Architecture* architecture, DwarfFile* file, CompilationUnit* compilationUnit, - DIESubprogram* subprogramEntry, target_addr_t instructionPointer, - target_addr_t framePointer, DwarfTargetInterface* targetInterface, - RegisterMap* fromDwarfRegisterMap) + DIESubprogram* subprogramEntry, GlobalTypeLookup* typeLookup, + GlobalTypeLookupContext* typeLookupContext, + target_addr_t instructionPointer, target_addr_t framePointer, + DwarfTargetInterface* targetInterface, RegisterMap* fromDwarfRegisterMap) : StackFrameDebugInfo(architecture), fFile(file), fCompilationUnit(compilationUnit), fSubprogramEntry(subprogramEntry), + fTypeLookup(typeLookup), + fTypeLookupContext(typeLookupContext), fInstructionPointer(instructionPointer), fFramePointer(framePointer), fTargetInterface(targetInterface), - fFromDwarfRegisterMap(fromDwarfRegisterMap), - fTypes(NULL) + fFromDwarfRegisterMap(fromDwarfRegisterMap) { + fTypeLookupContext->AcquireReference(); } DwarfStackFrameDebugInfo::~DwarfStackFrameDebugInfo() { - if (fTypes != NULL) { - DwarfType* type = fTypes->Clear(true); - while (type != NULL) { - DwarfType* next = type->fNext; - type->ReleaseReference(); - type = next; - } - - delete fTypes; - } + fTypeLookupContext->ReleaseReference(); } status_t DwarfStackFrameDebugInfo::Init() { - fTypes = new(std::nothrow) TypeTable; - if (fTypes == NULL) - return B_NO_MEMORY; - - return fTypes->Init(); + return B_OK; } @@ -1468,7 +1428,7 @@ DwarfStackFrameDebugInfo::ResolveArrayElementLocation(StackFrame* stackFrame, int64 byteOffset = elementOffset >= 0 ? elementOffset / 8 : (elementOffset - 7) / 8; piece.SetToMemory(piece.address + byteOffset); - piece.SetSize(type->BaseType()->ByteSize() * 8); + piece.SetSize(type->BaseType()->ByteSize()); // TODO: Support bit offsets correctly! // TODO: Support bit fields (primitive types) correctly! @@ -1647,39 +1607,73 @@ DwarfStackFrameDebugInfo::_ResolveDataMemberLocation(StackFrame* stackFrame, status_t DwarfStackFrameDebugInfo::_CreateType(DIEType* typeEntry, DwarfType*& _type) { - // Try the type cache first. If we don't know the type yet, create it. - DwarfType* type = fTypes->Lookup(typeEntry); + // 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). - if (type == NULL) { - status_t error = _CreateTypeInternal(typeEntry, type); - if (error != B_OK) - return error; - - // Insert the type into the hash table. Recheck, as the type may already - // have been inserted (e.g. in the compound type case). - if (fTypes->Lookup(typeEntry) == NULL) - fTypes->Insert(type); - - // try to get the type's size - uint64 size; - if (_ResolveTypeByteSize(typeEntry, size) == B_OK) - type->SetByteSize(size); + 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; + } } - type->AcquireReference(); - _type = type; + 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(DIEType* typeEntry, - DwarfType*& _type) +DwarfStackFrameDebugInfo::_CreateTypeInternal(const BString& name, + DIEType* typeEntry, DwarfType*& _type) { - BString name; - DwarfUtils::GetFullyQualifiedDIEName(typeEntry, name); -// TODO: The DIE may not have a name (e.g. pointer and reference types don't). - switch (typeEntry->Tag()) { case DW_TAG_class_type: case DW_TAG_structure_type: @@ -1775,10 +1769,17 @@ DwarfStackFrameDebugInfo::_CreateCompoundType(const BString& name, return B_NO_MEMORY; Reference typeReference(type, true); - // Already add the type at this pointer to the hash table, since otherwise + // 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. - fTypes->Insert(type); +// 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, @@ -1808,7 +1809,8 @@ DwarfStackFrameDebugInfo::_CreateCompoundType(const BString& name, memberEntry, memberName, memberType); Reference memberReference(member, true); if (member == NULL || !type->AddDataMember(member)) { - fTypes->Remove(type); + contextLocker.Lock(); + fTypeLookupContext->RemoveCachedType(name); return B_NO_MEMORY; } } @@ -1842,7 +1844,8 @@ DwarfStackFrameDebugInfo::_CreateCompoundType(const BString& name, Reference inheritanceReference(inheritance, true); if (inheritance == NULL || !type->AddInheritance(inheritance)) { - fTypes->Remove(type); + contextLocker.Lock(); + fTypeLookupContext->RemoveCachedType(name); return B_NO_MEMORY; } } diff --git a/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.h b/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.h index 2daab2b433..64f4f27076 100644 --- a/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.h +++ b/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.h @@ -8,8 +8,6 @@ #include -#include - #include "StackFrameDebugInfo.h" #include "Type.h" @@ -33,6 +31,8 @@ class DIEVariable; class DwarfFile; class DwarfTargetInterface; class FunctionID; +class GlobalTypeLookup; +class GlobalTypeLookupContext; class LocationDescription; class MemberLocation; class ObjectID; @@ -46,6 +46,8 @@ public: Architecture* architecture, DwarfFile* file, CompilationUnit* compilationUnit, DIESubprogram* subprogramEntry, + GlobalTypeLookup* typeLookup, + GlobalTypeLookupContext* typeLookupContext, target_addr_t instructionPointer, target_addr_t framePointer, DwarfTargetInterface* targetInterface, @@ -105,9 +107,6 @@ private: struct DwarfUnspecifiedType; struct DwarfFunctionType; struct DwarfPointerToMemberType; - struct DwarfTypeHashDefinition; - - typedef BOpenHashTable TypeTable; private: status_t _ResolveDataMemberLocation( @@ -121,8 +120,8 @@ private: status_t _CreateType(DIEType* typeEntry, DwarfType*& _type); - status_t _CreateTypeInternal(DIEType* typeEntry, - DwarfType*& _type); + status_t _CreateTypeInternal(const BString& name, + DIEType* typeEntry, DwarfType*& _type); status_t _CreateCompoundType(const BString& name, DIECompoundType* typeEntry, @@ -180,11 +179,12 @@ private: DwarfFile* fFile; CompilationUnit* fCompilationUnit; DIESubprogram* fSubprogramEntry; + GlobalTypeLookup* fTypeLookup; + GlobalTypeLookupContext* fTypeLookupContext; target_addr_t fInstructionPointer; target_addr_t fFramePointer; DwarfTargetInterface* fTargetInterface; RegisterMap* fFromDwarfRegisterMap; - TypeTable* fTypes; }; diff --git a/src/apps/debugger/debug_info/DwarfTeamDebugInfo.cpp b/src/apps/debugger/debug_info/DwarfTeamDebugInfo.cpp index 2b4b62a9b6..0cbdc89af9 100644 --- a/src/apps/debugger/debug_info/DwarfTeamDebugInfo.cpp +++ b/src/apps/debugger/debug_info/DwarfTeamDebugInfo.cpp @@ -15,12 +15,14 @@ DwarfTeamDebugInfo::DwarfTeamDebugInfo(Architecture* architecture, - TeamMemory* teamMemory, FileManager* fileManager) + TeamMemory* teamMemory, FileManager* fileManager, + GlobalTypeLookup* typeLookup) : fArchitecture(architecture), fTeamMemory(teamMemory), fFileManager(fileManager), - fManager(NULL) + fManager(NULL), + fTypeLookup(typeLookup) { } @@ -64,17 +66,17 @@ DwarfTeamDebugInfo::CreateImageDebugInfo(const ImageInfo& imageInfo, return error; // create the image debug info - DwarfImageDebugInfo* debuggerInfo = new(std::nothrow) DwarfImageDebugInfo( - imageInfo, fArchitecture, fTeamMemory, fFileManager, file); - if (debuggerInfo == NULL) + DwarfImageDebugInfo* debugInfo = new(std::nothrow) DwarfImageDebugInfo( + imageInfo, fArchitecture, fTeamMemory, fFileManager, fTypeLookup, file); + if (debugInfo == NULL) return B_NO_MEMORY; - error = debuggerInfo->Init(); + error = debugInfo->Init(); if (error != B_OK) { - delete debuggerInfo; + delete debugInfo; return error; } - _imageDebugInfo = debuggerInfo; + _imageDebugInfo = debugInfo; return B_OK; } diff --git a/src/apps/debugger/debug_info/DwarfTeamDebugInfo.h b/src/apps/debugger/debug_info/DwarfTeamDebugInfo.h index 9f6176f6a3..a8d6411cff 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 GlobalTypeLookup; class TeamMemory; @@ -19,7 +20,8 @@ class DwarfTeamDebugInfo : public SpecificTeamDebugInfo { public: DwarfTeamDebugInfo(Architecture* architecture, TeamMemory* teamMemory, - FileManager* fileManager); + FileManager* fileManager, + GlobalTypeLookup* typeLookup); virtual ~DwarfTeamDebugInfo(); status_t Init(); @@ -33,6 +35,7 @@ private: TeamMemory* fTeamMemory; FileManager* fFileManager; DwarfManager* fManager; + GlobalTypeLookup* fTypeLookup; }; diff --git a/src/apps/debugger/debug_info/GlobalTypeLookup.cpp b/src/apps/debugger/debug_info/GlobalTypeLookup.cpp new file mode 100644 index 0000000000..81061fbaea --- /dev/null +++ b/src/apps/debugger/debug_info/GlobalTypeLookup.cpp @@ -0,0 +1,142 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + + +#include "GlobalTypeLookup.h" + +#include + +#include + +#include "StringUtils.h" +#include "Type.h" + + +struct GlobalTypeLookupContext::TypeEntry { + BString name; + Type* type; + TypeEntry* fNext; + + TypeEntry(const BString& name, Type* type) + : + name(name), + type(type) + { + type->AcquireReference(); + } + + ~TypeEntry() + { + type->ReleaseReference(); + } +}; + + +struct GlobalTypeLookupContext::TypeEntryHashDefinition { + typedef const BString KeyType; + typedef TypeEntry ValueType; + + size_t HashKey(const BString& key) const + { + return StringUtils::HashValue(key); + } + + size_t Hash(const TypeEntry* value) const + { + return HashKey(value->name); + } + + bool Compare(const BString& key, const TypeEntry* value) const + { + return key == value->name; + } + + TypeEntry*& GetLink(TypeEntry* value) const + { + return value->fNext; + } +}; + + +// #pragma mark - GlobalTypeLookupContext + + +GlobalTypeLookupContext::GlobalTypeLookupContext() + : + fLock("global type lookup"), + fCachedTypes(NULL) +{ +} + + +GlobalTypeLookupContext::~GlobalTypeLookupContext() +{ + // release all cached type references + if (fCachedTypes != NULL) { + TypeEntry* entry = fCachedTypes->Clear(true); + while (entry != NULL) { + TypeEntry* nextEntry = entry->fNext; + delete entry; + entry = nextEntry; + } + } +} + + +status_t +GlobalTypeLookupContext::Init() +{ + status_t error = fLock.InitCheck(); + if (error != B_OK) + return error; + + fCachedTypes = new(std::nothrow) TypeTable; + if (fCachedTypes == NULL) + return B_NO_MEMORY; + + return fCachedTypes->Init(); +} + + +Type* +GlobalTypeLookupContext::CachedType(const BString& name) const +{ + TypeEntry* typeEntry = fCachedTypes->Lookup(name); + return typeEntry != NULL ? typeEntry->type : NULL; +} + + +status_t +GlobalTypeLookupContext::AddCachedType(const BString& name, Type* type) +{ + TypeEntry* typeEntry = fCachedTypes->Lookup(name); + if (typeEntry != NULL) + return B_BAD_VALUE; + + typeEntry = new(std::nothrow) TypeEntry(name, type); + if (typeEntry == NULL) + return B_NO_MEMORY; + + fCachedTypes->Insert(typeEntry); + return B_OK; +} + + +void +GlobalTypeLookupContext::RemoveCachedType(const BString& name) +{ + if (TypeEntry* typeEntry = fCachedTypes->Lookup(name)) { + fCachedTypes->Remove(typeEntry); + delete typeEntry; + } +} + + +// #pragma mark - GlobalTypeLookup + + +GlobalTypeLookup::~GlobalTypeLookup() +{ +} diff --git a/src/apps/debugger/debug_info/GlobalTypeLookup.h b/src/apps/debugger/debug_info/GlobalTypeLookup.h new file mode 100644 index 0000000000..544dea5502 --- /dev/null +++ b/src/apps/debugger/debug_info/GlobalTypeLookup.h @@ -0,0 +1,70 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef GLOBAL_TYPE_LOOKUP_H +#define GLOBAL_TYPE_LOOKUP_H + + +#include + +#include +#include + + +class BString; +class Type; + + +class GlobalTypeLookupContext : public Referenceable { +public: + GlobalTypeLookupContext(); + ~GlobalTypeLookupContext(); + + 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); + +private: + struct TypeEntry; + struct TypeEntryHashDefinition; + + typedef BOpenHashTable TypeTable; + +private: + BLocker fLock; + TypeTable* fCachedTypes; +}; + + +class GlobalTypeLookup { +public: + ~GlobalTypeLookup(); + + virtual status_t GetType(GlobalTypeLookupContext* context, + const BString& name, Type*& _type) = 0; + // returns a reference +}; + + +bool +GlobalTypeLookupContext::Lock() +{ + return fLock.Lock(); +} + + +void +GlobalTypeLookupContext::Unlock() +{ + fLock.Unlock(); +} + + +#endif // GLOBAL_TYPE_LOOKUP_H diff --git a/src/apps/debugger/debug_info/ImageDebugInfo.cpp b/src/apps/debugger/debug_info/ImageDebugInfo.cpp index e98be6223d..49ee4bceb2 100644 --- a/src/apps/debugger/debug_info/ImageDebugInfo.cpp +++ b/src/apps/debugger/debug_info/ImageDebugInfo.cpp @@ -75,6 +75,21 @@ ImageDebugInfo::FinishInit() } +status_t +ImageDebugInfo::GetType(GlobalTypeLookupContext* context, const BString& name, + Type*& _type) +{ + for (int32 i = 0; SpecificImageDebugInfo* specificInfo + = fSpecificInfos.ItemAt(i); i++) { + status_t error = specificInfo->GetType(context, name, _type); + if (error == B_OK || error == B_NO_MEMORY) + return error; + } + + return B_ENTRY_NOT_FOUND; +} + + int32 ImageDebugInfo::CountFunctions() const { diff --git a/src/apps/debugger/debug_info/ImageDebugInfo.h b/src/apps/debugger/debug_info/ImageDebugInfo.h index 887129efb7..31d1b96196 100644 --- a/src/apps/debugger/debug_info/ImageDebugInfo.h +++ b/src/apps/debugger/debug_info/ImageDebugInfo.h @@ -5,6 +5,7 @@ #ifndef IMAGE_DEBUG_INFO_H #define IMAGE_DEBUG_INFO_H + #include #include @@ -19,8 +20,10 @@ class DebuggerInterface; class FileSourceCode; class FunctionDebugInfo; class FunctionInstance; +class GlobalTypeLookupContext; class LocatableFile; class SpecificImageDebugInfo; +class Type; class ImageDebugInfo : public Referenceable { @@ -33,6 +36,10 @@ public: bool AddSpecificInfo(SpecificImageDebugInfo* info); status_t FinishInit(); + status_t GetType(GlobalTypeLookupContext* context, + const BString& name, Type*& _type); + // returns a reference + int32 CountFunctions() const; FunctionInstance* FunctionAt(int32 index) const; FunctionInstance* FunctionAtAddress(target_addr_t address) const; diff --git a/src/apps/debugger/debug_info/SpecificImageDebugInfo.h b/src/apps/debugger/debug_info/SpecificImageDebugInfo.h index a34e1b8ed6..8061974ae0 100644 --- a/src/apps/debugger/debug_info/SpecificImageDebugInfo.h +++ b/src/apps/debugger/debug_info/SpecificImageDebugInfo.h @@ -5,6 +5,7 @@ #ifndef SPECIFIC_IMAGE_DEBUG_INFO_H #define SPECIFIC_IMAGE_DEBUG_INFO_H + #include #include @@ -12,12 +13,14 @@ class Architecture; +class BString; class CpuState; class DataMember; class DebuggerInterface; class FileSourceCode; class FunctionDebugInfo; class FunctionInstance; +class GlobalTypeLookupContext; class Image; class LocatableFile; class SourceLanguage; @@ -37,6 +40,10 @@ public: = 0; // returns references + virtual status_t GetType(GlobalTypeLookupContext* context, + const BString& name, Type*& _type) = 0; + // returns a reference + virtual status_t CreateFrame(Image* image, FunctionInstance* functionInstance, CpuState* cpuState, diff --git a/src/apps/debugger/debug_info/TeamDebugInfo.cpp b/src/apps/debugger/debug_info/TeamDebugInfo.cpp index 1408d0f10e..e024485972 100644 --- a/src/apps/debugger/debug_info/TeamDebugInfo.cpp +++ b/src/apps/debugger/debug_info/TeamDebugInfo.cpp @@ -28,6 +28,7 @@ #include "SourceLanguage.h" #include "SpecificImageDebugInfo.h" #include "StringUtils.h" +#include "Type.h" // #pragma mark - FunctionHashDefinition @@ -319,7 +320,7 @@ TeamDebugInfo::Init() // DWARF DwarfTeamDebugInfo* dwarfInfo = new(std::nothrow) DwarfTeamDebugInfo( - fArchitecture, fDebuggerInterface, fFileManager); + fArchitecture, fDebuggerInterface, fFileManager, this); if (dwarfInfo == NULL || !fSpecificInfos.AddItem(dwarfInfo)) { delete dwarfInfo; return B_NO_MEMORY; @@ -346,6 +347,51 @@ TeamDebugInfo::Init() } +status_t +TeamDebugInfo::GetType(GlobalTypeLookupContext* context, const BString& name, + Type*& _type) +{ + // maybe the type is already cached + AutoLocker contextLocker(context); + Type* type = context->CachedType(name); + if (type != NULL) { + type->AcquireReference(); + _type = type; + return B_OK; + } + + contextLocker.Unlock(); + + // Clone the image list and get references to the images, so we can iterate + // through them without locking. + AutoLocker locker(fLock); + + ImageList images; + for (int32 i = 0; ImageDebugInfo* imageDebugInfo = fImages.ItemAt(i); i++) { + if (images.AddItem(imageDebugInfo)) + imageDebugInfo->AcquireReference(); + } + + locker.Unlock(); + + // 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); + if (error == B_OK) { + _type = type; + break; + } + } + + // release the references + for (int32 i = 0; ImageDebugInfo* imageDebugInfo = images.ItemAt(i); i++) + imageDebugInfo->ReleaseReference(); + + return error; +} + + status_t TeamDebugInfo::LoadImageDebugInfo(const ImageInfo& imageInfo, LocatableFile* imageFile, ImageDebugInfo*& _imageDebugInfo) diff --git a/src/apps/debugger/debug_info/TeamDebugInfo.h b/src/apps/debugger/debug_info/TeamDebugInfo.h index ea3ab63958..639f0dc9b2 100644 --- a/src/apps/debugger/debug_info/TeamDebugInfo.h +++ b/src/apps/debugger/debug_info/TeamDebugInfo.h @@ -12,6 +12,7 @@ #include #include +#include "GlobalTypeLookup.h" #include "ImageInfo.h" @@ -31,7 +32,7 @@ class SourceLocation; class SpecificTeamDebugInfo; -class TeamDebugInfo : public Referenceable { +class TeamDebugInfo : public Referenceable, public GlobalTypeLookup { public: TeamDebugInfo( DebuggerInterface* debuggerInterface, @@ -41,6 +42,9 @@ public: status_t Init(); + virtual status_t GetType(GlobalTypeLookupContext* context, + const BString& name, Type*& _type); + status_t LoadImageDebugInfo(const ImageInfo& imageInfo, LocatableFile* imageFile, ImageDebugInfo*& _imageDebugInfo); diff --git a/src/apps/debugger/dwarf/DwarfFile.cpp b/src/apps/debugger/dwarf/DwarfFile.cpp index 77638bd00b..4551933e86 100644 --- a/src/apps/debugger/dwarf/DwarfFile.cpp +++ b/src/apps/debugger/dwarf/DwarfFile.cpp @@ -61,6 +61,9 @@ public: virtual bool GetFrameAddress(target_addr_t& _address) { + if (fFramePointer == 0) + return false; + _address = fFramePointer; return true; } @@ -79,6 +82,8 @@ public: fFrameBaseEvaluated = true; // get the subprogram's frame base location + if (fSubprogramEntry == NULL) + return false; const LocationDescription* location = fSubprogramEntry->FrameBase(); if (!location->IsValid()) return false; @@ -219,8 +224,7 @@ DwarfFile::Load(const char* fileName) fDebugLineSection = fElfFile->GetSection(".debug_line"); fDebugFrameSection = fElfFile->GetSection(".debug_frame"); fDebugLocationSection = fElfFile->GetSection(".debug_loc"); -// fDebugPublicTypesSection = fElfFile->GetSection(".debug_pubtypes"); -fDebugPublicTypesSection = fElfFile->GetSection(".debug_pubnames"); + fDebugPublicTypesSection = fElfFile->GetSection(".debug_pubtypes"); // iterate through the debug info section DataReader dataReader(fDebugInfoSection->Data(), @@ -1914,7 +1918,7 @@ DwarfFile::_GetLocationExpression(CompilationUnit* unit, return B_OK; } - if (location->IsLocationList()) { + if (location->IsLocationList() && instructionPointer != 0) { return _FindLocationExpression(unit, location->listOffset, instructionPointer, _expression, _length); }