From 5b60969c5cd42c27295bb89746ef6882c0559a7a Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Mon, 29 Jun 2009 22:38:15 +0000 Subject: [PATCH] * Renamed ArchitectureTypes.h to Types.h. * Created "types" subdirectory for basic types and moved Types.h, SourceLocation, TargetAddressRange there. * Added TargetAddressRangeList, representing a list of address ranges. * Array: Added copy constructor and assignment operator. * Added DwarfFunctionDebugInfo. * ElfFile: Also read the program headers and provide access to the segment information. * DWARF: - Some work on DIECompileUnitBase and DIESubprogram to handle attributes we need. - Added DwarfUtils class which provides static utility methods. Currently some to get DIE names. Only provisionally implemented yet. - Read range list attribute values from the .debug_ranges section. Extended AttributeValue to handle them correctly (ref-counting). * DwarfImageDebugInfo: - Implemented GetFunctions() for real, i.e. we return functions for all subprogram debug info entries we find (those that refer to actual functions, that is). - Implemented the fallback part of LoadSourceCode() (reading the code from the file and disassembling it). Things should hopefully work as before, just a bit slower and with less accurate function names, if DWARF debug info is available. Promising, eh? ;-) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31321 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/apps/debugger/Array.h | 29 +++ src/apps/debugger/Jamfile | 6 + src/apps/debugger/arch/Architecture.h | 2 +- src/apps/debugger/arch/CpuState.h | 2 +- src/apps/debugger/arch/InstructionInfo.h | 2 +- .../arch/x86/disasm/DisassemblerX86.h | 2 +- src/apps/debugger/arch/x86/disasm/Jamfile | 1 + .../debug_info/DwarfFunctionDebugInfo.cpp | 86 +++++++ .../debug_info/DwarfFunctionDebugInfo.h | 44 ++++ .../debug_info/DwarfImageDebugInfo.cpp | 119 +++++++++- .../debugger/debug_info/DwarfImageDebugInfo.h | 6 + .../debugger/debug_info/FunctionDebugInfo.h | 2 +- src/apps/debugger/debug_info/ImageDebugInfo.h | 2 +- .../debug_info/SpecificImageDebugInfo.h | 2 +- .../debugger/debugger_interface/DebugEvent.h | 2 +- src/apps/debugger/dwarf/AttributeValue.h | 96 ++++++++ src/apps/debugger/dwarf/DebugInfoEntries.cpp | 213 ++++++++++++++++++ src/apps/debugger/dwarf/DebugInfoEntries.h | 84 ++++++- src/apps/debugger/dwarf/DebugInfoEntry.cpp | 31 ++- src/apps/debugger/dwarf/DebugInfoEntry.h | 13 ++ src/apps/debugger/dwarf/DwarfFile.cpp | 103 +++++++-- src/apps/debugger/dwarf/DwarfFile.h | 7 +- src/apps/debugger/dwarf/DwarfUtils.cpp | 79 +++++++ src/apps/debugger/dwarf/DwarfUtils.h | 27 +++ src/apps/debugger/dwarf/Jamfile | 2 + src/apps/debugger/elf/ElfFile.cpp | 100 +++++++- src/apps/debugger/elf/ElfFile.h | 31 +++ .../debugger/gui/team_window/SourceView.h | 2 +- src/apps/debugger/model/Breakpoint.h | 2 +- src/apps/debugger/model/ImageInfo.h | 2 +- src/apps/debugger/model/StackFrame.h | 2 +- src/apps/debugger/model/Statement.h | 2 +- src/apps/debugger/model/SymbolInfo.h | 2 +- .../{model => types}/SourceLocation.h | 0 .../{arch => types}/TargetAddressRange.h | 18 +- .../debugger/types/TargetAddressRangeList.cpp | 91 ++++++++ .../debugger/types/TargetAddressRangeList.h | 51 +++++ .../ArchitectureTypes.h => types/Types.h} | 0 38 files changed, 1208 insertions(+), 57 deletions(-) create mode 100644 src/apps/debugger/debug_info/DwarfFunctionDebugInfo.cpp create mode 100644 src/apps/debugger/debug_info/DwarfFunctionDebugInfo.h create mode 100644 src/apps/debugger/dwarf/DwarfUtils.cpp create mode 100644 src/apps/debugger/dwarf/DwarfUtils.h rename src/apps/debugger/{model => types}/SourceLocation.h (100%) rename src/apps/debugger/{arch => types}/TargetAddressRange.h (81%) create mode 100644 src/apps/debugger/types/TargetAddressRangeList.cpp create mode 100644 src/apps/debugger/types/TargetAddressRangeList.h rename src/apps/debugger/{arch/ArchitectureTypes.h => types/Types.h} (100%) diff --git a/src/apps/debugger/Array.h b/src/apps/debugger/Array.h index ba6dd180d3..4a9c2b92ee 100644 --- a/src/apps/debugger/Array.h +++ b/src/apps/debugger/Array.h @@ -14,6 +14,7 @@ template class Array { public: inline Array(); + Array(const Array& other); ~Array(); inline int Size() const { return fSize; } @@ -34,6 +35,8 @@ public: inline Element& operator[](int index); inline const Element& operator[](int index) const; + Array& operator=(const Array& other); + private: static const int kMinCapacity = 8; @@ -56,6 +59,17 @@ Array::Array() } +template +Array::Array(const Array& other) + : + fElements(NULL), + fSize(0), + fCapacity(0) +{ + *this = other; +} + + template Array::~Array() { @@ -177,6 +191,21 @@ Array::operator[](int index) const } +template +Array& +Array::operator=(const Array& other) +{ + Clear(); + + if (other.fSize > 0 && _Resize(0, other.fSize)) { + fSize = other.fSize; + memcpy(fElements, other.fElements, fSize * sizeof(Element)); + } + + return *this; +} + + template bool Array::_Resize(int index, int delta) diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile index 1b582a1333..f77f840674 100644 --- a/src/apps/debugger/Jamfile +++ b/src/apps/debugger/Jamfile @@ -13,6 +13,7 @@ SEARCH_SOURCE += [ FDirName $(SUBDIR) debugger_interface ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) elf ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) gui team_window ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) model ] ; +SEARCH_SOURCE += [ FDirName $(SUBDIR) types ] ; local debugAnalyzerSources = [ FDirName $(HAIKU_TOP) src apps debuganalyzer ] ; @@ -22,6 +23,7 @@ SubDirHdrs [ FDirName $(HAIKU_TOP) src bin debug ] ; SubDirHdrs [ FDirName $(debugAnalyzerSources) gui ] ; SourceHdrs + DwarfFunctionDebugInfo.cpp DwarfImageDebugInfo.cpp DwarfTeamDebugInfo.cpp : [ FDirName $(SUBDIR) dwarf ] @@ -49,6 +51,7 @@ Application Debugger : BasicFunctionDebugInfo.cpp DebuggerImageDebugInfo.cpp DebuggerTeamDebugInfo.cpp + DwarfFunctionDebugInfo.cpp DwarfImageDebugInfo.cpp DwarfTeamDebugInfo.cpp FunctionDebugInfo.cpp @@ -90,6 +93,9 @@ Application Debugger : Thread.cpp ThreadInfo.cpp + # types + TargetAddressRangeList.cpp + : Debugger_demangler.o Debugger_disasm_x86.o diff --git a/src/apps/debugger/arch/Architecture.h b/src/apps/debugger/arch/Architecture.h index 4575b8ed48..edb4390676 100644 --- a/src/apps/debugger/arch/Architecture.h +++ b/src/apps/debugger/arch/Architecture.h @@ -9,7 +9,7 @@ #include -#include "ArchitectureTypes.h" +#include "Types.h" class CpuState; diff --git a/src/apps/debugger/arch/CpuState.h b/src/apps/debugger/arch/CpuState.h index 6ebd1cdb9c..7f53d27fb9 100644 --- a/src/apps/debugger/arch/CpuState.h +++ b/src/apps/debugger/arch/CpuState.h @@ -10,7 +10,7 @@ #include #include -#include "ArchitectureTypes.h" +#include "Types.h" class Register; diff --git a/src/apps/debugger/arch/InstructionInfo.h b/src/apps/debugger/arch/InstructionInfo.h index 03452a3f2e..36c2fa2834 100644 --- a/src/apps/debugger/arch/InstructionInfo.h +++ b/src/apps/debugger/arch/InstructionInfo.h @@ -7,7 +7,7 @@ #include -#include "ArchitectureTypes.h" +#include "Types.h" enum instruction_type { diff --git a/src/apps/debugger/arch/x86/disasm/DisassemblerX86.h b/src/apps/debugger/arch/x86/disasm/DisassemblerX86.h index 6383750018..b66a0adbcd 100644 --- a/src/apps/debugger/arch/x86/disasm/DisassemblerX86.h +++ b/src/apps/debugger/arch/x86/disasm/DisassemblerX86.h @@ -7,7 +7,7 @@ #include -#include "ArchitectureTypes.h" +#include "Types.h" class DisassemblerX86 { diff --git a/src/apps/debugger/arch/x86/disasm/Jamfile b/src/apps/debugger/arch/x86/disasm/Jamfile index 0fd56ee5c7..a916ab0144 100644 --- a/src/apps/debugger/arch/x86/disasm/Jamfile +++ b/src/apps/debugger/arch/x86/disasm/Jamfile @@ -7,6 +7,7 @@ UseHeaders [ LibraryHeaders udis86 ] ; UseHeaders [ LibraryHeaders [ FDirName udis86 libudis86 ] ] ; SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) ] ; +SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) $(DOTDOT) types ] ; MergeObject Debugger_disasm_x86.o diff --git a/src/apps/debugger/debug_info/DwarfFunctionDebugInfo.cpp b/src/apps/debugger/debug_info/DwarfFunctionDebugInfo.cpp new file mode 100644 index 0000000000..6a396a8459 --- /dev/null +++ b/src/apps/debugger/debug_info/DwarfFunctionDebugInfo.cpp @@ -0,0 +1,86 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "DwarfFunctionDebugInfo.h" + +#include "DebugInfoEntries.h" +#include "DwarfImageDebugInfo.h" +#include "TargetAddressRangeList.h" + + +DwarfFunctionDebugInfo::DwarfFunctionDebugInfo( + DwarfImageDebugInfo* imageDebugInfo, DIESubprogram* subprogramEntry, + TargetAddressRangeList* addressRanges, const BString& name) + : + fImageDebugInfo(imageDebugInfo), + fAddressRanges(addressRanges), + fName(name) +{ + fImageDebugInfo->AddReference(); + fAddressRanges->AddReference(); +} + + +DwarfFunctionDebugInfo::~DwarfFunctionDebugInfo() +{ + fAddressRanges->RemoveReference(); + fImageDebugInfo->RemoveReference(); +} + + +SpecificImageDebugInfo* +DwarfFunctionDebugInfo::GetSpecificImageDebugInfo() const +{ + return fImageDebugInfo; +} + + +target_addr_t +DwarfFunctionDebugInfo::Address() const +{ + return fAddressRanges->LowestAddress() + fImageDebugInfo->RelocationDelta(); +} + + +target_size_t +DwarfFunctionDebugInfo::Size() const +{ + return fAddressRanges->CoveringRange().Size(); +} + + +const char* +DwarfFunctionDebugInfo::Name() const +{ + return fName.String(); +} + + +const char* +DwarfFunctionDebugInfo::PrettyName() const +{ + return fName.String(); +} + + +const char* +DwarfFunctionDebugInfo::SourceFileName() const +{ + return NULL; +} + + +SourceLocation +DwarfFunctionDebugInfo::SourceStartLocation() const +{ + return SourceLocation(); +} + + +SourceLocation +DwarfFunctionDebugInfo::SourceEndLocation() const +{ + return SourceLocation(); +} diff --git a/src/apps/debugger/debug_info/DwarfFunctionDebugInfo.h b/src/apps/debugger/debug_info/DwarfFunctionDebugInfo.h new file mode 100644 index 0000000000..4f7f025f0b --- /dev/null +++ b/src/apps/debugger/debug_info/DwarfFunctionDebugInfo.h @@ -0,0 +1,44 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef DWARF_FUNCTION_DEBUG_INFO_H +#define DWARF_FUNCTION_DEBUG_INFO_H + +#include + +#include "FunctionDebugInfo.h" + + +class DIESubprogram; +class DwarfImageDebugInfo; +class TargetAddressRangeList; + + +class DwarfFunctionDebugInfo : public FunctionDebugInfo { +public: + DwarfFunctionDebugInfo( + DwarfImageDebugInfo* imageDebugInfo, + DIESubprogram* subprogramEntry, + TargetAddressRangeList* addressRanges, + const BString& name); + virtual ~DwarfFunctionDebugInfo(); + + virtual SpecificImageDebugInfo* GetSpecificImageDebugInfo() const; + virtual target_addr_t Address() const; + virtual target_size_t Size() const; + virtual const char* Name() const; + virtual const char* PrettyName() const; + + virtual const char* SourceFileName() const; + virtual SourceLocation SourceStartLocation() const; + virtual SourceLocation SourceEndLocation() const; + +private: + DwarfImageDebugInfo* fImageDebugInfo; + TargetAddressRangeList* fAddressRanges; + const BString fName; +}; + + +#endif // DWARF_FUNCTION_DEBUG_INFO_H diff --git a/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp b/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp index 76b36632cb..8090654e74 100644 --- a/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp +++ b/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp @@ -6,6 +6,7 @@ #include "DwarfImageDebugInfo.h" #include +#include #include @@ -16,6 +17,9 @@ #include "DebugInfoEntries.h" #include "Dwarf.h" #include "DwarfFile.h" +#include "DwarfFunctionDebugInfo.h" +#include "DwarfUtils.h" +#include "ElfFile.h" DwarfImageDebugInfo::DwarfImageDebugInfo(const ImageInfo& imageInfo, @@ -23,7 +27,9 @@ DwarfImageDebugInfo::DwarfImageDebugInfo(const ImageInfo& imageInfo, : fImageInfo(imageInfo), fArchitecture(architecture), - fFile(file) + fFile(file), + fTextSegment(NULL), + fRelocationDelta(0) { } @@ -36,6 +42,12 @@ DwarfImageDebugInfo::~DwarfImageDebugInfo() status_t DwarfImageDebugInfo::Init() { + fTextSegment = fFile->GetElfFile()->TextSegment(); + if (fTextSegment == NULL) + return B_ENTRY_NOT_FOUND; + + fRelocationDelta = fImageInfo.TextBase() - fTextSegment->LoadAddress(); + return B_OK; } @@ -48,22 +60,94 @@ printf(" %ld compilation units\n", fFile->CountCompilationUnits()); for (int32 i = 0; CompilationUnit* unit = fFile->CompilationUnitAt(i); i++) { - printf(" %s:\n", unit->UnitEntry()->Name()); + DIECompileUnitBase* unitEntry = unit->UnitEntry(); +// printf(" %s:\n", unitEntry->Name()); +// printf(" address ranges:\n"); +// TargetAddressRangeList* rangeList = unitEntry->AddressRanges(); +// if (rangeList != NULL) { +// int32 count = rangeList->CountRanges(); +// for (int32 i = 0; i < count; i++) { +// TargetAddressRange range = rangeList->RangeAt(i); +// printf(" %#llx - %#llx\n", range.Start(), range.End()); +// } +// } else { +// printf(" %#llx - %#llx\n", (target_addr_t)unitEntry->LowPC(), +// (target_addr_t)unitEntry->HighPC()); +// } +// printf(" functions:\n"); for (DebugInfoEntryList::ConstIterator it - = unit->UnitEntry()->OtherChildren().GetIterator(); + = unitEntry->OtherChildren().GetIterator(); DebugInfoEntry* entry = it.Next();) { if (entry->Tag() != DW_TAG_subprogram) continue; DIESubprogram* subprogramEntry = static_cast(entry); - printf(" subprogram entry: %p, name: %s, declaration: %d\n", - subprogramEntry, subprogramEntry->Name(), - subprogramEntry->IsDeclaration()); + + // ignore declarations, prototypes, and inlined functions + if (subprogramEntry->IsDeclaration() + || subprogramEntry->IsPrototyped() + || subprogramEntry->Inline() == DW_INL_inlined + || subprogramEntry->Inline() == DW_INL_declared_inlined + || subprogramEntry->AbstractOrigin() != NULL) { + continue; + } + + // get the name + BString name; + DwarfUtils::GetFullyQualifiedDIEName(subprogramEntry, name); + if (name.Length() == 0) + continue; + + // get the address ranges + TargetAddressRangeList* rangeList + = subprogramEntry->AddressRanges(); + Reference rangeListReference(rangeList); + if (rangeList == NULL) { + target_addr_t lowPC = subprogramEntry->LowPC(); + target_addr_t highPC = subprogramEntry->HighPC(); + if (lowPC >= highPC) + continue; + + rangeList = new(std::nothrow) TargetAddressRangeList( + TargetAddressRange(lowPC, highPC - lowPC)); + if (rangeList == NULL) + return B_NO_MEMORY; + // TODO: Clean up already added functions! + rangeListReference.SetTo(rangeList, true); + } + + // create and add the functions + DwarfFunctionDebugInfo* function + = new(std::nothrow) DwarfFunctionDebugInfo(this, + subprogramEntry, rangeList, name); + if (function == NULL || !functions.AddItem(function)) { + delete function; + return B_NO_MEMORY; + // TODO: Clean up already added functions! + } + +// BString name; +// DwarfUtils::GetFullyQualifiedDIEName(subprogramEntry, name); +// printf(" subprogram entry: %p, name: %s, declaration: %d\n", +// subprogramEntry, name.String(), +// subprogramEntry->IsDeclaration()); +// +// rangeList = subprogramEntry->AddressRanges(); +// if (rangeList != NULL) { +// int32 count = rangeList->CountRanges(); +// for (int32 i = 0; i < count; i++) { +// TargetAddressRange range = rangeList->RangeAt(i); +// printf(" %#llx - %#llx\n", range.Start(), range.End()); +// } +// } else { +// printf(" %#llx - %#llx\n", +// (target_addr_t)subprogramEntry->LowPC(), +// (target_addr_t)subprogramEntry->HighPC()); +// } } } - // TODO:... return B_OK; } @@ -82,8 +166,25 @@ status_t DwarfImageDebugInfo::LoadSourceCode(FunctionDebugInfo* function, SourceCode*& _sourceCode) { - // TODO:... - return B_UNSUPPORTED; + // TODO: Load the actual source code! + + static const target_size_t kMaxBufferSize = 64 * 1024; + target_size_t bufferSize = std::min(function->Size(), kMaxBufferSize); + void* buffer = malloc(bufferSize); + if (buffer == NULL) + return B_NO_MEMORY; + MemoryDeleter bufferDeleter(buffer); + + // read the function code + target_addr_t functionOffset = function->Address() - fRelocationDelta + - fTextSegment->LoadAddress() + fTextSegment->FileOffset(); + ssize_t bytesRead = pread(fFile->GetElfFile()->FD(), buffer, bufferSize, + functionOffset); + if (bytesRead < 0) + return bytesRead; + + return fArchitecture->DisassembleCode(function, buffer, bytesRead, + _sourceCode); } diff --git a/src/apps/debugger/debug_info/DwarfImageDebugInfo.h b/src/apps/debugger/debug_info/DwarfImageDebugInfo.h index 4f944302aa..f5cad8a14d 100644 --- a/src/apps/debugger/debug_info/DwarfImageDebugInfo.h +++ b/src/apps/debugger/debug_info/DwarfImageDebugInfo.h @@ -11,6 +11,7 @@ class Architecture; class DwarfFile; +class ElfSegment; class DwarfImageDebugInfo : public SpecificImageDebugInfo { @@ -22,6 +23,9 @@ public: status_t Init(); + target_addr_t RelocationDelta() const + { return fRelocationDelta; } + virtual status_t GetFunctions( BObjectList& functions); virtual status_t CreateFrame(Image* image, @@ -39,6 +43,8 @@ private: ImageInfo fImageInfo; Architecture* fArchitecture; DwarfFile* fFile; + ElfSegment* fTextSegment; + target_addr_t fRelocationDelta; }; diff --git a/src/apps/debugger/debug_info/FunctionDebugInfo.h b/src/apps/debugger/debug_info/FunctionDebugInfo.h index 8204ebf440..63181814a1 100644 --- a/src/apps/debugger/debug_info/FunctionDebugInfo.h +++ b/src/apps/debugger/debug_info/FunctionDebugInfo.h @@ -8,8 +8,8 @@ #include #include -#include "ArchitectureTypes.h" #include "SourceLocation.h" +#include "Types.h" enum function_source_state { diff --git a/src/apps/debugger/debug_info/ImageDebugInfo.h b/src/apps/debugger/debug_info/ImageDebugInfo.h index 0464531122..593fee331e 100644 --- a/src/apps/debugger/debug_info/ImageDebugInfo.h +++ b/src/apps/debugger/debug_info/ImageDebugInfo.h @@ -10,8 +10,8 @@ #include #include -#include "ArchitectureTypes.h" #include "ImageInfo.h" +#include "Types.h" class Architecture; diff --git a/src/apps/debugger/debug_info/SpecificImageDebugInfo.h b/src/apps/debugger/debug_info/SpecificImageDebugInfo.h index 863acbfacf..85d4fd1588 100644 --- a/src/apps/debugger/debug_info/SpecificImageDebugInfo.h +++ b/src/apps/debugger/debug_info/SpecificImageDebugInfo.h @@ -8,7 +8,7 @@ #include #include -#include "ArchitectureTypes.h" +#include "Types.h" class Architecture; diff --git a/src/apps/debugger/debugger_interface/DebugEvent.h b/src/apps/debugger/debugger_interface/DebugEvent.h index 47fdc6f0fd..c53087c0bf 100644 --- a/src/apps/debugger/debugger_interface/DebugEvent.h +++ b/src/apps/debugger/debugger_interface/DebugEvent.h @@ -7,8 +7,8 @@ #include -#include "ArchitectureTypes.h" #include "ImageInfo.h" +#include "Types.h" class CpuState; diff --git a/src/apps/debugger/dwarf/AttributeValue.h b/src/apps/debugger/dwarf/AttributeValue.h index ad29ab832d..f3b0ba22d5 100644 --- a/src/apps/debugger/dwarf/AttributeValue.h +++ b/src/apps/debugger/dwarf/AttributeValue.h @@ -7,6 +7,7 @@ #include "AttributeClasses.h" #include "DwarfTypes.h" +#include "TargetAddressRangeList.h" class DebugInfoEntry; @@ -21,6 +22,7 @@ struct AttributeValue { } block; uint64 constant; bool flag; + TargetAddressRangeList* rangeList; dwarf_off_t pointer; DebugInfoEntry* reference; const char* string; @@ -30,6 +32,100 @@ struct AttributeValue { uint8 attributeClass; bool isSigned; + AttributeValue() + : + attributeClass(ATTRIBUTE_CLASS_UNKNOWN) + { + } + + ~AttributeValue() + { + Unset(); + } + + void SetToAddress(dwarf_addr_t address) + { + Unset(); + attributeClass = ATTRIBUTE_CLASS_ADDRESS; + this->address = address; + } + + void SetToBlock(const void* data, dwarf_size_t length) + { + Unset(); + attributeClass = ATTRIBUTE_CLASS_BLOCK; + block.data = data; + block.length = length; + } + + void SetToConstant(uint64 value, bool isSigned) + { + Unset(); + attributeClass = ATTRIBUTE_CLASS_CONSTANT; + this->constant = value; + this->isSigned = isSigned; + } + + void SetToFlag(bool value) + { + Unset(); + attributeClass = ATTRIBUTE_CLASS_FLAG; + this->flag = value; + } + + void SetToLinePointer(dwarf_off_t value) + { + Unset(); + attributeClass = ATTRIBUTE_CLASS_LINEPTR; + this->pointer = value; + } + + void SetToLocationListPointer(dwarf_off_t value) + { + Unset(); + attributeClass = ATTRIBUTE_CLASS_LOCLISTPTR; + this->pointer = value; + } + + void SetToMacroPointer(dwarf_off_t value) + { + Unset(); + attributeClass = ATTRIBUTE_CLASS_MACPTR; + this->pointer = value; + } + + void SetToRangeList(TargetAddressRangeList* rangeList) + { + Unset(); + attributeClass = ATTRIBUTE_CLASS_RANGELISTPTR; + this->rangeList = rangeList; + if (rangeList != NULL) + rangeList->AddReference(); + } + + void SetToReference(DebugInfoEntry* entry) + { + Unset(); + attributeClass = ATTRIBUTE_CLASS_REFERENCE; + this->reference = entry; + } + + void SetToString(const char* string) + { + Unset(); + attributeClass = ATTRIBUTE_CLASS_STRING; + this->string = string; + } + + void Unset() + { + if (attributeClass == ATTRIBUTE_CLASS_RANGELISTPTR + && rangeList != NULL) { + rangeList->RemoveReference(); + } + attributeClass = ATTRIBUTE_CLASS_UNKNOWN; + } + const char* ToString(char* buffer, size_t size); }; diff --git a/src/apps/debugger/dwarf/DebugInfoEntries.cpp b/src/apps/debugger/dwarf/DebugInfoEntries.cpp index aa7983755a..3942c0a888 100644 --- a/src/apps/debugger/dwarf/DebugInfoEntries.cpp +++ b/src/apps/debugger/dwarf/DebugInfoEntries.cpp @@ -24,6 +24,7 @@ DIECompileUnitBase::DIECompileUnitBase() fStatementListOffset(0), fMacroInfoOffset(0), // TODO: Is 0 a good invalid offset? + fAddressRanges(NULL), fBaseTypesUnit(NULL), fLanguage(0), fIdentifierCase(0), @@ -32,6 +33,13 @@ DIECompileUnitBase::DIECompileUnitBase() } +DIECompileUnitBase::~DIECompileUnitBase() +{ + if (fAddressRanges != NULL) + fAddressRanges->RemoveReference(); +} + + status_t DIECompileUnitBase::InitAfterAttributes(DebugInfoEntryInitInfo& info) { @@ -65,6 +73,16 @@ DIECompileUnitBase::Name() const } +dwarf_addr_t +DIECompileUnitBase::AddressRangeBase() const +{ + if (fAddressRanges != NULL) + return fAddressRanges->LowestAddress(); + + return fLowPC; +} + + status_t DIECompileUnitBase::AddChild(DebugInfoEntry* child) { @@ -175,6 +193,22 @@ DIECompileUnitBase::AddAttribute_use_UTF8(uint16 attributeName, } +status_t +DIECompileUnitBase::AddAttribute_ranges(uint16 attributeName, + const AttributeValue& value) +{ + if (fAddressRanges != NULL) + fAddressRanges->RemoveReference(); + + fAddressRanges = value.rangeList; + + if (fAddressRanges != NULL) + fAddressRanges->AddReference(); + + return B_OK; +} + + // #pragma mark - DIEType @@ -285,6 +319,13 @@ DIEDeclaredType::Description() const } +DebugInfoEntry* +DIEDeclaredType::AbstractOrigin() const +{ + return fAbstractOrigin; +} + + status_t DIEDeclaredType::AddAttribute_accessibility(uint16 attributeName, const AttributeValue& value) @@ -359,6 +400,20 @@ DIECompoundType::DIECompoundType() } +bool +DIECompoundType::IsNamespace() const +{ + return true; +} + + +DebugInfoEntry* +DIECompoundType::Specification() const +{ + return fSpecification; +} + + status_t DIECompoundType::AddChild(DebugInfoEntry* child) { @@ -569,6 +624,13 @@ DIEArrayType::InitAfterHierarchy(DebugInfoEntryInitInfo& info) } +DebugInfoEntry* +DIEArrayType::Specification() const +{ + return fSpecification; +} + + status_t DIEArrayType::AddChild(DebugInfoEntry* child) { @@ -672,6 +734,13 @@ DIEEnumerationType::Tag() const } +DebugInfoEntry* +DIEEnumerationType::Specification() const +{ + return fSpecification; +} + + status_t DIEEnumerationType::AddChild(DebugInfoEntry* child) { @@ -809,6 +878,13 @@ DIEPointerType::Tag() const } +DebugInfoEntry* +DIEPointerType::Specification() const +{ + return fSpecification; +} + + status_t DIEPointerType::AddAttribute_specification(uint16 attributeName, const AttributeValue& value) @@ -1461,10 +1537,27 @@ DIEPackedType::Tag() const DIESubprogram::DIESubprogram() + : + fLowPC(0), + fHighPC(0), + fAddressRanges(NULL), + fSpecification(NULL), + fAbstractOrigin(NULL), + fReturnType(NULL), + fAddressClass(0), + fPrototyped(false), + fInline(DW_INL_not_inlined) { } +DIESubprogram::~DIESubprogram() +{ + if (fAddressRanges != NULL) + fAddressRanges->RemoveReference(); +} + + uint16 DIESubprogram::Tag() const { @@ -1472,6 +1565,111 @@ DIESubprogram::Tag() const } +DebugInfoEntry* +DIESubprogram::Specification() const +{ + return fSpecification; +} + + + +DebugInfoEntry* +DIESubprogram::AbstractOrigin() const +{ + return fAbstractOrigin; +} + + +status_t +DIESubprogram::AddAttribute_low_pc(uint16 attributeName, + const AttributeValue& value) +{ + fLowPC = value.address; + return B_OK; +} + + +status_t +DIESubprogram::AddAttribute_high_pc(uint16 attributeName, + const AttributeValue& value) +{ + fHighPC = value.address; + return B_OK; +} + + +status_t +DIESubprogram::AddAttribute_ranges(uint16 attributeName, + const AttributeValue& value) +{ + if (fAddressRanges != NULL) + fAddressRanges->RemoveReference(); + + fAddressRanges = value.rangeList; + + if (fAddressRanges != NULL) + fAddressRanges->AddReference(); + + return B_OK; +} + + +status_t +DIESubprogram::AddAttribute_specification(uint16 attributeName, + const AttributeValue& value) +{ + fSpecification = dynamic_cast(value.reference); + return fSpecification != NULL ? B_OK : B_BAD_DATA; +} + + +status_t +DIESubprogram::AddAttribute_address_class(uint16 attributeName, + const AttributeValue& value) +{ +// TODO: How is the address class handled? + fAddressClass = value.constant; + return B_OK; +} + + +status_t +DIESubprogram::AddAttribute_prototyped(uint16 attributeName, + const AttributeValue& value) +{ + fPrototyped = value.flag; + return B_OK; +} + + +status_t +DIESubprogram::AddAttribute_type(uint16 attributeName, + const AttributeValue& value) +{ + fReturnType = dynamic_cast(value.reference); + return fReturnType != NULL ? B_OK : B_BAD_DATA; +} + + +status_t +DIESubprogram::AddAttribute_inline(uint16 attributeName, + const AttributeValue& value) +{ +// TODO: How is the address class handled? + fInline = value.constant; + return B_OK; +} + + +status_t +DIESubprogram::AddAttribute_abstract_origin(uint16 attributeName, + const AttributeValue& value) +{ + fAbstractOrigin = dynamic_cast(value.reference); + return fAbstractOrigin != NULL ? B_OK : B_BAD_DATA; +} + + // #pragma mark - DIETemplateTypeParameter @@ -1664,6 +1862,21 @@ DIENamespace::Tag() const } +bool +DIENamespace::IsNamespace() const +{ + return true; +} + + +status_t +DIENamespace::AddChild(DebugInfoEntry* child) +{ + fChildren.Add(child); + return B_OK; +} + + // #pragma mark - DIEImportedModule diff --git a/src/apps/debugger/dwarf/DebugInfoEntries.h b/src/apps/debugger/dwarf/DebugInfoEntries.h index 5495645998..2b71d6cb21 100644 --- a/src/apps/debugger/dwarf/DebugInfoEntries.h +++ b/src/apps/debugger/dwarf/DebugInfoEntries.h @@ -136,6 +136,7 @@ class DIECompileUnitBase : public DebugInfoEntry { public: DIECompileUnitBase(); + ~DIECompileUnitBase(); virtual status_t InitAfterAttributes( DebugInfoEntryInitInfo& info); @@ -145,6 +146,12 @@ public: const DebugInfoEntryList& Types() const { return fTypes; } const DebugInfoEntryList& OtherChildren() const { return fOtherChildren; } + TargetAddressRangeList* AddressRanges() const + { return fAddressRanges; } + + dwarf_addr_t LowPC() const { return fLowPC; } + dwarf_addr_t HighPC() const { return fHighPC; } + dwarf_addr_t AddressRangeBase() const; virtual status_t AddChild(DebugInfoEntry* child); @@ -171,10 +178,10 @@ public: const AttributeValue& value); virtual status_t AddAttribute_use_UTF8(uint16 attributeName, const AttributeValue& value); + virtual status_t AddAttribute_ranges(uint16 attributeName, + const AttributeValue& value); //TODO: -// virtual status_t AddAttribute_ranges(uint16 attributeName, -// const AttributeValue& value); // virtual status_t AddAttribute_segment(uint16 attributeName, // const AttributeValue& value); @@ -187,6 +194,7 @@ protected: dwarf_addr_t fHighPC; dwarf_off_t fStatementListOffset; dwarf_off_t fMacroInfoOffset; + TargetAddressRangeList* fAddressRanges; DIECompileUnitBase* fBaseTypesUnit; DebugInfoEntryList fTypes; DebugInfoEntryList fOtherChildren; @@ -251,6 +259,7 @@ public: DIEDeclaredType(); virtual const char* Description() const; + virtual DebugInfoEntry* AbstractOrigin() const; virtual status_t AddAttribute_accessibility(uint16 attributeName, const AttributeValue& value); @@ -297,6 +306,10 @@ class DIECompoundType : public DIEDeclaredType { public: DIECompoundType(); + virtual bool IsNamespace() const; + + virtual DebugInfoEntry* Specification() const; + virtual status_t AddChild(DebugInfoEntry* child); virtual status_t AddAttribute_byte_size(uint16 attributeName, @@ -398,6 +411,8 @@ public: virtual status_t InitAfterHierarchy( DebugInfoEntryInitInfo& info); + virtual DebugInfoEntry* Specification() const; + virtual status_t AddChild(DebugInfoEntry* child); virtual status_t AddAttribute_ordering(uint16 attributeName, @@ -453,6 +468,8 @@ public: virtual uint16 Tag() const; + virtual DebugInfoEntry* Specification() const; + virtual status_t AddChild(DebugInfoEntry* child); virtual status_t AddAttribute_bit_stride(uint16 attributeName, @@ -557,6 +574,8 @@ public: virtual uint16 Tag() const; + virtual DebugInfoEntry* Specification() const; + virtual status_t AddAttribute_specification(uint16 attributeName, const AttributeValue& value); @@ -990,12 +1009,55 @@ public: class DIESubprogram : public DIEDeclaredNamedBase { public: DIESubprogram(); + ~DIESubprogram(); virtual uint16 Tag() const; + virtual DebugInfoEntry* Specification() const; + virtual DebugInfoEntry* AbstractOrigin() const; + + TargetAddressRangeList* AddressRanges() const + { return fAddressRanges; } + + dwarf_addr_t LowPC() const { return fLowPC; } + dwarf_addr_t HighPC() const { return fHighPC; } + + bool IsPrototyped() const { return fPrototyped; } + uint8 Inline() const { return fInline; } + + virtual status_t AddAttribute_low_pc(uint16 attributeName, + const AttributeValue& value); + virtual status_t AddAttribute_high_pc(uint16 attributeName, + const AttributeValue& value); + virtual status_t AddAttribute_ranges(uint16 attributeName, + const AttributeValue& value); + virtual status_t AddAttribute_specification(uint16 attributeName, + const AttributeValue& value); + virtual status_t AddAttribute_address_class(uint16 attributeName, + const AttributeValue& value); + virtual status_t AddAttribute_prototyped(uint16 attributeName, + const AttributeValue& value); + virtual status_t AddAttribute_type(uint16 attributeName, + const AttributeValue& value); + virtual status_t AddAttribute_inline(uint16 attributeName, + const AttributeValue& value); + virtual status_t AddAttribute_abstract_origin( + uint16 attributeName, + const AttributeValue& value); + +protected: + dwarf_addr_t fLowPC; + dwarf_addr_t fHighPC; + TargetAddressRangeList* fAddressRanges; + DIESubprogram* fSpecification; + DIESubprogram* fAbstractOrigin; + DIEType* fReturnType; + uint8 fAddressClass; + bool fPrototyped; + uint8 fInline; + // TODO: // DW_AT_abstract_origin -// DW_AT_address_class // DW_AT_artificial // DW_AT_calling_convention // DW_AT_elemental @@ -1003,13 +1065,8 @@ public: // DW_AT_explicit // DW_AT_external // DW_AT_frame_base -// DW_AT_high_pc -// DW_AT_inline -// DW_AT_low_pc // DW_AT_object_pointer -// DW_AT_prototyped // DW_AT_pure -// DW_AT_ranges // DW_AT_recursive // DW_AT_return_addr // DW_AT_segment @@ -1017,7 +1074,6 @@ public: // DW_AT_start_scope // DW_AT_static_link // DW_AT_trampoline -// DW_AT_type // DW_AT_virtuality // DW_AT_vtable_elem_location }; @@ -1160,6 +1216,16 @@ public: virtual uint16 Tag() const; + virtual bool IsNamespace() const; + + const DebugInfoEntryList& Children() const + { return fChildren; } + + virtual status_t AddChild(DebugInfoEntry* child); + +private: + DebugInfoEntryList fChildren; + // TODO: // DW_AT_extension // DW_AT_start_scope diff --git a/src/apps/debugger/dwarf/DebugInfoEntry.cpp b/src/apps/debugger/dwarf/DebugInfoEntry.cpp index 9e6cff8a73..025229ce09 100644 --- a/src/apps/debugger/dwarf/DebugInfoEntry.cpp +++ b/src/apps/debugger/dwarf/DebugInfoEntry.cpp @@ -21,6 +21,8 @@ DebugInfoEntry::DebugInfoEntry() + : + fParent(NULL) { } @@ -44,6 +46,13 @@ DebugInfoEntry::InitAfterAttributes(DebugInfoEntryInitInfo& info) } +void +DebugInfoEntry::SetParent(DebugInfoEntry* parent) +{ + fParent = parent; +} + + bool DebugInfoEntry::IsType() const { @@ -51,13 +60,19 @@ DebugInfoEntry::IsType() const } +bool +DebugInfoEntry::IsNamespace() const +{ + return false; +} + + const char* DebugInfoEntry::Name() const { return NULL; } - const char* DebugInfoEntry::Description() const { @@ -65,6 +80,20 @@ DebugInfoEntry::Description() const } +DebugInfoEntry* +DebugInfoEntry::Specification() const +{ + return NULL; +} + + +DebugInfoEntry* +DebugInfoEntry::AbstractOrigin() const +{ + return NULL; +} + + status_t DebugInfoEntry::AddChild(DebugInfoEntry* child) { diff --git a/src/apps/debugger/dwarf/DebugInfoEntry.h b/src/apps/debugger/dwarf/DebugInfoEntry.h index cf0044b4b2..4e55dd0e36 100644 --- a/src/apps/debugger/dwarf/DebugInfoEntry.h +++ b/src/apps/debugger/dwarf/DebugInfoEntry.h @@ -5,6 +5,8 @@ #ifndef DEBUG_INFO_ENTRY_H #define DEBUG_INFO_ENTRY_H +#include + #include #include "DwarfTypes.h" @@ -44,10 +46,18 @@ public: virtual uint16 Tag() const = 0; + DebugInfoEntry* Parent() const { return fParent; } + void SetParent(DebugInfoEntry* parent); + virtual bool IsType() const; + virtual bool IsNamespace() const; + // a namespace-like thingy (namespace, + // class, ...) virtual const char* Name() const; virtual const char* Description() const; + virtual DebugInfoEntry* Specification() const; + virtual DebugInfoEntry* AbstractOrigin() const; virtual status_t AddChild(DebugInfoEntry* child); @@ -154,6 +164,9 @@ protected: status_t SetConstantAttributeValue( ConstantAttributeValue& toSet, const AttributeValue& value); + +protected: + DebugInfoEntry* fParent; }; diff --git a/src/apps/debugger/dwarf/DwarfFile.cpp b/src/apps/debugger/dwarf/DwarfFile.cpp index 09c72652ce..53409ef3f2 100644 --- a/src/apps/debugger/dwarf/DwarfFile.cpp +++ b/src/apps/debugger/dwarf/DwarfFile.cpp @@ -16,6 +16,7 @@ #include "DataReader.h" #include "ElfFile.h" #include "TagNames.h" +#include "TargetAddressRangeList.h" DwarfFile::DwarfFile() @@ -25,6 +26,7 @@ DwarfFile::DwarfFile() fDebugInfoSection(NULL), fDebugAbbrevSection(NULL), fDebugStringSection(NULL), + fDebugRangesSection(NULL), fCompilationUnits(20, true), fCurrentCompilationUnit(NULL), fFinished(false), @@ -42,6 +44,7 @@ DwarfFile::~DwarfFile() fElfFile->PutSection(fDebugInfoSection); fElfFile->PutSection(fDebugAbbrevSection); fElfFile->PutSection(fDebugStringSection); + fElfFile->PutSection(fDebugRangesSection); delete fElfFile; } @@ -69,6 +72,8 @@ DwarfFile::Load(const char* fileName) fDebugInfoSection = fElfFile->GetSection(".debug_info"); fDebugAbbrevSection = fElfFile->GetSection(".debug_abbrev"); fDebugStringSection = fElfFile->GetSection(".debug_str"); + fDebugRangesSection = fElfFile->GetSection(".debug_ranges"); + // not mandatory if (fDebugInfoSection == NULL || fDebugAbbrevSection == NULL || fDebugStringSection == NULL) { fprintf(stderr, "DwarfManager::File::Load(\"%s\"): no " @@ -286,7 +291,9 @@ abbreviationEntry.Tag(), abbreviationEntry.HasChildren()); if (childEntry != NULL) { if (entry != NULL) { error = entry->AddChild(childEntry); - if (error == ENTRY_NOT_HANDLED) { + if (error == B_OK) { + childEntry->SetParent(entry); + } else if (error == ENTRY_NOT_HANDLED) { error = B_OK; printf("%*s -> child unhandled\n", level * 2, ""); } @@ -384,7 +391,7 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader, // prepare an AttributeValue AttributeValue attributeValue; attributeValue.attributeForm = attributeForm; - attributeValue.isSigned = false; + bool isSigned = false; // Read the attribute value according to the attribute's form. For // the forms that don't map to a single attribute class only or @@ -414,7 +421,7 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader, value = dataReader.Read(0); break; case DW_FORM_string: - attributeValue.string = dataReader.ReadString(); + attributeValue.SetToString(dataReader.ReadString()); break; case DW_FORM_block: blockLength = dataReader.ReadUnsignedLEB128(0); @@ -426,11 +433,11 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader, value = dataReader.Read(0); break; case DW_FORM_flag: - attributeValue.flag = dataReader.Read(0) != 0; + attributeValue.SetToFlag(dataReader.Read(0) != 0); break; case DW_FORM_sdata: value = dataReader.ReadSignedLEB128(0); - attributeValue.isSigned = true; + isSigned = true; break; case DW_FORM_strp: { @@ -440,8 +447,8 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader, offset); return B_BAD_DATA; } - attributeValue.string - = (const char*)fDebugStringSection->Data() + offset; + attributeValue.SetToString( + (const char*)fDebugStringSection->Data() + offset); break; } case DW_FORM_udata: @@ -484,31 +491,43 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader, attributeForm); continue; } - attributeValue.attributeClass = attributeClass; +// attributeValue.attributeClass = attributeClass; // set the attribute value according to the attribute's class switch (attributeClass) { case ATTRIBUTE_CLASS_ADDRESS: - attributeValue.address = value; + attributeValue.SetToAddress(value); break; case ATTRIBUTE_CLASS_BLOCK: - attributeValue.block.data = dataReader.Data(); - attributeValue.block.length = blockLength; + attributeValue.SetToBlock(dataReader.Data(), blockLength); dataReader.Skip(blockLength); break; case ATTRIBUTE_CLASS_CONSTANT: - attributeValue.constant = value; + attributeValue.SetToConstant(value, isSigned); break; case ATTRIBUTE_CLASS_LINEPTR: - case ATTRIBUTE_CLASS_LOCLISTPTR: - case ATTRIBUTE_CLASS_MACPTR: - case ATTRIBUTE_CLASS_RANGELISTPTR: - attributeValue.pointer = value; + attributeValue.SetToLinePointer(value); break; + case ATTRIBUTE_CLASS_LOCLISTPTR: + attributeValue.SetToLocationListPointer(value); + break; + case ATTRIBUTE_CLASS_MACPTR: + attributeValue.SetToMacroPointer(value); + break; + case ATTRIBUTE_CLASS_RANGELISTPTR: + { + if (entry != NULL) { + TargetAddressRangeList* rangeList + = _ResolveRangeList(value); + Reference reference(rangeList); + attributeValue.SetToRangeList(rangeList); + } + break; + } case ATTRIBUTE_CLASS_REFERENCE: if (entry != NULL) { - attributeValue.reference = _ResolveReference(value, - localReference); + attributeValue.SetToReference(_ResolveReference(value, + localReference)); if (attributeValue.reference == NULL) { fprintf(stderr, "Failed to resolve reference: " "%s (%#lx) %s (%#lx): value: %llu\n", @@ -539,7 +558,7 @@ get_attribute_form_name(attributeForm), attributeClass, attributeValue.ToString( DebugInfoEntrySetter attributeSetter = get_attribute_name_setter(attributeName); - if (attributeSetter != NULL) { + if (attributeSetter != 0) { status_t error = (entry->*attributeSetter)(attributeName, attributeValue); @@ -605,3 +624,49 @@ DwarfFile::_ResolveReference(uint64 offset, bool localReference) const // TODO: Implement program-global references! return NULL; } + + +TargetAddressRangeList* +DwarfFile::_ResolveRangeList(uint64 offset) +{ + if (fDebugRangesSection == NULL) + return NULL; + + if (offset >= (uint64)fDebugRangesSection->Size()) + return NULL; + + TargetAddressRangeList* ranges = new(std::nothrow) TargetAddressRangeList; + if (ranges == NULL) { + fprintf(stderr, "Out of memory.\n"); + return NULL; + } + Reference rangesReference(ranges); + + dwarf_addr_t baseAddress + = fCurrentCompilationUnit->UnitEntry()->AddressRangeBase(); + + DataReader dataReader((uint8*)fDebugRangesSection->Data() + offset, + fDebugRangesSection->Size() - offset); + while (true) { + dwarf_addr_t start = dataReader.Read(0); + dwarf_addr_t end = dataReader.Read(0); + if (dataReader.HasOverflow()) + return NULL; + + if (start == 0 && end == 0) + break; + if (start == DWARF_ADDRESS_MAX) { + baseAddress = end; + continue; + } + if (start == end) + continue; + + if (!ranges->AddRange(baseAddress + start, end - start)) { + fprintf(stderr, "Out of memory.\n"); + return NULL; + } + } + + return rangesReference.Detach(); +} diff --git a/src/apps/debugger/dwarf/DwarfFile.h b/src/apps/debugger/dwarf/DwarfFile.h index c8030954c7..48f1e053de 100644 --- a/src/apps/debugger/dwarf/DwarfFile.h +++ b/src/apps/debugger/dwarf/DwarfFile.h @@ -17,6 +17,7 @@ class CompilationUnit; class DataReader; class ElfFile; class ElfSection; +class TargetAddressRangeList; class DwarfFile : public DoublyLinkedListLinkImpl { @@ -27,7 +28,8 @@ public: status_t Load(const char* fileName); status_t FinishLoading(); - const char* Name() const { return fName; } + const char* Name() const { return fName; } + ElfFile* GetElfFile() const { return fElfFile; } int32 CountCompilationUnits() const; CompilationUnit* CompilationUnitAt(int32 index) const; @@ -52,6 +54,8 @@ private: DebugInfoEntry* _ResolveReference(uint64 offset, bool localReference) const; + TargetAddressRangeList* _ResolveRangeList(uint64 offset); + // returns reference private: char* fName; @@ -59,6 +63,7 @@ private: ElfSection* fDebugInfoSection; ElfSection* fDebugAbbrevSection; ElfSection* fDebugStringSection; + ElfSection* fDebugRangesSection; AbbreviationTableList fAbbreviationTables; DebugInfoEntryFactory fDebugInfoFactory; CompilationUnitList fCompilationUnits; diff --git a/src/apps/debugger/dwarf/DwarfUtils.cpp b/src/apps/debugger/dwarf/DwarfUtils.cpp new file mode 100644 index 0000000000..5a2e584c77 --- /dev/null +++ b/src/apps/debugger/dwarf/DwarfUtils.cpp @@ -0,0 +1,79 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "DwarfUtils.h" + +#include + + +/*static*/ void +DwarfUtils::GetDIEName(const DebugInfoEntry* entry, BString& _name) +{ + // If we don't seem to have a name but a specification, return the + // specification's name. + const char* name = entry->Name(); + if (name == NULL) { + if (DebugInfoEntry* specification = entry->Specification()) + name = specification->Name(); + } + + _name = name; +} + + +/*static*/ void +DwarfUtils::GetFullDIEName(const DebugInfoEntry* entry, BString& _name) +{ + // If we don't seem to have a name but a specification, return the + // specification's name. + const char* name = entry->Name(); + if (name == NULL) { + if (DebugInfoEntry* specification = entry->Specification()) { + entry = specification; + name = specification->Name(); + } + } + + // TODO: Get template and function parameters! + + _name = name; +} + + +/*static*/ void +DwarfUtils::GetFullyQualifiedDIEName(const DebugInfoEntry* entry, + BString& _name) +{ + // If we don't seem to have a name but a specification, return the + // specification's name. + if (entry->Name() == NULL) { + if (DebugInfoEntry* specification = entry->Specification()) + entry = specification; + } + + _name.Truncate(0); + + // Get the namespace, if any. + DebugInfoEntry* parent = entry->Parent(); + while (parent != NULL) { + if (parent->IsNamespace()) { + GetFullyQualifiedDIEName(parent, _name); + break; + } + + parent = parent->Parent(); + } + + BString name; + GetFullDIEName(entry, name); + + if (name.Length() == 0) + return; + + if (_name.Length() > 0) { + _name << "::" << name; + } else + _name = name; +} diff --git a/src/apps/debugger/dwarf/DwarfUtils.h b/src/apps/debugger/dwarf/DwarfUtils.h new file mode 100644 index 0000000000..ef198cbf65 --- /dev/null +++ b/src/apps/debugger/dwarf/DwarfUtils.h @@ -0,0 +1,27 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef DWARF_UTILS_H +#define DWARF_UTILS_H + +#include "DebugInfoEntries.h" + + +class BString; +class DebugInfoEntry; + + +class DwarfUtils { +public: + static void GetDIEName(const DebugInfoEntry* entry, + BString& _name); + static void GetFullDIEName(const DebugInfoEntry* entry, + BString& _name); + static void GetFullyQualifiedDIEName( + const DebugInfoEntry* entry, + BString& _name); +}; + + +#endif // DWARF_UTILS_H diff --git a/src/apps/debugger/dwarf/Jamfile b/src/apps/debugger/dwarf/Jamfile index f90624529b..47f82f4491 100644 --- a/src/apps/debugger/dwarf/Jamfile +++ b/src/apps/debugger/dwarf/Jamfile @@ -8,6 +8,7 @@ UsePrivateSystemHeaders ; SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) ] ; SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) elf ] ; +SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) types ] ; MergeObject Debugger_dwarf.o @@ -20,6 +21,7 @@ MergeObject Debugger_dwarf.o DebugInfoEntry.cpp DwarfFile.cpp DwarfManager.cpp + DwarfUtils.cpp SourceLanguageInfo.cpp TagNames.cpp ; diff --git a/src/apps/debugger/elf/ElfFile.cpp b/src/apps/debugger/elf/ElfFile.cpp index 1f3be1e53e..868a475c7a 100644 --- a/src/apps/debugger/elf/ElfFile.cpp +++ b/src/apps/debugger/elf/ElfFile.cpp @@ -76,6 +76,26 @@ ElfSection::Unload() } +// #pragma mark - ElfSegment + + +ElfSegment::ElfSegment(off_t fileOffset, off_t fileSize, + target_addr_t loadAddress, target_size_t loadSize, bool writable) + : + fFileOffset(fileOffset), + fFileSize(fileSize), + fLoadAddress(loadAddress), + fLoadSize(loadSize), + fWritable(writable) +{ +} + + +ElfSegment::~ElfSegment() +{ +} + + // #pragma mark - ElfFile @@ -90,6 +110,9 @@ ElfFile::ElfFile() ElfFile::~ElfFile() { + while (ElfSegment* segment = fSegments.RemoveHead()) + delete segment; + while (ElfSection* section = fSections.RemoveHead()) delete section; @@ -148,8 +171,7 @@ printf("fFileSize: %lld\n", fFileSize); printf("sectionHeaderTable: %lld\n", sectionHeadersOffset); // read the section header table - uint8* sectionHeaderTable - = (uint8*)malloc(sectionHeaderTableSize); + uint8* sectionHeaderTable = (uint8*)malloc(sectionHeaderTableSize); if (sectionHeaderTable == NULL) return B_NO_MEMORY; MemoryDeleter sectionHeaderTableDeleter(sectionHeaderTable); @@ -202,6 +224,49 @@ printf("sectionStrings: %ld\n", stringSectionHeader->sh_offset); fSections.Add(section); } + // check program header table values + off_t programHeadersOffset = fElfHeader->e_phoff; + size_t programHeaderSize = fElfHeader->e_phentsize; + int segmentCount = fElfHeader->e_phnum; + size_t programHeaderTableSize = programHeaderSize * segmentCount; + if (!_CheckRange(programHeadersOffset, programHeaderTableSize)) { + fprintf(stderr, "\"%s\": Invalid ELF header\n", fileName); + return B_BAD_DATA; + } +printf("programHeaderTable: %lld\n", programHeadersOffset); + + // read the program header table + uint8* programHeaderTable = (uint8*)malloc(programHeaderTableSize); + if (programHeaderTable == NULL) + return B_NO_MEMORY; + MemoryDeleter programHeaderTableDeleter(programHeaderTable); + + bytesRead = pread(fFD, programHeaderTable, programHeaderTableSize, + programHeadersOffset); + if (bytesRead != (ssize_t)programHeaderTableSize) + return bytesRead < 0 ? errno : B_ERROR; + + // read the program headers and create ElfSegment objects + for (int i = 0; i < segmentCount; i++) { + Elf32_Phdr* programHeader = (Elf32_Phdr*)(programHeaderTable + + i * programHeaderSize); + // skip program headers we aren't interested in or that are invalid + if (programHeader->p_type != PT_LOAD || programHeader->p_filesz == 0 + || programHeader->p_memsz == 0 + || !_CheckRange(programHeader->p_offset, programHeader->p_filesz)) { + continue; + } + + // create an ElfSegment + ElfSegment* segment = new(std::nothrow) ElfSegment( + programHeader->p_offset, programHeader->p_filesz, + programHeader->p_vaddr, programHeader->p_memsz, + (programHeader->p_flags & PF_WRITE) != 0); + if (segment == NULL) + return B_NO_MEMORY; + fSegments.Add(segment); + } + return B_OK; } @@ -227,6 +292,32 @@ ElfFile::PutSection(ElfSection* section) } +ElfSegment* +ElfFile::TextSegment() const +{ + for (SegmentList::ConstIterator it = fSegments.GetIterator(); + ElfSegment* segment = it.Next();) { + if (!segment->IsWritable()) + return segment; + } + + return NULL; +} + + +ElfSegment* +ElfFile::DataSegment() const +{ + for (SegmentList::ConstIterator it = fSegments.GetIterator(); + ElfSegment* segment = it.Next();) { + if (segment->IsWritable()) + return segment; + } + + return NULL; +} + + bool ElfFile::_CheckRange(off_t offset, off_t size) const { @@ -243,5 +334,8 @@ ElfFile::_CheckElfHeader() const && fElfHeader->e_shnum > 0 && fElfHeader->e_shentsize >= sizeof(struct Elf32_Shdr) && fElfHeader->e_shstrndx != SHN_UNDEF - && fElfHeader->e_shstrndx < fElfHeader->e_shnum; + && fElfHeader->e_shstrndx < fElfHeader->e_shnum + && fElfHeader->e_phoff > 0 + && fElfHeader->e_phnum > 0 + && fElfHeader->e_phentsize >= sizeof(struct Elf32_Phdr); } diff --git a/src/apps/debugger/elf/ElfFile.h b/src/apps/debugger/elf/ElfFile.h index 99e76c7608..186fac8800 100644 --- a/src/apps/debugger/elf/ElfFile.h +++ b/src/apps/debugger/elf/ElfFile.h @@ -12,6 +12,8 @@ #include #include +#include "Types.h" + class ElfSection : public DoublyLinkedListLinkImpl { public: @@ -37,6 +39,28 @@ private: }; +class ElfSegment : public DoublyLinkedListLinkImpl { +public: + ElfSegment(off_t fileOffset, off_t fileSize, + target_addr_t loadAddress, + target_size_t loadSize, bool writable); + ~ElfSegment(); + + off_t FileOffset() const { return fFileOffset; } + off_t FileSize() const { return fFileSize; } + target_addr_t LoadAddress() const { return fLoadAddress; } + target_size_t LoadSize() const { return fLoadSize; } + bool IsWritable() const { return fWritable; } + +private: + off_t fFileOffset; + off_t fFileSize; + target_addr_t fLoadAddress; + target_size_t fLoadSize; + bool fWritable; +}; + + class ElfFile { public: ElfFile(); @@ -44,11 +68,17 @@ public: status_t Init(const char* fileName); + int FD() const { return fFD; } + ElfSection* GetSection(const char* name); void PutSection(ElfSection* section); + ElfSegment* TextSegment() const; + ElfSegment* DataSegment() const; + private: typedef DoublyLinkedList SectionList; + typedef DoublyLinkedList SegmentList; private: bool _CheckRange(off_t offset, off_t size) const; @@ -59,6 +89,7 @@ private: int fFD; Elf32_Ehdr* fElfHeader; SectionList fSections; + SegmentList fSegments; }; diff --git a/src/apps/debugger/gui/team_window/SourceView.h b/src/apps/debugger/gui/team_window/SourceView.h index 80afd09258..480679f14e 100644 --- a/src/apps/debugger/gui/team_window/SourceView.h +++ b/src/apps/debugger/gui/team_window/SourceView.h @@ -8,7 +8,7 @@ #include #include -#include "ArchitectureTypes.h" +#include "Types.h" class Breakpoint; diff --git a/src/apps/debugger/model/Breakpoint.h b/src/apps/debugger/model/Breakpoint.h index 1ccdfc8195..6b25ad2e2b 100644 --- a/src/apps/debugger/model/Breakpoint.h +++ b/src/apps/debugger/model/Breakpoint.h @@ -8,7 +8,7 @@ #include #include -#include "ArchitectureTypes.h" +#include "Types.h" enum user_breakpoint_state { diff --git a/src/apps/debugger/model/ImageInfo.h b/src/apps/debugger/model/ImageInfo.h index 8af5cf3960..83fb53beab 100644 --- a/src/apps/debugger/model/ImageInfo.h +++ b/src/apps/debugger/model/ImageInfo.h @@ -8,7 +8,7 @@ #include #include -#include "ArchitectureTypes.h" +#include "Types.h" class ImageInfo { diff --git a/src/apps/debugger/model/StackFrame.h b/src/apps/debugger/model/StackFrame.h index 079c833fac..7b8bc80feb 100644 --- a/src/apps/debugger/model/StackFrame.h +++ b/src/apps/debugger/model/StackFrame.h @@ -9,7 +9,7 @@ #include -#include "ArchitectureTypes.h" +#include "Types.h" enum stack_frame_type { diff --git a/src/apps/debugger/model/Statement.h b/src/apps/debugger/model/Statement.h index 586a301190..98e08d5f12 100644 --- a/src/apps/debugger/model/Statement.h +++ b/src/apps/debugger/model/Statement.h @@ -7,9 +7,9 @@ #include -#include "ArchitectureTypes.h" #include "SourceLocation.h" #include "TargetAddressRange.h" +#include "Types.h" class Statement : public Referenceable { diff --git a/src/apps/debugger/model/SymbolInfo.h b/src/apps/debugger/model/SymbolInfo.h index 3e091779c4..ecae1c36dd 100644 --- a/src/apps/debugger/model/SymbolInfo.h +++ b/src/apps/debugger/model/SymbolInfo.h @@ -7,7 +7,7 @@ #include -#include "ArchitectureTypes.h" +#include "Types.h" class SymbolInfo { diff --git a/src/apps/debugger/model/SourceLocation.h b/src/apps/debugger/types/SourceLocation.h similarity index 100% rename from src/apps/debugger/model/SourceLocation.h rename to src/apps/debugger/types/SourceLocation.h diff --git a/src/apps/debugger/arch/TargetAddressRange.h b/src/apps/debugger/types/TargetAddressRange.h similarity index 81% rename from src/apps/debugger/arch/TargetAddressRange.h rename to src/apps/debugger/types/TargetAddressRange.h index 83bb725c7b..74feac6d9c 100644 --- a/src/apps/debugger/arch/TargetAddressRange.h +++ b/src/apps/debugger/types/TargetAddressRange.h @@ -5,7 +5,9 @@ #ifndef TARGET_ADDRESS_RANGE_H #define TARGET_ADDRESS_RANGE_H -#include "ArchitectureTypes.h" +#include + +#include "Types.h" class TargetAddressRange { @@ -78,6 +80,20 @@ public: return Contains(other.Start()) || other.Contains(Start()); } + TargetAddressRange& operator|=(const TargetAddressRange& other) + { + if (fSize == 0) + return *this = other; + + if (other.fSize > 0) { + target_addr_t end = std::max(End(), other.End()); + fStart = std::min(fStart, other.fStart); + fSize = end - fStart; + } + + return *this; + } + private: target_addr_t fStart; target_size_t fSize; diff --git a/src/apps/debugger/types/TargetAddressRangeList.cpp b/src/apps/debugger/types/TargetAddressRangeList.cpp new file mode 100644 index 0000000000..d18918d6fc --- /dev/null +++ b/src/apps/debugger/types/TargetAddressRangeList.cpp @@ -0,0 +1,91 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "TargetAddressRangeList.h" + +#include + + +TargetAddressRangeList::TargetAddressRangeList() +{ +} + + +TargetAddressRangeList::TargetAddressRangeList(const TargetAddressRange& range) +{ + AddRange(range); +} + + +TargetAddressRangeList::TargetAddressRangeList( + const TargetAddressRangeList& other) + : + fRanges(other.fRanges) +{ +} + + +void +TargetAddressRangeList::Clear() +{ + fRanges.Clear(); +} + + +bool +TargetAddressRangeList::AddRange(const TargetAddressRange& range) +{ + return fRanges.Add(range); +} + + +int32 +TargetAddressRangeList::CountRanges() const +{ + return fRanges.Size(); +} + + +TargetAddressRange +TargetAddressRangeList::RangeAt(int32 index) const +{ + return index >= 0 && index < fRanges.Size() + ? fRanges[index] : TargetAddressRange(); +} + + +target_addr_t +TargetAddressRangeList::LowestAddress() const +{ + int32 count = fRanges.Size(); + if (count == 0) + return 0; + + target_addr_t lowest = fRanges[0].Start(); + for (int32 i = 0; i < count; i++) + lowest = std::min(lowest, fRanges[i].Start()); + + return lowest; +} + + +TargetAddressRange +TargetAddressRangeList::CoveringRange() const +{ + TargetAddressRange range; + int32 count = fRanges.Size(); + for (int32 i = 0; i < count; i++) + range |= fRanges[i]; + + return range; +} + + +TargetAddressRangeList& +TargetAddressRangeList::operator=(const TargetAddressRangeList& other) +{ + fRanges = other.fRanges; + return *this; +} diff --git a/src/apps/debugger/types/TargetAddressRangeList.h b/src/apps/debugger/types/TargetAddressRangeList.h new file mode 100644 index 0000000000..1eee138b72 --- /dev/null +++ b/src/apps/debugger/types/TargetAddressRangeList.h @@ -0,0 +1,51 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef TARGET_ADDRESS_RANGE_LIST_H +#define TARGET_ADDRESS_RANGE_LIST_H + +#include + +#include "Array.h" +#include "TargetAddressRange.h" + + +class TargetAddressRangeList : public Referenceable { +public: + TargetAddressRangeList(); + TargetAddressRangeList( + const TargetAddressRange& range); + TargetAddressRangeList( + const TargetAddressRangeList& other); + + void Clear(); + bool AddRange(const TargetAddressRange& range); + inline bool AddRange(target_addr_t start, + target_size_t size); + + int32 CountRanges() const; + TargetAddressRange RangeAt(int32 index) const; + + target_addr_t LowestAddress() const; + TargetAddressRange CoveringRange() const; + + TargetAddressRangeList& operator=( + const TargetAddressRangeList& other); + +private: + typedef Array RangeArray; + +private: + RangeArray fRanges; +}; + + +bool +TargetAddressRangeList::AddRange(target_addr_t start, target_size_t size) +{ + return AddRange(TargetAddressRange(start, size)); +} + + +#endif // TARGET_ADDRESS_RANGE_LIST_H diff --git a/src/apps/debugger/arch/ArchitectureTypes.h b/src/apps/debugger/types/Types.h similarity index 100% rename from src/apps/debugger/arch/ArchitectureTypes.h rename to src/apps/debugger/types/Types.h