* Renamed ArchitectureTypes.h to Types.h.

* Created "types" subdirectory for basic types and moved Types.h,
  SourceLocation, TargetAddressRange there.
* Added TargetAddressRangeList, representing a list of address ranges.
* Array: Added copy constructor and assignment operator.
* Added DwarfFunctionDebugInfo.
* ElfFile: Also read the program headers and provide access to the segment
  information.
* DWARF:
  - Some work on DIECompileUnitBase and DIESubprogram to handle attributes we
    need.
  - Added DwarfUtils class which provides static utility methods. Currently some
    to get DIE names. Only provisionally implemented yet.
  - Read range list attribute values from the .debug_ranges section. Extended
    AttributeValue to handle them correctly (ref-counting).
* DwarfImageDebugInfo:
  - Implemented GetFunctions() for real, i.e. we return functions for all
    subprogram debug info entries we find (those that refer to actual
    functions, that is).
  - Implemented the fallback part of LoadSourceCode() (reading the code from the
    file and disassembling it).

Things should hopefully work as before, just a bit slower and with less accurate
function names, if DWARF debug info is available. Promising, eh? ;-)


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31321 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2009-06-29 22:38:15 +00:00
parent e602845c35
commit 5b60969c5c
38 changed files with 1208 additions and 57 deletions

View File

@ -14,6 +14,7 @@ template<typename Element>
class Array { class Array {
public: public:
inline Array(); inline Array();
Array(const Array<Element>& other);
~Array(); ~Array();
inline int Size() const { return fSize; } inline int Size() const { return fSize; }
@ -34,6 +35,8 @@ public:
inline Element& operator[](int index); inline Element& operator[](int index);
inline const Element& operator[](int index) const; inline const Element& operator[](int index) const;
Array<Element>& operator=(const Array<Element>& other);
private: private:
static const int kMinCapacity = 8; static const int kMinCapacity = 8;
@ -56,6 +59,17 @@ Array<Element>::Array()
} }
template<typename Element>
Array<Element>::Array(const Array<Element>& other)
:
fElements(NULL),
fSize(0),
fCapacity(0)
{
*this = other;
}
template<typename Element> template<typename Element>
Array<Element>::~Array() Array<Element>::~Array()
{ {
@ -177,6 +191,21 @@ Array<Element>::operator[](int index) const
} }
template<typename Element>
Array<Element>&
Array<Element>::operator=(const Array<Element>& other)
{
Clear();
if (other.fSize > 0 && _Resize(0, other.fSize)) {
fSize = other.fSize;
memcpy(fElements, other.fElements, fSize * sizeof(Element));
}
return *this;
}
template<typename Element> template<typename Element>
bool bool
Array<Element>::_Resize(int index, int delta) Array<Element>::_Resize(int index, int delta)

View File

@ -13,6 +13,7 @@ SEARCH_SOURCE += [ FDirName $(SUBDIR) debugger_interface ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) elf ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) elf ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) gui team_window ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) gui team_window ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) model ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) model ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) types ] ;
local debugAnalyzerSources local debugAnalyzerSources
= [ FDirName $(HAIKU_TOP) src apps debuganalyzer ] ; = [ FDirName $(HAIKU_TOP) src apps debuganalyzer ] ;
@ -22,6 +23,7 @@ SubDirHdrs [ FDirName $(HAIKU_TOP) src bin debug ] ;
SubDirHdrs [ FDirName $(debugAnalyzerSources) gui ] ; SubDirHdrs [ FDirName $(debugAnalyzerSources) gui ] ;
SourceHdrs SourceHdrs
DwarfFunctionDebugInfo.cpp
DwarfImageDebugInfo.cpp DwarfImageDebugInfo.cpp
DwarfTeamDebugInfo.cpp DwarfTeamDebugInfo.cpp
: [ FDirName $(SUBDIR) dwarf ] : [ FDirName $(SUBDIR) dwarf ]
@ -49,6 +51,7 @@ Application Debugger :
BasicFunctionDebugInfo.cpp BasicFunctionDebugInfo.cpp
DebuggerImageDebugInfo.cpp DebuggerImageDebugInfo.cpp
DebuggerTeamDebugInfo.cpp DebuggerTeamDebugInfo.cpp
DwarfFunctionDebugInfo.cpp
DwarfImageDebugInfo.cpp DwarfImageDebugInfo.cpp
DwarfTeamDebugInfo.cpp DwarfTeamDebugInfo.cpp
FunctionDebugInfo.cpp FunctionDebugInfo.cpp
@ -90,6 +93,9 @@ Application Debugger :
Thread.cpp Thread.cpp
ThreadInfo.cpp ThreadInfo.cpp
# types
TargetAddressRangeList.cpp
: :
<nogrist>Debugger_demangler.o <nogrist>Debugger_demangler.o
<nogrist>Debugger_disasm_x86.o <nogrist>Debugger_disasm_x86.o

View File

@ -9,7 +9,7 @@
#include <Referenceable.h> #include <Referenceable.h>
#include "ArchitectureTypes.h" #include "Types.h"
class CpuState; class CpuState;

View File

@ -10,7 +10,7 @@
#include <Referenceable.h> #include <Referenceable.h>
#include <Variant.h> #include <Variant.h>
#include "ArchitectureTypes.h" #include "Types.h"
class Register; class Register;

View File

@ -7,7 +7,7 @@
#include <String.h> #include <String.h>
#include "ArchitectureTypes.h" #include "Types.h"
enum instruction_type { enum instruction_type {

View File

@ -7,7 +7,7 @@
#include <String.h> #include <String.h>
#include "ArchitectureTypes.h" #include "Types.h"
class DisassemblerX86 { class DisassemblerX86 {

View File

@ -7,6 +7,7 @@ UseHeaders [ LibraryHeaders udis86 ] ;
UseHeaders [ LibraryHeaders [ FDirName udis86 libudis86 ] ] ; UseHeaders [ LibraryHeaders [ FDirName udis86 libudis86 ] ] ;
SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) ] ; SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) ] ;
SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) $(DOTDOT) types ] ;
MergeObject Debugger_disasm_x86.o MergeObject Debugger_disasm_x86.o

View File

@ -0,0 +1,86 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "DwarfFunctionDebugInfo.h"
#include "DebugInfoEntries.h"
#include "DwarfImageDebugInfo.h"
#include "TargetAddressRangeList.h"
DwarfFunctionDebugInfo::DwarfFunctionDebugInfo(
DwarfImageDebugInfo* imageDebugInfo, DIESubprogram* subprogramEntry,
TargetAddressRangeList* addressRanges, const BString& name)
:
fImageDebugInfo(imageDebugInfo),
fAddressRanges(addressRanges),
fName(name)
{
fImageDebugInfo->AddReference();
fAddressRanges->AddReference();
}
DwarfFunctionDebugInfo::~DwarfFunctionDebugInfo()
{
fAddressRanges->RemoveReference();
fImageDebugInfo->RemoveReference();
}
SpecificImageDebugInfo*
DwarfFunctionDebugInfo::GetSpecificImageDebugInfo() const
{
return fImageDebugInfo;
}
target_addr_t
DwarfFunctionDebugInfo::Address() const
{
return fAddressRanges->LowestAddress() + fImageDebugInfo->RelocationDelta();
}
target_size_t
DwarfFunctionDebugInfo::Size() const
{
return fAddressRanges->CoveringRange().Size();
}
const char*
DwarfFunctionDebugInfo::Name() const
{
return fName.String();
}
const char*
DwarfFunctionDebugInfo::PrettyName() const
{
return fName.String();
}
const char*
DwarfFunctionDebugInfo::SourceFileName() const
{
return NULL;
}
SourceLocation
DwarfFunctionDebugInfo::SourceStartLocation() const
{
return SourceLocation();
}
SourceLocation
DwarfFunctionDebugInfo::SourceEndLocation() const
{
return SourceLocation();
}

View File

@ -0,0 +1,44 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef DWARF_FUNCTION_DEBUG_INFO_H
#define DWARF_FUNCTION_DEBUG_INFO_H
#include <String.h>
#include "FunctionDebugInfo.h"
class DIESubprogram;
class DwarfImageDebugInfo;
class TargetAddressRangeList;
class DwarfFunctionDebugInfo : public FunctionDebugInfo {
public:
DwarfFunctionDebugInfo(
DwarfImageDebugInfo* imageDebugInfo,
DIESubprogram* subprogramEntry,
TargetAddressRangeList* addressRanges,
const BString& name);
virtual ~DwarfFunctionDebugInfo();
virtual SpecificImageDebugInfo* GetSpecificImageDebugInfo() const;
virtual target_addr_t Address() const;
virtual target_size_t Size() const;
virtual const char* Name() const;
virtual const char* PrettyName() const;
virtual const char* SourceFileName() const;
virtual SourceLocation SourceStartLocation() const;
virtual SourceLocation SourceEndLocation() const;
private:
DwarfImageDebugInfo* fImageDebugInfo;
TargetAddressRangeList* fAddressRanges;
const BString fName;
};
#endif // DWARF_FUNCTION_DEBUG_INFO_H

View File

@ -6,6 +6,7 @@
#include "DwarfImageDebugInfo.h" #include "DwarfImageDebugInfo.h"
#include <stdio.h> #include <stdio.h>
#include <unistd.h>
#include <new> #include <new>
@ -16,6 +17,9 @@
#include "DebugInfoEntries.h" #include "DebugInfoEntries.h"
#include "Dwarf.h" #include "Dwarf.h"
#include "DwarfFile.h" #include "DwarfFile.h"
#include "DwarfFunctionDebugInfo.h"
#include "DwarfUtils.h"
#include "ElfFile.h"
DwarfImageDebugInfo::DwarfImageDebugInfo(const ImageInfo& imageInfo, DwarfImageDebugInfo::DwarfImageDebugInfo(const ImageInfo& imageInfo,
@ -23,7 +27,9 @@ DwarfImageDebugInfo::DwarfImageDebugInfo(const ImageInfo& imageInfo,
: :
fImageInfo(imageInfo), fImageInfo(imageInfo),
fArchitecture(architecture), fArchitecture(architecture),
fFile(file) fFile(file),
fTextSegment(NULL),
fRelocationDelta(0)
{ {
} }
@ -36,6 +42,12 @@ DwarfImageDebugInfo::~DwarfImageDebugInfo()
status_t status_t
DwarfImageDebugInfo::Init() DwarfImageDebugInfo::Init()
{ {
fTextSegment = fFile->GetElfFile()->TextSegment();
if (fTextSegment == NULL)
return B_ENTRY_NOT_FOUND;
fRelocationDelta = fImageInfo.TextBase() - fTextSegment->LoadAddress();
return B_OK; return B_OK;
} }
@ -48,22 +60,94 @@ printf(" %ld compilation units\n", fFile->CountCompilationUnits());
for (int32 i = 0; CompilationUnit* unit = fFile->CompilationUnitAt(i); for (int32 i = 0; CompilationUnit* unit = fFile->CompilationUnitAt(i);
i++) { i++) {
printf(" %s:\n", unit->UnitEntry()->Name()); DIECompileUnitBase* unitEntry = unit->UnitEntry();
// printf(" %s:\n", unitEntry->Name());
// printf(" address ranges:\n");
// TargetAddressRangeList* rangeList = unitEntry->AddressRanges();
// if (rangeList != NULL) {
// int32 count = rangeList->CountRanges();
// for (int32 i = 0; i < count; i++) {
// TargetAddressRange range = rangeList->RangeAt(i);
// printf(" %#llx - %#llx\n", range.Start(), range.End());
// }
// } else {
// printf(" %#llx - %#llx\n", (target_addr_t)unitEntry->LowPC(),
// (target_addr_t)unitEntry->HighPC());
// }
// printf(" functions:\n");
for (DebugInfoEntryList::ConstIterator it for (DebugInfoEntryList::ConstIterator it
= unit->UnitEntry()->OtherChildren().GetIterator(); = unitEntry->OtherChildren().GetIterator();
DebugInfoEntry* entry = it.Next();) { DebugInfoEntry* entry = it.Next();) {
if (entry->Tag() != DW_TAG_subprogram) if (entry->Tag() != DW_TAG_subprogram)
continue; continue;
DIESubprogram* subprogramEntry = static_cast<DIESubprogram*>(entry); DIESubprogram* subprogramEntry = static_cast<DIESubprogram*>(entry);
printf(" subprogram entry: %p, name: %s, declaration: %d\n",
subprogramEntry, subprogramEntry->Name(), // ignore declarations, prototypes, and inlined functions
subprogramEntry->IsDeclaration()); if (subprogramEntry->IsDeclaration()
|| subprogramEntry->IsPrototyped()
|| subprogramEntry->Inline() == DW_INL_inlined
|| subprogramEntry->Inline() == DW_INL_declared_inlined
|| subprogramEntry->AbstractOrigin() != NULL) {
continue;
}
// get the name
BString name;
DwarfUtils::GetFullyQualifiedDIEName(subprogramEntry, name);
if (name.Length() == 0)
continue;
// get the address ranges
TargetAddressRangeList* rangeList
= subprogramEntry->AddressRanges();
Reference<TargetAddressRangeList> rangeListReference(rangeList);
if (rangeList == NULL) {
target_addr_t lowPC = subprogramEntry->LowPC();
target_addr_t highPC = subprogramEntry->HighPC();
if (lowPC >= highPC)
continue;
rangeList = new(std::nothrow) TargetAddressRangeList(
TargetAddressRange(lowPC, highPC - lowPC));
if (rangeList == NULL)
return B_NO_MEMORY;
// TODO: Clean up already added functions!
rangeListReference.SetTo(rangeList, true);
}
// create and add the functions
DwarfFunctionDebugInfo* function
= new(std::nothrow) DwarfFunctionDebugInfo(this,
subprogramEntry, rangeList, name);
if (function == NULL || !functions.AddItem(function)) {
delete function;
return B_NO_MEMORY;
// TODO: Clean up already added functions!
}
// BString name;
// DwarfUtils::GetFullyQualifiedDIEName(subprogramEntry, name);
// printf(" subprogram entry: %p, name: %s, declaration: %d\n",
// subprogramEntry, name.String(),
// subprogramEntry->IsDeclaration());
//
// rangeList = subprogramEntry->AddressRanges();
// if (rangeList != NULL) {
// int32 count = rangeList->CountRanges();
// for (int32 i = 0; i < count; i++) {
// TargetAddressRange range = rangeList->RangeAt(i);
// printf(" %#llx - %#llx\n", range.Start(), range.End());
// }
// } else {
// printf(" %#llx - %#llx\n",
// (target_addr_t)subprogramEntry->LowPC(),
// (target_addr_t)subprogramEntry->HighPC());
// }
} }
} }
// TODO:...
return B_OK; return B_OK;
} }
@ -82,8 +166,25 @@ status_t
DwarfImageDebugInfo::LoadSourceCode(FunctionDebugInfo* function, DwarfImageDebugInfo::LoadSourceCode(FunctionDebugInfo* function,
SourceCode*& _sourceCode) SourceCode*& _sourceCode)
{ {
// TODO:... // TODO: Load the actual source code!
return B_UNSUPPORTED;
static const target_size_t kMaxBufferSize = 64 * 1024;
target_size_t bufferSize = std::min(function->Size(), kMaxBufferSize);
void* buffer = malloc(bufferSize);
if (buffer == NULL)
return B_NO_MEMORY;
MemoryDeleter bufferDeleter(buffer);
// read the function code
target_addr_t functionOffset = function->Address() - fRelocationDelta
- fTextSegment->LoadAddress() + fTextSegment->FileOffset();
ssize_t bytesRead = pread(fFile->GetElfFile()->FD(), buffer, bufferSize,
functionOffset);
if (bytesRead < 0)
return bytesRead;
return fArchitecture->DisassembleCode(function, buffer, bytesRead,
_sourceCode);
} }

View File

@ -11,6 +11,7 @@
class Architecture; class Architecture;
class DwarfFile; class DwarfFile;
class ElfSegment;
class DwarfImageDebugInfo : public SpecificImageDebugInfo { class DwarfImageDebugInfo : public SpecificImageDebugInfo {
@ -22,6 +23,9 @@ public:
status_t Init(); status_t Init();
target_addr_t RelocationDelta() const
{ return fRelocationDelta; }
virtual status_t GetFunctions( virtual status_t GetFunctions(
BObjectList<FunctionDebugInfo>& functions); BObjectList<FunctionDebugInfo>& functions);
virtual status_t CreateFrame(Image* image, virtual status_t CreateFrame(Image* image,
@ -39,6 +43,8 @@ private:
ImageInfo fImageInfo; ImageInfo fImageInfo;
Architecture* fArchitecture; Architecture* fArchitecture;
DwarfFile* fFile; DwarfFile* fFile;
ElfSegment* fTextSegment;
target_addr_t fRelocationDelta;
}; };

View File

@ -8,8 +8,8 @@
#include <Referenceable.h> #include <Referenceable.h>
#include <util/DoublyLinkedList.h> #include <util/DoublyLinkedList.h>
#include "ArchitectureTypes.h"
#include "SourceLocation.h" #include "SourceLocation.h"
#include "Types.h"
enum function_source_state { enum function_source_state {

View File

@ -10,8 +10,8 @@
#include <ObjectList.h> #include <ObjectList.h>
#include <Referenceable.h> #include <Referenceable.h>
#include "ArchitectureTypes.h"
#include "ImageInfo.h" #include "ImageInfo.h"
#include "Types.h"
class Architecture; class Architecture;

View File

@ -8,7 +8,7 @@
#include <ObjectList.h> #include <ObjectList.h>
#include <Referenceable.h> #include <Referenceable.h>
#include "ArchitectureTypes.h" #include "Types.h"
class Architecture; class Architecture;

View File

@ -7,8 +7,8 @@
#include <debugger.h> #include <debugger.h>
#include "ArchitectureTypes.h"
#include "ImageInfo.h" #include "ImageInfo.h"
#include "Types.h"
class CpuState; class CpuState;

View File

@ -7,6 +7,7 @@
#include "AttributeClasses.h" #include "AttributeClasses.h"
#include "DwarfTypes.h" #include "DwarfTypes.h"
#include "TargetAddressRangeList.h"
class DebugInfoEntry; class DebugInfoEntry;
@ -21,6 +22,7 @@ struct AttributeValue {
} block; } block;
uint64 constant; uint64 constant;
bool flag; bool flag;
TargetAddressRangeList* rangeList;
dwarf_off_t pointer; dwarf_off_t pointer;
DebugInfoEntry* reference; DebugInfoEntry* reference;
const char* string; const char* string;
@ -30,6 +32,100 @@ struct AttributeValue {
uint8 attributeClass; uint8 attributeClass;
bool isSigned; bool isSigned;
AttributeValue()
:
attributeClass(ATTRIBUTE_CLASS_UNKNOWN)
{
}
~AttributeValue()
{
Unset();
}
void SetToAddress(dwarf_addr_t address)
{
Unset();
attributeClass = ATTRIBUTE_CLASS_ADDRESS;
this->address = address;
}
void SetToBlock(const void* data, dwarf_size_t length)
{
Unset();
attributeClass = ATTRIBUTE_CLASS_BLOCK;
block.data = data;
block.length = length;
}
void SetToConstant(uint64 value, bool isSigned)
{
Unset();
attributeClass = ATTRIBUTE_CLASS_CONSTANT;
this->constant = value;
this->isSigned = isSigned;
}
void SetToFlag(bool value)
{
Unset();
attributeClass = ATTRIBUTE_CLASS_FLAG;
this->flag = value;
}
void SetToLinePointer(dwarf_off_t value)
{
Unset();
attributeClass = ATTRIBUTE_CLASS_LINEPTR;
this->pointer = value;
}
void SetToLocationListPointer(dwarf_off_t value)
{
Unset();
attributeClass = ATTRIBUTE_CLASS_LOCLISTPTR;
this->pointer = value;
}
void SetToMacroPointer(dwarf_off_t value)
{
Unset();
attributeClass = ATTRIBUTE_CLASS_MACPTR;
this->pointer = value;
}
void SetToRangeList(TargetAddressRangeList* rangeList)
{
Unset();
attributeClass = ATTRIBUTE_CLASS_RANGELISTPTR;
this->rangeList = rangeList;
if (rangeList != NULL)
rangeList->AddReference();
}
void SetToReference(DebugInfoEntry* entry)
{
Unset();
attributeClass = ATTRIBUTE_CLASS_REFERENCE;
this->reference = entry;
}
void SetToString(const char* string)
{
Unset();
attributeClass = ATTRIBUTE_CLASS_STRING;
this->string = string;
}
void Unset()
{
if (attributeClass == ATTRIBUTE_CLASS_RANGELISTPTR
&& rangeList != NULL) {
rangeList->RemoveReference();
}
attributeClass = ATTRIBUTE_CLASS_UNKNOWN;
}
const char* ToString(char* buffer, size_t size); const char* ToString(char* buffer, size_t size);
}; };

View File

@ -24,6 +24,7 @@ DIECompileUnitBase::DIECompileUnitBase()
fStatementListOffset(0), fStatementListOffset(0),
fMacroInfoOffset(0), fMacroInfoOffset(0),
// TODO: Is 0 a good invalid offset? // TODO: Is 0 a good invalid offset?
fAddressRanges(NULL),
fBaseTypesUnit(NULL), fBaseTypesUnit(NULL),
fLanguage(0), fLanguage(0),
fIdentifierCase(0), fIdentifierCase(0),
@ -32,6 +33,13 @@ DIECompileUnitBase::DIECompileUnitBase()
} }
DIECompileUnitBase::~DIECompileUnitBase()
{
if (fAddressRanges != NULL)
fAddressRanges->RemoveReference();
}
status_t status_t
DIECompileUnitBase::InitAfterAttributes(DebugInfoEntryInitInfo& info) DIECompileUnitBase::InitAfterAttributes(DebugInfoEntryInitInfo& info)
{ {
@ -65,6 +73,16 @@ DIECompileUnitBase::Name() const
} }
dwarf_addr_t
DIECompileUnitBase::AddressRangeBase() const
{
if (fAddressRanges != NULL)
return fAddressRanges->LowestAddress();
return fLowPC;
}
status_t status_t
DIECompileUnitBase::AddChild(DebugInfoEntry* child) DIECompileUnitBase::AddChild(DebugInfoEntry* child)
{ {
@ -175,6 +193,22 @@ DIECompileUnitBase::AddAttribute_use_UTF8(uint16 attributeName,
} }
status_t
DIECompileUnitBase::AddAttribute_ranges(uint16 attributeName,
const AttributeValue& value)
{
if (fAddressRanges != NULL)
fAddressRanges->RemoveReference();
fAddressRanges = value.rangeList;
if (fAddressRanges != NULL)
fAddressRanges->AddReference();
return B_OK;
}
// #pragma mark - DIEType // #pragma mark - DIEType
@ -285,6 +319,13 @@ DIEDeclaredType::Description() const
} }
DebugInfoEntry*
DIEDeclaredType::AbstractOrigin() const
{
return fAbstractOrigin;
}
status_t status_t
DIEDeclaredType::AddAttribute_accessibility(uint16 attributeName, DIEDeclaredType::AddAttribute_accessibility(uint16 attributeName,
const AttributeValue& value) const AttributeValue& value)
@ -359,6 +400,20 @@ DIECompoundType::DIECompoundType()
} }
bool
DIECompoundType::IsNamespace() const
{
return true;
}
DebugInfoEntry*
DIECompoundType::Specification() const
{
return fSpecification;
}
status_t status_t
DIECompoundType::AddChild(DebugInfoEntry* child) DIECompoundType::AddChild(DebugInfoEntry* child)
{ {
@ -569,6 +624,13 @@ DIEArrayType::InitAfterHierarchy(DebugInfoEntryInitInfo& info)
} }
DebugInfoEntry*
DIEArrayType::Specification() const
{
return fSpecification;
}
status_t status_t
DIEArrayType::AddChild(DebugInfoEntry* child) DIEArrayType::AddChild(DebugInfoEntry* child)
{ {
@ -672,6 +734,13 @@ DIEEnumerationType::Tag() const
} }
DebugInfoEntry*
DIEEnumerationType::Specification() const
{
return fSpecification;
}
status_t status_t
DIEEnumerationType::AddChild(DebugInfoEntry* child) DIEEnumerationType::AddChild(DebugInfoEntry* child)
{ {
@ -809,6 +878,13 @@ DIEPointerType::Tag() const
} }
DebugInfoEntry*
DIEPointerType::Specification() const
{
return fSpecification;
}
status_t status_t
DIEPointerType::AddAttribute_specification(uint16 attributeName, DIEPointerType::AddAttribute_specification(uint16 attributeName,
const AttributeValue& value) const AttributeValue& value)
@ -1461,10 +1537,27 @@ DIEPackedType::Tag() const
DIESubprogram::DIESubprogram() DIESubprogram::DIESubprogram()
:
fLowPC(0),
fHighPC(0),
fAddressRanges(NULL),
fSpecification(NULL),
fAbstractOrigin(NULL),
fReturnType(NULL),
fAddressClass(0),
fPrototyped(false),
fInline(DW_INL_not_inlined)
{ {
} }
DIESubprogram::~DIESubprogram()
{
if (fAddressRanges != NULL)
fAddressRanges->RemoveReference();
}
uint16 uint16
DIESubprogram::Tag() const DIESubprogram::Tag() const
{ {
@ -1472,6 +1565,111 @@ DIESubprogram::Tag() const
} }
DebugInfoEntry*
DIESubprogram::Specification() const
{
return fSpecification;
}
DebugInfoEntry*
DIESubprogram::AbstractOrigin() const
{
return fAbstractOrigin;
}
status_t
DIESubprogram::AddAttribute_low_pc(uint16 attributeName,
const AttributeValue& value)
{
fLowPC = value.address;
return B_OK;
}
status_t
DIESubprogram::AddAttribute_high_pc(uint16 attributeName,
const AttributeValue& value)
{
fHighPC = value.address;
return B_OK;
}
status_t
DIESubprogram::AddAttribute_ranges(uint16 attributeName,
const AttributeValue& value)
{
if (fAddressRanges != NULL)
fAddressRanges->RemoveReference();
fAddressRanges = value.rangeList;
if (fAddressRanges != NULL)
fAddressRanges->AddReference();
return B_OK;
}
status_t
DIESubprogram::AddAttribute_specification(uint16 attributeName,
const AttributeValue& value)
{
fSpecification = dynamic_cast<DIESubprogram*>(value.reference);
return fSpecification != NULL ? B_OK : B_BAD_DATA;
}
status_t
DIESubprogram::AddAttribute_address_class(uint16 attributeName,
const AttributeValue& value)
{
// TODO: How is the address class handled?
fAddressClass = value.constant;
return B_OK;
}
status_t
DIESubprogram::AddAttribute_prototyped(uint16 attributeName,
const AttributeValue& value)
{
fPrototyped = value.flag;
return B_OK;
}
status_t
DIESubprogram::AddAttribute_type(uint16 attributeName,
const AttributeValue& value)
{
fReturnType = dynamic_cast<DIEType*>(value.reference);
return fReturnType != NULL ? B_OK : B_BAD_DATA;
}
status_t
DIESubprogram::AddAttribute_inline(uint16 attributeName,
const AttributeValue& value)
{
// TODO: How is the address class handled?
fInline = value.constant;
return B_OK;
}
status_t
DIESubprogram::AddAttribute_abstract_origin(uint16 attributeName,
const AttributeValue& value)
{
fAbstractOrigin = dynamic_cast<DIESubprogram*>(value.reference);
return fAbstractOrigin != NULL ? B_OK : B_BAD_DATA;
}
// #pragma mark - DIETemplateTypeParameter // #pragma mark - DIETemplateTypeParameter
@ -1664,6 +1862,21 @@ DIENamespace::Tag() const
} }
bool
DIENamespace::IsNamespace() const
{
return true;
}
status_t
DIENamespace::AddChild(DebugInfoEntry* child)
{
fChildren.Add(child);
return B_OK;
}
// #pragma mark - DIEImportedModule // #pragma mark - DIEImportedModule

View File

@ -136,6 +136,7 @@
class DIECompileUnitBase : public DebugInfoEntry { class DIECompileUnitBase : public DebugInfoEntry {
public: public:
DIECompileUnitBase(); DIECompileUnitBase();
~DIECompileUnitBase();
virtual status_t InitAfterAttributes( virtual status_t InitAfterAttributes(
DebugInfoEntryInitInfo& info); DebugInfoEntryInitInfo& info);
@ -145,6 +146,12 @@ public:
const DebugInfoEntryList& Types() const { return fTypes; } const DebugInfoEntryList& Types() const { return fTypes; }
const DebugInfoEntryList& OtherChildren() const const DebugInfoEntryList& OtherChildren() const
{ return fOtherChildren; } { return fOtherChildren; }
TargetAddressRangeList* AddressRanges() const
{ return fAddressRanges; }
dwarf_addr_t LowPC() const { return fLowPC; }
dwarf_addr_t HighPC() const { return fHighPC; }
dwarf_addr_t AddressRangeBase() const;
virtual status_t AddChild(DebugInfoEntry* child); virtual status_t AddChild(DebugInfoEntry* child);
@ -171,10 +178,10 @@ public:
const AttributeValue& value); const AttributeValue& value);
virtual status_t AddAttribute_use_UTF8(uint16 attributeName, virtual status_t AddAttribute_use_UTF8(uint16 attributeName,
const AttributeValue& value); const AttributeValue& value);
virtual status_t AddAttribute_ranges(uint16 attributeName,
const AttributeValue& value);
//TODO: //TODO:
// virtual status_t AddAttribute_ranges(uint16 attributeName,
// const AttributeValue& value);
// virtual status_t AddAttribute_segment(uint16 attributeName, // virtual status_t AddAttribute_segment(uint16 attributeName,
// const AttributeValue& value); // const AttributeValue& value);
@ -187,6 +194,7 @@ protected:
dwarf_addr_t fHighPC; dwarf_addr_t fHighPC;
dwarf_off_t fStatementListOffset; dwarf_off_t fStatementListOffset;
dwarf_off_t fMacroInfoOffset; dwarf_off_t fMacroInfoOffset;
TargetAddressRangeList* fAddressRanges;
DIECompileUnitBase* fBaseTypesUnit; DIECompileUnitBase* fBaseTypesUnit;
DebugInfoEntryList fTypes; DebugInfoEntryList fTypes;
DebugInfoEntryList fOtherChildren; DebugInfoEntryList fOtherChildren;
@ -251,6 +259,7 @@ public:
DIEDeclaredType(); DIEDeclaredType();
virtual const char* Description() const; virtual const char* Description() const;
virtual DebugInfoEntry* AbstractOrigin() const;
virtual status_t AddAttribute_accessibility(uint16 attributeName, virtual status_t AddAttribute_accessibility(uint16 attributeName,
const AttributeValue& value); const AttributeValue& value);
@ -297,6 +306,10 @@ class DIECompoundType : public DIEDeclaredType {
public: public:
DIECompoundType(); DIECompoundType();
virtual bool IsNamespace() const;
virtual DebugInfoEntry* Specification() const;
virtual status_t AddChild(DebugInfoEntry* child); virtual status_t AddChild(DebugInfoEntry* child);
virtual status_t AddAttribute_byte_size(uint16 attributeName, virtual status_t AddAttribute_byte_size(uint16 attributeName,
@ -398,6 +411,8 @@ public:
virtual status_t InitAfterHierarchy( virtual status_t InitAfterHierarchy(
DebugInfoEntryInitInfo& info); DebugInfoEntryInitInfo& info);
virtual DebugInfoEntry* Specification() const;
virtual status_t AddChild(DebugInfoEntry* child); virtual status_t AddChild(DebugInfoEntry* child);
virtual status_t AddAttribute_ordering(uint16 attributeName, virtual status_t AddAttribute_ordering(uint16 attributeName,
@ -453,6 +468,8 @@ public:
virtual uint16 Tag() const; virtual uint16 Tag() const;
virtual DebugInfoEntry* Specification() const;
virtual status_t AddChild(DebugInfoEntry* child); virtual status_t AddChild(DebugInfoEntry* child);
virtual status_t AddAttribute_bit_stride(uint16 attributeName, virtual status_t AddAttribute_bit_stride(uint16 attributeName,
@ -557,6 +574,8 @@ public:
virtual uint16 Tag() const; virtual uint16 Tag() const;
virtual DebugInfoEntry* Specification() const;
virtual status_t AddAttribute_specification(uint16 attributeName, virtual status_t AddAttribute_specification(uint16 attributeName,
const AttributeValue& value); const AttributeValue& value);
@ -990,12 +1009,55 @@ public:
class DIESubprogram : public DIEDeclaredNamedBase { class DIESubprogram : public DIEDeclaredNamedBase {
public: public:
DIESubprogram(); DIESubprogram();
~DIESubprogram();
virtual uint16 Tag() const; virtual uint16 Tag() const;
virtual DebugInfoEntry* Specification() const;
virtual DebugInfoEntry* AbstractOrigin() const;
TargetAddressRangeList* AddressRanges() const
{ return fAddressRanges; }
dwarf_addr_t LowPC() const { return fLowPC; }
dwarf_addr_t HighPC() const { return fHighPC; }
bool IsPrototyped() const { return fPrototyped; }
uint8 Inline() const { return fInline; }
virtual status_t AddAttribute_low_pc(uint16 attributeName,
const AttributeValue& value);
virtual status_t AddAttribute_high_pc(uint16 attributeName,
const AttributeValue& value);
virtual status_t AddAttribute_ranges(uint16 attributeName,
const AttributeValue& value);
virtual status_t AddAttribute_specification(uint16 attributeName,
const AttributeValue& value);
virtual status_t AddAttribute_address_class(uint16 attributeName,
const AttributeValue& value);
virtual status_t AddAttribute_prototyped(uint16 attributeName,
const AttributeValue& value);
virtual status_t AddAttribute_type(uint16 attributeName,
const AttributeValue& value);
virtual status_t AddAttribute_inline(uint16 attributeName,
const AttributeValue& value);
virtual status_t AddAttribute_abstract_origin(
uint16 attributeName,
const AttributeValue& value);
protected:
dwarf_addr_t fLowPC;
dwarf_addr_t fHighPC;
TargetAddressRangeList* fAddressRanges;
DIESubprogram* fSpecification;
DIESubprogram* fAbstractOrigin;
DIEType* fReturnType;
uint8 fAddressClass;
bool fPrototyped;
uint8 fInline;
// TODO: // TODO:
// DW_AT_abstract_origin // DW_AT_abstract_origin
// DW_AT_address_class
// DW_AT_artificial // DW_AT_artificial
// DW_AT_calling_convention // DW_AT_calling_convention
// DW_AT_elemental // DW_AT_elemental
@ -1003,13 +1065,8 @@ public:
// DW_AT_explicit // DW_AT_explicit
// DW_AT_external // DW_AT_external
// DW_AT_frame_base // DW_AT_frame_base
// DW_AT_high_pc
// DW_AT_inline
// DW_AT_low_pc
// DW_AT_object_pointer // DW_AT_object_pointer
// DW_AT_prototyped
// DW_AT_pure // DW_AT_pure
// DW_AT_ranges
// DW_AT_recursive // DW_AT_recursive
// DW_AT_return_addr // DW_AT_return_addr
// DW_AT_segment // DW_AT_segment
@ -1017,7 +1074,6 @@ public:
// DW_AT_start_scope // DW_AT_start_scope
// DW_AT_static_link // DW_AT_static_link
// DW_AT_trampoline // DW_AT_trampoline
// DW_AT_type
// DW_AT_virtuality // DW_AT_virtuality
// DW_AT_vtable_elem_location // DW_AT_vtable_elem_location
}; };
@ -1160,6 +1216,16 @@ public:
virtual uint16 Tag() const; virtual uint16 Tag() const;
virtual bool IsNamespace() const;
const DebugInfoEntryList& Children() const
{ return fChildren; }
virtual status_t AddChild(DebugInfoEntry* child);
private:
DebugInfoEntryList fChildren;
// TODO: // TODO:
// DW_AT_extension // DW_AT_extension
// DW_AT_start_scope // DW_AT_start_scope

View File

@ -21,6 +21,8 @@
DebugInfoEntry::DebugInfoEntry() DebugInfoEntry::DebugInfoEntry()
:
fParent(NULL)
{ {
} }
@ -44,6 +46,13 @@ DebugInfoEntry::InitAfterAttributes(DebugInfoEntryInitInfo& info)
} }
void
DebugInfoEntry::SetParent(DebugInfoEntry* parent)
{
fParent = parent;
}
bool bool
DebugInfoEntry::IsType() const DebugInfoEntry::IsType() const
{ {
@ -51,13 +60,19 @@ DebugInfoEntry::IsType() const
} }
bool
DebugInfoEntry::IsNamespace() const
{
return false;
}
const char* const char*
DebugInfoEntry::Name() const DebugInfoEntry::Name() const
{ {
return NULL; return NULL;
} }
const char* const char*
DebugInfoEntry::Description() const DebugInfoEntry::Description() const
{ {
@ -65,6 +80,20 @@ DebugInfoEntry::Description() const
} }
DebugInfoEntry*
DebugInfoEntry::Specification() const
{
return NULL;
}
DebugInfoEntry*
DebugInfoEntry::AbstractOrigin() const
{
return NULL;
}
status_t status_t
DebugInfoEntry::AddChild(DebugInfoEntry* child) DebugInfoEntry::AddChild(DebugInfoEntry* child)
{ {

View File

@ -5,6 +5,8 @@
#ifndef DEBUG_INFO_ENTRY_H #ifndef DEBUG_INFO_ENTRY_H
#define DEBUG_INFO_ENTRY_H #define DEBUG_INFO_ENTRY_H
#include <String.h>
#include <util/DoublyLinkedList.h> #include <util/DoublyLinkedList.h>
#include "DwarfTypes.h" #include "DwarfTypes.h"
@ -44,10 +46,18 @@ public:
virtual uint16 Tag() const = 0; virtual uint16 Tag() const = 0;
DebugInfoEntry* Parent() const { return fParent; }
void SetParent(DebugInfoEntry* parent);
virtual bool IsType() const; virtual bool IsType() const;
virtual bool IsNamespace() const;
// a namespace-like thingy (namespace,
// class, ...)
virtual const char* Name() const; virtual const char* Name() const;
virtual const char* Description() const; virtual const char* Description() const;
virtual DebugInfoEntry* Specification() const;
virtual DebugInfoEntry* AbstractOrigin() const;
virtual status_t AddChild(DebugInfoEntry* child); virtual status_t AddChild(DebugInfoEntry* child);
@ -154,6 +164,9 @@ protected:
status_t SetConstantAttributeValue( status_t SetConstantAttributeValue(
ConstantAttributeValue& toSet, ConstantAttributeValue& toSet,
const AttributeValue& value); const AttributeValue& value);
protected:
DebugInfoEntry* fParent;
}; };

View File

@ -16,6 +16,7 @@
#include "DataReader.h" #include "DataReader.h"
#include "ElfFile.h" #include "ElfFile.h"
#include "TagNames.h" #include "TagNames.h"
#include "TargetAddressRangeList.h"
DwarfFile::DwarfFile() DwarfFile::DwarfFile()
@ -25,6 +26,7 @@ DwarfFile::DwarfFile()
fDebugInfoSection(NULL), fDebugInfoSection(NULL),
fDebugAbbrevSection(NULL), fDebugAbbrevSection(NULL),
fDebugStringSection(NULL), fDebugStringSection(NULL),
fDebugRangesSection(NULL),
fCompilationUnits(20, true), fCompilationUnits(20, true),
fCurrentCompilationUnit(NULL), fCurrentCompilationUnit(NULL),
fFinished(false), fFinished(false),
@ -42,6 +44,7 @@ DwarfFile::~DwarfFile()
fElfFile->PutSection(fDebugInfoSection); fElfFile->PutSection(fDebugInfoSection);
fElfFile->PutSection(fDebugAbbrevSection); fElfFile->PutSection(fDebugAbbrevSection);
fElfFile->PutSection(fDebugStringSection); fElfFile->PutSection(fDebugStringSection);
fElfFile->PutSection(fDebugRangesSection);
delete fElfFile; delete fElfFile;
} }
@ -69,6 +72,8 @@ DwarfFile::Load(const char* fileName)
fDebugInfoSection = fElfFile->GetSection(".debug_info"); fDebugInfoSection = fElfFile->GetSection(".debug_info");
fDebugAbbrevSection = fElfFile->GetSection(".debug_abbrev"); fDebugAbbrevSection = fElfFile->GetSection(".debug_abbrev");
fDebugStringSection = fElfFile->GetSection(".debug_str"); fDebugStringSection = fElfFile->GetSection(".debug_str");
fDebugRangesSection = fElfFile->GetSection(".debug_ranges");
// not mandatory
if (fDebugInfoSection == NULL || fDebugAbbrevSection == NULL if (fDebugInfoSection == NULL || fDebugAbbrevSection == NULL
|| fDebugStringSection == NULL) { || fDebugStringSection == NULL) {
fprintf(stderr, "DwarfManager::File::Load(\"%s\"): no " fprintf(stderr, "DwarfManager::File::Load(\"%s\"): no "
@ -286,7 +291,9 @@ abbreviationEntry.Tag(), abbreviationEntry.HasChildren());
if (childEntry != NULL) { if (childEntry != NULL) {
if (entry != NULL) { if (entry != NULL) {
error = entry->AddChild(childEntry); error = entry->AddChild(childEntry);
if (error == ENTRY_NOT_HANDLED) { if (error == B_OK) {
childEntry->SetParent(entry);
} else if (error == ENTRY_NOT_HANDLED) {
error = B_OK; error = B_OK;
printf("%*s -> child unhandled\n", level * 2, ""); printf("%*s -> child unhandled\n", level * 2, "");
} }
@ -384,7 +391,7 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
// prepare an AttributeValue // prepare an AttributeValue
AttributeValue attributeValue; AttributeValue attributeValue;
attributeValue.attributeForm = attributeForm; attributeValue.attributeForm = attributeForm;
attributeValue.isSigned = false; bool isSigned = false;
// Read the attribute value according to the attribute's form. For // Read the attribute value according to the attribute's form. For
// the forms that don't map to a single attribute class only or // the forms that don't map to a single attribute class only or
@ -414,7 +421,7 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
value = dataReader.Read<uint64>(0); value = dataReader.Read<uint64>(0);
break; break;
case DW_FORM_string: case DW_FORM_string:
attributeValue.string = dataReader.ReadString(); attributeValue.SetToString(dataReader.ReadString());
break; break;
case DW_FORM_block: case DW_FORM_block:
blockLength = dataReader.ReadUnsignedLEB128(0); blockLength = dataReader.ReadUnsignedLEB128(0);
@ -426,11 +433,11 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
value = dataReader.Read<uint8>(0); value = dataReader.Read<uint8>(0);
break; break;
case DW_FORM_flag: case DW_FORM_flag:
attributeValue.flag = dataReader.Read<uint8>(0) != 0; attributeValue.SetToFlag(dataReader.Read<uint8>(0) != 0);
break; break;
case DW_FORM_sdata: case DW_FORM_sdata:
value = dataReader.ReadSignedLEB128(0); value = dataReader.ReadSignedLEB128(0);
attributeValue.isSigned = true; isSigned = true;
break; break;
case DW_FORM_strp: case DW_FORM_strp:
{ {
@ -440,8 +447,8 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
offset); offset);
return B_BAD_DATA; return B_BAD_DATA;
} }
attributeValue.string attributeValue.SetToString(
= (const char*)fDebugStringSection->Data() + offset; (const char*)fDebugStringSection->Data() + offset);
break; break;
} }
case DW_FORM_udata: case DW_FORM_udata:
@ -484,31 +491,43 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
attributeForm); attributeForm);
continue; continue;
} }
attributeValue.attributeClass = attributeClass; // attributeValue.attributeClass = attributeClass;
// set the attribute value according to the attribute's class // set the attribute value according to the attribute's class
switch (attributeClass) { switch (attributeClass) {
case ATTRIBUTE_CLASS_ADDRESS: case ATTRIBUTE_CLASS_ADDRESS:
attributeValue.address = value; attributeValue.SetToAddress(value);
break; break;
case ATTRIBUTE_CLASS_BLOCK: case ATTRIBUTE_CLASS_BLOCK:
attributeValue.block.data = dataReader.Data(); attributeValue.SetToBlock(dataReader.Data(), blockLength);
attributeValue.block.length = blockLength;
dataReader.Skip(blockLength); dataReader.Skip(blockLength);
break; break;
case ATTRIBUTE_CLASS_CONSTANT: case ATTRIBUTE_CLASS_CONSTANT:
attributeValue.constant = value; attributeValue.SetToConstant(value, isSigned);
break; break;
case ATTRIBUTE_CLASS_LINEPTR: case ATTRIBUTE_CLASS_LINEPTR:
case ATTRIBUTE_CLASS_LOCLISTPTR: attributeValue.SetToLinePointer(value);
case ATTRIBUTE_CLASS_MACPTR:
case ATTRIBUTE_CLASS_RANGELISTPTR:
attributeValue.pointer = value;
break; break;
case ATTRIBUTE_CLASS_LOCLISTPTR:
attributeValue.SetToLocationListPointer(value);
break;
case ATTRIBUTE_CLASS_MACPTR:
attributeValue.SetToMacroPointer(value);
break;
case ATTRIBUTE_CLASS_RANGELISTPTR:
{
if (entry != NULL) {
TargetAddressRangeList* rangeList
= _ResolveRangeList(value);
Reference<TargetAddressRangeList> reference(rangeList);
attributeValue.SetToRangeList(rangeList);
}
break;
}
case ATTRIBUTE_CLASS_REFERENCE: case ATTRIBUTE_CLASS_REFERENCE:
if (entry != NULL) { if (entry != NULL) {
attributeValue.reference = _ResolveReference(value, attributeValue.SetToReference(_ResolveReference(value,
localReference); localReference));
if (attributeValue.reference == NULL) { if (attributeValue.reference == NULL) {
fprintf(stderr, "Failed to resolve reference: " fprintf(stderr, "Failed to resolve reference: "
"%s (%#lx) %s (%#lx): value: %llu\n", "%s (%#lx) %s (%#lx): value: %llu\n",
@ -539,7 +558,7 @@ get_attribute_form_name(attributeForm), attributeClass, attributeValue.ToString(
DebugInfoEntrySetter attributeSetter DebugInfoEntrySetter attributeSetter
= get_attribute_name_setter(attributeName); = get_attribute_name_setter(attributeName);
if (attributeSetter != NULL) { if (attributeSetter != 0) {
status_t error = (entry->*attributeSetter)(attributeName, status_t error = (entry->*attributeSetter)(attributeName,
attributeValue); attributeValue);
@ -605,3 +624,49 @@ DwarfFile::_ResolveReference(uint64 offset, bool localReference) const
// TODO: Implement program-global references! // TODO: Implement program-global references!
return NULL; return NULL;
} }
TargetAddressRangeList*
DwarfFile::_ResolveRangeList(uint64 offset)
{
if (fDebugRangesSection == NULL)
return NULL;
if (offset >= (uint64)fDebugRangesSection->Size())
return NULL;
TargetAddressRangeList* ranges = new(std::nothrow) TargetAddressRangeList;
if (ranges == NULL) {
fprintf(stderr, "Out of memory.\n");
return NULL;
}
Reference<TargetAddressRangeList> rangesReference(ranges);
dwarf_addr_t baseAddress
= fCurrentCompilationUnit->UnitEntry()->AddressRangeBase();
DataReader dataReader((uint8*)fDebugRangesSection->Data() + offset,
fDebugRangesSection->Size() - offset);
while (true) {
dwarf_addr_t start = dataReader.Read<dwarf_addr_t>(0);
dwarf_addr_t end = dataReader.Read<dwarf_addr_t>(0);
if (dataReader.HasOverflow())
return NULL;
if (start == 0 && end == 0)
break;
if (start == DWARF_ADDRESS_MAX) {
baseAddress = end;
continue;
}
if (start == end)
continue;
if (!ranges->AddRange(baseAddress + start, end - start)) {
fprintf(stderr, "Out of memory.\n");
return NULL;
}
}
return rangesReference.Detach();
}

View File

@ -17,6 +17,7 @@ class CompilationUnit;
class DataReader; class DataReader;
class ElfFile; class ElfFile;
class ElfSection; class ElfSection;
class TargetAddressRangeList;
class DwarfFile : public DoublyLinkedListLinkImpl<DwarfFile> { class DwarfFile : public DoublyLinkedListLinkImpl<DwarfFile> {
@ -27,7 +28,8 @@ public:
status_t Load(const char* fileName); status_t Load(const char* fileName);
status_t FinishLoading(); status_t FinishLoading();
const char* Name() const { return fName; } const char* Name() const { return fName; }
ElfFile* GetElfFile() const { return fElfFile; }
int32 CountCompilationUnits() const; int32 CountCompilationUnits() const;
CompilationUnit* CompilationUnitAt(int32 index) const; CompilationUnit* CompilationUnitAt(int32 index) const;
@ -52,6 +54,8 @@ private:
DebugInfoEntry* _ResolveReference(uint64 offset, DebugInfoEntry* _ResolveReference(uint64 offset,
bool localReference) const; bool localReference) const;
TargetAddressRangeList* _ResolveRangeList(uint64 offset);
// returns reference
private: private:
char* fName; char* fName;
@ -59,6 +63,7 @@ private:
ElfSection* fDebugInfoSection; ElfSection* fDebugInfoSection;
ElfSection* fDebugAbbrevSection; ElfSection* fDebugAbbrevSection;
ElfSection* fDebugStringSection; ElfSection* fDebugStringSection;
ElfSection* fDebugRangesSection;
AbbreviationTableList fAbbreviationTables; AbbreviationTableList fAbbreviationTables;
DebugInfoEntryFactory fDebugInfoFactory; DebugInfoEntryFactory fDebugInfoFactory;
CompilationUnitList fCompilationUnits; CompilationUnitList fCompilationUnits;

View File

@ -0,0 +1,79 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "DwarfUtils.h"
#include <String.h>
/*static*/ void
DwarfUtils::GetDIEName(const DebugInfoEntry* entry, BString& _name)
{
// If we don't seem to have a name but a specification, return the
// specification's name.
const char* name = entry->Name();
if (name == NULL) {
if (DebugInfoEntry* specification = entry->Specification())
name = specification->Name();
}
_name = name;
}
/*static*/ void
DwarfUtils::GetFullDIEName(const DebugInfoEntry* entry, BString& _name)
{
// If we don't seem to have a name but a specification, return the
// specification's name.
const char* name = entry->Name();
if (name == NULL) {
if (DebugInfoEntry* specification = entry->Specification()) {
entry = specification;
name = specification->Name();
}
}
// TODO: Get template and function parameters!
_name = name;
}
/*static*/ void
DwarfUtils::GetFullyQualifiedDIEName(const DebugInfoEntry* entry,
BString& _name)
{
// If we don't seem to have a name but a specification, return the
// specification's name.
if (entry->Name() == NULL) {
if (DebugInfoEntry* specification = entry->Specification())
entry = specification;
}
_name.Truncate(0);
// Get the namespace, if any.
DebugInfoEntry* parent = entry->Parent();
while (parent != NULL) {
if (parent->IsNamespace()) {
GetFullyQualifiedDIEName(parent, _name);
break;
}
parent = parent->Parent();
}
BString name;
GetFullDIEName(entry, name);
if (name.Length() == 0)
return;
if (_name.Length() > 0) {
_name << "::" << name;
} else
_name = name;
}

View File

@ -0,0 +1,27 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef DWARF_UTILS_H
#define DWARF_UTILS_H
#include "DebugInfoEntries.h"
class BString;
class DebugInfoEntry;
class DwarfUtils {
public:
static void GetDIEName(const DebugInfoEntry* entry,
BString& _name);
static void GetFullDIEName(const DebugInfoEntry* entry,
BString& _name);
static void GetFullyQualifiedDIEName(
const DebugInfoEntry* entry,
BString& _name);
};
#endif // DWARF_UTILS_H

View File

@ -8,6 +8,7 @@ UsePrivateSystemHeaders ;
SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) ] ; SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) ] ;
SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) elf ] ; SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) elf ] ;
SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) types ] ;
MergeObject Debugger_dwarf.o MergeObject Debugger_dwarf.o
@ -20,6 +21,7 @@ MergeObject Debugger_dwarf.o
DebugInfoEntry.cpp DebugInfoEntry.cpp
DwarfFile.cpp DwarfFile.cpp
DwarfManager.cpp DwarfManager.cpp
DwarfUtils.cpp
SourceLanguageInfo.cpp SourceLanguageInfo.cpp
TagNames.cpp TagNames.cpp
; ;

View File

@ -76,6 +76,26 @@ ElfSection::Unload()
} }
// #pragma mark - ElfSegment
ElfSegment::ElfSegment(off_t fileOffset, off_t fileSize,
target_addr_t loadAddress, target_size_t loadSize, bool writable)
:
fFileOffset(fileOffset),
fFileSize(fileSize),
fLoadAddress(loadAddress),
fLoadSize(loadSize),
fWritable(writable)
{
}
ElfSegment::~ElfSegment()
{
}
// #pragma mark - ElfFile // #pragma mark - ElfFile
@ -90,6 +110,9 @@ ElfFile::ElfFile()
ElfFile::~ElfFile() ElfFile::~ElfFile()
{ {
while (ElfSegment* segment = fSegments.RemoveHead())
delete segment;
while (ElfSection* section = fSections.RemoveHead()) while (ElfSection* section = fSections.RemoveHead())
delete section; delete section;
@ -148,8 +171,7 @@ printf("fFileSize: %lld\n", fFileSize);
printf("sectionHeaderTable: %lld\n", sectionHeadersOffset); printf("sectionHeaderTable: %lld\n", sectionHeadersOffset);
// read the section header table // read the section header table
uint8* sectionHeaderTable uint8* sectionHeaderTable = (uint8*)malloc(sectionHeaderTableSize);
= (uint8*)malloc(sectionHeaderTableSize);
if (sectionHeaderTable == NULL) if (sectionHeaderTable == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
MemoryDeleter sectionHeaderTableDeleter(sectionHeaderTable); MemoryDeleter sectionHeaderTableDeleter(sectionHeaderTable);
@ -202,6 +224,49 @@ printf("sectionStrings: %ld\n", stringSectionHeader->sh_offset);
fSections.Add(section); fSections.Add(section);
} }
// check program header table values
off_t programHeadersOffset = fElfHeader->e_phoff;
size_t programHeaderSize = fElfHeader->e_phentsize;
int segmentCount = fElfHeader->e_phnum;
size_t programHeaderTableSize = programHeaderSize * segmentCount;
if (!_CheckRange(programHeadersOffset, programHeaderTableSize)) {
fprintf(stderr, "\"%s\": Invalid ELF header\n", fileName);
return B_BAD_DATA;
}
printf("programHeaderTable: %lld\n", programHeadersOffset);
// read the program header table
uint8* programHeaderTable = (uint8*)malloc(programHeaderTableSize);
if (programHeaderTable == NULL)
return B_NO_MEMORY;
MemoryDeleter programHeaderTableDeleter(programHeaderTable);
bytesRead = pread(fFD, programHeaderTable, programHeaderTableSize,
programHeadersOffset);
if (bytesRead != (ssize_t)programHeaderTableSize)
return bytesRead < 0 ? errno : B_ERROR;
// read the program headers and create ElfSegment objects
for (int i = 0; i < segmentCount; i++) {
Elf32_Phdr* programHeader = (Elf32_Phdr*)(programHeaderTable
+ i * programHeaderSize);
// skip program headers we aren't interested in or that are invalid
if (programHeader->p_type != PT_LOAD || programHeader->p_filesz == 0
|| programHeader->p_memsz == 0
|| !_CheckRange(programHeader->p_offset, programHeader->p_filesz)) {
continue;
}
// create an ElfSegment
ElfSegment* segment = new(std::nothrow) ElfSegment(
programHeader->p_offset, programHeader->p_filesz,
programHeader->p_vaddr, programHeader->p_memsz,
(programHeader->p_flags & PF_WRITE) != 0);
if (segment == NULL)
return B_NO_MEMORY;
fSegments.Add(segment);
}
return B_OK; return B_OK;
} }
@ -227,6 +292,32 @@ ElfFile::PutSection(ElfSection* section)
} }
ElfSegment*
ElfFile::TextSegment() const
{
for (SegmentList::ConstIterator it = fSegments.GetIterator();
ElfSegment* segment = it.Next();) {
if (!segment->IsWritable())
return segment;
}
return NULL;
}
ElfSegment*
ElfFile::DataSegment() const
{
for (SegmentList::ConstIterator it = fSegments.GetIterator();
ElfSegment* segment = it.Next();) {
if (segment->IsWritable())
return segment;
}
return NULL;
}
bool bool
ElfFile::_CheckRange(off_t offset, off_t size) const ElfFile::_CheckRange(off_t offset, off_t size) const
{ {
@ -243,5 +334,8 @@ ElfFile::_CheckElfHeader() const
&& fElfHeader->e_shnum > 0 && fElfHeader->e_shnum > 0
&& fElfHeader->e_shentsize >= sizeof(struct Elf32_Shdr) && fElfHeader->e_shentsize >= sizeof(struct Elf32_Shdr)
&& fElfHeader->e_shstrndx != SHN_UNDEF && fElfHeader->e_shstrndx != SHN_UNDEF
&& fElfHeader->e_shstrndx < fElfHeader->e_shnum; && fElfHeader->e_shstrndx < fElfHeader->e_shnum
&& fElfHeader->e_phoff > 0
&& fElfHeader->e_phnum > 0
&& fElfHeader->e_phentsize >= sizeof(struct Elf32_Phdr);
} }

View File

@ -12,6 +12,8 @@
#include <elf32.h> #include <elf32.h>
#include <util/DoublyLinkedList.h> #include <util/DoublyLinkedList.h>
#include "Types.h"
class ElfSection : public DoublyLinkedListLinkImpl<ElfSection> { class ElfSection : public DoublyLinkedListLinkImpl<ElfSection> {
public: public:
@ -37,6 +39,28 @@ private:
}; };
class ElfSegment : public DoublyLinkedListLinkImpl<ElfSegment> {
public:
ElfSegment(off_t fileOffset, off_t fileSize,
target_addr_t loadAddress,
target_size_t loadSize, bool writable);
~ElfSegment();
off_t FileOffset() const { return fFileOffset; }
off_t FileSize() const { return fFileSize; }
target_addr_t LoadAddress() const { return fLoadAddress; }
target_size_t LoadSize() const { return fLoadSize; }
bool IsWritable() const { return fWritable; }
private:
off_t fFileOffset;
off_t fFileSize;
target_addr_t fLoadAddress;
target_size_t fLoadSize;
bool fWritable;
};
class ElfFile { class ElfFile {
public: public:
ElfFile(); ElfFile();
@ -44,11 +68,17 @@ public:
status_t Init(const char* fileName); status_t Init(const char* fileName);
int FD() const { return fFD; }
ElfSection* GetSection(const char* name); ElfSection* GetSection(const char* name);
void PutSection(ElfSection* section); void PutSection(ElfSection* section);
ElfSegment* TextSegment() const;
ElfSegment* DataSegment() const;
private: private:
typedef DoublyLinkedList<ElfSection> SectionList; typedef DoublyLinkedList<ElfSection> SectionList;
typedef DoublyLinkedList<ElfSegment> SegmentList;
private: private:
bool _CheckRange(off_t offset, off_t size) const; bool _CheckRange(off_t offset, off_t size) const;
@ -59,6 +89,7 @@ private:
int fFD; int fFD;
Elf32_Ehdr* fElfHeader; Elf32_Ehdr* fElfHeader;
SectionList fSections; SectionList fSections;
SegmentList fSegments;
}; };

View File

@ -8,7 +8,7 @@
#include <Font.h> #include <Font.h>
#include <View.h> #include <View.h>
#include "ArchitectureTypes.h" #include "Types.h"
class Breakpoint; class Breakpoint;

View File

@ -8,7 +8,7 @@
#include <ObjectList.h> #include <ObjectList.h>
#include <Referenceable.h> #include <Referenceable.h>
#include "ArchitectureTypes.h" #include "Types.h"
enum user_breakpoint_state { enum user_breakpoint_state {

View File

@ -8,7 +8,7 @@
#include <image.h> #include <image.h>
#include <String.h> #include <String.h>
#include "ArchitectureTypes.h" #include "Types.h"
class ImageInfo { class ImageInfo {

View File

@ -9,7 +9,7 @@
#include <Referenceable.h> #include <Referenceable.h>
#include "ArchitectureTypes.h" #include "Types.h"
enum stack_frame_type { enum stack_frame_type {

View File

@ -7,9 +7,9 @@
#include <Referenceable.h> #include <Referenceable.h>
#include "ArchitectureTypes.h"
#include "SourceLocation.h" #include "SourceLocation.h"
#include "TargetAddressRange.h" #include "TargetAddressRange.h"
#include "Types.h"
class Statement : public Referenceable { class Statement : public Referenceable {

View File

@ -7,7 +7,7 @@
#include <String.h> #include <String.h>
#include "ArchitectureTypes.h" #include "Types.h"
class SymbolInfo { class SymbolInfo {

View File

@ -5,7 +5,9 @@
#ifndef TARGET_ADDRESS_RANGE_H #ifndef TARGET_ADDRESS_RANGE_H
#define TARGET_ADDRESS_RANGE_H #define TARGET_ADDRESS_RANGE_H
#include "ArchitectureTypes.h" #include <algorithm>
#include "Types.h"
class TargetAddressRange { class TargetAddressRange {
@ -78,6 +80,20 @@ public:
return Contains(other.Start()) || other.Contains(Start()); return Contains(other.Start()) || other.Contains(Start());
} }
TargetAddressRange& operator|=(const TargetAddressRange& other)
{
if (fSize == 0)
return *this = other;
if (other.fSize > 0) {
target_addr_t end = std::max(End(), other.End());
fStart = std::min(fStart, other.fStart);
fSize = end - fStart;
}
return *this;
}
private: private:
target_addr_t fStart; target_addr_t fStart;
target_size_t fSize; target_size_t fSize;

View File

@ -0,0 +1,91 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "TargetAddressRangeList.h"
#include <algorithm>
TargetAddressRangeList::TargetAddressRangeList()
{
}
TargetAddressRangeList::TargetAddressRangeList(const TargetAddressRange& range)
{
AddRange(range);
}
TargetAddressRangeList::TargetAddressRangeList(
const TargetAddressRangeList& other)
:
fRanges(other.fRanges)
{
}
void
TargetAddressRangeList::Clear()
{
fRanges.Clear();
}
bool
TargetAddressRangeList::AddRange(const TargetAddressRange& range)
{
return fRanges.Add(range);
}
int32
TargetAddressRangeList::CountRanges() const
{
return fRanges.Size();
}
TargetAddressRange
TargetAddressRangeList::RangeAt(int32 index) const
{
return index >= 0 && index < fRanges.Size()
? fRanges[index] : TargetAddressRange();
}
target_addr_t
TargetAddressRangeList::LowestAddress() const
{
int32 count = fRanges.Size();
if (count == 0)
return 0;
target_addr_t lowest = fRanges[0].Start();
for (int32 i = 0; i < count; i++)
lowest = std::min(lowest, fRanges[i].Start());
return lowest;
}
TargetAddressRange
TargetAddressRangeList::CoveringRange() const
{
TargetAddressRange range;
int32 count = fRanges.Size();
for (int32 i = 0; i < count; i++)
range |= fRanges[i];
return range;
}
TargetAddressRangeList&
TargetAddressRangeList::operator=(const TargetAddressRangeList& other)
{
fRanges = other.fRanges;
return *this;
}

View File

@ -0,0 +1,51 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef TARGET_ADDRESS_RANGE_LIST_H
#define TARGET_ADDRESS_RANGE_LIST_H
#include <Referenceable.h>
#include "Array.h"
#include "TargetAddressRange.h"
class TargetAddressRangeList : public Referenceable {
public:
TargetAddressRangeList();
TargetAddressRangeList(
const TargetAddressRange& range);
TargetAddressRangeList(
const TargetAddressRangeList& other);
void Clear();
bool AddRange(const TargetAddressRange& range);
inline bool AddRange(target_addr_t start,
target_size_t size);
int32 CountRanges() const;
TargetAddressRange RangeAt(int32 index) const;
target_addr_t LowestAddress() const;
TargetAddressRange CoveringRange() const;
TargetAddressRangeList& operator=(
const TargetAddressRangeList& other);
private:
typedef Array<TargetAddressRange> RangeArray;
private:
RangeArray fRanges;
};
bool
TargetAddressRangeList::AddRange(target_addr_t start, target_size_t size)
{
return AddRange(TargetAddressRange(start, size));
}
#endif // TARGET_ADDRESS_RANGE_LIST_H