More work on the architecture abstraction, particularly regarding information
about what registers the architecture has and how to get them from the CpuState. Implemented the respective x86 part. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31109 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -32,6 +32,7 @@ Application Debugger :
|
|||||||
# arch
|
# arch
|
||||||
Architecture.cpp
|
Architecture.cpp
|
||||||
CpuState.cpp
|
CpuState.cpp
|
||||||
|
Register.cpp
|
||||||
StackFrame.cpp
|
StackFrame.cpp
|
||||||
StackTrace.cpp
|
StackTrace.cpp
|
||||||
|
|
||||||
|
|||||||
@@ -16,3 +16,10 @@ Architecture::Architecture(DebuggerInterface* debuggerInterface)
|
|||||||
Architecture::~Architecture()
|
Architecture::~Architecture()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Architecture::Init()
|
||||||
|
{
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
class CpuState;
|
class CpuState;
|
||||||
class DebuggerInterface;
|
class DebuggerInterface;
|
||||||
|
class Register;
|
||||||
|
|
||||||
|
|
||||||
class Architecture : public Referenceable {
|
class Architecture : public Referenceable {
|
||||||
@@ -20,6 +21,11 @@ public:
|
|||||||
DebuggerInterface* debuggerInterface);
|
DebuggerInterface* debuggerInterface);
|
||||||
virtual ~Architecture();
|
virtual ~Architecture();
|
||||||
|
|
||||||
|
virtual status_t Init();
|
||||||
|
|
||||||
|
virtual int32 CountRegisters() const = 0;
|
||||||
|
virtual const Register* Registers() const = 0;
|
||||||
|
|
||||||
virtual status_t CreateCpuState(const void* cpuStateData,
|
virtual status_t CreateCpuState(const void* cpuStateData,
|
||||||
size_t size, CpuState*& _state) = 0;
|
size_t size, CpuState*& _state) = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -9,10 +9,18 @@
|
|||||||
|
|
||||||
#include <Referenceable.h>
|
#include <Referenceable.h>
|
||||||
|
|
||||||
|
#include "Variant.h"
|
||||||
|
|
||||||
|
|
||||||
|
class Register;
|
||||||
|
|
||||||
|
|
||||||
class CpuState : public Referenceable {
|
class CpuState : public Referenceable {
|
||||||
public:
|
public:
|
||||||
virtual ~CpuState();
|
virtual ~CpuState();
|
||||||
|
|
||||||
|
virtual bool GetRegisterValue(const Register* reg,
|
||||||
|
Variant& _value) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Register.h"
|
||||||
|
|
||||||
|
|
||||||
|
Register::Register(int32 index, const char* name, register_format format,
|
||||||
|
uint32 bitSize, register_type type)
|
||||||
|
:
|
||||||
|
fIndex(index),
|
||||||
|
fName(name),
|
||||||
|
fFormat(format),
|
||||||
|
fBitSize(bitSize),
|
||||||
|
fType(type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Register::Register(const Register& other)
|
||||||
|
:
|
||||||
|
fIndex(other.fIndex),
|
||||||
|
fName(other.fName),
|
||||||
|
fFormat(other.fFormat),
|
||||||
|
fBitSize(other.fBitSize),
|
||||||
|
fType(other.fType)
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef REGISTER_H
|
||||||
|
#define REGISTER_H
|
||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
|
||||||
|
enum register_format {
|
||||||
|
REGISTER_FORMAT_INTEGER,
|
||||||
|
REGISTER_FORMAT_FLOAT
|
||||||
|
};
|
||||||
|
|
||||||
|
enum register_type {
|
||||||
|
REGISTER_TYPE_PROGRAM_COUNTER,
|
||||||
|
REGISTER_TYPE_STACK_POINTER,
|
||||||
|
REGISTER_TYPE_GENERAL_PURPOSE,
|
||||||
|
REGISTER_TYPE_SPECIAL_PURPOSE,
|
||||||
|
REGISTER_TYPE_EXTENDED
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Register {
|
||||||
|
public:
|
||||||
|
Register(int32 index, const char* name,
|
||||||
|
register_format format, uint32 bitSize,
|
||||||
|
register_type type);
|
||||||
|
// name will not be cloned
|
||||||
|
Register(const Register& other);
|
||||||
|
|
||||||
|
int32 Index() const { return fIndex; }
|
||||||
|
const char* Name() const { return fName; }
|
||||||
|
register_format Format() const { return fFormat; }
|
||||||
|
uint32 BitSize() const { return fBitSize; }
|
||||||
|
register_type Type() const { return fType; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
int32 fIndex;
|
||||||
|
const char* fName;
|
||||||
|
register_format fFormat;
|
||||||
|
uint32 fBitSize;
|
||||||
|
register_type fType;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // REGISTER_H
|
||||||
@@ -22,6 +22,65 @@ ArchitectureX86::~ArchitectureX86()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ArchitectureX86::Init()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
_AddIntegerRegister(X86_REGISTER_EIP, "eip", 32,
|
||||||
|
REGISTER_TYPE_PROGRAM_COUNTER);
|
||||||
|
_AddIntegerRegister(X86_REGISTER_ESP, "esp", 32,
|
||||||
|
REGISTER_TYPE_STACK_POINTER);
|
||||||
|
_AddIntegerRegister(X86_REGISTER_EBP, "ebp", 32,
|
||||||
|
REGISTER_TYPE_GENERAL_PURPOSE);
|
||||||
|
|
||||||
|
_AddIntegerRegister(X86_REGISTER_EAX, "eax", 32,
|
||||||
|
REGISTER_TYPE_GENERAL_PURPOSE);
|
||||||
|
_AddIntegerRegister(X86_REGISTER_EBX, "ebx", 32,
|
||||||
|
REGISTER_TYPE_GENERAL_PURPOSE);
|
||||||
|
_AddIntegerRegister(X86_REGISTER_ECX, "ecx", 32,
|
||||||
|
REGISTER_TYPE_GENERAL_PURPOSE);
|
||||||
|
_AddIntegerRegister(X86_REGISTER_EDX, "edx", 32,
|
||||||
|
REGISTER_TYPE_GENERAL_PURPOSE);
|
||||||
|
|
||||||
|
_AddIntegerRegister(X86_REGISTER_ESI, "esi", 32,
|
||||||
|
REGISTER_TYPE_GENERAL_PURPOSE);
|
||||||
|
_AddIntegerRegister(X86_REGISTER_EDI, "edi", 32,
|
||||||
|
REGISTER_TYPE_GENERAL_PURPOSE);
|
||||||
|
|
||||||
|
_AddIntegerRegister(X86_REGISTER_CS, "cs", 16,
|
||||||
|
REGISTER_TYPE_SPECIAL_PURPOSE);
|
||||||
|
_AddIntegerRegister(X86_REGISTER_DS, "ds", 16,
|
||||||
|
REGISTER_TYPE_SPECIAL_PURPOSE);
|
||||||
|
_AddIntegerRegister(X86_REGISTER_ES, "es", 16,
|
||||||
|
REGISTER_TYPE_SPECIAL_PURPOSE);
|
||||||
|
_AddIntegerRegister(X86_REGISTER_FS, "fs", 16,
|
||||||
|
REGISTER_TYPE_SPECIAL_PURPOSE);
|
||||||
|
_AddIntegerRegister(X86_REGISTER_GS, "gs", 16,
|
||||||
|
REGISTER_TYPE_SPECIAL_PURPOSE);
|
||||||
|
_AddIntegerRegister(X86_REGISTER_SS, "ss", 16,
|
||||||
|
REGISTER_TYPE_SPECIAL_PURPOSE);
|
||||||
|
} catch (std::bad_alloc) {
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
ArchitectureX86::CountRegisters() const
|
||||||
|
{
|
||||||
|
return fRegisters.Count();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Register*
|
||||||
|
ArchitectureX86::Registers() const
|
||||||
|
{
|
||||||
|
return fRegisters.Elements();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
ArchitectureX86::CreateCpuState(const void* cpuStateData, size_t size,
|
ArchitectureX86::CreateCpuState(const void* cpuStateData, size_t size,
|
||||||
CpuState*& _state)
|
CpuState*& _state)
|
||||||
@@ -37,3 +96,20 @@ ArchitectureX86::CreateCpuState(const void* cpuStateData, size_t size,
|
|||||||
_state = state;
|
_state = state;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ArchitectureX86::_AddRegister(int32 index, const char* name,
|
||||||
|
register_format format, uint32 bitSize, register_type type)
|
||||||
|
{
|
||||||
|
if (!fRegisters.Add(Register(index, name, format, bitSize, type)))
|
||||||
|
throw std::bad_alloc();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ArchitectureX86::_AddIntegerRegister(int32 index, const char* name,
|
||||||
|
uint32 bitSize, register_type type)
|
||||||
|
{
|
||||||
|
_AddRegister(index, name, REGISTER_FORMAT_INTEGER, bitSize, type);
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
#define ARCHITECTURE_X86_H
|
#define ARCHITECTURE_X86_H
|
||||||
|
|
||||||
#include "Architecture.h"
|
#include "Architecture.h"
|
||||||
|
#include "Array.h"
|
||||||
|
#include "Register.h"
|
||||||
|
|
||||||
|
|
||||||
class ArchitectureX86 : public Architecture {
|
class ArchitectureX86 : public Architecture {
|
||||||
@@ -14,8 +16,24 @@ public:
|
|||||||
DebuggerInterface* debuggerInterface);
|
DebuggerInterface* debuggerInterface);
|
||||||
virtual ~ArchitectureX86();
|
virtual ~ArchitectureX86();
|
||||||
|
|
||||||
|
virtual status_t Init();
|
||||||
|
|
||||||
|
virtual int32 CountRegisters() const;
|
||||||
|
virtual const Register* Registers() const;
|
||||||
|
|
||||||
virtual status_t CreateCpuState(const void* cpuStateData,
|
virtual status_t CreateCpuState(const void* cpuStateData,
|
||||||
size_t size, CpuState*& _state);
|
size_t size, CpuState*& _state);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _AddRegister(int32 index, const char* name,
|
||||||
|
register_format format, uint32 bitSize,
|
||||||
|
register_type type);
|
||||||
|
void _AddIntegerRegister(int32 index,
|
||||||
|
const char* name, uint32 bitSize,
|
||||||
|
register_type type);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Array<Register> fRegisters;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,14 +5,88 @@
|
|||||||
|
|
||||||
#include "CpuStateX86.h"
|
#include "CpuStateX86.h"
|
||||||
|
|
||||||
|
#include "Register.h"
|
||||||
|
|
||||||
|
|
||||||
CpuStateX86::CpuStateX86(const debug_cpu_state_x86& state)
|
CpuStateX86::CpuStateX86(const debug_cpu_state_x86& state)
|
||||||
:
|
:
|
||||||
fState(state)
|
fSetRegisters()
|
||||||
{
|
{
|
||||||
|
SetIntRegister(X86_REGISTER_EIP, state.eip);
|
||||||
|
SetIntRegister(X86_REGISTER_ESP, state.user_esp);
|
||||||
|
SetIntRegister(X86_REGISTER_EBP, state.ebp);
|
||||||
|
SetIntRegister(X86_REGISTER_EAX, state.eax);
|
||||||
|
SetIntRegister(X86_REGISTER_EBX, state.ebx);
|
||||||
|
SetIntRegister(X86_REGISTER_ECX, state.ecx);
|
||||||
|
SetIntRegister(X86_REGISTER_EDX, state.edx);
|
||||||
|
SetIntRegister(X86_REGISTER_ESI, state.esi);
|
||||||
|
SetIntRegister(X86_REGISTER_EDI, state.edi);
|
||||||
|
SetIntRegister(X86_REGISTER_CS, state.cs);
|
||||||
|
SetIntRegister(X86_REGISTER_DS, state.ds);
|
||||||
|
SetIntRegister(X86_REGISTER_ES, state.es);
|
||||||
|
SetIntRegister(X86_REGISTER_FS, state.fs);
|
||||||
|
SetIntRegister(X86_REGISTER_GS, state.gs);
|
||||||
|
SetIntRegister(X86_REGISTER_SS, state.user_ss);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CpuStateX86::~CpuStateX86()
|
CpuStateX86::~CpuStateX86()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
CpuStateX86::GetRegisterValue(const Register* reg, Variant& _value)
|
||||||
|
{
|
||||||
|
int32 index = reg->Index();
|
||||||
|
if (!IsRegisterSet(index))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (index >= X86_INT_REGISTER_END)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (reg->BitSize() == 16)
|
||||||
|
_value.SetTo((uint16)fIntRegisters[index]);
|
||||||
|
else
|
||||||
|
_value.SetTo(fIntRegisters[index]);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
CpuStateX86::IsRegisterSet(int32 index) const
|
||||||
|
{
|
||||||
|
return index >= 0 && index < X86_REGISTER_COUNT && fSetRegisters[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32
|
||||||
|
CpuStateX86::IntRegisterValue(int32 index) const
|
||||||
|
{
|
||||||
|
if (!IsRegisterSet(index) || index >= X86_INT_REGISTER_END)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return fIntRegisters[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CpuStateX86::SetIntRegister(int32 index, uint32 value)
|
||||||
|
{
|
||||||
|
if (index < 0 || index >= X86_INT_REGISTER_END)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fIntRegisters[index] = value;
|
||||||
|
fSetRegisters[index] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CpuStateX86::UnsetRegister(int32 index)
|
||||||
|
{
|
||||||
|
if (index < 0 || index >= X86_REGISTER_COUNT)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fSetRegisters[index] = 0;
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
#ifndef CPU_STATE_X86_H
|
#ifndef CPU_STATE_X86_H
|
||||||
#define CPU_STATE_X86_H
|
#define CPU_STATE_X86_H
|
||||||
|
|
||||||
|
#include <bitset>
|
||||||
|
|
||||||
#include <debugger.h>
|
#include <debugger.h>
|
||||||
|
|
||||||
#include "CpuState.h"
|
#include "CpuState.h"
|
||||||
@@ -13,16 +15,50 @@
|
|||||||
typedef debug_cpu_state debug_cpu_state_x86;
|
typedef debug_cpu_state debug_cpu_state_x86;
|
||||||
// TODO: Should be defined by <debugger.h>!
|
// TODO: Should be defined by <debugger.h>!
|
||||||
|
|
||||||
|
enum {
|
||||||
|
X86_REGISTER_EIP = 0,
|
||||||
|
X86_REGISTER_ESP,
|
||||||
|
X86_REGISTER_EBP,
|
||||||
|
|
||||||
|
X86_REGISTER_EAX,
|
||||||
|
X86_REGISTER_EBX,
|
||||||
|
X86_REGISTER_ECX,
|
||||||
|
X86_REGISTER_EDX,
|
||||||
|
|
||||||
|
X86_REGISTER_ESI,
|
||||||
|
X86_REGISTER_EDI,
|
||||||
|
|
||||||
|
X86_REGISTER_CS,
|
||||||
|
X86_REGISTER_DS,
|
||||||
|
X86_REGISTER_ES,
|
||||||
|
X86_REGISTER_FS,
|
||||||
|
X86_REGISTER_GS,
|
||||||
|
X86_REGISTER_SS,
|
||||||
|
|
||||||
|
X86_INT_REGISTER_END,
|
||||||
|
X86_REGISTER_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class CpuStateX86 : public CpuState {
|
class CpuStateX86 : public CpuState {
|
||||||
public:
|
public:
|
||||||
CpuStateX86(const debug_cpu_state_x86& state);
|
CpuStateX86(const debug_cpu_state_x86& state);
|
||||||
virtual ~CpuStateX86();
|
virtual ~CpuStateX86();
|
||||||
|
|
||||||
const debug_cpu_state_x86 State() const { return fState; }
|
virtual bool GetRegisterValue(const Register* reg,
|
||||||
|
Variant& _value);
|
||||||
|
|
||||||
|
bool IsRegisterSet(int32 index) const;
|
||||||
|
uint32 IntRegisterValue(int32 index) const;
|
||||||
|
void SetIntRegister(int32 index, uint32 value);
|
||||||
|
void UnsetRegister(int32 index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
debug_cpu_state_x86 fState;
|
typedef std::bitset<X86_REGISTER_COUNT> RegisterBitSet;
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32 fIntRegisters[X86_REGISTER_COUNT];
|
||||||
|
RegisterBitSet fSetRegisters;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -254,6 +254,10 @@ DebuggerInterface::Init()
|
|||||||
if (fArchitecture == NULL)
|
if (fArchitecture == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
status_t error = fArchitecture->Init();
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
// create debugger port
|
// create debugger port
|
||||||
char buffer[128];
|
char buffer[128];
|
||||||
snprintf(buffer, sizeof(buffer), "team %ld debugger", fTeamID);
|
snprintf(buffer, sizeof(buffer), "team %ld debugger", fTeamID);
|
||||||
@@ -271,7 +275,7 @@ DebuggerInterface::Init()
|
|||||||
if (fDebugContextPool == NULL)
|
if (fDebugContextPool == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
status_t error = fDebugContextPool->Init();
|
error = fDebugContextPool->Init();
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
@@ -425,13 +429,8 @@ DebuggerInterface::GetCpuState(thread_id thread, CpuState*& _state)
|
|||||||
if (reply.error != B_OK)
|
if (reply.error != B_OK)
|
||||||
return reply.error;
|
return reply.error;
|
||||||
|
|
||||||
// TODO: Correctly create the state...
|
return fArchitecture->CreateCpuState(&reply.cpu_state,
|
||||||
CpuState* state = new(std::nothrow) CpuState;
|
sizeof(debug_cpu_state), _state);
|
||||||
if (state == NULL)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
|
|
||||||
_state = state;
|
|
||||||
return B_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user