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); }