* 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:
parent
614e1dc42f
commit
f7526300d9
@ -18,26 +18,131 @@
|
||||
|
||||
#include "Architecture.h"
|
||||
#include "CompilationUnit.h"
|
||||
#include "CpuState.h"
|
||||
#include "DebugInfoEntries.h"
|
||||
#include "Dwarf.h"
|
||||
#include "DwarfFile.h"
|
||||
#include "DwarfFunctionDebugInfo.h"
|
||||
#include "DwarfTargetInterface.h"
|
||||
#include "DwarfUtils.h"
|
||||
#include "ElfFile.h"
|
||||
#include "FileManager.h"
|
||||
#include "FileSourceCode.h"
|
||||
#include "LocatableFile.h"
|
||||
#include "Register.h"
|
||||
#include "RegisterMap.h"
|
||||
#include "SourceFile.h"
|
||||
#include "StackFrame.h"
|
||||
#include "Statement.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,
|
||||
Architecture* architecture, FileManager* fileManager, DwarfFile* file)
|
||||
Architecture* architecture, TeamMemory* teamMemory,
|
||||
FileManager* fileManager, DwarfFile* file)
|
||||
:
|
||||
fLock("dwarf image debug info"),
|
||||
fImageInfo(imageInfo),
|
||||
fArchitecture(architecture),
|
||||
fTeamMemory(teamMemory),
|
||||
fFileManager(fileManager),
|
||||
fFile(file),
|
||||
fTextSegment(NULL),
|
||||
@ -188,8 +293,64 @@ DwarfImageDebugInfo::CreateFrame(Image* image, FunctionDebugInfo* function,
|
||||
CpuState* cpuState, StackFrame*& _previousFrame,
|
||||
CpuState*& _previousCpuState)
|
||||
{
|
||||
// TODO:...
|
||||
return B_UNSUPPORTED;
|
||||
int32 registerCount = fArchitecture->CountRegisters();
|
||||
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 LocatableFile;
|
||||
class SourceCode;
|
||||
class TeamMemory;
|
||||
|
||||
|
||||
class DwarfImageDebugInfo : public SpecificImageDebugInfo {
|
||||
public:
|
||||
DwarfImageDebugInfo(const ImageInfo& imageInfo,
|
||||
Architecture* architecture,
|
||||
TeamMemory* teamMemory,
|
||||
FileManager* fileManager, DwarfFile* file);
|
||||
virtual ~DwarfImageDebugInfo();
|
||||
|
||||
@ -57,6 +59,9 @@ public:
|
||||
virtual status_t AddSourceCodeInfo(LocatableFile* file,
|
||||
FileSourceCode* sourceCode);
|
||||
|
||||
private:
|
||||
struct UnwindTargetInterface;
|
||||
|
||||
private:
|
||||
status_t _AddSourceCodeInfo(CompilationUnit* unit,
|
||||
FileSourceCode* sourceCode,
|
||||
@ -68,6 +73,7 @@ private:
|
||||
BLocker fLock;
|
||||
ImageInfo fImageInfo;
|
||||
Architecture* fArchitecture;
|
||||
TeamMemory* fTeamMemory;
|
||||
FileManager* fFileManager;
|
||||
DwarfFile* fFile;
|
||||
ElfSegment* fTextSegment;
|
||||
|
@ -15,9 +15,10 @@
|
||||
|
||||
|
||||
DwarfTeamDebugInfo::DwarfTeamDebugInfo(Architecture* architecture,
|
||||
FileManager* fileManager)
|
||||
TeamMemory* teamMemory, FileManager* fileManager)
|
||||
:
|
||||
fArchitecture(architecture),
|
||||
fTeamMemory(teamMemory),
|
||||
fFileManager(fileManager),
|
||||
fManager(NULL)
|
||||
{
|
||||
@ -64,7 +65,7 @@ DwarfTeamDebugInfo::CreateImageDebugInfo(const ImageInfo& imageInfo,
|
||||
|
||||
// create the image debug info
|
||||
DwarfImageDebugInfo* debuggerInfo = new(std::nothrow) DwarfImageDebugInfo(
|
||||
imageInfo, fArchitecture, fFileManager, file);
|
||||
imageInfo, fArchitecture, fTeamMemory, fFileManager, file);
|
||||
if (debuggerInfo == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
|
@ -12,11 +12,13 @@ class Architecture;
|
||||
class DwarfManager;
|
||||
class FileManager;
|
||||
class ImageInfo;
|
||||
class TeamMemory;
|
||||
|
||||
|
||||
class DwarfTeamDebugInfo : public SpecificTeamDebugInfo {
|
||||
public:
|
||||
DwarfTeamDebugInfo(Architecture* architecture,
|
||||
TeamMemory* teamMemory,
|
||||
FileManager* fileManager);
|
||||
virtual ~DwarfTeamDebugInfo();
|
||||
|
||||
@ -28,6 +30,7 @@ public:
|
||||
|
||||
private:
|
||||
Architecture* fArchitecture;
|
||||
TeamMemory* fTeamMemory;
|
||||
FileManager* fFileManager;
|
||||
DwarfManager* fManager;
|
||||
};
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <AutoLocker.h>
|
||||
|
||||
#include "Architecture.h"
|
||||
#include "DebuggerInterface.h"
|
||||
#include "DebuggerTeamDebugInfo.h"
|
||||
#include "DisassembledCode.h"
|
||||
#include "DwarfTeamDebugInfo.h"
|
||||
@ -298,7 +299,7 @@ TeamDebugInfo::Init()
|
||||
|
||||
// DWARF
|
||||
DwarfTeamDebugInfo* dwarfInfo = new(std::nothrow) DwarfTeamDebugInfo(
|
||||
fArchitecture, fFileManager);
|
||||
fArchitecture, fDebuggerInterface, fFileManager);
|
||||
if (dwarfInfo == NULL || !fSpecificInfos.AddItem(dwarfInfo)) {
|
||||
delete dwarfInfo;
|
||||
return B_NO_MEMORY;
|
||||
|
117
src/apps/debugger/dwarf/CfaContext.cpp
Normal file
117
src/apps/debugger/dwarf/CfaContext.cpp
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* 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);
|
||||
}
|
||||
}
|
68
src/apps/debugger/dwarf/CfaContext.h
Normal file
68
src/apps/debugger/dwarf/CfaContext.h
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* 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
|
212
src/apps/debugger/dwarf/CfaRule.h
Normal file
212
src/apps/debugger/dwarf/CfaRule.h
Normal file
@ -0,0 +1,212 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* 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
|
59
src/apps/debugger/dwarf/CfaRuleSet.cpp
Normal file
59
src/apps/debugger/dwarf/CfaRuleSet.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* 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;
|
||||
}
|
31
src/apps/debugger/dwarf/CfaRuleSet.h
Normal file
31
src/apps/debugger/dwarf/CfaRuleSet.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* 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_expression = 0x16,
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
#include "DwarfFile.h"
|
||||
|
||||
#include <algorithm>
|
||||
@ -13,8 +14,10 @@
|
||||
#include "AttributeClasses.h"
|
||||
#include "AttributeValue.h"
|
||||
#include "AbbreviationTable.h"
|
||||
#include "CfaContext.h"
|
||||
#include "CompilationUnit.h"
|
||||
#include "DataReader.h"
|
||||
#include "DwarfTargetInterface.h"
|
||||
#include "ElfFile.h"
|
||||
#include "TagNames.h"
|
||||
#include "TargetAddressRangeList.h"
|
||||
@ -29,6 +32,7 @@ DwarfFile::DwarfFile()
|
||||
fDebugStringSection(NULL),
|
||||
fDebugRangesSection(NULL),
|
||||
fDebugLineSection(NULL),
|
||||
fDebugFrameSection(NULL),
|
||||
fCompilationUnits(20, true),
|
||||
fCurrentCompilationUnit(NULL),
|
||||
fFinished(false),
|
||||
@ -48,6 +52,7 @@ DwarfFile::~DwarfFile()
|
||||
fElfFile->PutSection(fDebugStringSection);
|
||||
fElfFile->PutSection(fDebugRangesSection);
|
||||
fElfFile->PutSection(fDebugLineSection);
|
||||
fElfFile->PutSection(fDebugFrameSection);
|
||||
delete fElfFile;
|
||||
}
|
||||
|
||||
@ -81,10 +86,11 @@ DwarfFile::Load(const char* fileName)
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
// not mandatory sections
|
||||
// non mandatory sections
|
||||
fDebugStringSection = fElfFile->GetSection(".debug_str");
|
||||
fDebugRangesSection = fElfFile->GetSection(".debug_ranges");
|
||||
fDebugLineSection = fElfFile->GetSection(".debug_line");
|
||||
fDebugFrameSection = fElfFile->GetSection(".debug_frame");
|
||||
|
||||
// iterate through the debug info section
|
||||
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
|
||||
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
|
||||
DwarfFile::_GetAbbreviationTable(off_t offset, AbbreviationTable*& _table)
|
||||
{
|
||||
|
@ -5,6 +5,7 @@
|
||||
#ifndef DWARF_FILE_H
|
||||
#define DWARF_FILE_H
|
||||
|
||||
|
||||
#include <ObjectList.h>
|
||||
#include <util/DoublyLinkedList.h>
|
||||
|
||||
@ -13,8 +14,10 @@
|
||||
|
||||
class AbbreviationEntry;
|
||||
class AbbreviationTable;
|
||||
class CfaContext;
|
||||
class CompilationUnit;
|
||||
class DataReader;
|
||||
class DwarfTargetInterface;
|
||||
class ElfFile;
|
||||
class ElfSection;
|
||||
class TargetAddressRangeList;
|
||||
@ -36,6 +39,11 @@ public:
|
||||
CompilationUnit* CompilationUnitForDIE(
|
||||
const DebugInfoEntry* entry) const;
|
||||
|
||||
status_t UnwindCallFrame(target_addr_t location,
|
||||
const DwarfTargetInterface* inputInterface,
|
||||
DwarfTargetInterface* outputInterface,
|
||||
target_addr_t& _framePointer);
|
||||
|
||||
private:
|
||||
typedef DoublyLinkedList<AbbreviationTable> AbbreviationTableList;
|
||||
typedef BObjectList<CompilationUnit> CompilationUnitList;
|
||||
@ -53,6 +61,12 @@ private:
|
||||
|
||||
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,
|
||||
AbbreviationTable*& _table);
|
||||
|
||||
@ -69,6 +83,7 @@ private:
|
||||
ElfSection* fDebugStringSection;
|
||||
ElfSection* fDebugRangesSection;
|
||||
ElfSection* fDebugLineSection;
|
||||
ElfSection* fDebugFrameSection;
|
||||
AbbreviationTableList fAbbreviationTables;
|
||||
DebugInfoEntryFactory fDebugInfoFactory;
|
||||
CompilationUnitList fCompilationUnits;
|
||||
|
12
src/apps/debugger/dwarf/DwarfTargetInterface.cpp
Normal file
12
src/apps/debugger/dwarf/DwarfTargetInterface.cpp
Normal file
@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "DwarfTargetInterface.h"
|
||||
|
||||
|
||||
DwarfTargetInterface::~DwarfTargetInterface()
|
||||
{
|
||||
}
|
39
src/apps/debugger/dwarf/DwarfTargetInterface.h
Normal file
39
src/apps/debugger/dwarf/DwarfTargetInterface.h
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* 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
|
||||
AttributeClasses.cpp
|
||||
AttributeValue.cpp
|
||||
CfaContext.cpp
|
||||
CfaRuleSet.cpp
|
||||
CompilationUnit.cpp
|
||||
DebugInfoEntries.cpp
|
||||
DebugInfoEntry.cpp
|
||||
DwarfFile.cpp
|
||||
DwarfManager.cpp
|
||||
DwarfTargetInterface.cpp
|
||||
DwarfUtils.cpp
|
||||
LineNumberProgram.cpp
|
||||
SourceLanguageInfo.cpp
|
||||
|
Loading…
Reference in New Issue
Block a user