* 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:
parent
e602845c35
commit
5b60969c5c
|
@ -14,6 +14,7 @@ template<typename Element>
|
|||
class Array {
|
||||
public:
|
||||
inline Array();
|
||||
Array(const Array<Element>& other);
|
||||
~Array();
|
||||
|
||||
inline int Size() const { return fSize; }
|
||||
|
@ -34,6 +35,8 @@ public:
|
|||
inline Element& operator[](int index);
|
||||
inline const Element& operator[](int index) const;
|
||||
|
||||
Array<Element>& operator=(const Array<Element>& other);
|
||||
|
||||
private:
|
||||
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>
|
||||
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>
|
||||
bool
|
||||
Array<Element>::_Resize(int index, int delta)
|
||||
|
|
|
@ -13,6 +13,7 @@ SEARCH_SOURCE += [ FDirName $(SUBDIR) debugger_interface ] ;
|
|||
SEARCH_SOURCE += [ FDirName $(SUBDIR) elf ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) gui team_window ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) model ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) types ] ;
|
||||
|
||||
local debugAnalyzerSources
|
||||
= [ FDirName $(HAIKU_TOP) src apps debuganalyzer ] ;
|
||||
|
@ -22,6 +23,7 @@ SubDirHdrs [ FDirName $(HAIKU_TOP) src bin debug ] ;
|
|||
SubDirHdrs [ FDirName $(debugAnalyzerSources) gui ] ;
|
||||
|
||||
SourceHdrs
|
||||
DwarfFunctionDebugInfo.cpp
|
||||
DwarfImageDebugInfo.cpp
|
||||
DwarfTeamDebugInfo.cpp
|
||||
: [ FDirName $(SUBDIR) dwarf ]
|
||||
|
@ -49,6 +51,7 @@ Application Debugger :
|
|||
BasicFunctionDebugInfo.cpp
|
||||
DebuggerImageDebugInfo.cpp
|
||||
DebuggerTeamDebugInfo.cpp
|
||||
DwarfFunctionDebugInfo.cpp
|
||||
DwarfImageDebugInfo.cpp
|
||||
DwarfTeamDebugInfo.cpp
|
||||
FunctionDebugInfo.cpp
|
||||
|
@ -90,6 +93,9 @@ Application Debugger :
|
|||
Thread.cpp
|
||||
ThreadInfo.cpp
|
||||
|
||||
# types
|
||||
TargetAddressRangeList.cpp
|
||||
|
||||
:
|
||||
<nogrist>Debugger_demangler.o
|
||||
<nogrist>Debugger_disasm_x86.o
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
#include <Referenceable.h>
|
||||
|
||||
#include "ArchitectureTypes.h"
|
||||
#include "Types.h"
|
||||
|
||||
|
||||
class CpuState;
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include <Referenceable.h>
|
||||
#include <Variant.h>
|
||||
|
||||
#include "ArchitectureTypes.h"
|
||||
#include "Types.h"
|
||||
|
||||
|
||||
class Register;
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
#include <String.h>
|
||||
|
||||
#include "ArchitectureTypes.h"
|
||||
#include "Types.h"
|
||||
|
||||
|
||||
enum instruction_type {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
#include <String.h>
|
||||
|
||||
#include "ArchitectureTypes.h"
|
||||
#include "Types.h"
|
||||
|
||||
|
||||
class DisassemblerX86 {
|
||||
|
|
|
@ -7,6 +7,7 @@ UseHeaders [ LibraryHeaders udis86 ] ;
|
|||
UseHeaders [ LibraryHeaders [ FDirName udis86 libudis86 ] ] ;
|
||||
|
||||
SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) ] ;
|
||||
SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) $(DOTDOT) types ] ;
|
||||
|
||||
|
||||
MergeObject Debugger_disasm_x86.o
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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
|
|
@ -6,6 +6,7 @@
|
|||
#include "DwarfImageDebugInfo.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <new>
|
||||
|
||||
|
@ -16,6 +17,9 @@
|
|||
#include "DebugInfoEntries.h"
|
||||
#include "Dwarf.h"
|
||||
#include "DwarfFile.h"
|
||||
#include "DwarfFunctionDebugInfo.h"
|
||||
#include "DwarfUtils.h"
|
||||
#include "ElfFile.h"
|
||||
|
||||
|
||||
DwarfImageDebugInfo::DwarfImageDebugInfo(const ImageInfo& imageInfo,
|
||||
|
@ -23,7 +27,9 @@ DwarfImageDebugInfo::DwarfImageDebugInfo(const ImageInfo& imageInfo,
|
|||
:
|
||||
fImageInfo(imageInfo),
|
||||
fArchitecture(architecture),
|
||||
fFile(file)
|
||||
fFile(file),
|
||||
fTextSegment(NULL),
|
||||
fRelocationDelta(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -36,6 +42,12 @@ DwarfImageDebugInfo::~DwarfImageDebugInfo()
|
|||
status_t
|
||||
DwarfImageDebugInfo::Init()
|
||||
{
|
||||
fTextSegment = fFile->GetElfFile()->TextSegment();
|
||||
if (fTextSegment == NULL)
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
|
||||
fRelocationDelta = fImageInfo.TextBase() - fTextSegment->LoadAddress();
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
@ -48,22 +60,94 @@ printf(" %ld compilation units\n", fFile->CountCompilationUnits());
|
|||
|
||||
for (int32 i = 0; CompilationUnit* unit = fFile->CompilationUnitAt(i);
|
||||
i++) {
|
||||
printf(" %s:\n", unit->UnitEntry()->Name());
|
||||
DIECompileUnitBase* unitEntry = unit->UnitEntry();
|
||||
// printf(" %s:\n", unitEntry->Name());
|
||||
// printf(" address ranges:\n");
|
||||
// TargetAddressRangeList* rangeList = unitEntry->AddressRanges();
|
||||
// if (rangeList != NULL) {
|
||||
// int32 count = rangeList->CountRanges();
|
||||
// for (int32 i = 0; i < count; i++) {
|
||||
// TargetAddressRange range = rangeList->RangeAt(i);
|
||||
// printf(" %#llx - %#llx\n", range.Start(), range.End());
|
||||
// }
|
||||
// } else {
|
||||
// printf(" %#llx - %#llx\n", (target_addr_t)unitEntry->LowPC(),
|
||||
// (target_addr_t)unitEntry->HighPC());
|
||||
// }
|
||||
|
||||
// printf(" functions:\n");
|
||||
for (DebugInfoEntryList::ConstIterator it
|
||||
= unit->UnitEntry()->OtherChildren().GetIterator();
|
||||
= unitEntry->OtherChildren().GetIterator();
|
||||
DebugInfoEntry* entry = it.Next();) {
|
||||
if (entry->Tag() != DW_TAG_subprogram)
|
||||
continue;
|
||||
|
||||
DIESubprogram* subprogramEntry = static_cast<DIESubprogram*>(entry);
|
||||
printf(" subprogram entry: %p, name: %s, declaration: %d\n",
|
||||
subprogramEntry, subprogramEntry->Name(),
|
||||
subprogramEntry->IsDeclaration());
|
||||
|
||||
// ignore declarations, prototypes, and inlined functions
|
||||
if (subprogramEntry->IsDeclaration()
|
||||
|| subprogramEntry->IsPrototyped()
|
||||
|| subprogramEntry->Inline() == DW_INL_inlined
|
||||
|| subprogramEntry->Inline() == DW_INL_declared_inlined
|
||||
|| subprogramEntry->AbstractOrigin() != NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// get the name
|
||||
BString name;
|
||||
DwarfUtils::GetFullyQualifiedDIEName(subprogramEntry, name);
|
||||
if (name.Length() == 0)
|
||||
continue;
|
||||
|
||||
// get the address ranges
|
||||
TargetAddressRangeList* rangeList
|
||||
= subprogramEntry->AddressRanges();
|
||||
Reference<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;
|
||||
}
|
||||
|
||||
|
@ -82,8 +166,25 @@ status_t
|
|||
DwarfImageDebugInfo::LoadSourceCode(FunctionDebugInfo* function,
|
||||
SourceCode*& _sourceCode)
|
||||
{
|
||||
// TODO:...
|
||||
return B_UNSUPPORTED;
|
||||
// TODO: Load the actual source code!
|
||||
|
||||
static const target_size_t kMaxBufferSize = 64 * 1024;
|
||||
target_size_t bufferSize = std::min(function->Size(), kMaxBufferSize);
|
||||
void* buffer = malloc(bufferSize);
|
||||
if (buffer == NULL)
|
||||
return B_NO_MEMORY;
|
||||
MemoryDeleter bufferDeleter(buffer);
|
||||
|
||||
// read the function code
|
||||
target_addr_t functionOffset = function->Address() - fRelocationDelta
|
||||
- fTextSegment->LoadAddress() + fTextSegment->FileOffset();
|
||||
ssize_t bytesRead = pread(fFile->GetElfFile()->FD(), buffer, bufferSize,
|
||||
functionOffset);
|
||||
if (bytesRead < 0)
|
||||
return bytesRead;
|
||||
|
||||
return fArchitecture->DisassembleCode(function, buffer, bytesRead,
|
||||
_sourceCode);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
class Architecture;
|
||||
class DwarfFile;
|
||||
class ElfSegment;
|
||||
|
||||
|
||||
class DwarfImageDebugInfo : public SpecificImageDebugInfo {
|
||||
|
@ -22,6 +23,9 @@ public:
|
|||
|
||||
status_t Init();
|
||||
|
||||
target_addr_t RelocationDelta() const
|
||||
{ return fRelocationDelta; }
|
||||
|
||||
virtual status_t GetFunctions(
|
||||
BObjectList<FunctionDebugInfo>& functions);
|
||||
virtual status_t CreateFrame(Image* image,
|
||||
|
@ -39,6 +43,8 @@ private:
|
|||
ImageInfo fImageInfo;
|
||||
Architecture* fArchitecture;
|
||||
DwarfFile* fFile;
|
||||
ElfSegment* fTextSegment;
|
||||
target_addr_t fRelocationDelta;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
#include <Referenceable.h>
|
||||
#include <util/DoublyLinkedList.h>
|
||||
|
||||
#include "ArchitectureTypes.h"
|
||||
#include "SourceLocation.h"
|
||||
#include "Types.h"
|
||||
|
||||
|
||||
enum function_source_state {
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
#include <ObjectList.h>
|
||||
#include <Referenceable.h>
|
||||
|
||||
#include "ArchitectureTypes.h"
|
||||
#include "ImageInfo.h"
|
||||
#include "Types.h"
|
||||
|
||||
|
||||
class Architecture;
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include <ObjectList.h>
|
||||
#include <Referenceable.h>
|
||||
|
||||
#include "ArchitectureTypes.h"
|
||||
#include "Types.h"
|
||||
|
||||
|
||||
class Architecture;
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
|
||||
#include <debugger.h>
|
||||
|
||||
#include "ArchitectureTypes.h"
|
||||
#include "ImageInfo.h"
|
||||
#include "Types.h"
|
||||
|
||||
|
||||
class CpuState;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include "AttributeClasses.h"
|
||||
#include "DwarfTypes.h"
|
||||
#include "TargetAddressRangeList.h"
|
||||
|
||||
|
||||
class DebugInfoEntry;
|
||||
|
@ -21,6 +22,7 @@ struct AttributeValue {
|
|||
} block;
|
||||
uint64 constant;
|
||||
bool flag;
|
||||
TargetAddressRangeList* rangeList;
|
||||
dwarf_off_t pointer;
|
||||
DebugInfoEntry* reference;
|
||||
const char* string;
|
||||
|
@ -30,6 +32,100 @@ struct AttributeValue {
|
|||
uint8 attributeClass;
|
||||
bool isSigned;
|
||||
|
||||
AttributeValue()
|
||||
:
|
||||
attributeClass(ATTRIBUTE_CLASS_UNKNOWN)
|
||||
{
|
||||
}
|
||||
|
||||
~AttributeValue()
|
||||
{
|
||||
Unset();
|
||||
}
|
||||
|
||||
void SetToAddress(dwarf_addr_t address)
|
||||
{
|
||||
Unset();
|
||||
attributeClass = ATTRIBUTE_CLASS_ADDRESS;
|
||||
this->address = address;
|
||||
}
|
||||
|
||||
void SetToBlock(const void* data, dwarf_size_t length)
|
||||
{
|
||||
Unset();
|
||||
attributeClass = ATTRIBUTE_CLASS_BLOCK;
|
||||
block.data = data;
|
||||
block.length = length;
|
||||
}
|
||||
|
||||
void SetToConstant(uint64 value, bool isSigned)
|
||||
{
|
||||
Unset();
|
||||
attributeClass = ATTRIBUTE_CLASS_CONSTANT;
|
||||
this->constant = value;
|
||||
this->isSigned = isSigned;
|
||||
}
|
||||
|
||||
void SetToFlag(bool value)
|
||||
{
|
||||
Unset();
|
||||
attributeClass = ATTRIBUTE_CLASS_FLAG;
|
||||
this->flag = value;
|
||||
}
|
||||
|
||||
void SetToLinePointer(dwarf_off_t value)
|
||||
{
|
||||
Unset();
|
||||
attributeClass = ATTRIBUTE_CLASS_LINEPTR;
|
||||
this->pointer = value;
|
||||
}
|
||||
|
||||
void SetToLocationListPointer(dwarf_off_t value)
|
||||
{
|
||||
Unset();
|
||||
attributeClass = ATTRIBUTE_CLASS_LOCLISTPTR;
|
||||
this->pointer = value;
|
||||
}
|
||||
|
||||
void SetToMacroPointer(dwarf_off_t value)
|
||||
{
|
||||
Unset();
|
||||
attributeClass = ATTRIBUTE_CLASS_MACPTR;
|
||||
this->pointer = value;
|
||||
}
|
||||
|
||||
void SetToRangeList(TargetAddressRangeList* rangeList)
|
||||
{
|
||||
Unset();
|
||||
attributeClass = ATTRIBUTE_CLASS_RANGELISTPTR;
|
||||
this->rangeList = rangeList;
|
||||
if (rangeList != NULL)
|
||||
rangeList->AddReference();
|
||||
}
|
||||
|
||||
void SetToReference(DebugInfoEntry* entry)
|
||||
{
|
||||
Unset();
|
||||
attributeClass = ATTRIBUTE_CLASS_REFERENCE;
|
||||
this->reference = entry;
|
||||
}
|
||||
|
||||
void SetToString(const char* string)
|
||||
{
|
||||
Unset();
|
||||
attributeClass = ATTRIBUTE_CLASS_STRING;
|
||||
this->string = string;
|
||||
}
|
||||
|
||||
void Unset()
|
||||
{
|
||||
if (attributeClass == ATTRIBUTE_CLASS_RANGELISTPTR
|
||||
&& rangeList != NULL) {
|
||||
rangeList->RemoveReference();
|
||||
}
|
||||
attributeClass = ATTRIBUTE_CLASS_UNKNOWN;
|
||||
}
|
||||
|
||||
const char* ToString(char* buffer, size_t size);
|
||||
};
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ DIECompileUnitBase::DIECompileUnitBase()
|
|||
fStatementListOffset(0),
|
||||
fMacroInfoOffset(0),
|
||||
// TODO: Is 0 a good invalid offset?
|
||||
fAddressRanges(NULL),
|
||||
fBaseTypesUnit(NULL),
|
||||
fLanguage(0),
|
||||
fIdentifierCase(0),
|
||||
|
@ -32,6 +33,13 @@ DIECompileUnitBase::DIECompileUnitBase()
|
|||
}
|
||||
|
||||
|
||||
DIECompileUnitBase::~DIECompileUnitBase()
|
||||
{
|
||||
if (fAddressRanges != NULL)
|
||||
fAddressRanges->RemoveReference();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
DIECompileUnitBase::InitAfterAttributes(DebugInfoEntryInitInfo& info)
|
||||
{
|
||||
|
@ -65,6 +73,16 @@ DIECompileUnitBase::Name() const
|
|||
}
|
||||
|
||||
|
||||
dwarf_addr_t
|
||||
DIECompileUnitBase::AddressRangeBase() const
|
||||
{
|
||||
if (fAddressRanges != NULL)
|
||||
return fAddressRanges->LowestAddress();
|
||||
|
||||
return fLowPC;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
DIECompileUnitBase::AddChild(DebugInfoEntry* child)
|
||||
{
|
||||
|
@ -175,6 +193,22 @@ DIECompileUnitBase::AddAttribute_use_UTF8(uint16 attributeName,
|
|||
}
|
||||
|
||||
|
||||
status_t
|
||||
DIECompileUnitBase::AddAttribute_ranges(uint16 attributeName,
|
||||
const AttributeValue& value)
|
||||
{
|
||||
if (fAddressRanges != NULL)
|
||||
fAddressRanges->RemoveReference();
|
||||
|
||||
fAddressRanges = value.rangeList;
|
||||
|
||||
if (fAddressRanges != NULL)
|
||||
fAddressRanges->AddReference();
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - DIEType
|
||||
|
||||
|
||||
|
@ -285,6 +319,13 @@ DIEDeclaredType::Description() const
|
|||
}
|
||||
|
||||
|
||||
DebugInfoEntry*
|
||||
DIEDeclaredType::AbstractOrigin() const
|
||||
{
|
||||
return fAbstractOrigin;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
DIEDeclaredType::AddAttribute_accessibility(uint16 attributeName,
|
||||
const AttributeValue& value)
|
||||
|
@ -359,6 +400,20 @@ DIECompoundType::DIECompoundType()
|
|||
}
|
||||
|
||||
|
||||
bool
|
||||
DIECompoundType::IsNamespace() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
DebugInfoEntry*
|
||||
DIECompoundType::Specification() const
|
||||
{
|
||||
return fSpecification;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
DIECompoundType::AddChild(DebugInfoEntry* child)
|
||||
{
|
||||
|
@ -569,6 +624,13 @@ DIEArrayType::InitAfterHierarchy(DebugInfoEntryInitInfo& info)
|
|||
}
|
||||
|
||||
|
||||
DebugInfoEntry*
|
||||
DIEArrayType::Specification() const
|
||||
{
|
||||
return fSpecification;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
DIEArrayType::AddChild(DebugInfoEntry* child)
|
||||
{
|
||||
|
@ -672,6 +734,13 @@ DIEEnumerationType::Tag() const
|
|||
}
|
||||
|
||||
|
||||
DebugInfoEntry*
|
||||
DIEEnumerationType::Specification() const
|
||||
{
|
||||
return fSpecification;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
DIEEnumerationType::AddChild(DebugInfoEntry* child)
|
||||
{
|
||||
|
@ -809,6 +878,13 @@ DIEPointerType::Tag() const
|
|||
}
|
||||
|
||||
|
||||
DebugInfoEntry*
|
||||
DIEPointerType::Specification() const
|
||||
{
|
||||
return fSpecification;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
DIEPointerType::AddAttribute_specification(uint16 attributeName,
|
||||
const AttributeValue& value)
|
||||
|
@ -1461,10 +1537,27 @@ DIEPackedType::Tag() const
|
|||
|
||||
|
||||
DIESubprogram::DIESubprogram()
|
||||
:
|
||||
fLowPC(0),
|
||||
fHighPC(0),
|
||||
fAddressRanges(NULL),
|
||||
fSpecification(NULL),
|
||||
fAbstractOrigin(NULL),
|
||||
fReturnType(NULL),
|
||||
fAddressClass(0),
|
||||
fPrototyped(false),
|
||||
fInline(DW_INL_not_inlined)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
DIESubprogram::~DIESubprogram()
|
||||
{
|
||||
if (fAddressRanges != NULL)
|
||||
fAddressRanges->RemoveReference();
|
||||
}
|
||||
|
||||
|
||||
uint16
|
||||
DIESubprogram::Tag() const
|
||||
{
|
||||
|
@ -1472,6 +1565,111 @@ DIESubprogram::Tag() const
|
|||
}
|
||||
|
||||
|
||||
DebugInfoEntry*
|
||||
DIESubprogram::Specification() const
|
||||
{
|
||||
return fSpecification;
|
||||
}
|
||||
|
||||
|
||||
|
||||
DebugInfoEntry*
|
||||
DIESubprogram::AbstractOrigin() const
|
||||
{
|
||||
return fAbstractOrigin;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
DIESubprogram::AddAttribute_low_pc(uint16 attributeName,
|
||||
const AttributeValue& value)
|
||||
{
|
||||
fLowPC = value.address;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
DIESubprogram::AddAttribute_high_pc(uint16 attributeName,
|
||||
const AttributeValue& value)
|
||||
{
|
||||
fHighPC = value.address;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
DIESubprogram::AddAttribute_ranges(uint16 attributeName,
|
||||
const AttributeValue& value)
|
||||
{
|
||||
if (fAddressRanges != NULL)
|
||||
fAddressRanges->RemoveReference();
|
||||
|
||||
fAddressRanges = value.rangeList;
|
||||
|
||||
if (fAddressRanges != NULL)
|
||||
fAddressRanges->AddReference();
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
DIESubprogram::AddAttribute_specification(uint16 attributeName,
|
||||
const AttributeValue& value)
|
||||
{
|
||||
fSpecification = dynamic_cast<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
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -136,6 +136,7 @@
|
|||
class DIECompileUnitBase : public DebugInfoEntry {
|
||||
public:
|
||||
DIECompileUnitBase();
|
||||
~DIECompileUnitBase();
|
||||
|
||||
virtual status_t InitAfterAttributes(
|
||||
DebugInfoEntryInitInfo& info);
|
||||
|
@ -145,6 +146,12 @@ public:
|
|||
const DebugInfoEntryList& Types() const { return fTypes; }
|
||||
const DebugInfoEntryList& OtherChildren() const
|
||||
{ return fOtherChildren; }
|
||||
TargetAddressRangeList* AddressRanges() const
|
||||
{ return fAddressRanges; }
|
||||
|
||||
dwarf_addr_t LowPC() const { return fLowPC; }
|
||||
dwarf_addr_t HighPC() const { return fHighPC; }
|
||||
dwarf_addr_t AddressRangeBase() const;
|
||||
|
||||
virtual status_t AddChild(DebugInfoEntry* child);
|
||||
|
||||
|
@ -171,10 +178,10 @@ public:
|
|||
const AttributeValue& value);
|
||||
virtual status_t AddAttribute_use_UTF8(uint16 attributeName,
|
||||
const AttributeValue& value);
|
||||
virtual status_t AddAttribute_ranges(uint16 attributeName,
|
||||
const AttributeValue& value);
|
||||
|
||||
//TODO:
|
||||
// virtual status_t AddAttribute_ranges(uint16 attributeName,
|
||||
// const AttributeValue& value);
|
||||
// virtual status_t AddAttribute_segment(uint16 attributeName,
|
||||
// const AttributeValue& value);
|
||||
|
||||
|
@ -187,6 +194,7 @@ protected:
|
|||
dwarf_addr_t fHighPC;
|
||||
dwarf_off_t fStatementListOffset;
|
||||
dwarf_off_t fMacroInfoOffset;
|
||||
TargetAddressRangeList* fAddressRanges;
|
||||
DIECompileUnitBase* fBaseTypesUnit;
|
||||
DebugInfoEntryList fTypes;
|
||||
DebugInfoEntryList fOtherChildren;
|
||||
|
@ -251,6 +259,7 @@ public:
|
|||
DIEDeclaredType();
|
||||
|
||||
virtual const char* Description() const;
|
||||
virtual DebugInfoEntry* AbstractOrigin() const;
|
||||
|
||||
virtual status_t AddAttribute_accessibility(uint16 attributeName,
|
||||
const AttributeValue& value);
|
||||
|
@ -297,6 +306,10 @@ class DIECompoundType : public DIEDeclaredType {
|
|||
public:
|
||||
DIECompoundType();
|
||||
|
||||
virtual bool IsNamespace() const;
|
||||
|
||||
virtual DebugInfoEntry* Specification() const;
|
||||
|
||||
virtual status_t AddChild(DebugInfoEntry* child);
|
||||
|
||||
virtual status_t AddAttribute_byte_size(uint16 attributeName,
|
||||
|
@ -398,6 +411,8 @@ public:
|
|||
virtual status_t InitAfterHierarchy(
|
||||
DebugInfoEntryInitInfo& info);
|
||||
|
||||
virtual DebugInfoEntry* Specification() const;
|
||||
|
||||
virtual status_t AddChild(DebugInfoEntry* child);
|
||||
|
||||
virtual status_t AddAttribute_ordering(uint16 attributeName,
|
||||
|
@ -453,6 +468,8 @@ public:
|
|||
|
||||
virtual uint16 Tag() const;
|
||||
|
||||
virtual DebugInfoEntry* Specification() const;
|
||||
|
||||
virtual status_t AddChild(DebugInfoEntry* child);
|
||||
|
||||
virtual status_t AddAttribute_bit_stride(uint16 attributeName,
|
||||
|
@ -557,6 +574,8 @@ public:
|
|||
|
||||
virtual uint16 Tag() const;
|
||||
|
||||
virtual DebugInfoEntry* Specification() const;
|
||||
|
||||
virtual status_t AddAttribute_specification(uint16 attributeName,
|
||||
const AttributeValue& value);
|
||||
|
||||
|
@ -990,12 +1009,55 @@ public:
|
|||
class DIESubprogram : public DIEDeclaredNamedBase {
|
||||
public:
|
||||
DIESubprogram();
|
||||
~DIESubprogram();
|
||||
|
||||
virtual uint16 Tag() const;
|
||||
|
||||
virtual DebugInfoEntry* Specification() const;
|
||||
virtual DebugInfoEntry* AbstractOrigin() const;
|
||||
|
||||
TargetAddressRangeList* AddressRanges() const
|
||||
{ return fAddressRanges; }
|
||||
|
||||
dwarf_addr_t LowPC() const { return fLowPC; }
|
||||
dwarf_addr_t HighPC() const { return fHighPC; }
|
||||
|
||||
bool IsPrototyped() const { return fPrototyped; }
|
||||
uint8 Inline() const { return fInline; }
|
||||
|
||||
virtual status_t AddAttribute_low_pc(uint16 attributeName,
|
||||
const AttributeValue& value);
|
||||
virtual status_t AddAttribute_high_pc(uint16 attributeName,
|
||||
const AttributeValue& value);
|
||||
virtual status_t AddAttribute_ranges(uint16 attributeName,
|
||||
const AttributeValue& value);
|
||||
virtual status_t AddAttribute_specification(uint16 attributeName,
|
||||
const AttributeValue& value);
|
||||
virtual status_t AddAttribute_address_class(uint16 attributeName,
|
||||
const AttributeValue& value);
|
||||
virtual status_t AddAttribute_prototyped(uint16 attributeName,
|
||||
const AttributeValue& value);
|
||||
virtual status_t AddAttribute_type(uint16 attributeName,
|
||||
const AttributeValue& value);
|
||||
virtual status_t AddAttribute_inline(uint16 attributeName,
|
||||
const AttributeValue& value);
|
||||
virtual status_t AddAttribute_abstract_origin(
|
||||
uint16 attributeName,
|
||||
const AttributeValue& value);
|
||||
|
||||
protected:
|
||||
dwarf_addr_t fLowPC;
|
||||
dwarf_addr_t fHighPC;
|
||||
TargetAddressRangeList* fAddressRanges;
|
||||
DIESubprogram* fSpecification;
|
||||
DIESubprogram* fAbstractOrigin;
|
||||
DIEType* fReturnType;
|
||||
uint8 fAddressClass;
|
||||
bool fPrototyped;
|
||||
uint8 fInline;
|
||||
|
||||
// TODO:
|
||||
// DW_AT_abstract_origin
|
||||
// DW_AT_address_class
|
||||
// DW_AT_artificial
|
||||
// DW_AT_calling_convention
|
||||
// DW_AT_elemental
|
||||
|
@ -1003,13 +1065,8 @@ public:
|
|||
// DW_AT_explicit
|
||||
// DW_AT_external
|
||||
// DW_AT_frame_base
|
||||
// DW_AT_high_pc
|
||||
// DW_AT_inline
|
||||
// DW_AT_low_pc
|
||||
// DW_AT_object_pointer
|
||||
// DW_AT_prototyped
|
||||
// DW_AT_pure
|
||||
// DW_AT_ranges
|
||||
// DW_AT_recursive
|
||||
// DW_AT_return_addr
|
||||
// DW_AT_segment
|
||||
|
@ -1017,7 +1074,6 @@ public:
|
|||
// DW_AT_start_scope
|
||||
// DW_AT_static_link
|
||||
// DW_AT_trampoline
|
||||
// DW_AT_type
|
||||
// DW_AT_virtuality
|
||||
// DW_AT_vtable_elem_location
|
||||
};
|
||||
|
@ -1160,6 +1216,16 @@ public:
|
|||
|
||||
virtual uint16 Tag() const;
|
||||
|
||||
virtual bool IsNamespace() const;
|
||||
|
||||
const DebugInfoEntryList& Children() const
|
||||
{ return fChildren; }
|
||||
|
||||
virtual status_t AddChild(DebugInfoEntry* child);
|
||||
|
||||
private:
|
||||
DebugInfoEntryList fChildren;
|
||||
|
||||
// TODO:
|
||||
// DW_AT_extension
|
||||
// DW_AT_start_scope
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
|
||||
|
||||
DebugInfoEntry::DebugInfoEntry()
|
||||
:
|
||||
fParent(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -44,6 +46,13 @@ DebugInfoEntry::InitAfterAttributes(DebugInfoEntryInitInfo& info)
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
DebugInfoEntry::SetParent(DebugInfoEntry* parent)
|
||||
{
|
||||
fParent = parent;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
DebugInfoEntry::IsType() const
|
||||
{
|
||||
|
@ -51,13 +60,19 @@ DebugInfoEntry::IsType() const
|
|||
}
|
||||
|
||||
|
||||
bool
|
||||
DebugInfoEntry::IsNamespace() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
const char*
|
||||
DebugInfoEntry::Name() const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
const char*
|
||||
DebugInfoEntry::Description() const
|
||||
{
|
||||
|
@ -65,6 +80,20 @@ DebugInfoEntry::Description() const
|
|||
}
|
||||
|
||||
|
||||
DebugInfoEntry*
|
||||
DebugInfoEntry::Specification() const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
DebugInfoEntry*
|
||||
DebugInfoEntry::AbstractOrigin() const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
DebugInfoEntry::AddChild(DebugInfoEntry* child)
|
||||
{
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#ifndef DEBUG_INFO_ENTRY_H
|
||||
#define DEBUG_INFO_ENTRY_H
|
||||
|
||||
#include <String.h>
|
||||
|
||||
#include <util/DoublyLinkedList.h>
|
||||
|
||||
#include "DwarfTypes.h"
|
||||
|
@ -44,10 +46,18 @@ public:
|
|||
|
||||
virtual uint16 Tag() const = 0;
|
||||
|
||||
DebugInfoEntry* Parent() const { return fParent; }
|
||||
void SetParent(DebugInfoEntry* parent);
|
||||
|
||||
virtual bool IsType() const;
|
||||
virtual bool IsNamespace() const;
|
||||
// a namespace-like thingy (namespace,
|
||||
// class, ...)
|
||||
|
||||
virtual const char* Name() const;
|
||||
virtual const char* Description() const;
|
||||
virtual DebugInfoEntry* Specification() const;
|
||||
virtual DebugInfoEntry* AbstractOrigin() const;
|
||||
|
||||
virtual status_t AddChild(DebugInfoEntry* child);
|
||||
|
||||
|
@ -154,6 +164,9 @@ protected:
|
|||
status_t SetConstantAttributeValue(
|
||||
ConstantAttributeValue& toSet,
|
||||
const AttributeValue& value);
|
||||
|
||||
protected:
|
||||
DebugInfoEntry* fParent;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "DataReader.h"
|
||||
#include "ElfFile.h"
|
||||
#include "TagNames.h"
|
||||
#include "TargetAddressRangeList.h"
|
||||
|
||||
|
||||
DwarfFile::DwarfFile()
|
||||
|
@ -25,6 +26,7 @@ DwarfFile::DwarfFile()
|
|||
fDebugInfoSection(NULL),
|
||||
fDebugAbbrevSection(NULL),
|
||||
fDebugStringSection(NULL),
|
||||
fDebugRangesSection(NULL),
|
||||
fCompilationUnits(20, true),
|
||||
fCurrentCompilationUnit(NULL),
|
||||
fFinished(false),
|
||||
|
@ -42,6 +44,7 @@ DwarfFile::~DwarfFile()
|
|||
fElfFile->PutSection(fDebugInfoSection);
|
||||
fElfFile->PutSection(fDebugAbbrevSection);
|
||||
fElfFile->PutSection(fDebugStringSection);
|
||||
fElfFile->PutSection(fDebugRangesSection);
|
||||
delete fElfFile;
|
||||
}
|
||||
|
||||
|
@ -69,6 +72,8 @@ DwarfFile::Load(const char* fileName)
|
|||
fDebugInfoSection = fElfFile->GetSection(".debug_info");
|
||||
fDebugAbbrevSection = fElfFile->GetSection(".debug_abbrev");
|
||||
fDebugStringSection = fElfFile->GetSection(".debug_str");
|
||||
fDebugRangesSection = fElfFile->GetSection(".debug_ranges");
|
||||
// not mandatory
|
||||
if (fDebugInfoSection == NULL || fDebugAbbrevSection == NULL
|
||||
|| fDebugStringSection == NULL) {
|
||||
fprintf(stderr, "DwarfManager::File::Load(\"%s\"): no "
|
||||
|
@ -286,7 +291,9 @@ abbreviationEntry.Tag(), abbreviationEntry.HasChildren());
|
|||
if (childEntry != NULL) {
|
||||
if (entry != NULL) {
|
||||
error = entry->AddChild(childEntry);
|
||||
if (error == ENTRY_NOT_HANDLED) {
|
||||
if (error == B_OK) {
|
||||
childEntry->SetParent(entry);
|
||||
} else if (error == ENTRY_NOT_HANDLED) {
|
||||
error = B_OK;
|
||||
printf("%*s -> child unhandled\n", level * 2, "");
|
||||
}
|
||||
|
@ -384,7 +391,7 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
|
|||
// prepare an AttributeValue
|
||||
AttributeValue attributeValue;
|
||||
attributeValue.attributeForm = attributeForm;
|
||||
attributeValue.isSigned = false;
|
||||
bool isSigned = false;
|
||||
|
||||
// Read the attribute value according to the attribute's form. For
|
||||
// the forms that don't map to a single attribute class only or
|
||||
|
@ -414,7 +421,7 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
|
|||
value = dataReader.Read<uint64>(0);
|
||||
break;
|
||||
case DW_FORM_string:
|
||||
attributeValue.string = dataReader.ReadString();
|
||||
attributeValue.SetToString(dataReader.ReadString());
|
||||
break;
|
||||
case DW_FORM_block:
|
||||
blockLength = dataReader.ReadUnsignedLEB128(0);
|
||||
|
@ -426,11 +433,11 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
|
|||
value = dataReader.Read<uint8>(0);
|
||||
break;
|
||||
case DW_FORM_flag:
|
||||
attributeValue.flag = dataReader.Read<uint8>(0) != 0;
|
||||
attributeValue.SetToFlag(dataReader.Read<uint8>(0) != 0);
|
||||
break;
|
||||
case DW_FORM_sdata:
|
||||
value = dataReader.ReadSignedLEB128(0);
|
||||
attributeValue.isSigned = true;
|
||||
isSigned = true;
|
||||
break;
|
||||
case DW_FORM_strp:
|
||||
{
|
||||
|
@ -440,8 +447,8 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
|
|||
offset);
|
||||
return B_BAD_DATA;
|
||||
}
|
||||
attributeValue.string
|
||||
= (const char*)fDebugStringSection->Data() + offset;
|
||||
attributeValue.SetToString(
|
||||
(const char*)fDebugStringSection->Data() + offset);
|
||||
break;
|
||||
}
|
||||
case DW_FORM_udata:
|
||||
|
@ -484,31 +491,43 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
|
|||
attributeForm);
|
||||
continue;
|
||||
}
|
||||
attributeValue.attributeClass = attributeClass;
|
||||
// attributeValue.attributeClass = attributeClass;
|
||||
|
||||
// set the attribute value according to the attribute's class
|
||||
switch (attributeClass) {
|
||||
case ATTRIBUTE_CLASS_ADDRESS:
|
||||
attributeValue.address = value;
|
||||
attributeValue.SetToAddress(value);
|
||||
break;
|
||||
case ATTRIBUTE_CLASS_BLOCK:
|
||||
attributeValue.block.data = dataReader.Data();
|
||||
attributeValue.block.length = blockLength;
|
||||
attributeValue.SetToBlock(dataReader.Data(), blockLength);
|
||||
dataReader.Skip(blockLength);
|
||||
break;
|
||||
case ATTRIBUTE_CLASS_CONSTANT:
|
||||
attributeValue.constant = value;
|
||||
attributeValue.SetToConstant(value, isSigned);
|
||||
break;
|
||||
case ATTRIBUTE_CLASS_LINEPTR:
|
||||
case ATTRIBUTE_CLASS_LOCLISTPTR:
|
||||
case ATTRIBUTE_CLASS_MACPTR:
|
||||
case ATTRIBUTE_CLASS_RANGELISTPTR:
|
||||
attributeValue.pointer = value;
|
||||
attributeValue.SetToLinePointer(value);
|
||||
break;
|
||||
case ATTRIBUTE_CLASS_LOCLISTPTR:
|
||||
attributeValue.SetToLocationListPointer(value);
|
||||
break;
|
||||
case ATTRIBUTE_CLASS_MACPTR:
|
||||
attributeValue.SetToMacroPointer(value);
|
||||
break;
|
||||
case ATTRIBUTE_CLASS_RANGELISTPTR:
|
||||
{
|
||||
if (entry != NULL) {
|
||||
TargetAddressRangeList* rangeList
|
||||
= _ResolveRangeList(value);
|
||||
Reference<TargetAddressRangeList> reference(rangeList);
|
||||
attributeValue.SetToRangeList(rangeList);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ATTRIBUTE_CLASS_REFERENCE:
|
||||
if (entry != NULL) {
|
||||
attributeValue.reference = _ResolveReference(value,
|
||||
localReference);
|
||||
attributeValue.SetToReference(_ResolveReference(value,
|
||||
localReference));
|
||||
if (attributeValue.reference == NULL) {
|
||||
fprintf(stderr, "Failed to resolve reference: "
|
||||
"%s (%#lx) %s (%#lx): value: %llu\n",
|
||||
|
@ -539,7 +558,7 @@ get_attribute_form_name(attributeForm), attributeClass, attributeValue.ToString(
|
|||
|
||||
DebugInfoEntrySetter attributeSetter
|
||||
= get_attribute_name_setter(attributeName);
|
||||
if (attributeSetter != NULL) {
|
||||
if (attributeSetter != 0) {
|
||||
status_t error = (entry->*attributeSetter)(attributeName,
|
||||
attributeValue);
|
||||
|
||||
|
@ -605,3 +624,49 @@ DwarfFile::_ResolveReference(uint64 offset, bool localReference) const
|
|||
// TODO: Implement program-global references!
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
TargetAddressRangeList*
|
||||
DwarfFile::_ResolveRangeList(uint64 offset)
|
||||
{
|
||||
if (fDebugRangesSection == NULL)
|
||||
return NULL;
|
||||
|
||||
if (offset >= (uint64)fDebugRangesSection->Size())
|
||||
return NULL;
|
||||
|
||||
TargetAddressRangeList* ranges = new(std::nothrow) TargetAddressRangeList;
|
||||
if (ranges == NULL) {
|
||||
fprintf(stderr, "Out of memory.\n");
|
||||
return NULL;
|
||||
}
|
||||
Reference<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();
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ class CompilationUnit;
|
|||
class DataReader;
|
||||
class ElfFile;
|
||||
class ElfSection;
|
||||
class TargetAddressRangeList;
|
||||
|
||||
|
||||
class DwarfFile : public DoublyLinkedListLinkImpl<DwarfFile> {
|
||||
|
@ -27,7 +28,8 @@ public:
|
|||
status_t Load(const char* fileName);
|
||||
status_t FinishLoading();
|
||||
|
||||
const char* Name() const { return fName; }
|
||||
const char* Name() const { return fName; }
|
||||
ElfFile* GetElfFile() const { return fElfFile; }
|
||||
|
||||
int32 CountCompilationUnits() const;
|
||||
CompilationUnit* CompilationUnitAt(int32 index) const;
|
||||
|
@ -52,6 +54,8 @@ private:
|
|||
|
||||
DebugInfoEntry* _ResolveReference(uint64 offset,
|
||||
bool localReference) const;
|
||||
TargetAddressRangeList* _ResolveRangeList(uint64 offset);
|
||||
// returns reference
|
||||
|
||||
private:
|
||||
char* fName;
|
||||
|
@ -59,6 +63,7 @@ private:
|
|||
ElfSection* fDebugInfoSection;
|
||||
ElfSection* fDebugAbbrevSection;
|
||||
ElfSection* fDebugStringSection;
|
||||
ElfSection* fDebugRangesSection;
|
||||
AbbreviationTableList fAbbreviationTables;
|
||||
DebugInfoEntryFactory fDebugInfoFactory;
|
||||
CompilationUnitList fCompilationUnits;
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -8,6 +8,7 @@ UsePrivateSystemHeaders ;
|
|||
|
||||
SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) ] ;
|
||||
SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) elf ] ;
|
||||
SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) types ] ;
|
||||
|
||||
|
||||
MergeObject Debugger_dwarf.o
|
||||
|
@ -20,6 +21,7 @@ MergeObject Debugger_dwarf.o
|
|||
DebugInfoEntry.cpp
|
||||
DwarfFile.cpp
|
||||
DwarfManager.cpp
|
||||
DwarfUtils.cpp
|
||||
SourceLanguageInfo.cpp
|
||||
TagNames.cpp
|
||||
;
|
||||
|
|
|
@ -76,6 +76,26 @@ ElfSection::Unload()
|
|||
}
|
||||
|
||||
|
||||
// #pragma mark - ElfSegment
|
||||
|
||||
|
||||
ElfSegment::ElfSegment(off_t fileOffset, off_t fileSize,
|
||||
target_addr_t loadAddress, target_size_t loadSize, bool writable)
|
||||
:
|
||||
fFileOffset(fileOffset),
|
||||
fFileSize(fileSize),
|
||||
fLoadAddress(loadAddress),
|
||||
fLoadSize(loadSize),
|
||||
fWritable(writable)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ElfSegment::~ElfSegment()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - ElfFile
|
||||
|
||||
|
||||
|
@ -90,6 +110,9 @@ ElfFile::ElfFile()
|
|||
|
||||
ElfFile::~ElfFile()
|
||||
{
|
||||
while (ElfSegment* segment = fSegments.RemoveHead())
|
||||
delete segment;
|
||||
|
||||
while (ElfSection* section = fSections.RemoveHead())
|
||||
delete section;
|
||||
|
||||
|
@ -148,8 +171,7 @@ printf("fFileSize: %lld\n", fFileSize);
|
|||
printf("sectionHeaderTable: %lld\n", sectionHeadersOffset);
|
||||
|
||||
// read the section header table
|
||||
uint8* sectionHeaderTable
|
||||
= (uint8*)malloc(sectionHeaderTableSize);
|
||||
uint8* sectionHeaderTable = (uint8*)malloc(sectionHeaderTableSize);
|
||||
if (sectionHeaderTable == NULL)
|
||||
return B_NO_MEMORY;
|
||||
MemoryDeleter sectionHeaderTableDeleter(sectionHeaderTable);
|
||||
|
@ -202,6 +224,49 @@ printf("sectionStrings: %ld\n", stringSectionHeader->sh_offset);
|
|||
fSections.Add(section);
|
||||
}
|
||||
|
||||
// check program header table values
|
||||
off_t programHeadersOffset = fElfHeader->e_phoff;
|
||||
size_t programHeaderSize = fElfHeader->e_phentsize;
|
||||
int segmentCount = fElfHeader->e_phnum;
|
||||
size_t programHeaderTableSize = programHeaderSize * segmentCount;
|
||||
if (!_CheckRange(programHeadersOffset, programHeaderTableSize)) {
|
||||
fprintf(stderr, "\"%s\": Invalid ELF header\n", fileName);
|
||||
return B_BAD_DATA;
|
||||
}
|
||||
printf("programHeaderTable: %lld\n", programHeadersOffset);
|
||||
|
||||
// read the program header table
|
||||
uint8* programHeaderTable = (uint8*)malloc(programHeaderTableSize);
|
||||
if (programHeaderTable == NULL)
|
||||
return B_NO_MEMORY;
|
||||
MemoryDeleter programHeaderTableDeleter(programHeaderTable);
|
||||
|
||||
bytesRead = pread(fFD, programHeaderTable, programHeaderTableSize,
|
||||
programHeadersOffset);
|
||||
if (bytesRead != (ssize_t)programHeaderTableSize)
|
||||
return bytesRead < 0 ? errno : B_ERROR;
|
||||
|
||||
// read the program headers and create ElfSegment objects
|
||||
for (int i = 0; i < segmentCount; i++) {
|
||||
Elf32_Phdr* programHeader = (Elf32_Phdr*)(programHeaderTable
|
||||
+ i * programHeaderSize);
|
||||
// skip program headers we aren't interested in or that are invalid
|
||||
if (programHeader->p_type != PT_LOAD || programHeader->p_filesz == 0
|
||||
|| programHeader->p_memsz == 0
|
||||
|| !_CheckRange(programHeader->p_offset, programHeader->p_filesz)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// create an ElfSegment
|
||||
ElfSegment* segment = new(std::nothrow) ElfSegment(
|
||||
programHeader->p_offset, programHeader->p_filesz,
|
||||
programHeader->p_vaddr, programHeader->p_memsz,
|
||||
(programHeader->p_flags & PF_WRITE) != 0);
|
||||
if (segment == NULL)
|
||||
return B_NO_MEMORY;
|
||||
fSegments.Add(segment);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
@ -227,6 +292,32 @@ ElfFile::PutSection(ElfSection* section)
|
|||
}
|
||||
|
||||
|
||||
ElfSegment*
|
||||
ElfFile::TextSegment() const
|
||||
{
|
||||
for (SegmentList::ConstIterator it = fSegments.GetIterator();
|
||||
ElfSegment* segment = it.Next();) {
|
||||
if (!segment->IsWritable())
|
||||
return segment;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
ElfSegment*
|
||||
ElfFile::DataSegment() const
|
||||
{
|
||||
for (SegmentList::ConstIterator it = fSegments.GetIterator();
|
||||
ElfSegment* segment = it.Next();) {
|
||||
if (segment->IsWritable())
|
||||
return segment;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ElfFile::_CheckRange(off_t offset, off_t size) const
|
||||
{
|
||||
|
@ -243,5 +334,8 @@ ElfFile::_CheckElfHeader() const
|
|||
&& fElfHeader->e_shnum > 0
|
||||
&& fElfHeader->e_shentsize >= sizeof(struct Elf32_Shdr)
|
||||
&& fElfHeader->e_shstrndx != SHN_UNDEF
|
||||
&& fElfHeader->e_shstrndx < fElfHeader->e_shnum;
|
||||
&& fElfHeader->e_shstrndx < fElfHeader->e_shnum
|
||||
&& fElfHeader->e_phoff > 0
|
||||
&& fElfHeader->e_phnum > 0
|
||||
&& fElfHeader->e_phentsize >= sizeof(struct Elf32_Phdr);
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#include <elf32.h>
|
||||
#include <util/DoublyLinkedList.h>
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
|
||||
class ElfSection : public DoublyLinkedListLinkImpl<ElfSection> {
|
||||
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 {
|
||||
public:
|
||||
ElfFile();
|
||||
|
@ -44,11 +68,17 @@ public:
|
|||
|
||||
status_t Init(const char* fileName);
|
||||
|
||||
int FD() const { return fFD; }
|
||||
|
||||
ElfSection* GetSection(const char* name);
|
||||
void PutSection(ElfSection* section);
|
||||
|
||||
ElfSegment* TextSegment() const;
|
||||
ElfSegment* DataSegment() const;
|
||||
|
||||
private:
|
||||
typedef DoublyLinkedList<ElfSection> SectionList;
|
||||
typedef DoublyLinkedList<ElfSegment> SegmentList;
|
||||
|
||||
private:
|
||||
bool _CheckRange(off_t offset, off_t size) const;
|
||||
|
@ -59,6 +89,7 @@ private:
|
|||
int fFD;
|
||||
Elf32_Ehdr* fElfHeader;
|
||||
SectionList fSections;
|
||||
SegmentList fSegments;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include <Font.h>
|
||||
#include <View.h>
|
||||
|
||||
#include "ArchitectureTypes.h"
|
||||
#include "Types.h"
|
||||
|
||||
|
||||
class Breakpoint;
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include <ObjectList.h>
|
||||
#include <Referenceable.h>
|
||||
|
||||
#include "ArchitectureTypes.h"
|
||||
#include "Types.h"
|
||||
|
||||
|
||||
enum user_breakpoint_state {
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include <image.h>
|
||||
#include <String.h>
|
||||
|
||||
#include "ArchitectureTypes.h"
|
||||
#include "Types.h"
|
||||
|
||||
|
||||
class ImageInfo {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
#include <Referenceable.h>
|
||||
|
||||
#include "ArchitectureTypes.h"
|
||||
#include "Types.h"
|
||||
|
||||
|
||||
enum stack_frame_type {
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
|
||||
#include <Referenceable.h>
|
||||
|
||||
#include "ArchitectureTypes.h"
|
||||
#include "SourceLocation.h"
|
||||
#include "TargetAddressRange.h"
|
||||
#include "Types.h"
|
||||
|
||||
|
||||
class Statement : public Referenceable {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
#include <String.h>
|
||||
|
||||
#include "ArchitectureTypes.h"
|
||||
#include "Types.h"
|
||||
|
||||
|
||||
class SymbolInfo {
|
||||
|
|
|
@ -5,7 +5,9 @@
|
|||
#ifndef TARGET_ADDRESS_RANGE_H
|
||||
#define TARGET_ADDRESS_RANGE_H
|
||||
|
||||
#include "ArchitectureTypes.h"
|
||||
#include <algorithm>
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
|
||||
class TargetAddressRange {
|
||||
|
@ -78,6 +80,20 @@ public:
|
|||
return Contains(other.Start()) || other.Contains(Start());
|
||||
}
|
||||
|
||||
TargetAddressRange& operator|=(const TargetAddressRange& other)
|
||||
{
|
||||
if (fSize == 0)
|
||||
return *this = other;
|
||||
|
||||
if (other.fSize > 0) {
|
||||
target_addr_t end = std::max(End(), other.End());
|
||||
fStart = std::min(fStart, other.fStart);
|
||||
fSize = end - fStart;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
target_addr_t fStart;
|
||||
target_size_t fSize;
|
|
@ -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;
|
||||
}
|
|
@ -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
|
Loading…
Reference in New Issue