From 44101b1f99e37cd9653c45338cff851e0da4889f Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Sun, 14 Jun 2009 12:53:29 +0000 Subject: [PATCH] The very beginnings of a debugger. Currently consisting only of the beginnings of a DWARF 3 reader. It can read the .debug_info section and create objects for the entries, but most attributes are ignored yet. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31047 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/apps/Jamfile | 1 + src/apps/debugger/Array.h | 193 +++ src/apps/debugger/AttributeValue.cpp | 48 + src/apps/debugger/AttributeValue.h | 69 + src/apps/debugger/DataReader.h | 163 +++ src/apps/debugger/DebugInfoEntries.cpp | 1483 ++++++++++++++++++++++ src/apps/debugger/DebugInfoEntries.h | 876 +++++++++++++ src/apps/debugger/DebugInfoEntry.cpp | 183 +++ src/apps/debugger/DebugInfoEntry.h | 152 +++ src/apps/debugger/DwarfManager.cpp | 974 ++++++++++++++ src/apps/debugger/DwarfManager.h | 36 + src/apps/debugger/ElfFile.cpp | 247 ++++ src/apps/debugger/ElfFile.h | 65 + src/apps/debugger/HaikuTypes.h | 43 + src/apps/debugger/Jamfile | 21 + src/apps/debugger/SourceLanguageInfo.cpp | 53 + src/apps/debugger/SourceLanguageInfo.h | 55 + src/apps/debugger/arch_elf.h | 22 + src/apps/debugger/attribute_classes.cpp | 238 ++++ src/apps/debugger/attribute_classes.h | 41 + src/apps/debugger/debugger.cpp | 26 + src/apps/debugger/dwarf.h | 457 +++++++ src/apps/debugger/tag_names.cpp | 100 ++ src/apps/debugger/tag_names.h | 14 + src/apps/debugger/types.h | 22 + 25 files changed, 5582 insertions(+) create mode 100644 src/apps/debugger/Array.h create mode 100644 src/apps/debugger/AttributeValue.cpp create mode 100644 src/apps/debugger/AttributeValue.h create mode 100644 src/apps/debugger/DataReader.h create mode 100644 src/apps/debugger/DebugInfoEntries.cpp create mode 100644 src/apps/debugger/DebugInfoEntries.h create mode 100644 src/apps/debugger/DebugInfoEntry.cpp create mode 100644 src/apps/debugger/DebugInfoEntry.h create mode 100644 src/apps/debugger/DwarfManager.cpp create mode 100644 src/apps/debugger/DwarfManager.h create mode 100644 src/apps/debugger/ElfFile.cpp create mode 100644 src/apps/debugger/ElfFile.h create mode 100644 src/apps/debugger/HaikuTypes.h create mode 100644 src/apps/debugger/Jamfile create mode 100644 src/apps/debugger/SourceLanguageInfo.cpp create mode 100644 src/apps/debugger/SourceLanguageInfo.h create mode 100644 src/apps/debugger/arch_elf.h create mode 100644 src/apps/debugger/attribute_classes.cpp create mode 100644 src/apps/debugger/attribute_classes.h create mode 100644 src/apps/debugger/debugger.cpp create mode 100644 src/apps/debugger/dwarf.h create mode 100644 src/apps/debugger/tag_names.cpp create mode 100644 src/apps/debugger/tag_names.h create mode 100644 src/apps/debugger/types.h diff --git a/src/apps/Jamfile b/src/apps/Jamfile index 26dfdae63c..8e1337291f 100644 --- a/src/apps/Jamfile +++ b/src/apps/Jamfile @@ -12,6 +12,7 @@ HaikuSubInclude clock ; HaikuSubInclude codycam ; HaikuSubInclude cortex ; HaikuSubInclude debuganalyzer ; +HaikuSubInclude debugger ; HaikuSubInclude deskbar ; HaikuSubInclude deskcalc ; HaikuSubInclude diskprobe ; diff --git a/src/apps/debugger/Array.h b/src/apps/debugger/Array.h new file mode 100644 index 0000000000..09d1646150 --- /dev/null +++ b/src/apps/debugger/Array.h @@ -0,0 +1,193 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef ARRAY_H +#define ARRAY_H + +#include +#include +#include + + +template +class Array { +public: + inline Array(); + ~Array(); + + inline int Size() const { return fSize; } + inline int Count() const { return fSize; } + inline bool IsEmpty() const { return fSize == 0; } + inline Element* Elements() const { return fElements; } + + inline bool Add(const Element& element); + inline bool Insert(const Element& element, int index); + inline bool Remove(int index); + + inline Element& ElementAt(int index); + inline const Element& ElementAt(int index) const; + + inline Element& operator[](int index); + inline const Element& operator[](int index) const; + +private: + static const int kMinCapacity = 8; + + bool _Resize(int index, int delta); + +private: + Element* fElements; + int fSize; + int fCapacity; +}; + + +template +Array::Array() + : + fElements(NULL), + fSize(0), + fCapacity(0) +{ +} + + +template +Array::~Array() +{ + free(fElements); +} + + +template +bool +Array::Add(const Element& element) +{ + if (fSize == fCapacity) { + if (!_Resize(fSize, 1)) + return false; + } + + fElements[fSize] = element; + fSize++; + return true; +} + + +template +bool +Array::Insert(const Element& element, int index) +{ + if (index < 0 || index > fSize) + index = fSize; + + if (fSize == fCapacity) { + if (!_Resize(index, 1)) + return false; + } else if (index < fSize) { + memmove(fElements + index + 1, fElements + index, + sizeof(Element) * (fSize - index)); + } + + fElements[index] = element; + fSize++; + return false; +} + + +template +bool +Array::Remove(int index) +{ + if (index < 0 || index >= fSize) { + char buffer[128]; + snprintf(buffer, sizeof(buffer), "Array::Remove(): index: %d, size: %d", + index, fSize); + return false; + } + + if (fSize <= fCapacity / 2 && fCapacity > kMinCapacity) { + _Resize(index, -1); + } else if (index < fSize) { + memmove(fElements + index, fElements + index + 1, + sizeof(Element) * (fSize - index - 1)); + } + + fSize--; + return true; +} + + +template +Element& +Array::ElementAt(int index) +{ + return fElements[index]; +} + + +template +const Element& +Array::ElementAt(int index) const +{ + return fElements[index]; +} + + +template +Element& +Array::operator[](int index) +{ + return fElements[index]; +} + + +template +const Element& +Array::operator[](int index) const +{ + return fElements[index]; +} + + +template +bool +Array::_Resize(int index, int delta) +{ + // determine new capacity + int newSize = fSize + delta; + int newCapacity = kMinCapacity; + while (newCapacity < newSize) + newCapacity *= 2; + + if (newCapacity == fCapacity) + return true; + + // allocate new array + Element* elements = (Element*)malloc(newCapacity * sizeof(Element)); + if (elements == NULL) + return false; + + if (index > 0) + memcpy(elements, fElements, index * sizeof(Element)); + if (index < fSize) { + if (delta > 0) { + // leave a gap of delta elements + memcpy(elements + index + delta, fElements + index, + (fSize - index) * sizeof(Element)); + } else if (index < fSize + delta) { + // drop -delta elements + memcpy(elements + index, fElements + index - delta, + (fSize - index + delta) * sizeof(Element)); + } + } + + free(fElements); + fElements = elements; + fCapacity = newCapacity; + return true; +} + + +#endif // ARRAY_H diff --git a/src/apps/debugger/AttributeValue.cpp b/src/apps/debugger/AttributeValue.cpp new file mode 100644 index 0000000000..7c22108efd --- /dev/null +++ b/src/apps/debugger/AttributeValue.cpp @@ -0,0 +1,48 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "AttributeValue.h" + +#include + +#include "attribute_classes.h" + + +const char* +AttributeValue::ToString(char* buffer, size_t size) +{ + switch (attributeClass) { + case ATTRIBUTE_CLASS_ADDRESS: + snprintf(buffer, size, "%#lx", address); + return buffer; + case ATTRIBUTE_CLASS_BLOCK: + snprintf(buffer, size, "(%p, %#lx)", block.data, block.length); + return buffer; + case ATTRIBUTE_CLASS_CONSTANT: + snprintf(buffer, size, "%#llx", constant); + return buffer; + case ATTRIBUTE_CLASS_FLAG: + snprintf(buffer, size, "%s", flag ? "true" : "false"); + return buffer; + case ATTRIBUTE_CLASS_LINEPTR: + case ATTRIBUTE_CLASS_LOCLISTPTR: + case ATTRIBUTE_CLASS_MACPTR: + case ATTRIBUTE_CLASS_RANGELISTPTR: + snprintf(buffer, size, "%#lx", pointer); + return buffer; + case ATTRIBUTE_CLASS_REFERENCE: + snprintf(buffer, size, "%p", reference); + return buffer; + case ATTRIBUTE_CLASS_STRING: + snprintf(buffer, size, "\"%s\"", string); + return buffer; + + default: + case ATTRIBUTE_CLASS_UNKNOWN: + return ""; + } + + return buffer; +} diff --git a/src/apps/debugger/AttributeValue.h b/src/apps/debugger/AttributeValue.h new file mode 100644 index 0000000000..f8f076606b --- /dev/null +++ b/src/apps/debugger/AttributeValue.h @@ -0,0 +1,69 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef ATTRIBUTE_VALUE_H +#define ATTRIBUTE_VALUE_H + +#include "attribute_classes.h" +#include "types.h" + + +class DebugInfoEntry; + + +struct AttributeValue { + union { + dwarf_addr_t address; + struct { + const void* data; + dwarf_size_t length; + } block; + uint64 constant; + bool flag; + dwarf_off_t pointer; + DebugInfoEntry* reference; + const char* string; + }; + + uint16 attributeForm; + uint8 attributeClass; + bool isSigned; + + const char* ToString(char* buffer, size_t size); +}; + + +struct DynamicAttributeValue { + union { + uint64 constant; + DebugInfoEntry* reference; + struct { + const void* data; + dwarf_size_t length; + } block; + }; + uint8 attributeClass; + + void SetTo(uint64 constant) + { + this->constant = constant; + attributeClass = ATTRIBUTE_CLASS_CONSTANT; + } + + void SetTo(DebugInfoEntry* reference) + { + this->reference = reference; + attributeClass = ATTRIBUTE_CLASS_REFERENCE; + } + + void SetTo(const void* data, dwarf_size_t length) + { + block.data = data; + block.length = length; + attributeClass = ATTRIBUTE_CLASS_BLOCK; + } +}; + + +#endif // ATTRIBUTE_VALUE_H diff --git a/src/apps/debugger/DataReader.h b/src/apps/debugger/DataReader.h new file mode 100644 index 0000000000..01c3225f05 --- /dev/null +++ b/src/apps/debugger/DataReader.h @@ -0,0 +1,163 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef DATA_READER_H +#define DATA_READER_H + +#include + + +class DataReader { +public: + DataReader() + : + fData(NULL), + fSize(0), + fInitialSize(0), + fOverflow(false) + { + } + + DataReader(const void* data, off_t size) + { + SetTo(data, size); + } + + void SetTo(const void* data, off_t size) + { + fData = (const uint8*)data; + fInitialSize = fSize = size; + fOverflow = false; + } + + bool HasData() const + { + return fSize > 0; + } + + bool HasOverflow() const + { + return fOverflow; + } + + const void* Data() const + { + return fData; + } + + off_t BytesRemaining() const + { + return fSize; + } + + off_t Offset() const + { + return fInitialSize - fSize; + } + + void SeekAbsolute(off_t offset) + { + if (offset < 0) + offset = 0; + else if (offset > fInitialSize) + offset = fInitialSize; + + fData += offset - Offset(); + fSize = fInitialSize - offset; + } + + template + Type Read(const Type& defaultValue) + { + if (fSize < sizeof(Type)) { + fOverflow = true; + fSize = 0; + return defaultValue; + } + + Type data; + memcpy(&data, fData, sizeof(Type)); + + fData += sizeof(Type); + fSize -= sizeof(Type); + + return data; + } + + uint64 ReadUnsignedLEB128(uint64 defaultValue) + { + uint64 result = 0; + int shift = 0; + while (true) { + uint8 byte = Read(0); + result |= uint64(byte & 0x7f) << shift; + if ((byte & 0x80) == 0) + break; + shift += 7; + } + + return fOverflow ? defaultValue : result; + } + + int64 ReadSignedLEB128(int64 defaultValue) + { + int64 result = 0; + int shift = 0; + while (true) { + uint8 byte = Read(0); + result |= uint64(byte & 0x7f) << shift; + shift += 7; + + if ((byte & 0x80) == 0) { + // sign extend + if ((byte & 0x40) != 0 && shift < 64) + result |= -((uint64)1 << shift); + break; + } + } + + return fOverflow ? defaultValue : result; + } + + const char* ReadString() + { + const char* string = (const char*)fData; + while (fSize > 0) { + fData++; + fSize--; + + if (fData[-1] == 0) + return string; + } + + fOverflow = true; + return NULL; + } + + bool Skip(off_t bytes) + { + if (bytes < 0) + return false; + + if (bytes > fSize) { + fSize = 0; + fOverflow = true; + return false; + } + + fData += bytes; + fSize -= bytes; + + return true; + } + +private: + const uint8* fData; + off_t fSize; + off_t fInitialSize; + bool fOverflow; +}; + + +#endif // DATA_READER_H diff --git a/src/apps/debugger/DebugInfoEntries.cpp b/src/apps/debugger/DebugInfoEntries.cpp new file mode 100644 index 0000000000..7aebca34b2 --- /dev/null +++ b/src/apps/debugger/DebugInfoEntries.cpp @@ -0,0 +1,1483 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "DebugInfoEntries.h" + +#include + +#include "AttributeValue.h" +#include "dwarf.h" +#include "SourceLanguageInfo.h" + + +// #pragma mark - DIECompileUnitBase + + +DIECompileUnitBase::DIECompileUnitBase() + : + fName(NULL), + fCompilationDir(NULL), + fLowPC(0), + fHighPC(0), + fStatementListOffset(0), + fMacroInfoOffset(0), + // TODO: Is 0 a good invalid offset? + fBaseTypesUnit(NULL), + fLanguage(0), + fIdentifierCase(0), + fUseUTF8(true) +{ +} + + +status_t +DIECompileUnitBase::InitAfterAttributes(DebugInfoEntryInitInfo& info) +{ + switch (fLanguage) { + case 0: + info.languageInfo = &kUnknownLanguageInfo; + return B_OK; + case DW_LANG_C89: + info.languageInfo = &kC89LanguageInfo; + return B_OK; + case DW_LANG_C: + info.languageInfo = &kCLanguageInfo; + return B_OK; + case DW_LANG_C_plus_plus: + info.languageInfo = &kCPlusPlusLanguageInfo; + return B_OK; + case DW_LANG_C99: + info.languageInfo = &kC99LanguageInfo; + return B_OK; + default: + info.languageInfo = &kUnsupportedLanguageInfo; + return B_OK; + } +} + + +const char* +DIECompileUnitBase::Name() const +{ + return fName; +} + + +status_t +DIECompileUnitBase::AddChild(DebugInfoEntry* child) +{ + if (child->IsType()) + fTypes.Add(child); + else + fOtherChildren.Add(child); + return B_OK; +} + + +status_t +DIECompileUnitBase::AddAttribute_name(uint16 attributeName, + const AttributeValue& value) +{ + fName = value.string; + return B_OK; +} + + +status_t +DIECompileUnitBase::AddAttribute_comp_dir(uint16 attributeName, + const AttributeValue& value) +{ + fCompilationDir = value.string; + return B_OK; +} + + +status_t +DIECompileUnitBase::AddAttribute_low_pc(uint16 attributeName, + const AttributeValue& value) +{ + fLowPC = value.address; + return B_OK; +} + + +status_t +DIECompileUnitBase::AddAttribute_high_pc(uint16 attributeName, + const AttributeValue& value) +{ + fHighPC = value.address; + return B_OK; +} + + +status_t +DIECompileUnitBase::AddAttribute_producer(uint16 attributeName, + const AttributeValue& value) +{ + // not interesting + return B_OK; +} + + +status_t +DIECompileUnitBase::AddAttribute_stmt_list(uint16 attributeName, + const AttributeValue& value) +{ + fStatementListOffset = value.pointer; + return B_OK; +} + + +status_t +DIECompileUnitBase::AddAttribute_macro_info(uint16 attributeName, + const AttributeValue& value) +{ + fMacroInfoOffset = value.pointer; + return B_OK; +} + + +status_t +DIECompileUnitBase::AddAttribute_base_types(uint16 attributeName, + const AttributeValue& value) +{ + fBaseTypesUnit = dynamic_cast(value.reference); + return fBaseTypesUnit != NULL ? B_OK : B_BAD_DATA; +} + + +status_t +DIECompileUnitBase::AddAttribute_language(uint16 attributeName, + const AttributeValue& value) +{ + fLanguage = value.constant; + return B_OK; +} + + +status_t +DIECompileUnitBase::AddAttribute_identifier_case(uint16 attributeName, + const AttributeValue& value) +{ + fIdentifierCase = value.constant; + return B_OK; +} + + +status_t +DIECompileUnitBase::AddAttribute_use_UTF8(uint16 attributeName, + const AttributeValue& value) +{ + fUseUTF8 = value.flag; + return B_OK; +} + + +// #pragma mark - DIEType + + +DIEType::DIEType() + : + fName(NULL) +{ + fAllocated.SetTo((uint64)0); + fAssociated.SetTo((uint64)0); +} + + +bool +DIEType::IsType() const +{ + return true; +} + + +const char* +DIEType::Name() const +{ + return fName; +} + + +status_t +DIEType::AddAttribute_name(uint16 attributeName, + const AttributeValue& value) +{ + fName = value.string; + return B_OK; +} + + +status_t +DIEType::AddAttribute_allocated(uint16 attributeName, + const AttributeValue& value) +{ + return SetDynamicAttributeValue(fAllocated, value); +} + + +status_t +DIEType::AddAttribute_associated(uint16 attributeName, + const AttributeValue& value) +{ + return SetDynamicAttributeValue(fAssociated, value); +} + + +// #pragma mark - DIEModifiedType + + +DIEModifiedType::DIEModifiedType() + : + fType(NULL) +{ +} + + +status_t +DIEModifiedType::AddAttribute_type(uint16 attributeName, + const AttributeValue& value) +{ + fType = dynamic_cast(value.reference); + return B_OK; +} + + +// #pragma mark - DIEAddressingType + + +DIEAddressingType::DIEAddressingType() + : + fAddressClass(0) +{ +} + + +status_t +DIEAddressingType::AddAttribute_address_class(uint16 attributeName, + const AttributeValue& value) +{ +// TODO: How is the address class handled? + fAddressClass = value.constant; + return B_OK; +} + + +// #pragma mark - DIEDeclaredType + + +DIEDeclaredType::DIEDeclaredType() +{ +} + + +// #pragma mark - DIEDerivedType + + +DIEDerivedType::DIEDerivedType() + : + fType(NULL) +{ +} + + +status_t +DIEDerivedType::AddAttribute_type(uint16 attributeName, + const AttributeValue& value) +{ + fType = dynamic_cast(value.reference); + return B_OK; +} + + + + +// #pragma mark - DIECompoundType + + +DIECompoundType::DIECompoundType() +{ +} + + +// #pragma mark - DIEClassBaseType + + +DIEClassBaseType::DIEClassBaseType() +{ +} + + +// #pragma mark - DIEArrayType + + +DIEArrayType::DIEArrayType() + : + fBitStride(0), + fByteSize(0), + fOrdering(DW_ORD_row_major) +{ +} + + +uint16 +DIEArrayType::Tag() const +{ + return DW_TAG_array_type; +} + + +status_t +DIEArrayType::InitAfterHierarchy(DebugInfoEntryInitInfo& info) +{ + fOrdering = info.languageInfo->arrayOrdering; + return B_OK; +} + + +status_t +DIEArrayType::AddChild(DebugInfoEntry* child) +{ + // a dimension child must be of subrange or enumeration type + uint16 tag = child->Tag(); + if (tag == DW_TAG_subrange_type || tag == DW_TAG_enumeration_type) { + fDimensions.Add(child); + return B_OK; + } + + return DIEDerivedType::AddChild(child); +} + + +status_t +DIEArrayType::AddAttribute_ordering(uint16 attributeName, + const AttributeValue& value) +{ + fOrdering = value.constant; + return B_OK; +} + + +status_t +DIEArrayType::AddAttribute_bit_stride(uint16 attributeName, + const AttributeValue& value) +{ + fBitStride = value.constant; + return B_OK; +} + + +status_t +DIEArrayType::AddAttribute_stride_size(uint16 attributeName, + const AttributeValue& value) +{ + fBitStride = value.constant; + return B_OK; +} + + +status_t +DIEArrayType::AddAttribute_byte_size(uint16 attributeName, + const AttributeValue& value) +{ + fByteSize = value.constant; + return B_OK; +} + + +// #pragma mark - DIEClassType + + +DIEClassType::DIEClassType() +{ +} + + +uint16 +DIEClassType::Tag() const +{ + return DW_TAG_class_type; +} + + +// #pragma mark - DIEEntryPoint + + +DIEEntryPoint::DIEEntryPoint() +{ +} + + +uint16 +DIEEntryPoint::Tag() const +{ + return DW_TAG_entry_point; +} + + +// #pragma mark - DIEEnumerationType + + +DIEEnumerationType::DIEEnumerationType() +{ +} + + +uint16 +DIEEnumerationType::Tag() const +{ + return DW_TAG_enumeration_type; +} + + +// #pragma mark - DIEFormalParameter + + +DIEFormalParameter::DIEFormalParameter() +{ +} + + +uint16 +DIEFormalParameter::Tag() const +{ + return DW_TAG_formal_parameter; +} + + +// #pragma mark - DIEImportedDeclaration + + +DIEImportedDeclaration::DIEImportedDeclaration() +{ +} + + +uint16 +DIEImportedDeclaration::Tag() const +{ + return DW_TAG_imported_declaration; +} + + +// #pragma mark - DIELabel + + +DIELabel::DIELabel() +{ +} + + +uint16 +DIELabel::Tag() const +{ + return DW_TAG_label; +} + + +// #pragma mark - DIELexicalBlock + + +DIELexicalBlock::DIELexicalBlock() +{ +} + + +uint16 +DIELexicalBlock::Tag() const +{ + return DW_TAG_lexical_block; +} + + +// #pragma mark - DIEMember + + +DIEMember::DIEMember() +{ +} + + +uint16 +DIEMember::Tag() const +{ + return DW_TAG_member; +} + + +// #pragma mark - DIEPointerType + + +DIEPointerType::DIEPointerType() +{ +} + + +uint16 +DIEPointerType::Tag() const +{ + return DW_TAG_pointer_type; +} + + +// #pragma mark - DIEReferenceType + + +DIEReferenceType::DIEReferenceType() +{ +} + + +uint16 +DIEReferenceType::Tag() const +{ + return DW_TAG_reference_type; +} + + +// #pragma mark - DIECompileUnit + + +DIECompileUnit::DIECompileUnit() +{ +} + + +uint16 +DIECompileUnit::Tag() const +{ + return DW_TAG_compile_unit; +} + + +// #pragma mark - DIEStringType + + +DIEStringType::DIEStringType() +{ +} + + +uint16 +DIEStringType::Tag() const +{ + return DW_TAG_string_type; +} + + +// #pragma mark - DIEStructureType + + +DIEStructureType::DIEStructureType() +{ +} + + +uint16 +DIEStructureType::Tag() const +{ + return DW_TAG_structure_type; +} + + +// #pragma mark - DIESubroutineType + + +DIESubroutineType::DIESubroutineType() +{ +} + + +uint16 +DIESubroutineType::Tag() const +{ + return DW_TAG_subroutine_type; +} + + +// #pragma mark - DIETypedef + + +DIETypedef::DIETypedef() +{ +} + + +uint16 +DIETypedef::Tag() const +{ + return DW_TAG_typedef; +} + + +// #pragma mark - DIEUnionType + + +DIEUnionType::DIEUnionType() +{ +} + + +uint16 +DIEUnionType::Tag() const +{ + return DW_TAG_union_type; +} + + +// #pragma mark - DIEUnspecifiedParameters + + +DIEUnspecifiedParameters::DIEUnspecifiedParameters() +{ +} + + +uint16 +DIEUnspecifiedParameters::Tag() const +{ + return DW_TAG_unspecified_parameters; +} + + +// #pragma mark - DIEVariant + + +DIEVariant::DIEVariant() +{ +} + + +uint16 +DIEVariant::Tag() const +{ + return DW_TAG_variant; +} + + +// #pragma mark - DIECommonBlock + + +DIECommonBlock::DIECommonBlock() +{ +} + + +uint16 +DIECommonBlock::Tag() const +{ + return DW_TAG_common_block; +} + + +// #pragma mark - DIECommonInclusion + + +DIECommonInclusion::DIECommonInclusion() +{ +} + + +uint16 +DIECommonInclusion::Tag() const +{ + return DW_TAG_common_inclusion; +} + + +// #pragma mark - DIEInheritance + + +DIEInheritance::DIEInheritance() +{ +} + + +uint16 +DIEInheritance::Tag() const +{ + return DW_TAG_inheritance; +} + + +// #pragma mark - DIEInlinedSubroutine + + +DIEInlinedSubroutine::DIEInlinedSubroutine() +{ +} + + +uint16 +DIEInlinedSubroutine::Tag() const +{ + return DW_TAG_inlined_subroutine; +} + + +// #pragma mark - DIEModule + + +DIEModule::DIEModule() +{ +} + + +uint16 +DIEModule::Tag() const +{ + return DW_TAG_module; +} + + +// #pragma mark - DIEPointerToMemberType + + +DIEPointerToMemberType::DIEPointerToMemberType() +{ +} + + +uint16 +DIEPointerToMemberType::Tag() const +{ + return DW_TAG_ptr_to_member_type; +} + + +// #pragma mark - DIESetType + + +DIESetType::DIESetType() +{ +} + + +uint16 +DIESetType::Tag() const +{ + return DW_TAG_set_type; +} + + +// #pragma mark - DIESubrangeType + + +DIESubrangeType::DIESubrangeType() +{ +} + + +uint16 +DIESubrangeType::Tag() const +{ + return DW_TAG_subrange_type; +} + + +// #pragma mark - DIEWithStatement + + +DIEWithStatement::DIEWithStatement() +{ +} + + +uint16 +DIEWithStatement::Tag() const +{ + return DW_TAG_with_stmt; +} + + +// #pragma mark - DIEAccessDeclaration + + +DIEAccessDeclaration::DIEAccessDeclaration() +{ +} + + +uint16 +DIEAccessDeclaration::Tag() const +{ + return DW_TAG_access_declaration; +} + + +// #pragma mark - DIEBaseType + + +DIEBaseType::DIEBaseType() + : + fEncoding(0), + fEndianity(0), + fByteSize(0), + fBitSize(0), + fBitOffset(0) +{ +} + + +uint16 +DIEBaseType::Tag() const +{ + return DW_TAG_base_type; +} + + +status_t +DIEBaseType::AddAttribute_encoding(uint16 attributeName, + const AttributeValue& value) +{ + fEncoding = value.constant; + return B_OK; +} + + +status_t +DIEBaseType::AddAttribute_byte_size(uint16 attributeName, + const AttributeValue& value) +{ + fByteSize = value.constant; + return B_OK; +} + + +status_t +DIEBaseType::AddAttribute_bit_size(uint16 attributeName, + const AttributeValue& value) +{ + fBitSize = value.constant; + return B_OK; +} + + +status_t +DIEBaseType::AddAttribute_bit_offset(uint16 attributeName, + const AttributeValue& value) +{ + fBitOffset = value.constant; + return B_OK; +} + + +status_t +DIEBaseType::AddAttribute_endianity(uint16 attributeName, + const AttributeValue& value) +{ + fEndianity = value.constant; + return B_OK; +} + + +// #pragma mark - DIECatchBlock + + +DIECatchBlock::DIECatchBlock() +{ +} + + +uint16 +DIECatchBlock::Tag() const +{ + return DW_TAG_catch_block; +} + + +// #pragma mark - DIEConstType + + +DIEConstType::DIEConstType() +{ +} + + +uint16 +DIEConstType::Tag() const +{ + return DW_TAG_const_type; +} + + +// #pragma mark - DIEConstant + + +DIEConstant::DIEConstant() +{ +} + + +uint16 +DIEConstant::Tag() const +{ + return DW_TAG_constant; +} + + +// #pragma mark - DIEEnumerator + + +DIEEnumerator::DIEEnumerator() +{ +} + + +uint16 +DIEEnumerator::Tag() const +{ + return DW_TAG_enumerator; +} + + +// #pragma mark - DIEFileType + + +DIEFileType::DIEFileType() +{ +} + + +uint16 +DIEFileType::Tag() const +{ + return DW_TAG_file_type; +} + + +// #pragma mark - DIEFriend + + +DIEFriend::DIEFriend() +{ +} + + +uint16 +DIEFriend::Tag() const +{ + return DW_TAG_friend; +} + + +// #pragma mark - DIENameList + + +DIENameList::DIENameList() +{ +} + + +uint16 +DIENameList::Tag() const +{ + return DW_TAG_namelist; +} + + +// #pragma mark - DIENameListItem + + +DIENameListItem::DIENameListItem() +{ +} + + +uint16 +DIENameListItem::Tag() const +{ + return DW_TAG_namelist_item; +} + + +// #pragma mark - DIEPackedType + + +DIEPackedType::DIEPackedType() +{ +} + + +uint16 +DIEPackedType::Tag() const +{ + return DW_TAG_packed_type; +} + + +// #pragma mark - DIESubprogram + + +DIESubprogram::DIESubprogram() +{ +} + + +uint16 +DIESubprogram::Tag() const +{ + return DW_TAG_subprogram; +} + + +// #pragma mark - DIETemplateTypeParameter + + +DIETemplateTypeParameter::DIETemplateTypeParameter() +{ +} + + +uint16 +DIETemplateTypeParameter::Tag() const +{ + return DW_TAG_template_type_parameter; +} + + +// #pragma mark - DIETemplateValueParameter + + +DIETemplateValueParameter::DIETemplateValueParameter() +{ +} + + +uint16 +DIETemplateValueParameter::Tag() const +{ + return DW_TAG_template_value_parameter; +} + + +// #pragma mark - DIEThrownType + + +DIEThrownType::DIEThrownType() +{ +} + + +uint16 +DIEThrownType::Tag() const +{ + return DW_TAG_thrown_type; +} + + +// #pragma mark - DIETryBlock + + +DIETryBlock::DIETryBlock() +{ +} + + +uint16 +DIETryBlock::Tag() const +{ + return DW_TAG_try_block; +} + + +// #pragma mark - DIEVariantPart + + +DIEVariantPart::DIEVariantPart() +{ +} + + +uint16 +DIEVariantPart::Tag() const +{ + return DW_TAG_variant_part; +} + + +// #pragma mark - DIEVariable + + +DIEVariable::DIEVariable() +{ +} + + +uint16 +DIEVariable::Tag() const +{ + return DW_TAG_variable; +} + + +// #pragma mark - DIEVolatileType + + +DIEVolatileType::DIEVolatileType() +{ +} + + +uint16 +DIEVolatileType::Tag() const +{ + return DW_TAG_volatile_type; +} + + +// #pragma mark - DIEDwarfProcedure + + +DIEDwarfProcedure::DIEDwarfProcedure() +{ +} + + +uint16 +DIEDwarfProcedure::Tag() const +{ + return DW_TAG_dwarf_procedure; +} + + +// #pragma mark - DIERestrictType + + +DIERestrictType::DIERestrictType() +{ +} + + +uint16 +DIERestrictType::Tag() const +{ + return DW_TAG_restrict_type; +} + + +// #pragma mark - DIEInterfaceType + + +DIEInterfaceType::DIEInterfaceType() +{ +} + + +uint16 +DIEInterfaceType::Tag() const +{ + return DW_TAG_interface_type; +} + + +// #pragma mark - DIENamespace + + +DIENamespace::DIENamespace() +{ +} + + +uint16 +DIENamespace::Tag() const +{ + return DW_TAG_namespace; +} + + +// #pragma mark - DIEImportedModule + + +DIEImportedModule::DIEImportedModule() +{ +} + + +uint16 +DIEImportedModule::Tag() const +{ + return DW_TAG_imported_module; +} + + +// #pragma mark - DIEUnspecifiedType + + +DIEUnspecifiedType::DIEUnspecifiedType() +{ +} + + +uint16 +DIEUnspecifiedType::Tag() const +{ + return DW_TAG_unspecified_type; +} + + +// #pragma mark - DIEPartialUnit + + +DIEPartialUnit::DIEPartialUnit() +{ +} + + +uint16 +DIEPartialUnit::Tag() const +{ + return DW_TAG_partial_unit; +} + + +// #pragma mark - DIEImportedUnit + + +DIEImportedUnit::DIEImportedUnit() +{ +} + + +uint16 +DIEImportedUnit::Tag() const +{ + return DW_TAG_imported_unit; +} + + +// #pragma mark - DIECondition + + +DIECondition::DIECondition() +{ +} + + +uint16 +DIECondition::Tag() const +{ + return DW_TAG_condition; +} + + +// #pragma mark - DIESharedType + + +DIESharedType::DIESharedType() + : + fBlockSize(DWARF_ADDRESS_MAX) +{ +} + + +uint16 +DIESharedType::Tag() const +{ + return DW_TAG_shared_type; +} + + +status_t +DIESharedType::AddAttribute_count(uint16 attributeName, + const AttributeValue& value) +{ + fBlockSize = value.constant; + return B_OK; +} + + +// #pragma mark - DebugInfoEntryFactory + + +DebugInfoEntryFactory::DebugInfoEntryFactory() +{ +} + + +status_t +DebugInfoEntryFactory::CreateDebugInfoEntry(uint16 tag, DebugInfoEntry*& _entry) +{ + DebugInfoEntry* entry = NULL; + + switch (tag) { + case DW_TAG_array_type: + entry = new(std::nothrow) DIEArrayType; + break; + case DW_TAG_class_type: + entry = new(std::nothrow) DIEClassType; + break; + case DW_TAG_entry_point: + entry = new(std::nothrow) DIEEntryPoint; + break; + case DW_TAG_enumeration_type: + entry = new(std::nothrow) DIEEnumerationType; + break; + case DW_TAG_formal_parameter: + entry = new(std::nothrow) DIEFormalParameter; + break; + case DW_TAG_imported_declaration: + entry = new(std::nothrow) DIEImportedDeclaration; + break; + case DW_TAG_label: + entry = new(std::nothrow) DIELabel; + break; + case DW_TAG_lexical_block: + entry = new(std::nothrow) DIELexicalBlock; + break; + case DW_TAG_member: + entry = new(std::nothrow) DIEMember; + break; + case DW_TAG_pointer_type: + entry = new(std::nothrow) DIEPointerType; + break; + case DW_TAG_reference_type: + entry = new(std::nothrow) DIEReferenceType; + break; + case DW_TAG_compile_unit: + entry = new(std::nothrow) DIECompileUnit; + break; + case DW_TAG_string_type: + entry = new(std::nothrow) DIEStringType; + break; + case DW_TAG_structure_type: + entry = new(std::nothrow) DIEStructureType; + break; + case DW_TAG_subroutine_type: + entry = new(std::nothrow) DIESubroutineType; + break; + case DW_TAG_typedef: + entry = new(std::nothrow) DIETypedef; + break; + case DW_TAG_union_type: + entry = new(std::nothrow) DIEUnionType; + break; + case DW_TAG_unspecified_parameters: + entry = new(std::nothrow) DIEUnspecifiedParameters; + break; + case DW_TAG_variant: + entry = new(std::nothrow) DIEVariant; + break; + case DW_TAG_common_block: + entry = new(std::nothrow) DIECommonBlock; + break; + case DW_TAG_common_inclusion: + entry = new(std::nothrow) DIECommonInclusion; + break; + case DW_TAG_inheritance: + entry = new(std::nothrow) DIEInheritance; + break; + case DW_TAG_inlined_subroutine: + entry = new(std::nothrow) DIEInlinedSubroutine; + break; + case DW_TAG_module: + entry = new(std::nothrow) DIEModule; + break; + case DW_TAG_ptr_to_member_type: + entry = new(std::nothrow) DIEPointerToMemberType; + break; + case DW_TAG_set_type: + entry = new(std::nothrow) DIESetType; + break; + case DW_TAG_subrange_type: + entry = new(std::nothrow) DIESubrangeType; + break; + case DW_TAG_with_stmt: + entry = new(std::nothrow) DIEWithStatement; + break; + case DW_TAG_access_declaration: + entry = new(std::nothrow) DIEAccessDeclaration; + break; + case DW_TAG_base_type: + entry = new(std::nothrow) DIEBaseType; + break; + case DW_TAG_catch_block: + entry = new(std::nothrow) DIECatchBlock; + break; + case DW_TAG_const_type: + entry = new(std::nothrow) DIEConstType; + break; + case DW_TAG_constant: + entry = new(std::nothrow) DIEConstant; + break; + case DW_TAG_enumerator: + entry = new(std::nothrow) DIEEnumerator; + break; + case DW_TAG_file_type: + entry = new(std::nothrow) DIEFileType; + break; + case DW_TAG_friend: + entry = new(std::nothrow) DIEFriend; + break; + case DW_TAG_namelist: + entry = new(std::nothrow) DIENameList; + break; + case DW_TAG_namelist_item: + entry = new(std::nothrow) DIENameListItem; + break; + case DW_TAG_packed_type: + entry = new(std::nothrow) DIEPackedType; + break; + case DW_TAG_subprogram: + entry = new(std::nothrow) DIESubprogram; + break; + case DW_TAG_template_type_parameter: + entry = new(std::nothrow) DIETemplateTypeParameter; + break; + case DW_TAG_template_value_parameter: + entry = new(std::nothrow) DIETemplateValueParameter; + break; + case DW_TAG_thrown_type: + entry = new(std::nothrow) DIEThrownType; + break; + case DW_TAG_try_block: + entry = new(std::nothrow) DIETryBlock; + break; + case DW_TAG_variant_part: + entry = new(std::nothrow) DIEVariantPart; + break; + case DW_TAG_variable: + entry = new(std::nothrow) DIEVariable; + break; + case DW_TAG_volatile_type: + entry = new(std::nothrow) DIEVolatileType; + break; + case DW_TAG_dwarf_procedure: + entry = new(std::nothrow) DIEDwarfProcedure; + break; + case DW_TAG_restrict_type: + entry = new(std::nothrow) DIERestrictType; + break; + case DW_TAG_interface_type: + entry = new(std::nothrow) DIEInterfaceType; + break; + case DW_TAG_namespace: + entry = new(std::nothrow) DIENamespace; + break; + case DW_TAG_imported_module: + entry = new(std::nothrow) DIEImportedModule; + break; + case DW_TAG_unspecified_type: + entry = new(std::nothrow) DIEUnspecifiedType; + break; + case DW_TAG_partial_unit: + entry = new(std::nothrow) DIEPartialUnit; + break; + case DW_TAG_imported_unit: + entry = new(std::nothrow) DIEImportedUnit; + break; + case DW_TAG_condition: + entry = new(std::nothrow) DIECondition; + break; + case DW_TAG_shared_type: + entry = new(std::nothrow) DIESharedType; + break; + default: + break; + } + + _entry = entry; + return B_OK; +} diff --git a/src/apps/debugger/DebugInfoEntries.h b/src/apps/debugger/DebugInfoEntries.h new file mode 100644 index 0000000000..218536e2da --- /dev/null +++ b/src/apps/debugger/DebugInfoEntries.h @@ -0,0 +1,876 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef DEBUG_INFO_ENTRIES_H +#define DEBUG_INFO_ENTRIES_H + +#include "DebugInfoEntry.h" + +#include "AttributeValue.h" + + +// common: +// DW_AT_name +// // not supported by all types: +// DW_AT_allocated +// DW_AT_associated +// DW_AT_data_location +// DW_AT_start_scope + +// modified: +// DW_AT_type + +// declared: +// DECL +// DW_AT_accessibility // !file, !pointer to member +// DW_AT_declaration // !file +// DW_AT_abstract_origin // !interface +// DW_AT_description // !interface +// DW_AT_visibility // !interface + +// derived: declared +// DW_AT_type + +// addressing: modified +// DW_AT_address_class + +// compound: declared +// DW_AT_byte_size // !interface +// DW_AT_specification // !interface + +// class base: compound + + +// unspecified: common +// DECL +// DW_AT_description + + + +// class/structure: class base + +// interface: class base + +// union: compound + +// string: declared +// DW_AT_byte_size +// DW_AT_string_length + +// subroutine: declared +// DW_AT_address_class +// DW_AT_prototyped +// DW_AT_type + + +// enumeration: derived +// DW_AT_bit_stride +// DW_AT_byte_size +// DW_AT_byte_stride +// DW_AT_specification + +// pointer to member: derived +// DW_AT_address_class +// DW_AT_containing_type +// DW_AT_use_location + +// set: derived +// DW_AT_byte_size + +// subrange: derived +// DW_AT_bit_stride +// DW_AT_byte_size +// DW_AT_byte_stride +// DW_AT_count +// DW_AT_lower_bound +// DW_AT_threads_scaled +// DW_AT_upper_bound + +// array: derived +// DW_AT_bit_stride +// DW_AT_byte_size +// DW_AT_ordering +// DW_AT_specification + +// typedef: derived + +// file: derived +// DW_AT_byte_size + + +// shared: modified +// DECL +// DW_AT_count + +// const: modified + +// packed: modified + +// volatile: modified +// DECL + +// restrict: modified + +// pointer: addressing +// DW_AT_specification + +// reference: addressing + + +// basetype: +// DW_AT_binary_scale +// DW_AT_bit_offset +// DW_AT_bit_size +// DW_AT_byte_size +// DW_AT_decimal_scale +// DW_AT_decimal_sign +// DW_AT_description +// DW_AT_digit_count +// DW_AT_encoding +// DW_AT_endianity +// DW_AT_picture_string +// DW_AT_small + + +class DIECompileUnitBase : public DebugInfoEntry { +public: + DIECompileUnitBase(); + + virtual status_t InitAfterAttributes( + DebugInfoEntryInitInfo& info); + + virtual const char* Name() const; + + virtual status_t AddChild(DebugInfoEntry* child); + + virtual status_t AddAttribute_name(uint16 attributeName, + const AttributeValue& value); + virtual status_t AddAttribute_comp_dir(uint16 attributeName, + const AttributeValue& value); + 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_producer(uint16 attributeName, + const AttributeValue& value); + virtual status_t AddAttribute_stmt_list(uint16 attributeName, + const AttributeValue& value); + virtual status_t AddAttribute_macro_info(uint16 attributeName, + const AttributeValue& value); + virtual status_t AddAttribute_base_types(uint16 attributeName, + const AttributeValue& value); + virtual status_t AddAttribute_language(uint16 attributeName, + const AttributeValue& value); + virtual status_t AddAttribute_identifier_case( + uint16 attributeName, + const AttributeValue& value); + virtual status_t AddAttribute_use_UTF8(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); + +// TODO: DW_AT_import + +protected: + const char* fName; + const char* fCompilationDir; + dwarf_addr_t fLowPC; + dwarf_addr_t fHighPC; + dwarf_off_t fStatementListOffset; + dwarf_off_t fMacroInfoOffset; + DIECompileUnitBase* fBaseTypesUnit; + DebugInfoEntryList fTypes; + DebugInfoEntryList fOtherChildren; + uint16 fLanguage; + uint8 fIdentifierCase; + bool fUseUTF8; +}; + + +class DIEType : public DebugInfoEntry { +public: + DIEType(); + + virtual bool IsType() const; + + virtual const char* Name() const; + + virtual status_t AddAttribute_name(uint16 attributeName, + const AttributeValue& value); + virtual status_t AddAttribute_allocated(uint16 attributeName, + const AttributeValue& value); + virtual status_t AddAttribute_associated(uint16 attributeName, + const AttributeValue& value); + +// TODO: +// DW_AT_data_location +// DW_AT_start_scope + +protected: + const char* fName; + DynamicAttributeValue fAllocated; + DynamicAttributeValue fAssociated; +}; + + +class DIEModifiedType : public DIEType { +public: + DIEModifiedType(); + + virtual status_t AddAttribute_type(uint16 attributeName, + const AttributeValue& value); + +protected: + DIEType* fType; +}; + + +class DIEAddressingType : public DIEModifiedType { +public: + DIEAddressingType(); + + virtual status_t AddAttribute_address_class(uint16 attributeName, + const AttributeValue& value); + +protected: + uint64 fAddressClass; +}; + + +class DIEDeclaredType : public DIEType { +public: + DIEDeclaredType(); + +// TODO: +// DECL +// DW_AT_accessibility // !file, !pointer to member +// DW_AT_declaration // !file +// DW_AT_abstract_origin // !interface +// DW_AT_description // !interface +// DW_AT_visibility // !interface + +protected: +}; + + +class DIEDerivedType : public DIEDeclaredType { +public: + DIEDerivedType(); + + virtual status_t AddAttribute_type(uint16 attributeName, + const AttributeValue& value); + +// TODO: +// DW_AT_type + +protected: + DIEType* fType; +}; + + +class DIECompoundType : public DIEDeclaredType { +public: + DIECompoundType(); + +// TODO: +// DW_AT_byte_size // !interface +// DW_AT_specification // !interface + +protected: +}; + + +class DIEClassBaseType : public DIECompoundType { +public: + DIEClassBaseType(); + +protected: +}; + + + +// #pragma mark - + + +class DIEArrayType : public DIEDerivedType { +public: + DIEArrayType(); + + virtual uint16 Tag() const; + + virtual status_t InitAfterHierarchy( + DebugInfoEntryInitInfo& info); + + virtual status_t AddChild(DebugInfoEntry* child); + + virtual status_t AddAttribute_ordering(uint16 attributeName, + const AttributeValue& value); + virtual status_t AddAttribute_bit_stride(uint16 attributeName, + const AttributeValue& value); + virtual status_t AddAttribute_stride_size(uint16 attributeName, + const AttributeValue& value); + virtual status_t AddAttribute_byte_size(uint16 attributeName, + const AttributeValue& value); + +// TODO: +// DW_AT_specification + +private: + uint64 fBitStride; + dwarf_addr_t fByteSize; + uint8 fOrdering; + DebugInfoEntryList fDimensions; +}; + + +class DIEClassType : public DIEClassBaseType { +public: + DIEClassType(); + + virtual uint16 Tag() const; +}; + + +class DIEEntryPoint : public DebugInfoEntry { +public: + DIEEntryPoint(); + + virtual uint16 Tag() const; +}; + + +class DIEEnumerationType : public DIEDerivedType { +public: + DIEEnumerationType(); + + virtual uint16 Tag() const; + +// TODO: +// DW_AT_bit_stride +// DW_AT_byte_size +// DW_AT_byte_stride +// DW_AT_specification +}; + + +class DIEFormalParameter : public DebugInfoEntry { +public: + DIEFormalParameter(); + + virtual uint16 Tag() const; +}; + + +class DIEImportedDeclaration : public DebugInfoEntry { +public: + DIEImportedDeclaration(); + + virtual uint16 Tag() const; +}; + + +class DIELabel : public DebugInfoEntry { +public: + DIELabel(); + + virtual uint16 Tag() const; +}; + + +class DIELexicalBlock : public DebugInfoEntry { +public: + DIELexicalBlock(); + + virtual uint16 Tag() const; +}; + + +class DIEMember : public DebugInfoEntry { +public: + DIEMember(); + + virtual uint16 Tag() const; +}; + + +class DIEPointerType : public DIEAddressingType { +public: + DIEPointerType(); + + virtual uint16 Tag() const; + +// TODO: +// DW_AT_specification +}; + + +class DIEReferenceType : public DIEAddressingType { +public: + DIEReferenceType(); + + virtual uint16 Tag() const; +}; + + +class DIECompileUnit : public DIECompileUnitBase { +public: + DIECompileUnit(); + + virtual uint16 Tag() const; +}; + + +class DIEStringType : public DIEDeclaredType { +public: + DIEStringType(); + + virtual uint16 Tag() const; + +// TODO: +// DW_AT_byte_size +// DW_AT_string_length +}; + + +class DIEStructureType : public DIEClassBaseType { +public: + DIEStructureType(); + + virtual uint16 Tag() const; +}; + + +class DIESubroutineType : public DIEDeclaredType { +public: + DIESubroutineType(); + + virtual uint16 Tag() const; + +// TODO: +// DW_AT_address_class +// DW_AT_prototyped +// DW_AT_type +}; + + +class DIETypedef : public DIEDerivedType { +public: + DIETypedef(); + + virtual uint16 Tag() const; +}; + + +class DIEUnionType : public DIECompoundType { +public: + DIEUnionType(); + + virtual uint16 Tag() const; +}; + + +class DIEUnspecifiedParameters : public DebugInfoEntry { +public: + DIEUnspecifiedParameters(); + + virtual uint16 Tag() const; +}; + + +class DIEVariant : public DebugInfoEntry { +public: + DIEVariant(); + + virtual uint16 Tag() const; +}; + + +class DIECommonBlock : public DebugInfoEntry { +public: + DIECommonBlock(); + + virtual uint16 Tag() const; +}; + + +class DIECommonInclusion : public DebugInfoEntry { +public: + DIECommonInclusion(); + + virtual uint16 Tag() const; +}; + + +class DIEInheritance : public DebugInfoEntry { +public: + DIEInheritance(); + + virtual uint16 Tag() const; +}; + + +class DIEInlinedSubroutine : public DebugInfoEntry { +public: + DIEInlinedSubroutine(); + + virtual uint16 Tag() const; +}; + + +class DIEModule : public DebugInfoEntry { +public: + DIEModule(); + + virtual uint16 Tag() const; +}; + + +class DIEPointerToMemberType : public DIEDerivedType { +public: + DIEPointerToMemberType(); + + virtual uint16 Tag() const; + +// TODO: +// DW_AT_address_class +// DW_AT_containing_type +// DW_AT_use_location +}; + + +class DIESetType : public DIEDerivedType { +public: + DIESetType(); + + virtual uint16 Tag() const; + +// TODO: +// DW_AT_byte_size +}; + + +class DIESubrangeType : public DIEDerivedType { +public: + DIESubrangeType(); + + virtual uint16 Tag() const; + +// TODO: +// DW_AT_bit_stride +// DW_AT_byte_size +// DW_AT_byte_stride +// DW_AT_count +// DW_AT_lower_bound +// DW_AT_threads_scaled +// DW_AT_upper_bound +}; + + +class DIEWithStatement : public DebugInfoEntry { +public: + DIEWithStatement(); + + virtual uint16 Tag() const; +}; + + +class DIEAccessDeclaration : public DebugInfoEntry { +public: + DIEAccessDeclaration(); + + virtual uint16 Tag() const; +}; + + +class DIEBaseType : public DIEType { +public: + DIEBaseType(); + + virtual uint16 Tag() const; + + virtual status_t AddAttribute_encoding(uint16 attributeName, + const AttributeValue& value); + virtual status_t AddAttribute_byte_size(uint16 attributeName, + const AttributeValue& value); + virtual status_t AddAttribute_bit_size(uint16 attributeName, + const AttributeValue& value); + virtual status_t AddAttribute_bit_offset(uint16 attributeName, + const AttributeValue& value); + virtual status_t AddAttribute_endianity(uint16 attributeName, + const AttributeValue& value); + +// TODO: +// DW_AT_binary_scale +// DW_AT_decimal_scale +// DW_AT_decimal_sign +// DW_AT_description +// DW_AT_digit_count +// DW_AT_picture_string +// DW_AT_small + +private: + uint8 fEncoding; + uint8 fEndianity; + uint16 fByteSize; + uint16 fBitSize; + uint16 fBitOffset; +}; + + +class DIECatchBlock : public DebugInfoEntry { +public: + DIECatchBlock(); + + virtual uint16 Tag() const; +}; + + +class DIEConstType : public DIEModifiedType { +public: + DIEConstType(); + + virtual uint16 Tag() const; +}; + + +class DIEConstant : public DebugInfoEntry { +public: + DIEConstant(); + + virtual uint16 Tag() const; +}; + + +class DIEEnumerator : public DebugInfoEntry { +public: + DIEEnumerator(); + + virtual uint16 Tag() const; +}; + + +class DIEFileType : public DIEDerivedType { +public: + DIEFileType(); + + virtual uint16 Tag() const; + +// TODO: +// DW_AT_byte_size +}; + + +class DIEFriend : public DebugInfoEntry { +public: + DIEFriend(); + + virtual uint16 Tag() const; +}; + + +class DIENameList : public DebugInfoEntry { +public: + DIENameList(); + + virtual uint16 Tag() const; +}; + + +class DIENameListItem : public DebugInfoEntry { +public: + DIENameListItem(); + + virtual uint16 Tag() const; +}; + + +class DIEPackedType : public DIEModifiedType { +public: + DIEPackedType(); + + virtual uint16 Tag() const; +}; + + +class DIESubprogram : public DebugInfoEntry { +public: + DIESubprogram(); + + virtual uint16 Tag() const; +}; + + +class DIETemplateTypeParameter : public DebugInfoEntry { +public: + DIETemplateTypeParameter(); + + virtual uint16 Tag() const; +}; + + +class DIETemplateValueParameter : public DebugInfoEntry { +public: + DIETemplateValueParameter(); + + virtual uint16 Tag() const; +}; + + +class DIEThrownType : public DebugInfoEntry { +public: + DIEThrownType(); + + virtual uint16 Tag() const; +}; + + +class DIETryBlock : public DebugInfoEntry { +public: + DIETryBlock(); + + virtual uint16 Tag() const; +}; + + +class DIEVariantPart : public DebugInfoEntry { +public: + DIEVariantPart(); + + virtual uint16 Tag() const; +}; + + +class DIEVariable : public DebugInfoEntry { +public: + DIEVariable(); + + virtual uint16 Tag() const; +}; + + +class DIEVolatileType : public DIEModifiedType { +public: + DIEVolatileType(); + + virtual uint16 Tag() const; + +// TODO: +// DECL +}; + + +class DIEDwarfProcedure : public DebugInfoEntry { +public: + DIEDwarfProcedure(); + + virtual uint16 Tag() const; +}; + + +class DIERestrictType : public DIEModifiedType { +public: + DIERestrictType(); + + virtual uint16 Tag() const; +}; + + +class DIEInterfaceType : public DIEClassBaseType { +public: + DIEInterfaceType(); + + virtual uint16 Tag() const; +}; + + +class DIENamespace : public DebugInfoEntry { +public: + DIENamespace(); + + virtual uint16 Tag() const; +}; + + +class DIEImportedModule : public DebugInfoEntry { +public: + DIEImportedModule(); + + virtual uint16 Tag() const; +}; + + +class DIEUnspecifiedType : public DIEType { +public: + DIEUnspecifiedType(); + + virtual uint16 Tag() const; + +// TODO: +// DECL +// DW_AT_description +}; + + +class DIEPartialUnit : public DIECompileUnitBase { +public: + DIEPartialUnit(); + + virtual uint16 Tag() const; + +// TODO: +// DW_AT_description +}; + + +class DIEImportedUnit : public DebugInfoEntry { +public: + DIEImportedUnit(); + + virtual uint16 Tag() const; +}; + + +class DIECondition : public DebugInfoEntry { +public: + DIECondition(); + + virtual uint16 Tag() const; +}; + + + +class DIESharedType : public DIEModifiedType { +public: + DIESharedType(); + + virtual uint16 Tag() const; + + virtual status_t AddAttribute_count(uint16 attributeName, + const AttributeValue& value); + +// TODO: +// DECL + +private: + uint64 fBlockSize; +}; + + +// #pragma mark - DebugInfoEntryFactory + + +class DebugInfoEntryFactory { +public: + DebugInfoEntryFactory(); + + status_t CreateDebugInfoEntry(uint16 tag, + DebugInfoEntry*& entry); +}; + + +#endif // DEBUG_INFO_ENTRIES_H diff --git a/src/apps/debugger/DebugInfoEntry.cpp b/src/apps/debugger/DebugInfoEntry.cpp new file mode 100644 index 0000000000..6b2e30299b --- /dev/null +++ b/src/apps/debugger/DebugInfoEntry.cpp @@ -0,0 +1,183 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "DebugInfoEntries.h" + +#include + +#include "AttributeValue.h" +#include "dwarf.h" + + +#define DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(name) \ + status_t \ + DebugInfoEntry::AddAttribute_##name(uint16 attributeName, \ + const AttributeValue& value) \ + { \ + return ATTRIBUTE_NOT_HANDLED; \ + } + + +DebugInfoEntry::DebugInfoEntry() +{ +} + + +DebugInfoEntry::~DebugInfoEntry() +{ +} + + +status_t +DebugInfoEntry::InitAfterHierarchy(DebugInfoEntryInitInfo& info) +{ + return B_OK; +} + + +status_t +DebugInfoEntry::InitAfterAttributes(DebugInfoEntryInitInfo& info) +{ + return B_OK; +} + + +bool +DebugInfoEntry::IsType() const +{ + return false; +} + + +const char* +DebugInfoEntry::Name() const +{ + return NULL; +} + + +status_t +DebugInfoEntry::AddChild(DebugInfoEntry* child) +{ + // ignore children where we don't expect them + return ENTRY_NOT_HANDLED; +} + + +status_t +DebugInfoEntry::AddAttribute_sibling(uint16 attributeName, + const AttributeValue& value) +{ + // This attribute is only intended to help the debug info consumer. We don't + // need it. + return B_OK; +} + + +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(location) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(name) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(ordering) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(byte_size) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(bit_offset) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(bit_size) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(stmt_list) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(low_pc) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(high_pc) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(language) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(discr) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(discr_value) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(visibility) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(import) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(string_length) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(common_reference) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(comp_dir) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(const_value) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(containing_type) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(default_value) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(inline) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(is_optional) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(lower_bound) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(producer) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(prototyped) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(return_addr) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(start_scope) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(bit_stride) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(upper_bound) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(abstract_origin) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(accessibility) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(address_class) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(artificial) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(base_types) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(calling_convention) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(count) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(data_member_location) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(decl_column) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(decl_file) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(decl_line) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(declaration) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(discr_list) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(encoding) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(external) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(frame_base) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(friend) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(identifier_case) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(macro_info) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(namelist_item) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(priority) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(segment) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(specification) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(static_link) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(type) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(use_location) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(variable_parameter) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(virtuality) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(vtable_elem_location) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(allocated) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(associated) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(data_location) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(byte_stride) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(entry_pc) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(use_UTF8) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(extension) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(ranges) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(trampoline) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(call_column) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(call_file) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(call_line) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(description) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(binary_scale) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(decimal_scale) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(small) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(decimal_sign) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(digit_count) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(picture_string) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(mutable) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(threads_scaled) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(explicit) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(object_pointer) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(endianity) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(elemental) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(pure) +DEFINE_DEBUG_INFO_ENTRY_ATTR_SETTER(recursive) + + +status_t +DebugInfoEntry::SetDynamicAttributeValue(DynamicAttributeValue& toSet, + const AttributeValue& value) +{ + switch (value.attributeClass) { + case ATTRIBUTE_CLASS_CONSTANT: + toSet.SetTo(value.constant); + return B_OK; + case ATTRIBUTE_CLASS_REFERENCE: + toSet.SetTo(value.reference); + return B_OK; + case ATTRIBUTE_CLASS_BLOCK: + toSet.SetTo(value.block.data, value.block.length); + return B_OK; + default: + return B_BAD_DATA; + } +} diff --git a/src/apps/debugger/DebugInfoEntry.h b/src/apps/debugger/DebugInfoEntry.h new file mode 100644 index 0000000000..d7fd3dddd3 --- /dev/null +++ b/src/apps/debugger/DebugInfoEntry.h @@ -0,0 +1,152 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef DEBUG_INFO_ENTRY_H +#define DEBUG_INFO_ENTRY_H + +#include + +#include "types.h" + + +#define DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(name) \ + virtual status_t AddAttribute_##name(uint16 attributeName, \ + const AttributeValue& value); + +enum { + ATTRIBUTE_NOT_HANDLED = 1, + ENTRY_NOT_HANDLED = 2 +}; + + +class AttributeValue; +class DynamicAttributeValue; +struct SourceLanguageInfo; + + +struct DebugInfoEntryInitInfo { + const SourceLanguageInfo* languageInfo; +}; + + +class DebugInfoEntry : public DoublyLinkedListLinkImpl { +public: + DebugInfoEntry(); + virtual ~DebugInfoEntry(); + + virtual status_t InitAfterHierarchy( + DebugInfoEntryInitInfo& info); + virtual status_t InitAfterAttributes( + DebugInfoEntryInitInfo& info); + + virtual uint16 Tag() const = 0; + + virtual bool IsType() const; + + virtual const char* Name() const; + + virtual status_t AddChild(DebugInfoEntry* child); + + virtual status_t AddAttribute_sibling(uint16 attributeName, + const AttributeValue& value); + +// TODO: Handle (ignore?) DW_AT_description here? + + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(location) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(name) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(ordering) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(byte_size) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(bit_offset) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(bit_size) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(stmt_list) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(low_pc) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(high_pc) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(language) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(discr) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(discr_value) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(visibility) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(import) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(string_length) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(common_reference) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(comp_dir) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(const_value) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(containing_type) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(default_value) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(inline) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(is_optional) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(lower_bound) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(producer) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(prototyped) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(return_addr) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(start_scope) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(bit_stride) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(upper_bound) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(abstract_origin) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(accessibility) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(address_class) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(artificial) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(base_types) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(calling_convention) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(count) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(data_member_location) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(decl_column) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(decl_file) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(decl_line) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(declaration) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(discr_list) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(encoding) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(external) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(frame_base) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(friend) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(identifier_case) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(macro_info) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(namelist_item) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(priority) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(segment) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(specification) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(static_link) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(type) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(use_location) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(variable_parameter) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(virtuality) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(vtable_elem_location) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(allocated) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(associated) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(data_location) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(byte_stride) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(entry_pc) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(use_UTF8) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(extension) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(ranges) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(trampoline) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(call_column) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(call_file) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(call_line) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(description) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(binary_scale) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(decimal_scale) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(small) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(decimal_sign) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(digit_count) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(picture_string) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(mutable) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(threads_scaled) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(explicit) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(object_pointer) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(endianity) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(elemental) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(pure) + DECLARE_DEBUG_INFO_ENTRY_ATTR_SETTER(recursive) + +protected: + status_t SetDynamicAttributeValue( + DynamicAttributeValue& toSet, + const AttributeValue& value); +}; + + +typedef DoublyLinkedList DebugInfoEntryList; + + +#endif // DEBUG_INFO_ENTRY_H diff --git a/src/apps/debugger/DwarfManager.cpp b/src/apps/debugger/DwarfManager.cpp new file mode 100644 index 0000000000..7166a6e62c --- /dev/null +++ b/src/apps/debugger/DwarfManager.cpp @@ -0,0 +1,974 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "DwarfManager.h" + +#include +#include + +#include +#include + +#include "Array.h" +#include "attribute_classes.h" +#include "AttributeValue.h" +#include "DataReader.h" +#include "DebugInfoEntries.h" +#include "dwarf.h" +#include "ElfFile.h" +#include "tag_names.h" + + +struct AbbreviationTableEntry : HashTableLink { + uint32 code; + off_t offset; + off_t size; + + AbbreviationTableEntry(uint32 code, off_t offset, off_t size) + : + code(code), + offset(offset), + size(size) + { + } +}; + + +struct AbbreviationEntry { + AbbreviationEntry() + { + } + + AbbreviationEntry(uint32 code, const void* data, off_t size) + { + SetTo(code, data, size); + } + + void SetTo(uint32 code, const void* data, off_t size) + { + fCode = code; + fAttributesReader.SetTo(data, size); + fTag = fAttributesReader.ReadUnsignedLEB128(0); + fHasChildren = fAttributesReader.Read(0); + fData = fAttributesReader.Data(); + fSize = fAttributesReader.BytesRemaining(); + } + + uint32 Code() const { return fCode; } + uint32 Tag() const { return fTag; } + bool HasChildren() const { return fHasChildren == DW_CHILDREN_yes; } + + bool GetNextAttribute(uint32& name, uint32& form) + { + name = fAttributesReader.ReadUnsignedLEB128(0); + form = fAttributesReader.ReadUnsignedLEB128(0); + return !fAttributesReader.HasOverflow() && (name != 0 || form != 0); + } + +private: + uint32 fCode; + const void* fData; + off_t fSize; + uint32 fTag; + uint8 fHasChildren; + DataReader fAttributesReader; +}; + + +struct AbbreviationTableHashDefinition { + typedef uint32 KeyType; + typedef AbbreviationTableEntry ValueType; + + size_t HashKey(uint32 key) const + { + return (size_t)key; + } + + size_t Hash(AbbreviationTableEntry* value) const + { + return HashKey(value->code); + } + + bool Compare(uint32 key, AbbreviationTableEntry* value) const + { + return value->code == key; + } + + HashTableLink* GetLink( + AbbreviationTableEntry* value) const + { + return value; + } +}; + +typedef OpenHashTable AbbreviationEntryTable; + + +class AbbreviationTable : public DoublyLinkedListLinkImpl { +public: + AbbreviationTable(off_t offset) + : + fOffset(offset), + fData(NULL), + fSize(0) + { + } + + ~AbbreviationTable() + { + } + + status_t Init(const void* section, off_t sectionSize) + { + if (fOffset < 0 || fOffset >= sectionSize) + return B_BAD_DATA; + + fData = (uint8*)section + fOffset; + fSize = sectionSize - fOffset; + // That's only the maximum size. Will be adjusted at the end. + + status_t error = fEntryTable.Init(); + if (error != B_OK) + return error; + + DataReader abbrevReader(fData, fSize); + + while (true) { + bool nullEntry; + status_t error = _ParseAbbreviationEntry(abbrevReader, nullEntry); + if (error != B_OK) + return error; + + if (nullEntry) + break; + } + + fSize -= abbrevReader.BytesRemaining(); + + return B_OK; + } + + off_t Offset() const + { + return fOffset; + } + + bool GetAbbreviationEntry(uint32 code, AbbreviationEntry& entry) + { + AbbreviationTableEntry* tableEntry = fEntryTable.Lookup(code); + if (tableEntry == NULL) + return false; + + entry.SetTo(code, fData + tableEntry->offset, tableEntry->size); + return true; + } + + status_t _ParseAbbreviationEntry(DataReader& abbrevReader, bool& _nullEntry) + { + uint32 code = abbrevReader.ReadUnsignedLEB128(0); + if (code == 0) { + if (abbrevReader.HasOverflow()) { + fprintf(stderr, "Invalid abbreviation table 1!\n"); + return B_BAD_DATA; + } + _nullEntry = true; + return B_OK; + } + + off_t remaining = abbrevReader.BytesRemaining(); + +/* uint32 tag =*/ abbrevReader.ReadUnsignedLEB128(0); +/* uint8 hasChildren =*/ abbrevReader.Read(DW_CHILDREN_no); + +// printf("entry: %lu, tag: %lu, children: %d\n", code, tag, +// hasChildren); + + // parse attribute specifications + while (true) { + uint32 attributeName = abbrevReader.ReadUnsignedLEB128(0); + uint32 attributeForm = abbrevReader.ReadUnsignedLEB128(0); + if (abbrevReader.HasOverflow()) { + fprintf(stderr, "Invalid abbreviation table 2!\n"); + return B_BAD_DATA; + } + + if (attributeName == 0 && attributeForm == 0) + break; + +// printf(" attr: name: %lu, form: %lu\n", attributeName, +// attributeForm); + } + + // create the entry + if (fEntryTable.Lookup(code) == NULL) { + AbbreviationTableEntry* entry = new(std::nothrow) + AbbreviationTableEntry(code, fSize - remaining, + remaining - abbrevReader.BytesRemaining()); + if (entry == NULL) + return B_NO_MEMORY; + + fEntryTable.Insert(entry); + } else + fprintf(stderr, "Duplicate abbreviation table entry %lu!\n", code); + + _nullEntry = false; + return B_OK; + } + +private: + off_t fOffset; + const uint8* fData; + off_t fSize; + AbbreviationEntryTable fEntryTable; +}; + + +// #pragma mark - CompilationUnit + + +struct DwarfManager::CompilationUnit + : DoublyLinkedListLinkImpl { + CompilationUnit(dwarf_off_t headerOffset, dwarf_off_t contentOffset, + dwarf_off_t totalSize, dwarf_off_t abbreviationOffset) + : + fHeaderOffset(headerOffset), + fContentOffset(contentOffset), + fTotalSize(totalSize), + fAbbreviationOffset(abbreviationOffset), + fAbbreviationTable(NULL) + { + } + + ~CompilationUnit() + { + } + + dwarf_off_t HeaderOffset() const + { + return fHeaderOffset; + } + + dwarf_off_t ContentOffset() const + { + return fContentOffset; + } + + dwarf_off_t RelativeContentOffset() const + { + return fContentOffset - fHeaderOffset; + } + + dwarf_off_t TotalSize() const + { + return fTotalSize; + } + + dwarf_off_t ContentSize() const + { + return fTotalSize - RelativeContentOffset(); + } + + dwarf_off_t AbbreviationOffset() const + { + return fAbbreviationOffset; + } + + void SetAbbreviationTable(AbbreviationTable* abbreviationTable) + { + fAbbreviationTable = abbreviationTable; + } + + AbbreviationTable* GetAbbreviationTable() const + { + return fAbbreviationTable; + } + + status_t AddDebugInfoEntry(DebugInfoEntry* entry, dwarf_off_t offset) + { + if (!fEntries.Add(entry)) + return B_NO_MEMORY; + if (!fEntryOffsets.Add(offset)) { + fEntries.Remove(fEntries.Count() - 1); + return B_NO_MEMORY; + } + + return B_OK; + } + + int CountEntries() const + { + return fEntries.Count(); + } + + void GetEntryAt(int index, DebugInfoEntry*& entry, + dwarf_off_t& offset) const + { + entry = fEntries[index]; + offset = fEntryOffsets[index]; + } + + DebugInfoEntry* EntryForOffset(dwarf_off_t offset) const + { + if (fEntries.IsEmpty()) + return NULL; + + // binary search + int lower = 0; + int upper = fEntries.Count() - 1; + while (lower < upper) { + int mid = (lower + upper + 1) / 2; + if (fEntryOffsets[mid] > offset) + upper = mid - 1; + else + lower = mid; + } + + return fEntryOffsets[lower] == offset ? fEntries[lower] : NULL; + } + +private: + dwarf_off_t fHeaderOffset; + dwarf_off_t fContentOffset; + dwarf_off_t fTotalSize; + dwarf_off_t fAbbreviationOffset; + AbbreviationTable* fAbbreviationTable; + Array fEntries; + Array fEntryOffsets; +}; + + +// #pragma mark - File + + +struct DwarfManager::File : DoublyLinkedListLinkImpl { + File() + : + fName(NULL), + fElfFile(NULL), + fDebugInfoSection(NULL), + fDebugAbbrevSection(NULL), + fDebugStringSection(NULL), + fCurrentCompilationUnit(NULL), + fFinished(false), + fFinishError(B_OK) + { + } + + ~File() + { + while (CompilationUnit* unit = fCompilationUnits.RemoveHead()) + delete unit; + + while (AbbreviationTable* table = fAbbreviationTables.RemoveHead()) + delete table; + + if (fElfFile != NULL) { + fElfFile->PutSection(fDebugInfoSection); + fElfFile->PutSection(fDebugAbbrevSection); + fElfFile->PutSection(fDebugStringSection); + delete fElfFile; + } + + free(fName); + } + + status_t Load(const char* fileName) + { + fName = strdup(fileName); + if (fName == NULL) + return B_NO_MEMORY; + + // load the ELF file + fElfFile = new(std::nothrow) ElfFile; + if (fElfFile == NULL) + return B_NO_MEMORY; + + status_t error = fElfFile->Init(fileName); + if (error != B_OK) + return error; + + // get the interesting sections + fDebugInfoSection = fElfFile->GetSection(".debug_info"); + fDebugAbbrevSection = fElfFile->GetSection(".debug_abbrev"); + fDebugStringSection = fElfFile->GetSection(".debug_str"); + if (fDebugInfoSection == NULL || fDebugAbbrevSection == NULL + || fDebugStringSection == NULL) { + fprintf(stderr, "DwarfManager::File::Load(\"%s\"): no " + ".debug_info, .debug_abbrev, or .debug_str section.\n", + fileName); + return B_ERROR; + } + + // iterate through the debug info section + DataReader dataReader(fDebugInfoSection->Data(), + fDebugInfoSection->Size()); + while (dataReader.HasData()) { + dwarf_off_t unitHeaderOffset = dataReader.Offset(); + uint64 unitLength = dataReader.Read(0); + bool dwarf64 = (unitLength == 0xffffffff); + if (dwarf64) + unitLength = dataReader.Read(0); + + dwarf_off_t unitLengthOffset = dataReader.Offset(); + // the unitLength starts here + + if (unitLengthOffset + unitLength + > (uint64)fDebugInfoSection->Size()) { + printf("\"%s\": Invalid compilation unit length.\n", fileName); + break; + } + + int version = dataReader.Read(0); + off_t abbrevOffset = dwarf64 + ? dataReader.Read(0) + : dataReader.Read(0); + uint8 addressSize = dataReader.Read(0); + + if (dataReader.HasOverflow()) { + printf("\"%s\": Unexpected end of data in compilation unit " + "header.\n", fileName); + break; + } + + printf("DWARF%d compilation unit: version %d, length: %lld, " + "abbrevOffset: %lld, address size: %d\n", dwarf64 ? 64 : 32, + version, unitLength, abbrevOffset, addressSize); + + if (version != 2 && version != 3) { + printf("\"%s\": Unsupported compilation unit version: %d\n", + fileName, version); + break; + } + + if (addressSize != 4) { + printf("\"%s\": Unsupported address size: %d\n", fileName, + addressSize); + break; + } + + dwarf_off_t unitContentOffset = dataReader.Offset(); + + // create a compilation unit object + CompilationUnit* unit = new(std::nothrow) CompilationUnit( + unitHeaderOffset, unitContentOffset, + unitLength + (unitLengthOffset - unitHeaderOffset), + abbrevOffset); + if (unit == NULL) + return B_NO_MEMORY; + + fCompilationUnits.Add(unit); + + // parse the debug info for the unit + fCurrentCompilationUnit = unit; + error = _ParseCompilationUnit(unit); + if (error != B_OK) + return error; + + dataReader.SeekAbsolute(unitLengthOffset + unitLength); + } + + return B_OK; + } + + status_t FinishLoading() + { + if (fFinished) + return B_OK; + if (fFinishError != B_OK) + return fFinishError; + + for (CompilationUnitList::Iterator it = fCompilationUnits.GetIterator(); + CompilationUnit* unit = it.Next();) { + fCurrentCompilationUnit = unit; + status_t error = _FinishCompilationUnit(unit); + if (error != B_OK) + return fFinishError = error; + } + + fFinished = true; + return B_OK; + } + + const char* Name() const + { + return fName; + } + +private: + typedef DoublyLinkedList AbbreviationTableList; + typedef DoublyLinkedList CompilationUnitList; + +private: + status_t _ParseCompilationUnit(CompilationUnit* unit) + { + AbbreviationTable* abbreviationTable; + status_t error = _GetAbbreviationTable(unit->AbbreviationOffset(), + abbreviationTable); + if (error != B_OK) + return error; + + unit->SetAbbreviationTable(abbreviationTable); + + DataReader dataReader( + (const uint8*)fDebugInfoSection->Data() + unit->ContentOffset(), + unit->ContentSize()); + + DebugInfoEntry* entry; + bool endOfEntryList; + error = _ParseDebugInfoEntry(dataReader, abbreviationTable, entry, + endOfEntryList); + if (error != B_OK) + return error; + + if (dynamic_cast(entry) == NULL) { + fprintf(stderr, "No compilation unit entry in .debug_info " + "section.\n"); + return B_BAD_DATA; + } + +printf("remaining bytes in unit: %lld\n", dataReader.BytesRemaining()); +if (dataReader.HasData()) { +printf(" "); +while (dataReader.HasData()) { + printf("%02x", dataReader.Read(0)); +} +printf("\n"); +} + return B_OK; + } + + status_t _ParseDebugInfoEntry(DataReader& dataReader, + AbbreviationTable* abbreviationTable, DebugInfoEntry*& _entry, + bool& _endOfEntryList, int level = 0) + { + dwarf_off_t entryOffset = dataReader.Offset() + + fCurrentCompilationUnit->RelativeContentOffset(); + + uint32 code = dataReader.ReadUnsignedLEB128(0); + if (code == 0) { + if (dataReader.HasOverflow()) { + fprintf(stderr, "Unexpected end of .debug_info section.\n"); + return B_BAD_DATA; + } + _entry = NULL; + _endOfEntryList = true; + return B_OK; + } + + // get the corresponding abbreviation entry + AbbreviationEntry abbreviationEntry; + if (!abbreviationTable->GetAbbreviationEntry(code, abbreviationEntry)) { + fprintf(stderr, "No abbreviation entry for code %lu\n", code); + return B_BAD_DATA; + } +printf("%*sentry at %lu: %lu, tag: %s (%lu), children: %d\n", level * 2, "", +entryOffset, abbreviationEntry.Code(), get_entry_tag_name(abbreviationEntry.Tag()), +abbreviationEntry.Tag(), abbreviationEntry.HasChildren()); + + DebugInfoEntry* entry; + status_t error = fDebugInfoFactory.CreateDebugInfoEntry( + abbreviationEntry.Tag(), entry); + if (error != B_OK) + return error; + ObjectDeleter entryDeleter(entry); + + error = fCurrentCompilationUnit->AddDebugInfoEntry(entry, entryOffset); + if (error != B_OK) + return error; + + // parse the attributes (supply NULL entry to avoid adding them yet) + error = _ParseEntryAttributes(dataReader, NULL, abbreviationEntry); + if (error != B_OK) + return error; + + // parse children, if the entry has any + if (abbreviationEntry.HasChildren()) { + while (true) { + DebugInfoEntry* childEntry; + bool endOfEntryList; + status_t error = _ParseDebugInfoEntry(dataReader, + abbreviationTable, childEntry, endOfEntryList, level + 1); + if (error != B_OK) + return error; + + // add the child to our entry + if (childEntry != NULL) { + if (entry != NULL) { + error = entry->AddChild(childEntry); + if (error == ENTRY_NOT_HANDLED) { + error = B_OK; +printf("%*s -> child unhandled\n", level * 2, ""); + } + + if (error != B_OK) { + delete childEntry; + return error; + } + } else + delete childEntry; + } + + if (endOfEntryList) + break; + } + } + + entryDeleter.Detach(); + _entry = entry; + _endOfEntryList = false; + return B_OK; + } + + status_t _FinishCompilationUnit(CompilationUnit* unit) + { +printf("\nfinishing compilation unit %p\n", unit); + AbbreviationTable* abbreviationTable = unit->GetAbbreviationTable(); + + DataReader dataReader( + (const uint8*)fDebugInfoSection->Data() + unit->HeaderOffset(), + unit->TotalSize()); +// DataReader dataReader( +// (const uint8*)fDebugInfoSection->Data() + unit->ContentOffset(), +// unit->ContentSize()); + + DebugInfoEntryInitInfo entryInitInfo; + + int entryCount = unit->CountEntries(); + for (int i = 0; i < entryCount; i++) { + // get the entry + DebugInfoEntry* entry; + dwarf_off_t offset; + unit->GetEntryAt(i, entry, offset); +printf("entry %p at %lu\n", entry, offset); + + // seek the reader to the entry + dataReader.SeekAbsolute(offset); + + // read the entry code + uint32 code = dataReader.ReadUnsignedLEB128(0); + + // get the respective abbreviation entry + AbbreviationEntry abbreviationEntry; + abbreviationTable->GetAbbreviationEntry(code, abbreviationEntry); + + // initialization before setting the attributes + status_t error = entry->InitAfterHierarchy(entryInitInfo); + if (error != B_OK) { + fprintf(stderr, "Init after hierarchy failed!\n"); + return error; + } + + // parse the attributes -- this time pass the entry, so that the + // attribute get set on it + error = _ParseEntryAttributes(dataReader, entry, abbreviationEntry); + if (error != B_OK) + return error; + + // initialization after setting the attributes + error = entry->InitAfterAttributes(entryInitInfo); + if (error != B_OK) { + fprintf(stderr, "Init after attributes failed!\n"); + return error; + } + } + + return B_OK; + } + + status_t _ParseEntryAttributes(DataReader& dataReader, + DebugInfoEntry* entry, AbbreviationEntry& abbreviationEntry) + { + uint32 attributeName; + uint32 attributeForm; + while (abbreviationEntry.GetNextAttribute(attributeName, + attributeForm)) { + // resolve attribute form indirection + if (attributeForm == DW_FORM_indirect) + attributeForm = dataReader.ReadUnsignedLEB128(0); + + // prepare an AttributeValue + AttributeValue attributeValue; + attributeValue.attributeForm = attributeForm; + attributeValue.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 + // those that need additional processing, we read a temporary value + // first. + uint64 value = 0; + dwarf_size_t blockLength = 0; + bool localReference = true; + + switch (attributeForm) { + case DW_FORM_addr: + value = dataReader.Read(0); + break; + case DW_FORM_block2: + blockLength = dataReader.Read(0); + break; + case DW_FORM_block4: + blockLength = dataReader.Read(0); + break; + case DW_FORM_data2: + value = dataReader.Read(0); + break; + case DW_FORM_data4: + value = dataReader.Read(0); + break; + case DW_FORM_data8: + value = dataReader.Read(0); + break; + case DW_FORM_string: + attributeValue.string = dataReader.ReadString(); + break; + case DW_FORM_block: + blockLength = dataReader.ReadUnsignedLEB128(0); + break; + case DW_FORM_block1: + blockLength = dataReader.Read(0); + break; + case DW_FORM_data1: + value = dataReader.Read(0); + break; + case DW_FORM_flag: + attributeValue.flag = dataReader.Read(0) != 0; + break; + case DW_FORM_sdata: + value = dataReader.ReadSignedLEB128(0); + attributeValue.isSigned = true; + break; + case DW_FORM_strp: + { + dwarf_off_t offset = dataReader.Read(0); + if (offset >= fDebugStringSection->Size()) { + fprintf(stderr, "Invalid DW_FORM_strp offset: %lu\n", + offset); + return B_BAD_DATA; + } + attributeValue.string + = (const char*)fDebugStringSection->Data() + offset; + break; + } + case DW_FORM_udata: + value = dataReader.ReadUnsignedLEB128(0); + break; + case DW_FORM_ref_addr: + value = dataReader.Read(0); + localReference = false; + break; + case DW_FORM_ref1: + value = dataReader.Read(0); + break; + case DW_FORM_ref2: + value = dataReader.Read(0); + break; + case DW_FORM_ref4: + value = dataReader.Read(0); + break; + case DW_FORM_ref8: + value = dataReader.Read(0); + break; + case DW_FORM_ref_udata: + value = dataReader.ReadUnsignedLEB128(0); + break; + case DW_FORM_indirect: + default: + fprintf(stderr, "Unsupported attribute form: %lu\n", + attributeForm); + return B_BAD_DATA; + } + + // get the attribute class -- skip the attribute, if we can't handle + // it + uint8 attributeClass = get_attribute_class(attributeName, + attributeForm); + if (attributeClass == ATTRIBUTE_CLASS_UNKNOWN) { + printf("skipping attribute with unrecognized class: %s (%#lx) " + "%s (%#lx)\n", get_attribute_name_name(attributeName), + attributeName, get_attribute_form_name(attributeForm), + attributeForm); + continue; + } + attributeValue.attributeClass = attributeClass; + + // set the attribute value according to the attribute's class + switch (attributeClass) { + case ATTRIBUTE_CLASS_ADDRESS: + attributeValue.address = value; + break; + case ATTRIBUTE_CLASS_BLOCK: + attributeValue.block.data = dataReader.Data(); + attributeValue.block.length = blockLength; + dataReader.Skip(blockLength); + break; + case ATTRIBUTE_CLASS_CONSTANT: + attributeValue.constant = value; + break; + case ATTRIBUTE_CLASS_LINEPTR: + case ATTRIBUTE_CLASS_LOCLISTPTR: + case ATTRIBUTE_CLASS_MACPTR: + case ATTRIBUTE_CLASS_RANGELISTPTR: + attributeValue.pointer = value; + break; + case ATTRIBUTE_CLASS_REFERENCE: + if (entry != NULL) { + attributeValue.reference = _ResolveReference(value, + localReference); + if (attributeValue.reference == NULL) { + fprintf(stderr, "Failed to resolve reference: " + "%s (%#lx) %s (%#lx): value: %llu\n", + get_attribute_name_name(attributeName), + attributeName, + get_attribute_form_name(attributeForm), + attributeForm, value); + return B_ENTRY_NOT_FOUND; + } + } + break; + case ATTRIBUTE_CLASS_FLAG: + case ATTRIBUTE_CLASS_STRING: + // already set + break; + } + + if (dataReader.HasOverflow()) { + fprintf(stderr, "Unexpected end of .debug_info section.\n"); + return B_BAD_DATA; + } + + // add the attribute + if (entry != NULL) { +char buffer[1024]; +printf(" attr %s %s (%d): %s\n", get_attribute_name_name(attributeName), +get_attribute_form_name(attributeForm), attributeClass, attributeValue.ToString(buffer, sizeof(buffer))); + + DebugInfoEntrySetter attributeSetter + = get_attribute_name_setter(attributeName); + if (attributeSetter != NULL) { + status_t error = (entry->*attributeSetter)(attributeName, + attributeValue); + + if (error == ATTRIBUTE_NOT_HANDLED) { + error = B_OK; +printf(" -> unhandled\n"); + } + + if (error != B_OK) { + fprintf(stderr, "Failed to set attribute: name: %s, " + "form: %s: %s\n", + get_attribute_name_name(attributeName), + get_attribute_form_name(attributeForm), + strerror(error)); + } + } +else +printf(" -> no attribute setter!\n"); + } + } + + return B_OK; + } + + status_t _GetAbbreviationTable(off_t offset, AbbreviationTable*& _table) + { + // check, whether we've already loaded it + for (AbbreviationTableList::Iterator it + = fAbbreviationTables.GetIterator(); + AbbreviationTable* table = it.Next();) { + if (offset == table->Offset()) { + _table = table; + return B_OK; + } + } + + // create a new table + AbbreviationTable* table = new(std::nothrow) AbbreviationTable(offset); + if (table == NULL) + return B_NO_MEMORY; + + status_t error = table->Init(fDebugAbbrevSection->Data(), + fDebugAbbrevSection->Size()); + if (error != B_OK) { + delete table; + return error; + } + + fAbbreviationTables.Add(table); + _table = table; + return B_OK; + } + + DebugInfoEntry* _ResolveReference(uint64 offset, bool localReference) const + { + if (localReference) + return fCurrentCompilationUnit->EntryForOffset(offset); + + // TODO: Implement program-global references! + return NULL; + } + +private: + char* fName; + ElfFile* fElfFile; + ElfSection* fDebugInfoSection; + ElfSection* fDebugAbbrevSection; + ElfSection* fDebugStringSection; + AbbreviationTableList fAbbreviationTables; + DebugInfoEntryFactory fDebugInfoFactory; + CompilationUnitList fCompilationUnits; + CompilationUnit* fCurrentCompilationUnit; + bool fFinished; + status_t fFinishError; +}; + + +DwarfManager::DwarfManager() +{ +} + + +DwarfManager::~DwarfManager() +{ +} + + +status_t +DwarfManager::Init() +{ + return B_OK; +} + + +status_t +DwarfManager::LoadFile(const char* fileName) +{ + File* file = new(std::nothrow) File; + if (file == NULL) + return B_NO_MEMORY; + + status_t error = file->Load(fileName); + if (error != B_OK) { + delete file; + return error; + } + + fFiles.Add(file); + + return B_OK; +} + + +status_t +DwarfManager::FinishLoading() +{ + for (FileList::Iterator it = fFiles.GetIterator(); + File* file = it.Next();) { + status_t error = file->FinishLoading(); + if (error != B_OK) + return error; + } + + return B_OK; +} diff --git a/src/apps/debugger/DwarfManager.h b/src/apps/debugger/DwarfManager.h new file mode 100644 index 0000000000..ff72b65213 --- /dev/null +++ b/src/apps/debugger/DwarfManager.h @@ -0,0 +1,36 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef DWARF_MANAGER_H +#define DWARF_MANAGER_H + +#include + +#include + +#include + + +class DwarfManager { +public: + DwarfManager(); + ~DwarfManager(); + + status_t Init(); + + status_t LoadFile(const char* fileName); + status_t FinishLoading(); + +private: + struct CompilationUnit; + struct File; + typedef DoublyLinkedList FileList; + +private: + FileList fFiles; +}; + + + +#endif // DWARF_MANAGER_H diff --git a/src/apps/debugger/ElfFile.cpp b/src/apps/debugger/ElfFile.cpp new file mode 100644 index 0000000000..1f3be1e53e --- /dev/null +++ b/src/apps/debugger/ElfFile.cpp @@ -0,0 +1,247 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "ElfFile.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + + +// #pragma mark - ElfSection + + +ElfSection::ElfSection(const char* name, int fd, off_t offset, off_t size) + : + fName(name), + fFD(fd), + fOffset(offset), + fSize(size), + fData(NULL), + fLoadCount(0) +{ +} + + +ElfSection::~ElfSection() +{ + free(fData); +} + + +status_t +ElfSection::Load() +{ + if (fLoadCount > 0) { + fLoadCount++; + return B_OK; + } + + fData = malloc(fSize); + if (fData == NULL) + return B_NO_MEMORY; + + ssize_t bytesRead = pread(fFD, fData, fSize, fOffset); + if (bytesRead != fSize) { + free(fData); + fData = NULL; + return bytesRead < 0 ? errno : B_ERROR; + } + + fLoadCount++; + return B_OK; +} + + +void +ElfSection::Unload() +{ + if (fLoadCount == 0) + return; + + if (--fLoadCount == 0) { + free(fData); + fData = NULL; + } +} + + +// #pragma mark - ElfFile + + +ElfFile::ElfFile() + : + fFileSize(0), + fFD(-1), + fElfHeader(NULL) +{ +} + + +ElfFile::~ElfFile() +{ + while (ElfSection* section = fSections.RemoveHead()) + delete section; + + free(fElfHeader); + + if (fFD >= 0) + close(fFD); +} + + +status_t +ElfFile::Init(const char* fileName) +{ + // open file + fFD = open(fileName, O_RDONLY); + if (fFD < 0) { + fprintf(stderr, "Failed to open \"%s\": %s\n", fileName, + strerror(errno)); + return errno; + } + + // stat() file to get its size + struct stat st; + if (fstat(fFD, &st) < 0) { + fprintf(stderr, "Failed to stat \"%s\": %s\n", fileName, + strerror(errno)); + return errno; + } + fFileSize = st.st_size; +printf("fFileSize: %lld\n", fFileSize); + + // read the elf header + fElfHeader = (Elf32_Ehdr*)malloc(sizeof(Elf32_Ehdr)); + if (fElfHeader == NULL) + return B_NO_MEMORY; + + ssize_t bytesRead = pread(fFD, fElfHeader, sizeof(Elf32_Ehdr), 0); + if (bytesRead != (ssize_t)sizeof(Elf32_Ehdr)) + return bytesRead < 0 ? errno : B_ERROR; + + // check the ELF header + if (!_CheckRange(0, sizeof(Elf32_Ehdr)) || !_CheckElfHeader()) { + fprintf(stderr, "\"%s\": Not an ELF file\n", fileName); + return B_BAD_DATA; + } + + // check section header table values + off_t sectionHeadersOffset = fElfHeader->e_shoff; + size_t sectionHeaderSize = fElfHeader->e_shentsize; + int sectionCount = fElfHeader->e_shnum; + size_t sectionHeaderTableSize = sectionHeaderSize * sectionCount; + if (!_CheckRange(sectionHeadersOffset, sectionHeaderTableSize)) { + fprintf(stderr, "\"%s\": Invalid ELF header\n", fileName); + return B_BAD_DATA; + } +printf("sectionHeaderTable: %lld\n", sectionHeadersOffset); + + // read the section header table + uint8* sectionHeaderTable + = (uint8*)malloc(sectionHeaderTableSize); + if (sectionHeaderTable == NULL) + return B_NO_MEMORY; + MemoryDeleter sectionHeaderTableDeleter(sectionHeaderTable); + + bytesRead = pread(fFD, sectionHeaderTable, sectionHeaderTableSize, + sectionHeadersOffset); + if (bytesRead != (ssize_t)sectionHeaderTableSize) + return bytesRead < 0 ? errno : B_ERROR; + + // check and get the section header string section + Elf32_Shdr* stringSectionHeader = (Elf32_Shdr*)(sectionHeaderTable + + fElfHeader->e_shstrndx * sectionHeaderSize); + if (!_CheckRange(stringSectionHeader->sh_offset, + stringSectionHeader->sh_size)) { + fprintf(stderr, "\"%s\": Invalid string section header\n", fileName); + return B_BAD_DATA; + } + size_t sectionStringSize = stringSectionHeader->sh_size; +printf("sectionStrings: %ld\n", stringSectionHeader->sh_offset); + + ElfSection* sectionStringSection = new(std::nothrow) ElfSection(".shstrtab", + fFD, stringSectionHeader->sh_offset, sectionStringSize); + if (sectionStringSection == NULL) + return B_NO_MEMORY; + fSections.Add(sectionStringSection); + + status_t error = sectionStringSection->Load(); + if (error != B_OK) + return error; + + const char* sectionStrings = (const char*)sectionStringSection->Data(); + + // read the other sections + for (int i = 0; i < sectionCount; i++) { + Elf32_Shdr* sectionHeader = (Elf32_Shdr*)(sectionHeaderTable + + i * sectionHeaderSize); + // skip invalid sections and the section header string section + const char* name = sectionStrings + sectionHeader->sh_name; + if (sectionHeader->sh_name >= sectionStringSize + || !_CheckRange(sectionHeader->sh_offset, sectionHeader->sh_size) + || i == fElfHeader->e_shstrndx) { + continue; + } + + // create an ElfSection + ElfSection* section = new(std::nothrow) ElfSection(name, fFD, + sectionHeader->sh_offset, sectionHeader->sh_size); + if (section == NULL) + return B_NO_MEMORY; + fSections.Add(section); + } + + return B_OK; +} + + +ElfSection* +ElfFile::GetSection(const char* name) +{ + for (SectionList::Iterator it = fSections.GetIterator(); + ElfSection* section = it.Next();) { + if (strcmp(section->Name(), name) == 0) + return section->Load() == B_OK ? section : NULL; + } + + return NULL; +} + + +void +ElfFile::PutSection(ElfSection* section) +{ + if (section != NULL) + section->Unload(); +} + + +bool +ElfFile::_CheckRange(off_t offset, off_t size) const +{ + return offset < fFileSize && offset + size < fFileSize; +} + + +bool +ElfFile::_CheckElfHeader() const +{ + return memcmp(fElfHeader->e_ident, ELF_MAGIC, 4) == 0 + && fElfHeader->e_ident[4] == ELFCLASS32 + && fElfHeader->e_shoff > 0 + && fElfHeader->e_shnum > 0 + && fElfHeader->e_shentsize >= sizeof(struct Elf32_Shdr) + && fElfHeader->e_shstrndx != SHN_UNDEF + && fElfHeader->e_shstrndx < fElfHeader->e_shnum; +} diff --git a/src/apps/debugger/ElfFile.h b/src/apps/debugger/ElfFile.h new file mode 100644 index 0000000000..99e76c7608 --- /dev/null +++ b/src/apps/debugger/ElfFile.h @@ -0,0 +1,65 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef ELF_FILE_H +#define ELF_FILE_H + +#include + +#include + +#include +#include + + +class ElfSection : public DoublyLinkedListLinkImpl { +public: + ElfSection(const char* name, int fd, + off_t offset, off_t size); + ~ElfSection(); + + const char* Name() const { return fName; } + off_t Offset() const { return fOffset; } + off_t Size() const { return fSize; } + const void* Data() const { return fData; } + + status_t Load(); + void Unload(); + +private: + const char* fName; + int fFD; + off_t fOffset; + off_t fSize; + void* fData; + int32 fLoadCount; +}; + + +class ElfFile { +public: + ElfFile(); + ~ElfFile(); + + status_t Init(const char* fileName); + + ElfSection* GetSection(const char* name); + void PutSection(ElfSection* section); + +private: + typedef DoublyLinkedList SectionList; + +private: + bool _CheckRange(off_t offset, off_t size) const; + bool _CheckElfHeader() const; + +private: + off_t fFileSize; + int fFD; + Elf32_Ehdr* fElfHeader; + SectionList fSections; +}; + + +#endif // ELF_FILE_H diff --git a/src/apps/debugger/HaikuTypes.h b/src/apps/debugger/HaikuTypes.h new file mode 100644 index 0000000000..de4c30eb8c --- /dev/null +++ b/src/apps/debugger/HaikuTypes.h @@ -0,0 +1,43 @@ +#ifndef HAIKU_TYPES_H +#define HAIKU_TYPES_H + +#include +#include + + +typedef signed char int8; +typedef unsigned char uint8; + +typedef short int16; +typedef unsigned short uint16; + +typedef long int32; +typedef unsigned long uint32; + +typedef long long int64; +typedef unsigned long long uint64; + +typedef long status_t; + +#define B_OK 0 +#define B_NO_MEMORY 0x80000000 +#define B_BAD_DATA 0x80000001 +#define B_ERROR 0x80000002 +#define B_ENTRY_NOT_FOUND 0x80000003 +#define B_UNSUPPORTED 0x80000004 + +#define B_HOST_IS_LENDIAN 1 + + +#define WRAP_ERROR(error) (-(error)) + + +static inline void +debugger(const char* message) +{ + fprintf(stderr, "debugger(): %s\n", message); + exit(1); +} + + +#endif // HAIKU_TYPES_H diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile new file mode 100644 index 0000000000..b9cdfbd723 --- /dev/null +++ b/src/apps/debugger/Jamfile @@ -0,0 +1,21 @@ +SubDir HAIKU_TOP src apps debugger ; + +CCFLAGS += -Werror ; +C++FLAGS += -Werror ; + +UsePrivateHeaders kernel shared ; +UsePrivateSystemHeaders ; + +Application Debugger : + attribute_classes.cpp + AttributeValue.cpp + debugger.cpp + DebugInfoEntries.cpp + DebugInfoEntry.cpp + DwarfManager.cpp + ElfFile.cpp + SourceLanguageInfo.cpp + tag_names.cpp + + : $(TARGET_LIBSUPC++) +; diff --git a/src/apps/debugger/SourceLanguageInfo.cpp b/src/apps/debugger/SourceLanguageInfo.cpp new file mode 100644 index 0000000000..2ed3fcc197 --- /dev/null +++ b/src/apps/debugger/SourceLanguageInfo.cpp @@ -0,0 +1,53 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "SourceLanguageInfo.h" + +#include "dwarf.h" + + +UnknownSourceLanguageInfo::UnknownSourceLanguageInfo() +{ + name = "unknown"; + arrayOrdering = DW_ORD_row_major; +} + + +CFamilySourceLanguageInfo::CFamilySourceLanguageInfo() +{ + arrayOrdering = DW_ORD_row_major; +} + + +CSourceLanguageInfo::CSourceLanguageInfo() +{ + name = "C"; +} + + +C89SourceLanguageInfo::C89SourceLanguageInfo() +{ + name = "C 89"; +} + + +C99SourceLanguageInfo::C99SourceLanguageInfo() +{ + name = "C 99"; +} + + +CPlusPlusSourceLanguageInfo::CPlusPlusSourceLanguageInfo() +{ + name = "C++"; +} + + +const UnknownSourceLanguageInfo kUnknownLanguageInfo; +const UnknownSourceLanguageInfo kUnsupportedLanguageInfo; +const CSourceLanguageInfo kCLanguageInfo; +const C89SourceLanguageInfo kC89LanguageInfo; +const C99SourceLanguageInfo kC99LanguageInfo; +const CPlusPlusSourceLanguageInfo kCPlusPlusLanguageInfo; diff --git a/src/apps/debugger/SourceLanguageInfo.h b/src/apps/debugger/SourceLanguageInfo.h new file mode 100644 index 0000000000..2bc8e5c6fd --- /dev/null +++ b/src/apps/debugger/SourceLanguageInfo.h @@ -0,0 +1,55 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef SOURCE_LANGUAGE_INFO_H +#define SOURCE_LANGUAGE_INFO_H + +#include + + +struct SourceLanguageInfo { + const char* name; + uint8 arrayOrdering; +}; + + +struct UnknownSourceLanguageInfo : SourceLanguageInfo { + UnknownSourceLanguageInfo(); +}; + + +struct CFamilySourceLanguageInfo : SourceLanguageInfo { + CFamilySourceLanguageInfo(); +}; + + +struct CSourceLanguageInfo : CFamilySourceLanguageInfo { + CSourceLanguageInfo(); +}; + + +struct C89SourceLanguageInfo : CFamilySourceLanguageInfo { + C89SourceLanguageInfo(); +}; + + +struct C99SourceLanguageInfo : CFamilySourceLanguageInfo { + C99SourceLanguageInfo(); +}; + + +struct CPlusPlusSourceLanguageInfo : CFamilySourceLanguageInfo { + CPlusPlusSourceLanguageInfo(); +}; + + +extern const UnknownSourceLanguageInfo kUnknownLanguageInfo; +extern const UnknownSourceLanguageInfo kUnsupportedLanguageInfo; +extern const CSourceLanguageInfo kCLanguageInfo; +extern const C89SourceLanguageInfo kC89LanguageInfo; +extern const C99SourceLanguageInfo kC99LanguageInfo; +extern const CPlusPlusSourceLanguageInfo kCPlusPlusLanguageInfo; + + +#endif // SOURCE_LANGUAGE_INFO_H diff --git a/src/apps/debugger/arch_elf.h b/src/apps/debugger/arch_elf.h new file mode 100644 index 0000000000..4ec86759cb --- /dev/null +++ b/src/apps/debugger/arch_elf.h @@ -0,0 +1,22 @@ +/* +** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ +#ifndef _KERNEL_ARCH_x86_ELF_H +#define _KERNEL_ARCH_x86_ELF_H + +/* relocation types */ + +#define R_386_NONE 0 +#define R_386_32 1 /* add symbol value */ +#define R_386_PC32 2 /* add PC relative symbol value */ +#define R_386_GOT32 3 /* add PC relative GOT offset */ +#define R_386_PLT32 4 /* add PC relative PLT offset */ +#define R_386_COPY 5 /* copy data from shared object */ +#define R_386_GLOB_DAT 6 /* set GOT entry to data address */ +#define R_386_JMP_SLOT 7 /* set GOT entry to code address */ +#define R_386_RELATIVE 8 /* add load address of shared object */ +#define R_386_GOTOFF 9 /* add GOT relative symbol address */ +#define R_386_GOTPC 10 /* add PC relative GOT table address */ + +#endif /* _KERNEL_ARCH_x86_ELF_H */ diff --git a/src/apps/debugger/attribute_classes.cpp b/src/apps/debugger/attribute_classes.cpp new file mode 100644 index 0000000000..049c9b5743 --- /dev/null +++ b/src/apps/debugger/attribute_classes.cpp @@ -0,0 +1,238 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "attribute_classes.h" +#include "dwarf.h" + + +enum { + AC_ADDRESS = 1 << (ATTRIBUTE_CLASS_ADDRESS - 1), + AC_BLOCK = 1 << (ATTRIBUTE_CLASS_BLOCK - 1), + AC_CONSTANT = 1 << (ATTRIBUTE_CLASS_CONSTANT - 1), + AC_FLAG = 1 << (ATTRIBUTE_CLASS_FLAG - 1), + AC_LINEPTR = 1 << (ATTRIBUTE_CLASS_LINEPTR - 1), + AC_LOCLISTPTR = 1 << (ATTRIBUTE_CLASS_LOCLISTPTR - 1), + AC_MACPTR = 1 << (ATTRIBUTE_CLASS_MACPTR - 1), + AC_RANGELISTPTR = 1 << (ATTRIBUTE_CLASS_RANGELISTPTR - 1), + AC_REFERENCE = 1 << (ATTRIBUTE_CLASS_REFERENCE - 1), + AC_STRING = 1 << (ATTRIBUTE_CLASS_STRING - 1) +}; + + +struct attribute_info_entry { + const char* name; + uint16 value; + uint16 classes; +}; + +struct attribute_name_info_entry { + const char* name; + DebugInfoEntrySetter setter; + uint16 value; + uint16 classes; +}; + + +#undef ENTRY +#define ENTRY(name) "DW_AT_" #name, &DebugInfoEntry::AddAttribute_##name, \ + DW_AT_##name + +static const attribute_name_info_entry kAttributeNameInfos[] = { + { ENTRY(sibling), AC_REFERENCE }, + { ENTRY(location), AC_BLOCK | AC_LOCLISTPTR }, + { ENTRY(name), AC_STRING }, + { ENTRY(ordering), AC_CONSTANT }, + { ENTRY(byte_size), AC_BLOCK | AC_CONSTANT | AC_REFERENCE }, + { ENTRY(bit_offset), AC_BLOCK | AC_CONSTANT | AC_REFERENCE }, + { ENTRY(bit_size), AC_BLOCK | AC_CONSTANT | AC_REFERENCE }, + { ENTRY(stmt_list), AC_LINEPTR }, + { ENTRY(low_pc), AC_ADDRESS }, + { ENTRY(high_pc), AC_ADDRESS }, + { ENTRY(language), AC_CONSTANT }, + { ENTRY(discr), AC_REFERENCE }, + { ENTRY(discr_value), AC_CONSTANT }, + { ENTRY(visibility), AC_CONSTANT }, + { ENTRY(import), AC_REFERENCE }, + { ENTRY(string_length), AC_BLOCK | AC_LOCLISTPTR }, + { ENTRY(common_reference), AC_REFERENCE }, + { ENTRY(comp_dir), AC_STRING }, + { ENTRY(const_value), AC_BLOCK | AC_CONSTANT | AC_STRING }, + { ENTRY(containing_type), AC_REFERENCE }, + { ENTRY(default_value), AC_REFERENCE }, + { ENTRY(inline), AC_CONSTANT }, + { ENTRY(is_optional), AC_FLAG }, + { ENTRY(lower_bound), AC_BLOCK | AC_CONSTANT | AC_REFERENCE }, + { ENTRY(producer), AC_STRING }, + { ENTRY(prototyped), AC_FLAG }, + { ENTRY(return_addr), AC_BLOCK | AC_LOCLISTPTR }, + { ENTRY(start_scope), AC_CONSTANT }, + { ENTRY(bit_stride), AC_CONSTANT }, + { ENTRY(upper_bound), AC_BLOCK | AC_CONSTANT | AC_REFERENCE }, + { ENTRY(abstract_origin), AC_REFERENCE }, + { ENTRY(accessibility), AC_CONSTANT }, + { ENTRY(address_class), AC_CONSTANT }, + { ENTRY(artificial), AC_FLAG }, + { ENTRY(base_types), AC_REFERENCE }, + { ENTRY(calling_convention), AC_CONSTANT }, + { ENTRY(count), AC_BLOCK | AC_CONSTANT | AC_REFERENCE }, + { ENTRY(data_member_location), AC_BLOCK | AC_CONSTANT | AC_LOCLISTPTR }, + { ENTRY(decl_column), AC_CONSTANT }, + { ENTRY(decl_file), AC_CONSTANT }, + { ENTRY(decl_line), AC_CONSTANT }, + { ENTRY(declaration), AC_FLAG }, + { ENTRY(discr_list), AC_BLOCK }, + { ENTRY(encoding), AC_CONSTANT }, + { ENTRY(external), AC_FLAG }, + { ENTRY(frame_base), AC_BLOCK | AC_LOCLISTPTR }, + { ENTRY(friend), AC_REFERENCE }, + { ENTRY(identifier_case), AC_CONSTANT }, + { ENTRY(macro_info), AC_MACPTR }, + { ENTRY(namelist_item), AC_BLOCK }, + { ENTRY(priority), AC_REFERENCE }, + { ENTRY(segment), AC_BLOCK | AC_LOCLISTPTR }, + { ENTRY(specification), AC_REFERENCE }, + { ENTRY(static_link), AC_BLOCK | AC_LOCLISTPTR }, + { ENTRY(type), AC_REFERENCE }, + { ENTRY(use_location), AC_BLOCK | AC_LOCLISTPTR }, + { ENTRY(variable_parameter), AC_FLAG }, + { ENTRY(virtuality), AC_CONSTANT }, + { ENTRY(vtable_elem_location), AC_BLOCK | AC_LOCLISTPTR }, + { ENTRY(allocated), AC_BLOCK | AC_CONSTANT | AC_REFERENCE }, + { ENTRY(associated), AC_BLOCK | AC_CONSTANT | AC_REFERENCE }, + { ENTRY(data_location), AC_BLOCK }, + { ENTRY(byte_stride), AC_BLOCK | AC_CONSTANT | AC_REFERENCE }, + { ENTRY(entry_pc), AC_ADDRESS }, + { ENTRY(use_UTF8), AC_FLAG }, + { ENTRY(extension), AC_REFERENCE }, + { ENTRY(ranges), AC_RANGELISTPTR }, + { ENTRY(trampoline), AC_ADDRESS | AC_FLAG | AC_REFERENCE + | AC_STRING }, + { ENTRY(call_column), AC_CONSTANT }, + { ENTRY(call_file), AC_CONSTANT }, + { ENTRY(call_line), AC_CONSTANT }, + { ENTRY(description), AC_STRING }, + { ENTRY(binary_scale), AC_CONSTANT }, + { ENTRY(decimal_scale), AC_CONSTANT }, + { ENTRY(small), AC_REFERENCE }, + { ENTRY(decimal_sign), AC_CONSTANT }, + { ENTRY(digit_count), AC_CONSTANT }, + { ENTRY(picture_string), AC_STRING }, + { ENTRY(mutable), AC_FLAG }, + { ENTRY(threads_scaled), AC_FLAG }, + { ENTRY(explicit), AC_FLAG }, + { ENTRY(object_pointer), AC_REFERENCE }, + { ENTRY(endianity), AC_CONSTANT }, + { ENTRY(elemental), AC_FLAG }, + { ENTRY(pure), AC_FLAG }, + { ENTRY(recursive), AC_FLAG }, + {} +}; + +static const uint32 kAttributeNameInfoCount = DW_AT_recursive + 1; +static attribute_name_info_entry sAttributeNameInfos[kAttributeNameInfoCount]; + + +#undef ENTRY +#define ENTRY(name) "DW_FORM_" #name, DW_FORM_##name + +static const attribute_info_entry kAttributeFormInfos[] = { + { ENTRY(addr), AC_ADDRESS }, + { ENTRY(block2), AC_BLOCK }, + { ENTRY(block4), AC_BLOCK }, + { ENTRY(data2), AC_CONSTANT }, + { ENTRY(data4), AC_CONSTANT | AC_LINEPTR | AC_LOCLISTPTR + | AC_MACPTR | AC_RANGELISTPTR }, + { ENTRY(data8), AC_CONSTANT | AC_LINEPTR | AC_LOCLISTPTR + | AC_MACPTR | AC_RANGELISTPTR }, + { ENTRY(string), AC_STRING }, + { ENTRY(block), AC_BLOCK }, + { ENTRY(block1), AC_BLOCK }, + { ENTRY(data1), AC_CONSTANT }, + { ENTRY(flag), AC_FLAG }, + { ENTRY(sdata), AC_CONSTANT }, + { ENTRY(strp), AC_STRING }, + { ENTRY(udata), AC_CONSTANT }, + { ENTRY(ref_addr), AC_REFERENCE }, + { ENTRY(ref1), AC_REFERENCE }, + { ENTRY(ref2), AC_REFERENCE }, + { ENTRY(ref4), AC_REFERENCE }, + { ENTRY(ref8), AC_REFERENCE }, + { ENTRY(ref_udata), AC_REFERENCE }, + {} +}; + +static const uint32 kAttributeFormInfoCount = DW_FORM_ref_udata + 1; +static attribute_info_entry sAttributeFormInfos[kAttributeFormInfoCount]; + +static struct InitAttributeInfos { + InitAttributeInfos() + { + for (uint32 i = 0; kAttributeNameInfos[i].name != NULL; i++) { + const attribute_name_info_entry& entry = kAttributeNameInfos[i]; + sAttributeNameInfos[entry.value] = entry; + } + + for (uint32 i = 0; kAttributeFormInfos[i].name != NULL; i++) { + const attribute_info_entry& entry = kAttributeFormInfos[i]; + sAttributeFormInfos[entry.value] = entry; + } + } +} sInitAttributeInfos; + + +uint16 +get_attribute_name_classes(uint32 name) +{ + return name < kAttributeNameInfoCount + ? sAttributeNameInfos[name].classes : 0; +} + + +uint16 +get_attribute_form_classes(uint32 form) +{ + return form < kAttributeFormInfoCount + ? sAttributeFormInfos[form].classes : 0; +} + + +uint8 +get_attribute_class(uint32 name, uint32 form) +{ + uint16 classes = get_attribute_name_classes(name) + & get_attribute_form_classes(form); + + int clazz = 0; + while (classes != 0) { + classes >>= 1; + clazz++; + } + + return clazz; +} + + +const char* +get_attribute_name_name(uint32 name) +{ + return name < kAttributeNameInfoCount + ? sAttributeNameInfos[name].name : NULL; +} + + +const char* +get_attribute_form_name(uint32 form) +{ + return form < kAttributeFormInfoCount + ? sAttributeFormInfos[form].name : NULL; +} + + +DebugInfoEntrySetter +get_attribute_name_setter(uint32 name) +{ + return name < kAttributeNameInfoCount + ? sAttributeNameInfos[name].setter : NULL; +} diff --git a/src/apps/debugger/attribute_classes.h b/src/apps/debugger/attribute_classes.h new file mode 100644 index 0000000000..ae9424fd65 --- /dev/null +++ b/src/apps/debugger/attribute_classes.h @@ -0,0 +1,41 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef ATTRIBUTE_TABLES_H +#define ATTRIBUTE_TABLES_H + +#include "DebugInfoEntry.h" + + +typedef status_t (DebugInfoEntry::* DebugInfoEntrySetter)(uint16, + const AttributeValue&); + + +// attribute classes +enum { + ATTRIBUTE_CLASS_UNKNOWN = 0, + ATTRIBUTE_CLASS_ADDRESS = 1, + ATTRIBUTE_CLASS_BLOCK = 2, + ATTRIBUTE_CLASS_CONSTANT = 3, + ATTRIBUTE_CLASS_FLAG = 4, + ATTRIBUTE_CLASS_LINEPTR = 5, + ATTRIBUTE_CLASS_LOCLISTPTR = 6, + ATTRIBUTE_CLASS_MACPTR = 7, + ATTRIBUTE_CLASS_RANGELISTPTR = 8, + ATTRIBUTE_CLASS_REFERENCE = 9, + ATTRIBUTE_CLASS_STRING = 10 +}; + + +uint16 get_attribute_name_classes(uint32 name); +uint16 get_attribute_form_classes(uint32 form); +uint8 get_attribute_class(uint32 name, uint32 form); + +const char* get_attribute_name_name(uint32 name); +const char* get_attribute_form_name(uint32 form); + +DebugInfoEntrySetter get_attribute_name_setter(uint32 name); + + +#endif // ATTRIBUTE_TABLES_H diff --git a/src/apps/debugger/debugger.cpp b/src/apps/debugger/debugger.cpp new file mode 100644 index 0000000000..017ecb3c40 --- /dev/null +++ b/src/apps/debugger/debugger.cpp @@ -0,0 +1,26 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include + +#include "DwarfManager.h" + + +int +main(int argc, const char* const* argv) +{ + if (argc != 2) { + fprintf(stderr, "Usage:...\n"); + return 1; + } + + const char* fileName = argv[1]; + + DwarfManager manager; + manager.LoadFile(fileName); + manager.FinishLoading(); + + return 0; +} diff --git a/src/apps/debugger/dwarf.h b/src/apps/debugger/dwarf.h new file mode 100644 index 0000000000..9543cfaee1 --- /dev/null +++ b/src/apps/debugger/dwarf.h @@ -0,0 +1,457 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef DWARF_H +#define DWARF_H + +// tag +enum { + DW_TAG_array_type = 0x01, + DW_TAG_class_type = 0x02, + DW_TAG_entry_point = 0x03, + DW_TAG_enumeration_type = 0x04, + DW_TAG_formal_parameter = 0x05, + DW_TAG_imported_declaration = 0x08, + DW_TAG_label = 0x0a, + DW_TAG_lexical_block = 0x0b, + DW_TAG_member = 0x0d, + DW_TAG_pointer_type = 0x0f, + DW_TAG_reference_type = 0x10, + DW_TAG_compile_unit = 0x11, + DW_TAG_string_type = 0x12, + DW_TAG_structure_type = 0x13, + DW_TAG_subroutine_type = 0x15, + DW_TAG_typedef = 0x16, + DW_TAG_union_type = 0x17, + DW_TAG_unspecified_parameters = 0x18, + DW_TAG_variant = 0x19, + DW_TAG_common_block = 0x1a, + DW_TAG_common_inclusion = 0x1b, + DW_TAG_inheritance = 0x1c, + DW_TAG_inlined_subroutine = 0x1d, + DW_TAG_module = 0x1e, + DW_TAG_ptr_to_member_type = 0x1f, + DW_TAG_set_type = 0x20, + DW_TAG_subrange_type = 0x21, + DW_TAG_with_stmt = 0x22, + DW_TAG_access_declaration = 0x23, + DW_TAG_base_type = 0x24, + DW_TAG_catch_block = 0x25, + DW_TAG_const_type = 0x26, + DW_TAG_constant = 0x27, + DW_TAG_enumerator = 0x28, + DW_TAG_file_type = 0x29, + DW_TAG_friend = 0x2a, + DW_TAG_namelist = 0x2b, + DW_TAG_namelist_item = 0x2c, + DW_TAG_packed_type = 0x2d, + DW_TAG_subprogram = 0x2e, + DW_TAG_template_type_parameter = 0x2f, + DW_TAG_template_value_parameter = 0x30, + DW_TAG_thrown_type = 0x31, + DW_TAG_try_block = 0x32, + DW_TAG_variant_part = 0x33, + DW_TAG_variable = 0x34, + DW_TAG_volatile_type = 0x35, + DW_TAG_dwarf_procedure = 0x36, + DW_TAG_restrict_type = 0x37, + DW_TAG_interface_type = 0x38, + DW_TAG_namespace = 0x39, + DW_TAG_imported_module = 0x3a, + DW_TAG_unspecified_type = 0x3b, + DW_TAG_partial_unit = 0x3c, + DW_TAG_imported_unit = 0x3d, + DW_TAG_condition = 0x3f, + DW_TAG_shared_type = 0x40, + DW_TAG_lo_user = 0x4080, + DW_TAG_hi_user = 0xffff +}; + +// has children flag value +enum { + DW_CHILDREN_no = 0x00, + DW_CHILDREN_yes = 0x01 +}; + +// attribute name +enum { + DW_AT_sibling = 0x01, // reference + DW_AT_location = 0x02, // block, loclistptr + DW_AT_name = 0x03, // string + DW_AT_ordering = 0x09, // constant + DW_AT_byte_size = 0x0b, // block, constant, reference + DW_AT_bit_offset = 0x0c, // block, constant, reference + DW_AT_bit_size = 0x0d, // block, constant, reference + DW_AT_stmt_list = 0x10, // lineptr + DW_AT_low_pc = 0x11, // address + DW_AT_high_pc = 0x12, // address + DW_AT_language = 0x13, // constant + DW_AT_discr = 0x15, // reference + DW_AT_discr_value = 0x16, // constant + DW_AT_visibility = 0x17, // constant + DW_AT_import = 0x18, // reference + DW_AT_string_length = 0x19, // block, loclistptr + DW_AT_common_reference = 0x1a, // reference + DW_AT_comp_dir = 0x1b, // string + DW_AT_const_value = 0x1c, // block, constant, string + DW_AT_containing_type = 0x1d, // reference + DW_AT_default_value = 0x1e, // reference + DW_AT_inline = 0x20, // constant + DW_AT_is_optional = 0x21, // flag + DW_AT_lower_bound = 0x22, // block, constant, reference + DW_AT_producer = 0x25, // string + DW_AT_prototyped = 0x27, // flag + DW_AT_return_addr = 0x2a, // block, loclistptr + DW_AT_start_scope = 0x2c, // constant + DW_AT_bit_stride = 0x2e, // constant + DW_AT_upper_bound = 0x2f, // block, constant, reference + DW_AT_abstract_origin = 0x31, // reference + DW_AT_accessibility = 0x32, // constant + DW_AT_address_class = 0x33, // constant + DW_AT_artificial = 0x34, // flag + DW_AT_base_types = 0x35, // reference + DW_AT_calling_convention = 0x36, // constant + DW_AT_count = 0x37, // block, constant, reference + DW_AT_data_member_location = 0x38, // block, constant, loclistptr + DW_AT_decl_column = 0x39, // constant + DW_AT_decl_file = 0x3a, // constant + DW_AT_decl_line = 0x3b, // constant + DW_AT_declaration = 0x3c, // flag + DW_AT_discr_list = 0x3d, // block + DW_AT_encoding = 0x3e, // constant + DW_AT_external = 0x3f, // flag + DW_AT_frame_base = 0x40, // block, loclistptr + DW_AT_friend = 0x41, // reference + DW_AT_identifier_case = 0x42, // constant + DW_AT_macro_info = 0x43, // macptr + DW_AT_namelist_item = 0x44, // block + DW_AT_priority = 0x45, // reference + DW_AT_segment = 0x46, // block, loclistptr + DW_AT_specification = 0x47, // reference + DW_AT_static_link = 0x48, // block, loclistptr + DW_AT_type = 0x49, // reference + DW_AT_use_location = 0x4a, // block, loclistptr + DW_AT_variable_parameter = 0x4b, // flag + DW_AT_virtuality = 0x4c, // constant + DW_AT_vtable_elem_location = 0x4d, // block, loclistptr + DW_AT_allocated = 0x4e, // block, constant, reference + DW_AT_associated = 0x4f, // block, constant, reference + DW_AT_data_location = 0x50, // block + DW_AT_byte_stride = 0x51, // block, constant, reference + DW_AT_entry_pc = 0x52, // address + DW_AT_use_UTF8 = 0x53, // flag + DW_AT_extension = 0x54, // reference + DW_AT_ranges = 0x55, // rangelistptr + DW_AT_trampoline = 0x56, // address, flag, reference, string + DW_AT_call_column = 0x57, // constant + DW_AT_call_file = 0x58, // constant + DW_AT_call_line = 0x59, // constant + DW_AT_description = 0x5a, // string + DW_AT_binary_scale = 0x5b, // constant + DW_AT_decimal_scale = 0x5c, // constant + DW_AT_small = 0x5d, // reference + DW_AT_decimal_sign = 0x5e, // constant + DW_AT_digit_count = 0x5f, // constant + DW_AT_picture_string = 0x60, // string + DW_AT_mutable = 0x61, // flag + DW_AT_threads_scaled = 0x62, // flag + DW_AT_explicit = 0x63, // flag + DW_AT_object_pointer = 0x64, // reference + DW_AT_endianity = 0x65, // constant + DW_AT_elemental = 0x66, // flag + DW_AT_pure = 0x67, // flag + DW_AT_recursive = 0x68, // flag + DW_AT_lo_user = 0x2000, + DW_AT_hi_user = 0x3fff +}; + +// attribute form +enum { + DW_FORM_addr = 0x01, // address + DW_FORM_block2 = 0x03, // block + DW_FORM_block4 = 0x04, // block + DW_FORM_data2 = 0x05, // constant + DW_FORM_data4 = 0x06, // constant, lineptr, loclistptr, macptr, + // rangelistptr + DW_FORM_data8 = 0x07, // constant, lineptr, loclistptr, macptr, + // rangelistptr + DW_FORM_string = 0x08, // string + DW_FORM_block = 0x09, // block + DW_FORM_block1 = 0x0a, // block + DW_FORM_data1 = 0x0b, // constant + DW_FORM_flag = 0x0c, // flag + DW_FORM_sdata = 0x0d, // constant + DW_FORM_strp = 0x0e, // string + DW_FORM_udata = 0x0f, // constant + DW_FORM_ref_addr = 0x10, // reference + DW_FORM_ref1 = 0x11, // reference + DW_FORM_ref2 = 0x12, // reference + DW_FORM_ref4 = 0x13, // reference + DW_FORM_ref8 = 0x14, // reference + DW_FORM_ref_udata = 0x15, // reference + DW_FORM_indirect = 0x16, // form in .debug_info +}; + +// expression operation +enum { + DW_OP_addr = 0x03, + DW_OP_deref = 0x06, + DW_OP_const1u = 0x08, + DW_OP_const1s = 0x09, + DW_OP_const2u = 0x0a, + DW_OP_const2s = 0x0b, + DW_OP_const4u = 0x0c, + DW_OP_const4s = 0x0d, + DW_OP_const8u = 0x0e, + DW_OP_const8s = 0x0f, + DW_OP_constu = 0x10, + DW_OP_consts = 0x11, + DW_OP_dup = 0x12, + DW_OP_drop = 0x13, + DW_OP_over = 0x14, + DW_OP_pick = 0x15, + DW_OP_swap = 0x16, + DW_OP_rot = 0x17, + DW_OP_xderef = 0x18, + DW_OP_abs = 0x19, + DW_OP_and = 0x1a, + DW_OP_div = 0x1b, + DW_OP_minus = 0x1c, + DW_OP_mod = 0x1d, + DW_OP_mul = 0x1e, + DW_OP_neg = 0x1f, + DW_OP_not = 0x20, + DW_OP_or = 0x21, + DW_OP_plus = 0x22, + DW_OP_plus_uconst = 0x23, + DW_OP_shl = 0x24, + DW_OP_shr = 0x25, + DW_OP_shra = 0x26, + DW_OP_xor = 0x27, + DW_OP_skip = 0x2f, + DW_OP_bra = 0x28, + DW_OP_eq = 0x29, + DW_OP_ge = 0x2a, + DW_OP_gt = 0x2b, + DW_OP_le = 0x2c, + DW_OP_lt = 0x2d, + DW_OP_ne = 0x2e, + DW_OP_lit0 = 0x30, + DW_OP_lit1 = 0x31, + DW_OP_lit31 = 0x4f, + DW_OP_reg0 = 0x50, + DW_OP_reg1 = 0x51, + DW_OP_reg31 = 0x6f, + DW_OP_breg0 = 0x70, + DW_OP_breg1 = 0x71, + DW_OP_breg31 = 0x8f, + DW_OP_regx = 0x90, + DW_OP_fbreg = 0x91, + DW_OP_bregx = 0x92, + DW_OP_piece = 0x93, + DW_OP_deref_size = 0x94, + DW_OP_xderef_size = 0x95, + DW_OP_nop = 0x96, + DW_OP_push_object_address = 0x97, + DW_OP_call2 = 0x98, + DW_OP_call4 = 0x99, + DW_OP_call_ref = 0x9a, + DW_OP_form_tls_address = 0x9b, + DW_OP_call_frame_cfa = 0x9c, + DW_OP_bit_piece = 0x9d, + DW_OP_lo_user = 0xe0, + DW_OP_hi_user = 0xff +}; + +// base type +enum { + DW_ATE_address = 0x01, + DW_ATE_boolean = 0x02, + DW_ATE_complex_float = 0x03, + DW_ATE_float = 0x04, + DW_ATE_signed = 0x05, + DW_ATE_signed_char = 0x06, + DW_ATE_unsigned = 0x07, + DW_ATE_unsigned_char = 0x08, + DW_ATE_imaginary_float = 0x09, + DW_ATE_packed_decimal = 0x0a, + DW_ATE_numeric_string = 0x0b, + DW_ATE_edited = 0x0c, + DW_ATE_signed_fixed = 0x0d, + DW_ATE_unsigned_fixed = 0x0e, + DW_ATE_decimal_float = 0x0f, + DW_ATE_lo_user = 0x80, + DW_ATE_hi_user = 0xff +}; + +// decimal sign +enum { + DW_DS_unsigned = 0x01, + DW_DS_leading_overpunch = 0x02, + DW_DS_trailing_overpunch = 0x03, + DW_DS_leading_separate = 0x04, + DW_DS_trailing_separate = 0x05 +}; + +// endianess +enum { + DW_END_default = 0x00, + DW_END_big = 0x01, + DW_END_little = 0x02, + DW_END_lo_user = 0x40, + DW_END_hi_user = 0xff +}; + +// accessibility +enum { + DW_ACCESS_public = 0x01, + DW_ACCESS_protected = 0x02, + DW_ACCESS_private = 0x03 +}; + +// visibility +enum { + DW_VIS_local = 0x01, + DW_VIS_exported = 0x02, + DW_VIS_qualified = 0x03 +}; + +// virtuality +enum { + DW_VIRTUALITY_none = 0x00, + DW_VIRTUALITY_virtual = 0x01, + DW_VIRTUALITY_pure_virtual = 0x02 +}; + +// source language +enum { + DW_LANG_C89 = 0x0001, + DW_LANG_C = 0x0002, + DW_LANG_Ada83 = 0x0003, + DW_LANG_C_plus_plus = 0x0004, + DW_LANG_Cobol74 = 0x0005, + DW_LANG_Cobol85 = 0x0006, + DW_LANG_Fortran77 = 0x0007, + DW_LANG_Fortran90 = 0x0008, + DW_LANG_Pascal83 = 0x0009, + DW_LANG_Modula2 = 0x000a, + DW_LANG_Java = 0x000b, + DW_LANG_C99 = 0x000c, + DW_LANG_Ada95 = 0x000d, + DW_LANG_Fortran95 = 0x000e, + DW_LANG_PLI = 0x000f, + DW_LANG_ObjC = 0x0010, + DW_LANG_ObjC_plus_plus = 0x0011, + DW_LANG_UPC = 0x0012, + DW_LANG_D = 0x0013, + DW_LANG_lo_user = 0x8000, + DW_LANG_hi_user = 0xffff +}; + +// identifier case +enum { + DW_ID_case_sensitive = 0x00, + DW_ID_up_case = 0x01, + DW_ID_down_case = 0x02, + DW_ID_case_insensitive = 0x03 +}; + +// calling convention +enum { + DW_CC_normal = 0x01, + DW_CC_program = 0x02, + DW_CC_nocall = 0x03, + DW_CC_lo_user = 0x40, + DW_CC_hi_user = 0xff +}; + +// inlining +enum { + DW_INL_not_inlined = 0x00, + DW_INL_inlined = 0x01, + DW_INL_declared_not_inlined = 0x02, + DW_INL_declared_inlined = 0x03 +}; + +// array ordering +enum { + DW_ORD_row_major = 0x00, + DW_ORD_col_major = 0x01 +}; + +// discriminant descriptor +enum { + DW_DSC_label = 0x00, + DW_DSC_range = 0x01 +}; + +// line number standard opcode +enum { + DW_LNS_copy = 0x01, + DW_LNS_advance_pc = 0x02, + DW_LNS_advance_line = 0x03, + DW_LNS_set_file = 0x04, + DW_LNS_set_column = 0x05, + DW_LNS_negate_stmt = 0x06, + DW_LNS_set_basic_block = 0x07, + DW_LNS_const_add_pc = 0x08, + DW_LNS_fixed_advance_pc = 0x09, + DW_LNS_set_prologue_end = 0x0a, + DW_LNS_set_epilogue_begin = 0x0b, + DW_LNS_set_isa = 0x0c +}; + +// line number extended opcode +enum { + DW_LNE_end_sequence = 0x01, + DW_LNE_set_address = 0x02, + DW_LNE_define_file = 0x03, + DW_LNE_lo_user = 0x80, + DW_LNE_hi_user = 0xff +}; + +// macro information type +enum { + DW_MACINFO_define = 0x01, + DW_MACINFO_undef = 0x02, + DW_MACINFO_start_file = 0x03, + DW_MACINFO_end_file = 0x04, + DW_MACINFO_vendor_ext = 0xff +}; + +// call frame instruction (high 2 bits for the first 3 items, low 6 bits for +// the remaining ones) +enum { + DW_CFA_advance_loc = 0x1, // high 2 bits + DW_CFA_offset = 0x2, // high 2 bits + DW_CFA_restore = 0x3, // high 2 bits + DW_CFA_nop = 0, // whole byte + DW_CFA_set_loc = 0x01, + DW_CFA_advance_loc1 = 0x02, + DW_CFA_advance_loc2 = 0x03, + DW_CFA_advance_loc4 = 0x04, + DW_CFA_offset_extended = 0x05, + DW_CFA_restore_extended = 0x06, + DW_CFA_undefined = 0x07, + DW_CFA_same_value = 0x08, + DW_CFA_register = 0x09, + DW_CFA_remember_state = 0x0a, + DW_CFA_restore_state = 0x0b, + DW_CFA_def_cfa = 0x0c, + DW_CFA_def_cfa_register = 0x0d, + DW_CFA_def_cfa_offset = 0x0e, + DW_CFA_def_cfa_expression = 0x0f, + DW_CFA_expression = 0x10, + DW_CFA_offset_extended_sf = 0x11, + DW_CFA_def_cfa_sf = 0x12, + DW_CFA_def_cfa_offset_sf = 0x13, + DW_CFA_val_offset = 0x14, + DW_CFA_val_offset_sf = 0x15, + DW_CFA_val_expression = 0x16, + DW_CFA_lo_user = 0x1c, + DW_CFA_hi_user = 0x3f +}; + + +#endif // DWARF_H diff --git a/src/apps/debugger/tag_names.cpp b/src/apps/debugger/tag_names.cpp new file mode 100644 index 0000000000..96bc105448 --- /dev/null +++ b/src/apps/debugger/tag_names.cpp @@ -0,0 +1,100 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "tag_names.h" + +#include "dwarf.h" + + +struct tag_name_info { + uint16 tag; + const char* name; +}; + + +#undef ENTRY +#define ENTRY(name) { DW_TAG_##name, "DW_TAG_" #name } + +static const tag_name_info kTagNameInfos[] = { + ENTRY(array_type), + ENTRY(class_type), + ENTRY(entry_point), + ENTRY(enumeration_type), + ENTRY(formal_parameter), + ENTRY(imported_declaration), + ENTRY(label), + ENTRY(lexical_block), + ENTRY(member), + ENTRY(pointer_type), + ENTRY(reference_type), + ENTRY(compile_unit), + ENTRY(string_type), + ENTRY(structure_type), + ENTRY(subroutine_type), + ENTRY(typedef), + ENTRY(union_type), + ENTRY(unspecified_parameters), + ENTRY(variant), + ENTRY(common_block), + ENTRY(common_inclusion), + ENTRY(inheritance), + ENTRY(inlined_subroutine), + ENTRY(module), + ENTRY(ptr_to_member_type), + ENTRY(set_type), + ENTRY(subrange_type), + ENTRY(with_stmt), + ENTRY(access_declaration), + ENTRY(base_type), + ENTRY(catch_block), + ENTRY(const_type), + ENTRY(constant), + ENTRY(enumerator), + ENTRY(file_type), + ENTRY(friend), + ENTRY(namelist), + ENTRY(namelist_item), + ENTRY(packed_type), + ENTRY(subprogram), + ENTRY(template_type_parameter), + ENTRY(template_value_parameter), + ENTRY(thrown_type), + ENTRY(try_block), + ENTRY(variant_part), + ENTRY(variable), + ENTRY(volatile_type), + ENTRY(dwarf_procedure), + ENTRY(restrict_type), + ENTRY(interface_type), + ENTRY(namespace), + ENTRY(imported_module), + ENTRY(unspecified_type), + ENTRY(partial_unit), + ENTRY(imported_unit), + ENTRY(condition), + ENTRY(shared_type), + {} +}; + + +static const uint32 kTagNameInfoCount = DW_TAG_shared_type + 1; +static const char* sTagNames[kTagNameInfoCount]; + +static struct InitTagNames { + InitTagNames() + { + for (uint32 i = 0; kTagNameInfos[i].name != NULL; i++) { + const tag_name_info& info = kTagNameInfos[i]; + sTagNames[info.tag] = info.name; + } + } +} sInitTagNames; + + +const char* +get_entry_tag_name(uint16 tag) +{ + return tag < kTagNameInfoCount ? sTagNames[tag] : NULL; +} diff --git a/src/apps/debugger/tag_names.h b/src/apps/debugger/tag_names.h new file mode 100644 index 0000000000..7b3d6f10ad --- /dev/null +++ b/src/apps/debugger/tag_names.h @@ -0,0 +1,14 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef TAG_NAMES_H +#define TAG_NAMES_H + +#include + + +const char* get_entry_tag_name(uint16 tag); + + +#endif // TAG_NAMES_H diff --git a/src/apps/debugger/types.h b/src/apps/debugger/types.h new file mode 100644 index 0000000000..f4587b480f --- /dev/null +++ b/src/apps/debugger/types.h @@ -0,0 +1,22 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef TYPES_H +#define TYPES_H + +#include + + +// target address type +typedef uint32 dwarf_addr_t; + +// DWARF 32 or 64 offset/size types +typedef uint32 dwarf_off_t; +typedef uint32 dwarf_size_t; + + +#define DWARF_ADDRESS_MAX 0xffffffff + + +#endif // TYPES_H