* DWARF: Implemented parsing the DWARF frame info and evaluating it (save for
DWARF expressions). Several related new classes: CfaRule[Set], CfaContext, DwarfTargetInterface (for accessing target registers and memory). * Implemented DwarfImageDebugInfo::CreateFrame(), so the DWARF frame info is used for unwinding the stack. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31540 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -18,26 +18,131 @@
|
|||||||
|
|
||||||
#include "Architecture.h"
|
#include "Architecture.h"
|
||||||
#include "CompilationUnit.h"
|
#include "CompilationUnit.h"
|
||||||
|
#include "CpuState.h"
|
||||||
#include "DebugInfoEntries.h"
|
#include "DebugInfoEntries.h"
|
||||||
#include "Dwarf.h"
|
#include "Dwarf.h"
|
||||||
#include "DwarfFile.h"
|
#include "DwarfFile.h"
|
||||||
#include "DwarfFunctionDebugInfo.h"
|
#include "DwarfFunctionDebugInfo.h"
|
||||||
|
#include "DwarfTargetInterface.h"
|
||||||
#include "DwarfUtils.h"
|
#include "DwarfUtils.h"
|
||||||
#include "ElfFile.h"
|
#include "ElfFile.h"
|
||||||
#include "FileManager.h"
|
#include "FileManager.h"
|
||||||
#include "FileSourceCode.h"
|
#include "FileSourceCode.h"
|
||||||
#include "LocatableFile.h"
|
#include "LocatableFile.h"
|
||||||
|
#include "Register.h"
|
||||||
|
#include "RegisterMap.h"
|
||||||
#include "SourceFile.h"
|
#include "SourceFile.h"
|
||||||
|
#include "StackFrame.h"
|
||||||
#include "Statement.h"
|
#include "Statement.h"
|
||||||
#include "StringUtils.h"
|
#include "StringUtils.h"
|
||||||
|
#include "TeamMemory.h"
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - UnwindTargetInterface
|
||||||
|
|
||||||
|
|
||||||
|
struct DwarfImageDebugInfo::UnwindTargetInterface : DwarfTargetInterface {
|
||||||
|
UnwindTargetInterface(const Register* registers, int32 registerCount,
|
||||||
|
RegisterMap* fromDwarfMap, RegisterMap* toDwarfMap, CpuState* cpuState,
|
||||||
|
Architecture* architecture, TeamMemory* teamMemory)
|
||||||
|
:
|
||||||
|
fRegisters(registers),
|
||||||
|
fRegisterCount(registerCount),
|
||||||
|
fFromDwarfMap(fromDwarfMap),
|
||||||
|
fToDwarfMap(toDwarfMap),
|
||||||
|
fCpuState(cpuState),
|
||||||
|
fArchitecture(architecture),
|
||||||
|
fTeamMemory(teamMemory)
|
||||||
|
{
|
||||||
|
fFromDwarfMap->AcquireReference();
|
||||||
|
fToDwarfMap->AcquireReference();
|
||||||
|
fCpuState->AcquireReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
~UnwindTargetInterface()
|
||||||
|
{
|
||||||
|
fFromDwarfMap->ReleaseReference();
|
||||||
|
fToDwarfMap->ReleaseReference();
|
||||||
|
fCpuState->ReleaseReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual uint32 CountRegisters() const
|
||||||
|
{
|
||||||
|
return fRegisterCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual uint32 RegisterValueType(uint32 index) const
|
||||||
|
{
|
||||||
|
const Register* reg = _RegisterAt(index);
|
||||||
|
return reg != NULL ? reg->ValueType() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool GetRegisterValue(uint32 index, BVariant& _value) const
|
||||||
|
{
|
||||||
|
const Register* reg = _RegisterAt(index);
|
||||||
|
if (reg == NULL)
|
||||||
|
return false;
|
||||||
|
return fCpuState->GetRegisterValue(reg, _value);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool SetRegisterValue(uint32 index, const BVariant& value)
|
||||||
|
{
|
||||||
|
const Register* reg = _RegisterAt(index);
|
||||||
|
if (reg == NULL)
|
||||||
|
return false;
|
||||||
|
return fCpuState->SetRegisterValue(reg, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool IsCalleePreservedRegister(uint32 index) const
|
||||||
|
{
|
||||||
|
const Register* reg = _RegisterAt(index);
|
||||||
|
return reg != NULL && reg->IsCalleePreserved();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool ReadMemory(target_addr_t address, void* buffer,
|
||||||
|
size_t size) const
|
||||||
|
{
|
||||||
|
ssize_t bytesRead = fTeamMemory->ReadMemory(address, buffer, size);
|
||||||
|
return bytesRead >= 0 && (size_t)bytesRead == size;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool ReadValueFromMemory(target_addr_t address,
|
||||||
|
uint32 valueType, BVariant& _value) const
|
||||||
|
{
|
||||||
|
return fArchitecture->ReadValueFromMemory(address, valueType, _value)
|
||||||
|
== B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const Register* _RegisterAt(uint32 dwarfIndex) const
|
||||||
|
{
|
||||||
|
int32 index = fFromDwarfMap->MapRegisterIndex(dwarfIndex);
|
||||||
|
return index >= 0 && index < fRegisterCount ? fRegisters + index : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const Register* fRegisters;
|
||||||
|
int32 fRegisterCount;
|
||||||
|
RegisterMap* fFromDwarfMap;
|
||||||
|
RegisterMap* fToDwarfMap;
|
||||||
|
CpuState* fCpuState;
|
||||||
|
Architecture* fArchitecture;
|
||||||
|
TeamMemory* fTeamMemory;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - DwarfImageDebugInfo
|
||||||
|
|
||||||
|
|
||||||
DwarfImageDebugInfo::DwarfImageDebugInfo(const ImageInfo& imageInfo,
|
DwarfImageDebugInfo::DwarfImageDebugInfo(const ImageInfo& imageInfo,
|
||||||
Architecture* architecture, FileManager* fileManager, DwarfFile* file)
|
Architecture* architecture, TeamMemory* teamMemory,
|
||||||
|
FileManager* fileManager, DwarfFile* file)
|
||||||
:
|
:
|
||||||
fLock("dwarf image debug info"),
|
fLock("dwarf image debug info"),
|
||||||
fImageInfo(imageInfo),
|
fImageInfo(imageInfo),
|
||||||
fArchitecture(architecture),
|
fArchitecture(architecture),
|
||||||
|
fTeamMemory(teamMemory),
|
||||||
fFileManager(fileManager),
|
fFileManager(fileManager),
|
||||||
fFile(file),
|
fFile(file),
|
||||||
fTextSegment(NULL),
|
fTextSegment(NULL),
|
||||||
@@ -188,8 +293,64 @@ DwarfImageDebugInfo::CreateFrame(Image* image, FunctionDebugInfo* function,
|
|||||||
CpuState* cpuState, StackFrame*& _previousFrame,
|
CpuState* cpuState, StackFrame*& _previousFrame,
|
||||||
CpuState*& _previousCpuState)
|
CpuState*& _previousCpuState)
|
||||||
{
|
{
|
||||||
// TODO:...
|
int32 registerCount = fArchitecture->CountRegisters();
|
||||||
return B_UNSUPPORTED;
|
const Register* registers = fArchitecture->Registers();
|
||||||
|
|
||||||
|
// get the DWARF <-> architecture register maps
|
||||||
|
RegisterMap* toDwarfMap;
|
||||||
|
RegisterMap* fromDwarfMap;
|
||||||
|
status_t error = fArchitecture->GetDwarfRegisterMaps(&toDwarfMap,
|
||||||
|
&fromDwarfMap);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
Reference<RegisterMap> toDwarfMapReference(toDwarfMap, true);
|
||||||
|
Reference<RegisterMap> fromDwarfMapReference(fromDwarfMap, true);
|
||||||
|
|
||||||
|
// create a clean CPU state for the previous frame
|
||||||
|
CpuState* previousCpuState;
|
||||||
|
error = fArchitecture->CreateCpuState(previousCpuState);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
Reference<CpuState> previousCpuStateReference(previousCpuState, true);
|
||||||
|
|
||||||
|
// create the target interfaces
|
||||||
|
UnwindTargetInterface inputInterface(registers, registerCount,
|
||||||
|
fromDwarfMap, toDwarfMap, cpuState, fArchitecture, fTeamMemory);
|
||||||
|
UnwindTargetInterface outputInterface(registers, registerCount,
|
||||||
|
fromDwarfMap, toDwarfMap, previousCpuState, fArchitecture, fTeamMemory);
|
||||||
|
|
||||||
|
// do the unwinding
|
||||||
|
target_addr_t framePointer;
|
||||||
|
error = fFile->UnwindCallFrame(
|
||||||
|
cpuState->InstructionPointer() - fRelocationDelta,
|
||||||
|
&inputInterface, &outputInterface, framePointer);
|
||||||
|
if (error != B_OK)
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
|
||||||
|
printf("unwound registers:\n");
|
||||||
|
for (int32 i = 0; i < registerCount; i++) {
|
||||||
|
const Register* reg = registers + i;
|
||||||
|
BVariant value;
|
||||||
|
if (previousCpuState->GetRegisterValue(reg, value)) {
|
||||||
|
printf(" %3s: %#lx\n", reg->Name(), value.ToUInt32());
|
||||||
|
} else
|
||||||
|
printf(" %3s: undefined\n", reg->Name());
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the stack frame
|
||||||
|
StackFrame* frame = new(std::nothrow) StackFrame(STACK_FRAME_TYPE_STANDARD,
|
||||||
|
cpuState, framePointer, cpuState->InstructionPointer());
|
||||||
|
if (frame == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
frame->SetReturnAddress(previousCpuState->InstructionPointer());
|
||||||
|
// Note, this is correct, since we actually retrieved the return
|
||||||
|
// address. Our caller will fix the IP for us.
|
||||||
|
|
||||||
|
_previousFrame = frame;
|
||||||
|
_previousCpuState = previousCpuStateReference.Detach();
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -22,12 +22,14 @@ class FileManager;
|
|||||||
class FileSourceCode;
|
class FileSourceCode;
|
||||||
class LocatableFile;
|
class LocatableFile;
|
||||||
class SourceCode;
|
class SourceCode;
|
||||||
|
class TeamMemory;
|
||||||
|
|
||||||
|
|
||||||
class DwarfImageDebugInfo : public SpecificImageDebugInfo {
|
class DwarfImageDebugInfo : public SpecificImageDebugInfo {
|
||||||
public:
|
public:
|
||||||
DwarfImageDebugInfo(const ImageInfo& imageInfo,
|
DwarfImageDebugInfo(const ImageInfo& imageInfo,
|
||||||
Architecture* architecture,
|
Architecture* architecture,
|
||||||
|
TeamMemory* teamMemory,
|
||||||
FileManager* fileManager, DwarfFile* file);
|
FileManager* fileManager, DwarfFile* file);
|
||||||
virtual ~DwarfImageDebugInfo();
|
virtual ~DwarfImageDebugInfo();
|
||||||
|
|
||||||
@@ -57,6 +59,9 @@ public:
|
|||||||
virtual status_t AddSourceCodeInfo(LocatableFile* file,
|
virtual status_t AddSourceCodeInfo(LocatableFile* file,
|
||||||
FileSourceCode* sourceCode);
|
FileSourceCode* sourceCode);
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct UnwindTargetInterface;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
status_t _AddSourceCodeInfo(CompilationUnit* unit,
|
status_t _AddSourceCodeInfo(CompilationUnit* unit,
|
||||||
FileSourceCode* sourceCode,
|
FileSourceCode* sourceCode,
|
||||||
@@ -68,6 +73,7 @@ private:
|
|||||||
BLocker fLock;
|
BLocker fLock;
|
||||||
ImageInfo fImageInfo;
|
ImageInfo fImageInfo;
|
||||||
Architecture* fArchitecture;
|
Architecture* fArchitecture;
|
||||||
|
TeamMemory* fTeamMemory;
|
||||||
FileManager* fFileManager;
|
FileManager* fFileManager;
|
||||||
DwarfFile* fFile;
|
DwarfFile* fFile;
|
||||||
ElfSegment* fTextSegment;
|
ElfSegment* fTextSegment;
|
||||||
|
|||||||
@@ -15,9 +15,10 @@
|
|||||||
|
|
||||||
|
|
||||||
DwarfTeamDebugInfo::DwarfTeamDebugInfo(Architecture* architecture,
|
DwarfTeamDebugInfo::DwarfTeamDebugInfo(Architecture* architecture,
|
||||||
FileManager* fileManager)
|
TeamMemory* teamMemory, FileManager* fileManager)
|
||||||
:
|
:
|
||||||
fArchitecture(architecture),
|
fArchitecture(architecture),
|
||||||
|
fTeamMemory(teamMemory),
|
||||||
fFileManager(fileManager),
|
fFileManager(fileManager),
|
||||||
fManager(NULL)
|
fManager(NULL)
|
||||||
{
|
{
|
||||||
@@ -64,7 +65,7 @@ DwarfTeamDebugInfo::CreateImageDebugInfo(const ImageInfo& imageInfo,
|
|||||||
|
|
||||||
// create the image debug info
|
// create the image debug info
|
||||||
DwarfImageDebugInfo* debuggerInfo = new(std::nothrow) DwarfImageDebugInfo(
|
DwarfImageDebugInfo* debuggerInfo = new(std::nothrow) DwarfImageDebugInfo(
|
||||||
imageInfo, fArchitecture, fFileManager, file);
|
imageInfo, fArchitecture, fTeamMemory, fFileManager, file);
|
||||||
if (debuggerInfo == NULL)
|
if (debuggerInfo == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
|||||||
@@ -12,11 +12,13 @@ class Architecture;
|
|||||||
class DwarfManager;
|
class DwarfManager;
|
||||||
class FileManager;
|
class FileManager;
|
||||||
class ImageInfo;
|
class ImageInfo;
|
||||||
|
class TeamMemory;
|
||||||
|
|
||||||
|
|
||||||
class DwarfTeamDebugInfo : public SpecificTeamDebugInfo {
|
class DwarfTeamDebugInfo : public SpecificTeamDebugInfo {
|
||||||
public:
|
public:
|
||||||
DwarfTeamDebugInfo(Architecture* architecture,
|
DwarfTeamDebugInfo(Architecture* architecture,
|
||||||
|
TeamMemory* teamMemory,
|
||||||
FileManager* fileManager);
|
FileManager* fileManager);
|
||||||
virtual ~DwarfTeamDebugInfo();
|
virtual ~DwarfTeamDebugInfo();
|
||||||
|
|
||||||
@@ -28,6 +30,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Architecture* fArchitecture;
|
Architecture* fArchitecture;
|
||||||
|
TeamMemory* fTeamMemory;
|
||||||
FileManager* fFileManager;
|
FileManager* fFileManager;
|
||||||
DwarfManager* fManager;
|
DwarfManager* fManager;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include <AutoLocker.h>
|
#include <AutoLocker.h>
|
||||||
|
|
||||||
#include "Architecture.h"
|
#include "Architecture.h"
|
||||||
|
#include "DebuggerInterface.h"
|
||||||
#include "DebuggerTeamDebugInfo.h"
|
#include "DebuggerTeamDebugInfo.h"
|
||||||
#include "DisassembledCode.h"
|
#include "DisassembledCode.h"
|
||||||
#include "DwarfTeamDebugInfo.h"
|
#include "DwarfTeamDebugInfo.h"
|
||||||
@@ -298,7 +299,7 @@ TeamDebugInfo::Init()
|
|||||||
|
|
||||||
// DWARF
|
// DWARF
|
||||||
DwarfTeamDebugInfo* dwarfInfo = new(std::nothrow) DwarfTeamDebugInfo(
|
DwarfTeamDebugInfo* dwarfInfo = new(std::nothrow) DwarfTeamDebugInfo(
|
||||||
fArchitecture, fFileManager);
|
fArchitecture, fDebuggerInterface, fFileManager);
|
||||||
if (dwarfInfo == NULL || !fSpecificInfos.AddItem(dwarfInfo)) {
|
if (dwarfInfo == NULL || !fSpecificInfos.AddItem(dwarfInfo)) {
|
||||||
delete dwarfInfo;
|
delete dwarfInfo;
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|||||||
@@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
#include "CfaContext.h"
|
||||||
|
|
||||||
|
|
||||||
|
CfaContext::CfaContext(dwarf_addr_t targetLocation,
|
||||||
|
dwarf_addr_t initialLocation)
|
||||||
|
:
|
||||||
|
fTargetLocation(targetLocation),
|
||||||
|
fLocation(initialLocation),
|
||||||
|
fCodeAlignment(0),
|
||||||
|
fDataAlignment(0),
|
||||||
|
fReturnAddressRegister(0),
|
||||||
|
fRuleSet(NULL),
|
||||||
|
fInitialRuleSet(NULL),
|
||||||
|
fRuleSetStack(10, true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CfaContext::~CfaContext()
|
||||||
|
{
|
||||||
|
delete fRuleSet;
|
||||||
|
delete fInitialRuleSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
CfaContext::Init(uint32 registerCount)
|
||||||
|
{
|
||||||
|
fRuleSet = new(std::nothrow) CfaRuleSet;
|
||||||
|
if (fRuleSet == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
return fRuleSet->Init(registerCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
CfaContext::SaveInitialRuleSet()
|
||||||
|
{
|
||||||
|
fInitialRuleSet = fRuleSet->Clone();
|
||||||
|
if (fInitialRuleSet == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
CfaContext::PushRuleSet()
|
||||||
|
{
|
||||||
|
CfaRuleSet* ruleSet = fRuleSet->Clone();
|
||||||
|
if (ruleSet == NULL || !fRuleSetStack.AddItem(ruleSet)) {
|
||||||
|
delete ruleSet;
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
CfaContext::PopRuleSet()
|
||||||
|
{
|
||||||
|
if (fRuleSetStack.IsEmpty())
|
||||||
|
return B_BAD_DATA;
|
||||||
|
|
||||||
|
delete fRuleSet;
|
||||||
|
fRuleSet = fRuleSetStack.RemoveItemAt(
|
||||||
|
fRuleSetStack.CountItems() - 1);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CfaContext::SetLocation(dwarf_addr_t location)
|
||||||
|
{
|
||||||
|
fLocation = location;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CfaContext::SetCodeAlignment(uint32 alignment)
|
||||||
|
{
|
||||||
|
fCodeAlignment = alignment;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CfaContext::SetDataAlignment(int32 alignment)
|
||||||
|
{
|
||||||
|
fDataAlignment = alignment;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CfaContext::SetReturnAddressRegister(uint32 reg)
|
||||||
|
{
|
||||||
|
fReturnAddressRegister = reg;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CfaContext::RestoreRegisterRule(uint32 reg)
|
||||||
|
{
|
||||||
|
if (CfaRule* rule = RegisterRule(reg)) {
|
||||||
|
if (fInitialRuleSet != NULL)
|
||||||
|
*rule = *fInitialRuleSet->RegisterRule(reg);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef CFA_CONTEXT_H
|
||||||
|
#define CFA_CONTEXT_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <ObjectList.h>
|
||||||
|
|
||||||
|
#include "CfaRuleSet.h"
|
||||||
|
|
||||||
|
|
||||||
|
class CfaContext {
|
||||||
|
public:
|
||||||
|
CfaContext(dwarf_addr_t targetLocation,
|
||||||
|
dwarf_addr_t initialLocation);
|
||||||
|
~CfaContext();
|
||||||
|
|
||||||
|
status_t Init(uint32 registerCount);
|
||||||
|
status_t SaveInitialRuleSet();
|
||||||
|
|
||||||
|
status_t PushRuleSet();
|
||||||
|
status_t PopRuleSet();
|
||||||
|
|
||||||
|
dwarf_addr_t TargetLocation() const
|
||||||
|
{ return fTargetLocation; }
|
||||||
|
|
||||||
|
dwarf_addr_t Location() const
|
||||||
|
{ return fLocation; }
|
||||||
|
void SetLocation(dwarf_addr_t location);
|
||||||
|
|
||||||
|
uint32 CodeAlignment() const
|
||||||
|
{ return fCodeAlignment; }
|
||||||
|
void SetCodeAlignment(uint32 alignment);
|
||||||
|
|
||||||
|
int32 DataAlignment() const
|
||||||
|
{ return fDataAlignment; }
|
||||||
|
void SetDataAlignment(int32 alignment);
|
||||||
|
|
||||||
|
uint32 ReturnAddressRegister() const
|
||||||
|
{ return fReturnAddressRegister; }
|
||||||
|
void SetReturnAddressRegister(uint32 reg);
|
||||||
|
|
||||||
|
CfaCfaRule* GetCfaCfaRule() const
|
||||||
|
{ return fRuleSet->GetCfaCfaRule(); }
|
||||||
|
CfaRule* RegisterRule(uint32 index) const
|
||||||
|
{ return fRuleSet->RegisterRule(index); }
|
||||||
|
|
||||||
|
void RestoreRegisterRule(uint32 reg);
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef BObjectList<CfaRuleSet> RuleSetList;
|
||||||
|
|
||||||
|
private:
|
||||||
|
dwarf_addr_t fTargetLocation;
|
||||||
|
dwarf_addr_t fLocation;
|
||||||
|
uint32 fCodeAlignment;
|
||||||
|
int32 fDataAlignment;
|
||||||
|
uint32 fReturnAddressRegister;
|
||||||
|
CfaRuleSet* fRuleSet;
|
||||||
|
CfaRuleSet* fInitialRuleSet;
|
||||||
|
RuleSetList fRuleSetStack;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif // CFA_CONTEXT_H
|
||||||
@@ -0,0 +1,212 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef CFA_RULE_H
|
||||||
|
#define CFA_RULE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "DwarfTypes.h"
|
||||||
|
|
||||||
|
|
||||||
|
enum cfa_rule_type {
|
||||||
|
CFA_RULE_UNDEFINED,
|
||||||
|
CFA_RULE_SAME_VALUE,
|
||||||
|
CFA_RULE_LOCATION_OFFSET,
|
||||||
|
CFA_RULE_VALUE_OFFSET,
|
||||||
|
CFA_RULE_REGISTER,
|
||||||
|
CFA_RULE_LOCATION_EXPRESSION,
|
||||||
|
CFA_RULE_VALUE_EXPRESSION
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum cfa_cfa_rule_type {
|
||||||
|
CFA_CFA_RULE_UNDEFINED,
|
||||||
|
CFA_CFA_RULE_REGISTER_OFFSET,
|
||||||
|
CFA_CFA_RULE_EXPRESSION
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct CfaExpression {
|
||||||
|
const void* block;
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class CfaRule {
|
||||||
|
public:
|
||||||
|
inline CfaRule();
|
||||||
|
|
||||||
|
cfa_rule_type Type() const { return fType; }
|
||||||
|
|
||||||
|
int64 Offset() const { return fOffset; }
|
||||||
|
uint32 Register() const { return fRegister; }
|
||||||
|
const CfaExpression& Expression() const { return fExpression; }
|
||||||
|
|
||||||
|
inline void SetToUndefined();
|
||||||
|
inline void SetToSameValue();
|
||||||
|
inline void SetToLocationOffset(int64 offset);
|
||||||
|
inline void SetToValueOffset(int64 offset);
|
||||||
|
inline void SetToRegister(uint32 reg);
|
||||||
|
inline void SetToLocationExpression(const void* block,
|
||||||
|
size_t size);
|
||||||
|
inline void SetToValueExpression(const void* block,
|
||||||
|
size_t size);
|
||||||
|
|
||||||
|
private:
|
||||||
|
cfa_rule_type fType;
|
||||||
|
union {
|
||||||
|
int64 fOffset;
|
||||||
|
uint32 fRegister;
|
||||||
|
CfaExpression fExpression;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class CfaCfaRule {
|
||||||
|
public:
|
||||||
|
inline CfaCfaRule();
|
||||||
|
|
||||||
|
cfa_cfa_rule_type Type() const { return fType; }
|
||||||
|
|
||||||
|
uint64 Offset() const
|
||||||
|
{ return fRegisterOffset.offset; }
|
||||||
|
uint32 Register() const
|
||||||
|
{ return fRegisterOffset.reg; }
|
||||||
|
const CfaExpression& Expression() const { return fExpression; }
|
||||||
|
|
||||||
|
inline void SetToUndefined();
|
||||||
|
inline void SetToRegisterOffset(uint32 reg, uint64 offset);
|
||||||
|
inline void SetToExpression(const void* block, size_t size);
|
||||||
|
|
||||||
|
inline void SetRegister(uint32 reg);
|
||||||
|
inline void SetOffset(uint64 offset);
|
||||||
|
|
||||||
|
private:
|
||||||
|
cfa_cfa_rule_type fType;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
uint64 offset;
|
||||||
|
uint32 reg;
|
||||||
|
} fRegisterOffset;
|
||||||
|
CfaExpression fExpression;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - CfaRule
|
||||||
|
|
||||||
|
|
||||||
|
CfaRule::CfaRule()
|
||||||
|
:
|
||||||
|
fType(CFA_RULE_UNDEFINED)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CfaRule::SetToUndefined()
|
||||||
|
{
|
||||||
|
fType = CFA_RULE_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CfaRule::SetToSameValue()
|
||||||
|
{
|
||||||
|
fType = CFA_RULE_SAME_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CfaRule::SetToLocationOffset(int64 offset)
|
||||||
|
{
|
||||||
|
fType = CFA_RULE_LOCATION_OFFSET;
|
||||||
|
fOffset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CfaRule::SetToValueOffset(int64 offset)
|
||||||
|
{
|
||||||
|
fType = CFA_RULE_VALUE_OFFSET;
|
||||||
|
fOffset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CfaRule::SetToRegister(uint32 reg)
|
||||||
|
{
|
||||||
|
fType = CFA_RULE_REGISTER;
|
||||||
|
fRegister = reg;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CfaRule::SetToLocationExpression(const void* block, size_t size)
|
||||||
|
{
|
||||||
|
fType = CFA_RULE_LOCATION_EXPRESSION;
|
||||||
|
fExpression.block = block;
|
||||||
|
fExpression.size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CfaRule::SetToValueExpression(const void* block, size_t size)
|
||||||
|
{
|
||||||
|
fType = CFA_RULE_VALUE_EXPRESSION;
|
||||||
|
fExpression.block = block;
|
||||||
|
fExpression.size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - CfaCfaRule
|
||||||
|
|
||||||
|
|
||||||
|
CfaCfaRule::CfaCfaRule()
|
||||||
|
:
|
||||||
|
fType(CFA_CFA_RULE_UNDEFINED)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CfaCfaRule::SetToUndefined()
|
||||||
|
{
|
||||||
|
fType = CFA_CFA_RULE_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CfaCfaRule::SetToRegisterOffset(uint32 reg, uint64 offset)
|
||||||
|
{
|
||||||
|
fType = CFA_CFA_RULE_REGISTER_OFFSET;
|
||||||
|
fRegisterOffset.reg = reg;
|
||||||
|
fRegisterOffset.offset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CfaCfaRule::SetToExpression(const void* block, size_t size)
|
||||||
|
{
|
||||||
|
fType = CFA_CFA_RULE_EXPRESSION;
|
||||||
|
fExpression.block = block;
|
||||||
|
fExpression.size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CfaCfaRule::SetRegister(uint32 reg)
|
||||||
|
{
|
||||||
|
fRegisterOffset.reg = reg;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CfaCfaRule::SetOffset(uint64 offset)
|
||||||
|
{
|
||||||
|
fRegisterOffset.offset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // CFA_RULE_H
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
#include "CfaRuleSet.h"
|
||||||
|
|
||||||
|
|
||||||
|
CfaRuleSet::CfaRuleSet()
|
||||||
|
:
|
||||||
|
fRegisterRules(NULL),
|
||||||
|
fRegisterCount(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
CfaRuleSet::Init(uint32 registerCount)
|
||||||
|
{
|
||||||
|
fRegisterRules = new(std::nothrow) CfaRule[registerCount];
|
||||||
|
if (fRegisterRules == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
fRegisterCount = registerCount;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CfaRuleSet*
|
||||||
|
CfaRuleSet::Clone() const
|
||||||
|
{
|
||||||
|
CfaRuleSet* other = new(std::nothrow) CfaRuleSet;
|
||||||
|
if (other == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (other->Init(fRegisterCount) != B_OK) {
|
||||||
|
delete other;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
other->fCfaCfaRule = fCfaCfaRule;
|
||||||
|
memcpy(other->fRegisterRules, fRegisterRules,
|
||||||
|
sizeof(CfaRule) * fRegisterCount);
|
||||||
|
|
||||||
|
return other;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CfaRule*
|
||||||
|
CfaRuleSet::RegisterRule(uint32 index) const
|
||||||
|
{
|
||||||
|
return index < fRegisterCount ? fRegisterRules + index : NULL;
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef CFA_RULE_SET_H
|
||||||
|
#define CFA_RULE_SET_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "CfaRule.h"
|
||||||
|
|
||||||
|
|
||||||
|
class CfaRuleSet {
|
||||||
|
public:
|
||||||
|
CfaRuleSet();
|
||||||
|
|
||||||
|
status_t Init(uint32 registerCount);
|
||||||
|
CfaRuleSet* Clone() const;
|
||||||
|
|
||||||
|
CfaCfaRule* GetCfaCfaRule() { return &fCfaCfaRule; }
|
||||||
|
const CfaCfaRule* GetCfaCfaRule() const { return &fCfaCfaRule; }
|
||||||
|
|
||||||
|
CfaRule* RegisterRule(uint32 index) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
CfaCfaRule fCfaCfaRule;
|
||||||
|
CfaRule* fRegisterRules;
|
||||||
|
uint32 fRegisterCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // CFA_RULE_SET_H
|
||||||
@@ -450,7 +450,13 @@ enum {
|
|||||||
DW_CFA_val_offset_sf = 0x15,
|
DW_CFA_val_offset_sf = 0x15,
|
||||||
DW_CFA_val_expression = 0x16,
|
DW_CFA_val_expression = 0x16,
|
||||||
DW_CFA_lo_user = 0x1c,
|
DW_CFA_lo_user = 0x1c,
|
||||||
DW_CFA_hi_user = 0x3f
|
DW_CFA_hi_user = 0x3f,
|
||||||
|
|
||||||
|
// extensions
|
||||||
|
DW_CFA_MIPS_advance_loc8 = 0x1d,
|
||||||
|
DW_CFA_GNU_window_save = 0x2d,
|
||||||
|
DW_CFA_GNU_args_size = 0x2e,
|
||||||
|
DW_CFA_GNU_negative_offset_extended = 0x2f
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "DwarfFile.h"
|
#include "DwarfFile.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -13,8 +14,10 @@
|
|||||||
#include "AttributeClasses.h"
|
#include "AttributeClasses.h"
|
||||||
#include "AttributeValue.h"
|
#include "AttributeValue.h"
|
||||||
#include "AbbreviationTable.h"
|
#include "AbbreviationTable.h"
|
||||||
|
#include "CfaContext.h"
|
||||||
#include "CompilationUnit.h"
|
#include "CompilationUnit.h"
|
||||||
#include "DataReader.h"
|
#include "DataReader.h"
|
||||||
|
#include "DwarfTargetInterface.h"
|
||||||
#include "ElfFile.h"
|
#include "ElfFile.h"
|
||||||
#include "TagNames.h"
|
#include "TagNames.h"
|
||||||
#include "TargetAddressRangeList.h"
|
#include "TargetAddressRangeList.h"
|
||||||
@@ -29,6 +32,7 @@ DwarfFile::DwarfFile()
|
|||||||
fDebugStringSection(NULL),
|
fDebugStringSection(NULL),
|
||||||
fDebugRangesSection(NULL),
|
fDebugRangesSection(NULL),
|
||||||
fDebugLineSection(NULL),
|
fDebugLineSection(NULL),
|
||||||
|
fDebugFrameSection(NULL),
|
||||||
fCompilationUnits(20, true),
|
fCompilationUnits(20, true),
|
||||||
fCurrentCompilationUnit(NULL),
|
fCurrentCompilationUnit(NULL),
|
||||||
fFinished(false),
|
fFinished(false),
|
||||||
@@ -48,6 +52,7 @@ DwarfFile::~DwarfFile()
|
|||||||
fElfFile->PutSection(fDebugStringSection);
|
fElfFile->PutSection(fDebugStringSection);
|
||||||
fElfFile->PutSection(fDebugRangesSection);
|
fElfFile->PutSection(fDebugRangesSection);
|
||||||
fElfFile->PutSection(fDebugLineSection);
|
fElfFile->PutSection(fDebugLineSection);
|
||||||
|
fElfFile->PutSection(fDebugFrameSection);
|
||||||
delete fElfFile;
|
delete fElfFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,10 +86,11 @@ DwarfFile::Load(const char* fileName)
|
|||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// not mandatory sections
|
// non mandatory sections
|
||||||
fDebugStringSection = fElfFile->GetSection(".debug_str");
|
fDebugStringSection = fElfFile->GetSection(".debug_str");
|
||||||
fDebugRangesSection = fElfFile->GetSection(".debug_ranges");
|
fDebugRangesSection = fElfFile->GetSection(".debug_ranges");
|
||||||
fDebugLineSection = fElfFile->GetSection(".debug_line");
|
fDebugLineSection = fElfFile->GetSection(".debug_line");
|
||||||
|
fDebugFrameSection = fElfFile->GetSection(".debug_frame");
|
||||||
|
|
||||||
// iterate through the debug info section
|
// iterate through the debug info section
|
||||||
DataReader dataReader(fDebugInfoSection->Data(),
|
DataReader dataReader(fDebugInfoSection->Data(),
|
||||||
@@ -215,6 +221,184 @@ DwarfFile::CompilationUnitForDIE(const DebugInfoEntry* entry) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DwarfFile::UnwindCallFrame(target_addr_t location,
|
||||||
|
const DwarfTargetInterface* inputInterface,
|
||||||
|
DwarfTargetInterface* outputInterface, target_addr_t& _framePointer)
|
||||||
|
{
|
||||||
|
if (fDebugFrameSection == NULL)
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
|
||||||
|
printf("DwarfFile::UnwindCallFrame(%#llx)\n", location);
|
||||||
|
|
||||||
|
DataReader dataReader((uint8*)fDebugFrameSection->Data(),
|
||||||
|
fDebugFrameSection->Size());
|
||||||
|
|
||||||
|
while (dataReader.BytesRemaining() > 0) {
|
||||||
|
// length
|
||||||
|
bool dwarf64;
|
||||||
|
uint64 length = dataReader.ReadInitialLength(dwarf64);
|
||||||
|
if (length > (uint64)dataReader.BytesRemaining())
|
||||||
|
return B_BAD_DATA;
|
||||||
|
off_t lengthOffset = dataReader.Offset();
|
||||||
|
|
||||||
|
// CIE ID/CIE pointer
|
||||||
|
uint64 cieID = dwarf64
|
||||||
|
? dataReader.Read<uint64>(0) : dataReader.Read<uint32>(0);
|
||||||
|
if (dwarf64 ? cieID == 0xffffffffffffffffULL : cieID == 0xffffffff) {
|
||||||
|
// this is a CIE -- skip it
|
||||||
|
} else {
|
||||||
|
// this is a FDE
|
||||||
|
dwarf_addr_t initialLocation = dataReader.Read<dwarf_addr_t>(0);
|
||||||
|
dwarf_size_t addressRange = dataReader.Read<dwarf_addr_t>(0);
|
||||||
|
|
||||||
|
if (dataReader.HasOverflow())
|
||||||
|
return B_BAD_DATA;
|
||||||
|
|
||||||
|
if (location >= initialLocation
|
||||||
|
&& location < initialLocation + addressRange) {
|
||||||
|
// This is the FDE we're looking for.
|
||||||
|
off_t remaining = (off_t)length
|
||||||
|
- (dataReader.Offset() - lengthOffset);
|
||||||
|
if (remaining < 0)
|
||||||
|
return B_BAD_DATA;
|
||||||
|
printf(" found fde: length: %llu (%lld), CIE offset: %llu, location: %#lx, range: %#lx\n", length, remaining, cieID,
|
||||||
|
initialLocation, addressRange);
|
||||||
|
|
||||||
|
CfaContext context(location, initialLocation);
|
||||||
|
uint32 registerCount = outputInterface->CountRegisters();
|
||||||
|
status_t error = context.Init(registerCount);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// Init the initial register rules. The DWARF 3 specs on the
|
||||||
|
// matter: "The default rule for all columns before
|
||||||
|
// interpretation of the initial instructions is the undefined
|
||||||
|
// rule. However, an ABI authoring body or a compilation system
|
||||||
|
// authoring body may specify an alternate default value for any
|
||||||
|
// or all columns."
|
||||||
|
// GCC's assumes the "same value" rule for all callee preserved
|
||||||
|
// registers. We set them respectively.
|
||||||
|
for (uint32 i = 0; i < registerCount; i++) {
|
||||||
|
if (outputInterface->IsCalleePreservedRegister(i))
|
||||||
|
context.RegisterRule(i)->SetToSameValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
// process the CIE
|
||||||
|
error = _ParseCIE(context, cieID);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
error = context.SaveInitialRuleSet();
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
error = _ParseFrameInfoInstructions(context,
|
||||||
|
dataReader.Offset(), remaining);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
printf(" found row!\n");
|
||||||
|
|
||||||
|
// apply the rules of the final row
|
||||||
|
// get the frameAddress first
|
||||||
|
dwarf_addr_t frameAddress;
|
||||||
|
CfaCfaRule* cfaCfaRule = context.GetCfaCfaRule();
|
||||||
|
switch (cfaCfaRule->Type()) {
|
||||||
|
case CFA_CFA_RULE_REGISTER_OFFSET:
|
||||||
|
{
|
||||||
|
BVariant value;
|
||||||
|
if (!inputInterface->GetRegisterValue(
|
||||||
|
cfaCfaRule->Register(), value)
|
||||||
|
|| !value.IsNumber()) {
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
frameAddress = value.ToUInt64() + cfaCfaRule->Offset();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CFA_CFA_RULE_EXPRESSION:
|
||||||
|
// TODO: Implement!
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
case CFA_CFA_RULE_UNDEFINED:
|
||||||
|
default:
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
printf(" frame address: %#lx\n", frameAddress);
|
||||||
|
|
||||||
|
// apply the register rules
|
||||||
|
for (uint32 i = 0; i < registerCount; i++) {
|
||||||
|
printf(" reg %lu\n", i);
|
||||||
|
uint32 valueType = outputInterface->RegisterValueType(i);
|
||||||
|
if (valueType == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
CfaRule* rule = context.RegisterRule(i);
|
||||||
|
if (rule == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// apply the rule
|
||||||
|
switch (rule->Type()) {
|
||||||
|
case CFA_RULE_SAME_VALUE:
|
||||||
|
{
|
||||||
|
printf(" -> CFA_RULE_SAME_VALUE\n");
|
||||||
|
BVariant value;
|
||||||
|
if (inputInterface->GetRegisterValue(i, value))
|
||||||
|
outputInterface->SetRegisterValue(i, value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CFA_RULE_LOCATION_OFFSET:
|
||||||
|
{
|
||||||
|
printf(" -> CFA_RULE_LOCATION_OFFSET: %lld\n", rule->Offset());
|
||||||
|
BVariant value;
|
||||||
|
if (inputInterface->ReadValueFromMemory(
|
||||||
|
frameAddress + rule->Offset(), valueType,
|
||||||
|
value)) {
|
||||||
|
outputInterface->SetRegisterValue(i, value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CFA_RULE_VALUE_OFFSET:
|
||||||
|
printf(" -> CFA_RULE_VALUE_OFFSET\n");
|
||||||
|
outputInterface->SetRegisterValue(i,
|
||||||
|
frameAddress + rule->Offset());
|
||||||
|
break;
|
||||||
|
case CFA_RULE_REGISTER:
|
||||||
|
{
|
||||||
|
printf(" -> CFA_RULE_REGISTER\n");
|
||||||
|
BVariant value;
|
||||||
|
if (inputInterface->GetRegisterValue(
|
||||||
|
rule->Register(), value)) {
|
||||||
|
outputInterface->SetRegisterValue(i, value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CFA_RULE_LOCATION_EXPRESSION:
|
||||||
|
printf(" -> CFA_RULE_LOCATION_EXPRESSION\n");
|
||||||
|
// TODO:...
|
||||||
|
break;
|
||||||
|
case CFA_RULE_VALUE_EXPRESSION:
|
||||||
|
printf(" -> CFA_RULE_VALUE_EXPRESSION\n");
|
||||||
|
// TODO:...
|
||||||
|
break;
|
||||||
|
case CFA_RULE_UNDEFINED:
|
||||||
|
printf(" -> CFA_RULE_UNDEFINED\n");
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_framePointer = frameAddress;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dataReader.SeekAbsolute(lengthOffset + length);
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DwarfFile::_ParseCompilationUnit(CompilationUnit* unit)
|
DwarfFile::_ParseCompilationUnit(CompilationUnit* unit)
|
||||||
{
|
{
|
||||||
@@ -736,6 +920,375 @@ printf("DwarfFile::_ParseLineInfo(%p), offset: %lu\n", unit, offset);
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DwarfFile::_ParseCIE(CfaContext& context, dwarf_off_t cieOffset)
|
||||||
|
{
|
||||||
|
if (cieOffset < 0 || cieOffset >= fDebugFrameSection->Size())
|
||||||
|
return B_BAD_DATA;
|
||||||
|
|
||||||
|
DataReader dataReader((uint8*)fDebugFrameSection->Data() + cieOffset,
|
||||||
|
fDebugFrameSection->Size() - cieOffset);
|
||||||
|
|
||||||
|
// length
|
||||||
|
bool dwarf64;
|
||||||
|
uint64 length = dataReader.ReadInitialLength(dwarf64);
|
||||||
|
if (length > (uint64)dataReader.BytesRemaining())
|
||||||
|
return B_BAD_DATA;
|
||||||
|
off_t lengthOffset = dataReader.Offset();
|
||||||
|
|
||||||
|
// CIE ID/CIE pointer
|
||||||
|
uint64 cieID = dwarf64
|
||||||
|
? dataReader.Read<uint64>(0) : dataReader.Read<uint32>(0);
|
||||||
|
if (dwarf64 ? cieID != 0xffffffffffffffffULL : cieID != 0xffffffff)
|
||||||
|
return B_BAD_DATA;
|
||||||
|
|
||||||
|
uint8 version = dataReader.Read<uint8>(0);
|
||||||
|
const char* augmentation = dataReader.ReadString();
|
||||||
|
if (version != 1 || augmentation == NULL || *augmentation != '\0')
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
|
||||||
|
context.SetCodeAlignment(dataReader.ReadUnsignedLEB128(0));
|
||||||
|
context.SetDataAlignment(dataReader.ReadSignedLEB128(0));
|
||||||
|
context.SetReturnAddressRegister(dataReader.ReadUnsignedLEB128(0));
|
||||||
|
printf(" cie: length: %llu, version: %u, augmentation: \"%s\", "
|
||||||
|
"aligment: code: %lu, data: %ld, return address reg: %lu\n",
|
||||||
|
length, version, augmentation, context.CodeAlignment(), context.DataAlignment(),
|
||||||
|
context.ReturnAddressRegister());
|
||||||
|
|
||||||
|
if (dataReader.HasOverflow())
|
||||||
|
return B_BAD_DATA;
|
||||||
|
off_t remaining = (off_t)length
|
||||||
|
- (dataReader.Offset() - lengthOffset);
|
||||||
|
if (remaining < 0)
|
||||||
|
return B_BAD_DATA;
|
||||||
|
|
||||||
|
return _ParseFrameInfoInstructions(context, dataReader.Offset(), remaining);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DwarfFile::_ParseFrameInfoInstructions(CfaContext& context,
|
||||||
|
dwarf_off_t instructionOffset, dwarf_off_t instructionSize)
|
||||||
|
{
|
||||||
|
if (instructionSize <= 0)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
DataReader dataReader(
|
||||||
|
(uint8*)fDebugFrameSection->Data() + instructionOffset,
|
||||||
|
instructionSize);
|
||||||
|
|
||||||
|
while (dataReader.BytesRemaining() > 0) {
|
||||||
|
printf(" [%2lld]", dataReader.BytesRemaining());
|
||||||
|
uint8 opcode = dataReader.Read<uint8>(0);
|
||||||
|
if ((opcode >> 6) != 0) {
|
||||||
|
uint32 operand = opcode & 0x3f;
|
||||||
|
|
||||||
|
switch (opcode >> 6) {
|
||||||
|
case DW_CFA_advance_loc:
|
||||||
|
{
|
||||||
|
printf(" DW_CFA_advance_loc: %#lx\n", operand);
|
||||||
|
dwarf_addr_t location = context.Location()
|
||||||
|
+ operand * context.CodeAlignment();
|
||||||
|
if (location > context.TargetLocation())
|
||||||
|
return B_OK;
|
||||||
|
context.SetLocation(location);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DW_CFA_offset:
|
||||||
|
{
|
||||||
|
uint64 offset = dataReader.ReadUnsignedLEB128(0);
|
||||||
|
printf(" DW_CFA_offset: reg: %lu, offset: %llu\n", operand, offset);
|
||||||
|
if (CfaRule* rule = context.RegisterRule(operand)) {
|
||||||
|
rule->SetToLocationOffset(
|
||||||
|
offset * context.DataAlignment());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DW_CFA_restore:
|
||||||
|
{
|
||||||
|
printf(" DW_CFA_restore: %#lx\n", operand);
|
||||||
|
context.RestoreRegisterRule(operand);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (opcode) {
|
||||||
|
case DW_CFA_nop:
|
||||||
|
{
|
||||||
|
printf(" DW_CFA_nop\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DW_CFA_set_loc:
|
||||||
|
{
|
||||||
|
dwarf_addr_t location = dataReader.Read<dwarf_addr_t>(0);
|
||||||
|
printf(" DW_CFA_set_loc: %#lx\n", location);
|
||||||
|
if (location < context.Location())
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
if (location > context.TargetLocation())
|
||||||
|
return B_OK;
|
||||||
|
context.SetLocation(location);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DW_CFA_advance_loc1:
|
||||||
|
{
|
||||||
|
uint32 delta = dataReader.Read<uint8>(0);
|
||||||
|
printf(" DW_CFA_advance_loc1: %#lx\n", delta);
|
||||||
|
dwarf_addr_t location = context.Location()
|
||||||
|
+ delta * context.CodeAlignment();
|
||||||
|
if (location > context.TargetLocation())
|
||||||
|
return B_OK;
|
||||||
|
context.SetLocation(location);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DW_CFA_advance_loc2:
|
||||||
|
{
|
||||||
|
uint32 delta = dataReader.Read<uint16>(0);
|
||||||
|
printf(" DW_CFA_advance_loc2: %#lx\n", delta);
|
||||||
|
dwarf_addr_t location = context.Location()
|
||||||
|
+ delta * context.CodeAlignment();
|
||||||
|
if (location > context.TargetLocation())
|
||||||
|
return B_OK;
|
||||||
|
context.SetLocation(location);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DW_CFA_advance_loc4:
|
||||||
|
{
|
||||||
|
uint32 delta = dataReader.Read<uint32>(0);
|
||||||
|
printf(" DW_CFA_advance_loc4: %#lx\n", delta);
|
||||||
|
dwarf_addr_t location = context.Location()
|
||||||
|
+ delta * context.CodeAlignment();
|
||||||
|
if (location > context.TargetLocation())
|
||||||
|
return B_OK;
|
||||||
|
context.SetLocation(location);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DW_CFA_offset_extended:
|
||||||
|
{
|
||||||
|
uint32 reg = dataReader.ReadUnsignedLEB128(0);
|
||||||
|
uint64 offset = dataReader.ReadUnsignedLEB128(0);
|
||||||
|
printf(" DW_CFA_offset_extended: reg: %lu, offset: %llu\n", reg, offset);
|
||||||
|
if (CfaRule* rule = context.RegisterRule(reg)) {
|
||||||
|
rule->SetToLocationOffset(
|
||||||
|
offset * context.DataAlignment());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DW_CFA_restore_extended:
|
||||||
|
{
|
||||||
|
uint32 reg = dataReader.ReadUnsignedLEB128(0);
|
||||||
|
printf(" DW_CFA_restore_extended: %#lx\n", reg);
|
||||||
|
context.RestoreRegisterRule(reg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DW_CFA_undefined:
|
||||||
|
{
|
||||||
|
uint32 reg = dataReader.ReadUnsignedLEB128(0);
|
||||||
|
printf(" DW_CFA_undefined: %lu\n", reg);
|
||||||
|
if (CfaRule* rule = context.RegisterRule(reg))
|
||||||
|
rule->SetToUndefined();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DW_CFA_same_value:
|
||||||
|
{
|
||||||
|
uint32 reg = dataReader.ReadUnsignedLEB128(0);
|
||||||
|
printf(" DW_CFA_same_value: %lu\n", reg);
|
||||||
|
if (CfaRule* rule = context.RegisterRule(reg))
|
||||||
|
rule->SetToSameValue();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DW_CFA_register:
|
||||||
|
{
|
||||||
|
uint32 reg1 = dataReader.ReadUnsignedLEB128(0);
|
||||||
|
uint32 reg2 = dataReader.ReadUnsignedLEB128(0);
|
||||||
|
printf(" DW_CFA_register: reg1: %lu, reg2: %lu\n", reg1, reg2);
|
||||||
|
if (CfaRule* rule = context.RegisterRule(reg1))
|
||||||
|
rule->SetToValueOffset(reg2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DW_CFA_remember_state:
|
||||||
|
{
|
||||||
|
printf(" DW_CFA_remember_state\n");
|
||||||
|
status_t error = context.PushRuleSet();
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DW_CFA_restore_state:
|
||||||
|
{
|
||||||
|
printf(" DW_CFA_restore_state\n");
|
||||||
|
status_t error = context.PopRuleSet();
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DW_CFA_def_cfa:
|
||||||
|
{
|
||||||
|
uint32 reg = dataReader.ReadUnsignedLEB128(0);
|
||||||
|
uint64 offset = dataReader.ReadUnsignedLEB128(0);
|
||||||
|
printf(" DW_CFA_def_cfa: reg: %lu, offset: %llu\n", reg, offset);
|
||||||
|
context.GetCfaCfaRule()->SetToRegisterOffset(reg, offset);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DW_CFA_def_cfa_register:
|
||||||
|
{
|
||||||
|
uint32 reg = dataReader.ReadUnsignedLEB128(0);
|
||||||
|
printf(" DW_CFA_def_cfa_register: %lu\n", reg);
|
||||||
|
if (context.GetCfaCfaRule()->Type()
|
||||||
|
!= CFA_CFA_RULE_REGISTER_OFFSET) {
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
context.GetCfaCfaRule()->SetRegister(reg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DW_CFA_def_cfa_offset:
|
||||||
|
{
|
||||||
|
uint64 offset = dataReader.ReadUnsignedLEB128(0);
|
||||||
|
printf(" DW_CFA_def_cfa_offset: %llu\n", offset);
|
||||||
|
if (context.GetCfaCfaRule()->Type()
|
||||||
|
!= CFA_CFA_RULE_REGISTER_OFFSET) {
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
context.GetCfaCfaRule()->SetOffset(offset);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DW_CFA_def_cfa_expression:
|
||||||
|
{
|
||||||
|
uint8* block = (uint8*)dataReader.Data();
|
||||||
|
uint64 blockLength = dataReader.ReadUnsignedLEB128(0);
|
||||||
|
dataReader.Skip(blockLength);
|
||||||
|
printf(" DW_CFA_def_cfa_expression: %p, %llu\n", block, blockLength);
|
||||||
|
context.GetCfaCfaRule()->SetToExpression(block,
|
||||||
|
blockLength);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DW_CFA_expression:
|
||||||
|
{
|
||||||
|
uint32 reg = dataReader.ReadUnsignedLEB128(0);
|
||||||
|
uint8* block = (uint8*)dataReader.Data();
|
||||||
|
uint64 blockLength = dataReader.ReadUnsignedLEB128(0);
|
||||||
|
dataReader.Skip(blockLength);
|
||||||
|
printf(" DW_CFA_expression: reg: %lu, block: %p, %llu\n", reg, block, blockLength);
|
||||||
|
if (CfaRule* rule = context.RegisterRule(reg))
|
||||||
|
rule->SetToLocationExpression(block, blockLength);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DW_CFA_offset_extended_sf:
|
||||||
|
{
|
||||||
|
uint32 reg = dataReader.ReadUnsignedLEB128(0);
|
||||||
|
int64 offset = dataReader.ReadSignedLEB128(0);
|
||||||
|
printf(" DW_CFA_offset_extended: reg: %lu, offset: %lld\n", reg, offset);
|
||||||
|
if (CfaRule* rule = context.RegisterRule(reg)) {
|
||||||
|
rule->SetToLocationOffset(
|
||||||
|
offset * (int32)context.DataAlignment());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DW_CFA_def_cfa_sf:
|
||||||
|
{
|
||||||
|
uint32 reg = dataReader.ReadUnsignedLEB128(0);
|
||||||
|
int64 offset = dataReader.ReadSignedLEB128(0);
|
||||||
|
printf(" DW_CFA_def_cfa_sf: reg: %lu, offset: %lld\n", reg, offset);
|
||||||
|
context.GetCfaCfaRule()->SetToRegisterOffset(reg,
|
||||||
|
offset * (int32)context.DataAlignment());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DW_CFA_def_cfa_offset_sf:
|
||||||
|
{
|
||||||
|
int64 offset = dataReader.ReadSignedLEB128(0);
|
||||||
|
printf(" DW_CFA_def_cfa_offset: %lld\n", offset);
|
||||||
|
if (context.GetCfaCfaRule()->Type()
|
||||||
|
!= CFA_CFA_RULE_REGISTER_OFFSET) {
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
context.GetCfaCfaRule()->SetOffset(
|
||||||
|
offset * (int32)context.DataAlignment());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DW_CFA_val_offset:
|
||||||
|
{
|
||||||
|
uint32 reg = dataReader.ReadUnsignedLEB128(0);
|
||||||
|
uint64 offset = dataReader.ReadUnsignedLEB128(0);
|
||||||
|
printf(" DW_CFA_val_offset: reg: %lu, offset: %llu\n", reg, offset);
|
||||||
|
if (CfaRule* rule = context.RegisterRule(reg)) {
|
||||||
|
rule->SetToValueOffset(
|
||||||
|
offset * context.DataAlignment());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DW_CFA_val_offset_sf:
|
||||||
|
{
|
||||||
|
uint32 reg = dataReader.ReadUnsignedLEB128(0);
|
||||||
|
int64 offset = dataReader.ReadSignedLEB128(0);
|
||||||
|
printf(" DW_CFA_val_offset_sf: reg: %lu, offset: %lld\n", reg, offset);
|
||||||
|
if (CfaRule* rule = context.RegisterRule(reg)) {
|
||||||
|
rule->SetToValueOffset(
|
||||||
|
offset * (int32)context.DataAlignment());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DW_CFA_val_expression:
|
||||||
|
{
|
||||||
|
uint32 reg = dataReader.ReadUnsignedLEB128(0);
|
||||||
|
uint8* block = (uint8*)dataReader.Data();
|
||||||
|
uint64 blockLength = dataReader.ReadUnsignedLEB128(0);
|
||||||
|
dataReader.Skip(blockLength);
|
||||||
|
printf(" DW_CFA_val_expression: reg: %lu, block: %p, %llu\n", reg, block, blockLength);
|
||||||
|
if (CfaRule* rule = context.RegisterRule(reg))
|
||||||
|
rule->SetToValueExpression(block, blockLength);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// extensions
|
||||||
|
case DW_CFA_MIPS_advance_loc8:
|
||||||
|
{
|
||||||
|
uint64 delta = dataReader.Read<uint64>(0);
|
||||||
|
printf(" DW_CFA_MIPS_advance_loc8: %#llx\n", delta);
|
||||||
|
dwarf_addr_t location = context.Location()
|
||||||
|
+ delta * context.CodeAlignment();
|
||||||
|
if (location > context.TargetLocation())
|
||||||
|
return B_OK;
|
||||||
|
context.SetLocation(location);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DW_CFA_GNU_window_save:
|
||||||
|
{
|
||||||
|
// SPARC specific, no args
|
||||||
|
printf(" DW_CFA_GNU_window_save\n");
|
||||||
|
// TODO: Implement once we have SPARC support!
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DW_CFA_GNU_args_size:
|
||||||
|
{
|
||||||
|
// Updates the total size of arguments on the stack.
|
||||||
|
uint64 size = dataReader.ReadUnsignedLEB128(0);
|
||||||
|
printf(" DW_CFA_GNU_args_size: %llu\n", size);
|
||||||
|
// TODO: Implement!
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DW_CFA_GNU_negative_offset_extended:
|
||||||
|
{
|
||||||
|
// obsolete
|
||||||
|
uint32 reg = dataReader.ReadUnsignedLEB128(0);
|
||||||
|
int64 offset = dataReader.ReadSignedLEB128(0);
|
||||||
|
printf(" DW_CFA_GNU_negative_offset_extended: reg: %lu, offset: %lld\n", reg, offset);
|
||||||
|
if (CfaRule* rule = context.RegisterRule(reg)) {
|
||||||
|
rule->SetToLocationOffset(
|
||||||
|
offset * (int32)context.DataAlignment());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
printf(" unknown opcode %u!\n", opcode);
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DwarfFile::_GetAbbreviationTable(off_t offset, AbbreviationTable*& _table)
|
DwarfFile::_GetAbbreviationTable(off_t offset, AbbreviationTable*& _table)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#ifndef DWARF_FILE_H
|
#ifndef DWARF_FILE_H
|
||||||
#define DWARF_FILE_H
|
#define DWARF_FILE_H
|
||||||
|
|
||||||
|
|
||||||
#include <ObjectList.h>
|
#include <ObjectList.h>
|
||||||
#include <util/DoublyLinkedList.h>
|
#include <util/DoublyLinkedList.h>
|
||||||
|
|
||||||
@@ -13,8 +14,10 @@
|
|||||||
|
|
||||||
class AbbreviationEntry;
|
class AbbreviationEntry;
|
||||||
class AbbreviationTable;
|
class AbbreviationTable;
|
||||||
|
class CfaContext;
|
||||||
class CompilationUnit;
|
class CompilationUnit;
|
||||||
class DataReader;
|
class DataReader;
|
||||||
|
class DwarfTargetInterface;
|
||||||
class ElfFile;
|
class ElfFile;
|
||||||
class ElfSection;
|
class ElfSection;
|
||||||
class TargetAddressRangeList;
|
class TargetAddressRangeList;
|
||||||
@@ -36,6 +39,11 @@ public:
|
|||||||
CompilationUnit* CompilationUnitForDIE(
|
CompilationUnit* CompilationUnitForDIE(
|
||||||
const DebugInfoEntry* entry) const;
|
const DebugInfoEntry* entry) const;
|
||||||
|
|
||||||
|
status_t UnwindCallFrame(target_addr_t location,
|
||||||
|
const DwarfTargetInterface* inputInterface,
|
||||||
|
DwarfTargetInterface* outputInterface,
|
||||||
|
target_addr_t& _framePointer);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef DoublyLinkedList<AbbreviationTable> AbbreviationTableList;
|
typedef DoublyLinkedList<AbbreviationTable> AbbreviationTableList;
|
||||||
typedef BObjectList<CompilationUnit> CompilationUnitList;
|
typedef BObjectList<CompilationUnit> CompilationUnitList;
|
||||||
@@ -53,6 +61,12 @@ private:
|
|||||||
|
|
||||||
status_t _ParseLineInfo(CompilationUnit* unit);
|
status_t _ParseLineInfo(CompilationUnit* unit);
|
||||||
|
|
||||||
|
status_t _ParseCIE(CfaContext& context,
|
||||||
|
dwarf_off_t cieOffset);
|
||||||
|
status_t _ParseFrameInfoInstructions(CfaContext& context,
|
||||||
|
dwarf_off_t instructionOffset,
|
||||||
|
dwarf_off_t instructionSize);
|
||||||
|
|
||||||
status_t _GetAbbreviationTable(off_t offset,
|
status_t _GetAbbreviationTable(off_t offset,
|
||||||
AbbreviationTable*& _table);
|
AbbreviationTable*& _table);
|
||||||
|
|
||||||
@@ -69,6 +83,7 @@ private:
|
|||||||
ElfSection* fDebugStringSection;
|
ElfSection* fDebugStringSection;
|
||||||
ElfSection* fDebugRangesSection;
|
ElfSection* fDebugRangesSection;
|
||||||
ElfSection* fDebugLineSection;
|
ElfSection* fDebugLineSection;
|
||||||
|
ElfSection* fDebugFrameSection;
|
||||||
AbbreviationTableList fAbbreviationTables;
|
AbbreviationTableList fAbbreviationTables;
|
||||||
DebugInfoEntryFactory fDebugInfoFactory;
|
DebugInfoEntryFactory fDebugInfoFactory;
|
||||||
CompilationUnitList fCompilationUnits;
|
CompilationUnitList fCompilationUnits;
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "DwarfTargetInterface.h"
|
||||||
|
|
||||||
|
|
||||||
|
DwarfTargetInterface::~DwarfTargetInterface()
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef DWARF_TARGET_INTERFACE_H
|
||||||
|
#define DWARF_TARGET_INTERFACE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <Variant.h>
|
||||||
|
|
||||||
|
#include "Types.h"
|
||||||
|
|
||||||
|
|
||||||
|
class Register;
|
||||||
|
|
||||||
|
|
||||||
|
class DwarfTargetInterface {
|
||||||
|
public:
|
||||||
|
virtual ~DwarfTargetInterface();
|
||||||
|
|
||||||
|
virtual uint32 CountRegisters() const = 0;
|
||||||
|
virtual uint32 RegisterValueType(uint32 index) const = 0;
|
||||||
|
|
||||||
|
virtual bool GetRegisterValue(uint32 index,
|
||||||
|
BVariant& _value) const = 0;
|
||||||
|
virtual bool SetRegisterValue(uint32 index,
|
||||||
|
const BVariant& value) = 0;
|
||||||
|
virtual bool IsCalleePreservedRegister(uint32 index) const
|
||||||
|
= 0;
|
||||||
|
|
||||||
|
virtual bool ReadMemory(target_addr_t address, void* buffer,
|
||||||
|
size_t size) const = 0;
|
||||||
|
virtual bool ReadValueFromMemory(target_addr_t address,
|
||||||
|
uint32 valueType, BVariant& _value) const
|
||||||
|
= 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // DWARF_TARGET_INTERFACE_H
|
||||||
@@ -17,11 +17,14 @@ MergeObject Debugger_dwarf.o
|
|||||||
AbbreviationTable.cpp
|
AbbreviationTable.cpp
|
||||||
AttributeClasses.cpp
|
AttributeClasses.cpp
|
||||||
AttributeValue.cpp
|
AttributeValue.cpp
|
||||||
|
CfaContext.cpp
|
||||||
|
CfaRuleSet.cpp
|
||||||
CompilationUnit.cpp
|
CompilationUnit.cpp
|
||||||
DebugInfoEntries.cpp
|
DebugInfoEntries.cpp
|
||||||
DebugInfoEntry.cpp
|
DebugInfoEntry.cpp
|
||||||
DwarfFile.cpp
|
DwarfFile.cpp
|
||||||
DwarfManager.cpp
|
DwarfManager.cpp
|
||||||
|
DwarfTargetInterface.cpp
|
||||||
DwarfUtils.cpp
|
DwarfUtils.cpp
|
||||||
LineNumberProgram.cpp
|
LineNumberProgram.cpp
|
||||||
SourceLanguageInfo.cpp
|
SourceLanguageInfo.cpp
|
||||||
|
|||||||
Reference in New Issue
Block a user