* 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 {
|
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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
#include <Referenceable.h>
|
#include <Referenceable.h>
|
||||||
|
|
||||||
#include "ArchitectureTypes.h"
|
#include "Types.h"
|
||||||
|
|
||||||
|
|
||||||
class CpuState;
|
class CpuState;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
|
|
||||||
#include "ArchitectureTypes.h"
|
#include "Types.h"
|
||||||
|
|
||||||
|
|
||||||
enum instruction_type {
|
enum instruction_type {
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
|
|
||||||
#include "ArchitectureTypes.h"
|
#include "Types.h"
|
||||||
|
|
||||||
|
|
||||||
class DisassemblerX86 {
|
class DisassemblerX86 {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 "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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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) ] ;
|
||||||
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
|
||||||
;
|
;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
#include <Referenceable.h>
|
#include <Referenceable.h>
|
||||||
|
|
||||||
#include "ArchitectureTypes.h"
|
#include "Types.h"
|
||||||
|
|
||||||
|
|
||||||
enum stack_frame_type {
|
enum stack_frame_type {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
|
|
||||||
#include "ArchitectureTypes.h"
|
#include "Types.h"
|
||||||
|
|
||||||
|
|
||||||
class SymbolInfo {
|
class SymbolInfo {
|
||||||
|
|
|
@ -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;
|
|
@ -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