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:
parent
c43e377cff
commit
44101b1f99
@ -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
193
src/apps/debugger/Array.h
Normal 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
|
48
src/apps/debugger/AttributeValue.cpp
Normal file
48
src/apps/debugger/AttributeValue.cpp
Normal 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;
|
||||
}
|
69
src/apps/debugger/AttributeValue.h
Normal file
69
src/apps/debugger/AttributeValue.h
Normal 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
|
163
src/apps/debugger/DataReader.h
Normal file
163
src/apps/debugger/DataReader.h
Normal 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
|
1483
src/apps/debugger/DebugInfoEntries.cpp
Normal file
1483
src/apps/debugger/DebugInfoEntries.cpp
Normal file
File diff suppressed because it is too large
Load Diff
876
src/apps/debugger/DebugInfoEntries.h
Normal file
876
src/apps/debugger/DebugInfoEntries.h
Normal 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
|
183
src/apps/debugger/DebugInfoEntry.cpp
Normal file
183
src/apps/debugger/DebugInfoEntry.cpp
Normal 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;
|
||||
}
|
||||
}
|
152
src/apps/debugger/DebugInfoEntry.h
Normal file
152
src/apps/debugger/DebugInfoEntry.h
Normal 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
|
974
src/apps/debugger/DwarfManager.cpp
Normal file
974
src/apps/debugger/DwarfManager.cpp
Normal 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;
|
||||
}
|
36
src/apps/debugger/DwarfManager.h
Normal file
36
src/apps/debugger/DwarfManager.h
Normal 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
|
247
src/apps/debugger/ElfFile.cpp
Normal file
247
src/apps/debugger/ElfFile.cpp
Normal 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;
|
||||
}
|
65
src/apps/debugger/ElfFile.h
Normal file
65
src/apps/debugger/ElfFile.h
Normal 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
|
43
src/apps/debugger/HaikuTypes.h
Normal file
43
src/apps/debugger/HaikuTypes.h
Normal 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
21
src/apps/debugger/Jamfile
Normal 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++)
|
||||
;
|
53
src/apps/debugger/SourceLanguageInfo.cpp
Normal file
53
src/apps/debugger/SourceLanguageInfo.cpp
Normal 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;
|
55
src/apps/debugger/SourceLanguageInfo.h
Normal file
55
src/apps/debugger/SourceLanguageInfo.h
Normal 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
|
22
src/apps/debugger/arch_elf.h
Normal file
22
src/apps/debugger/arch_elf.h
Normal 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 */
|
238
src/apps/debugger/attribute_classes.cpp
Normal file
238
src/apps/debugger/attribute_classes.cpp
Normal 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;
|
||||
}
|
41
src/apps/debugger/attribute_classes.h
Normal file
41
src/apps/debugger/attribute_classes.h
Normal 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
|
26
src/apps/debugger/debugger.cpp
Normal file
26
src/apps/debugger/debugger.cpp
Normal 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
457
src/apps/debugger/dwarf.h
Normal 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
|
100
src/apps/debugger/tag_names.cpp
Normal file
100
src/apps/debugger/tag_names.cpp
Normal 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;
|
||||
}
|
14
src/apps/debugger/tag_names.h
Normal file
14
src/apps/debugger/tag_names.h
Normal 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
22
src/apps/debugger/types.h
Normal 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
|
Loading…
Reference in New Issue
Block a user