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
This commit is contained in:
Ingo Weinhold 2009-06-14 12:53:29 +00:00
parent c43e377cff
commit 44101b1f99
25 changed files with 5582 additions and 0 deletions

View File

@ -12,6 +12,7 @@ HaikuSubInclude clock ;
HaikuSubInclude codycam ;
HaikuSubInclude cortex ;
HaikuSubInclude debuganalyzer ;
HaikuSubInclude debugger ;
HaikuSubInclude deskbar ;
HaikuSubInclude deskcalc ;
HaikuSubInclude diskprobe ;

193
src/apps/debugger/Array.h Normal file
View File

@ -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 <stdio.h>
#include <stdlib.h>
#include <string.h>
template<typename Element>
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<typename Element>
Array<Element>::Array()
:
fElements(NULL),
fSize(0),
fCapacity(0)
{
}
template<typename Element>
Array<Element>::~Array()
{
free(fElements);
}
template<typename Element>
bool
Array<Element>::Add(const Element& element)
{
if (fSize == fCapacity) {
if (!_Resize(fSize, 1))
return false;
}
fElements[fSize] = element;
fSize++;
return true;
}
template<typename Element>
bool
Array<Element>::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<typename Element>
bool
Array<Element>::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<typename Element>
Element&
Array<Element>::ElementAt(int index)
{
return fElements[index];
}
template<typename Element>
const Element&
Array<Element>::ElementAt(int index) const
{
return fElements[index];
}
template<typename Element>
Element&
Array<Element>::operator[](int index)
{
return fElements[index];
}
template<typename Element>
const Element&
Array<Element>::operator[](int index) const
{
return fElements[index];
}
template<typename Element>
bool
Array<Element>::_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

View File

@ -0,0 +1,48 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "AttributeValue.h"
#include <stdio.h>
#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 "<unknown>";
}
return buffer;
}

View File

@ -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

View File

@ -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 <SupportDefs.h>
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<typename Type>
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<uint8>(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<uint8>(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

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -0,0 +1,183 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "DebugInfoEntries.h"
#include <new>
#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;
}
}

View File

@ -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 <util/DoublyLinkedList.h>
#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<DebugInfoEntry> {
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<DebugInfoEntry> DebugInfoEntryList;
#endif // DEBUG_INFO_ENTRY_H

View File

@ -0,0 +1,974 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "DwarfManager.h"
#include <algorithm>
#include <new>
#include <AutoDeleter.h>
#include <util/OpenHashTable.h>
#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<AbbreviationTableEntry> {
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<uint8>(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<AbbreviationTableEntry>* GetLink(
AbbreviationTableEntry* value) const
{
return value;
}
};
typedef OpenHashTable<AbbreviationTableHashDefinition> AbbreviationEntryTable;
class AbbreviationTable : public DoublyLinkedListLinkImpl<AbbreviationTable> {
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<uint8>(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> {
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<DebugInfoEntry*> fEntries;
Array<dwarf_off_t> fEntryOffsets;
};
// #pragma mark - File
struct DwarfManager::File : DoublyLinkedListLinkImpl<File> {
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<uint32>(0);
bool dwarf64 = (unitLength == 0xffffffff);
if (dwarf64)
unitLength = dataReader.Read<uint64>(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<uint16>(0);
off_t abbrevOffset = dwarf64
? dataReader.Read<uint64>(0)
: dataReader.Read<uint32>(0);
uint8 addressSize = dataReader.Read<uint8>(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<AbbreviationTable> AbbreviationTableList;
typedef DoublyLinkedList<CompilationUnit> 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<DIECompileUnitBase*>(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<uint8>(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<DebugInfoEntry> 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<dwarf_addr_t>(0);
break;
case DW_FORM_block2:
blockLength = dataReader.Read<uint16>(0);
break;
case DW_FORM_block4:
blockLength = dataReader.Read<uint32>(0);
break;
case DW_FORM_data2:
value = dataReader.Read<uint16>(0);
break;
case DW_FORM_data4:
value = dataReader.Read<uint32>(0);
break;
case DW_FORM_data8:
value = dataReader.Read<uint64>(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<uint8>(0);
break;
case DW_FORM_data1:
value = dataReader.Read<uint8>(0);
break;
case DW_FORM_flag:
attributeValue.flag = dataReader.Read<uint8>(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<dwarf_off_t>(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<dwarf_off_t>(0);
localReference = false;
break;
case DW_FORM_ref1:
value = dataReader.Read<uint8>(0);
break;
case DW_FORM_ref2:
value = dataReader.Read<uint16>(0);
break;
case DW_FORM_ref4:
value = dataReader.Read<uint32>(0);
break;
case DW_FORM_ref8:
value = dataReader.Read<uint64>(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;
}

View File

@ -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 <sys/types.h>
#include <SupportDefs.h>
#include <util/DoublyLinkedList.h>
class DwarfManager {
public:
DwarfManager();
~DwarfManager();
status_t Init();
status_t LoadFile(const char* fileName);
status_t FinishLoading();
private:
struct CompilationUnit;
struct File;
typedef DoublyLinkedList<File> FileList;
private:
FileList fFiles;
};
#endif // DWARF_MANAGER_H

View File

@ -0,0 +1,247 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "ElfFile.h"
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <new>
#include <AutoDeleter.h>
// #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;
}

View File

@ -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 <sys/types.h>
#include <SupportDefs.h>
#include <elf32.h>
#include <util/DoublyLinkedList.h>
class ElfSection : public DoublyLinkedListLinkImpl<ElfSection> {
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<ElfSection> 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

View File

@ -0,0 +1,43 @@
#ifndef HAIKU_TYPES_H
#define HAIKU_TYPES_H
#include <stdio.h>
#include <stdlib.h>
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

21
src/apps/debugger/Jamfile Normal file
View File

@ -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++)
;

View File

@ -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;

View File

@ -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 <SupportDefs.h>
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

View File

@ -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 */

View File

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

View File

@ -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

View File

@ -0,0 +1,26 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include <stdio.h>
#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;
}

457
src/apps/debugger/dwarf.h Normal file
View File

@ -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

View File

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

View File

@ -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 <SupportDefs.h>
const char* get_entry_tag_name(uint16 tag);
#endif // TAG_NAMES_H

22
src/apps/debugger/types.h Normal file
View File

@ -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 <SupportDefs.h>
// 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