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:
Ingo Weinhold 2009-06-19 00:05:45 +00:00
parent 3c4cb05b95
commit c42fe1eb57
11 changed files with 314 additions and 11 deletions

View File

@ -32,6 +32,7 @@ Application Debugger :
# arch
Architecture.cpp
CpuState.cpp
Register.cpp
StackFrame.cpp
StackTrace.cpp

View File

@ -16,3 +16,10 @@ Architecture::Architecture(DebuggerInterface* debuggerInterface)
Architecture::~Architecture()
{
}
status_t
Architecture::Init()
{
return B_OK;
}

View File

@ -12,6 +12,7 @@
class CpuState;
class DebuggerInterface;
class Register;
class Architecture : public Referenceable {
@ -20,6 +21,11 @@ public:
DebuggerInterface* debuggerInterface);
virtual ~Architecture();
virtual status_t Init();
virtual int32 CountRegisters() const = 0;
virtual const Register* Registers() const = 0;
virtual status_t CreateCpuState(const void* cpuStateData,
size_t size, CpuState*& _state) = 0;

View File

@ -9,10 +9,18 @@
#include <Referenceable.h>
#include "Variant.h"
class Register;
class CpuState : public Referenceable {
public:
virtual ~CpuState();
virtual bool GetRegisterValue(const Register* reg,
Variant& _value) = 0;
};

View File

@ -0,0 +1,29 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* 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)
{
}

View File

@ -0,0 +1,49 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* 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

View File

@ -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
ArchitectureX86::CreateCpuState(const void* cpuStateData, size_t size,
CpuState*& _state)
@ -37,3 +96,20 @@ ArchitectureX86::CreateCpuState(const void* cpuStateData, size_t size,
_state = state;
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);
}

View File

@ -6,6 +6,8 @@
#define ARCHITECTURE_X86_H
#include "Architecture.h"
#include "Array.h"
#include "Register.h"
class ArchitectureX86 : public Architecture {
@ -14,8 +16,24 @@ public:
DebuggerInterface* debuggerInterface);
virtual ~ArchitectureX86();
virtual status_t Init();
virtual int32 CountRegisters() const;
virtual const Register* Registers() const;
virtual status_t CreateCpuState(const void* cpuStateData,
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;
};

View File

@ -5,14 +5,88 @@
#include "CpuStateX86.h"
#include "Register.h"
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()
{
}
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;
}

View File

@ -5,6 +5,8 @@
#ifndef CPU_STATE_X86_H
#define CPU_STATE_X86_H
#include <bitset>
#include <debugger.h>
#include "CpuState.h"
@ -13,16 +15,50 @@
typedef debug_cpu_state debug_cpu_state_x86;
// 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 {
public:
CpuStateX86(const debug_cpu_state_x86& state);
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:
debug_cpu_state_x86 fState;
typedef std::bitset<X86_REGISTER_COUNT> RegisterBitSet;
private:
uint32 fIntRegisters[X86_REGISTER_COUNT];
RegisterBitSet fSetRegisters;
};

View File

@ -254,6 +254,10 @@ DebuggerInterface::Init()
if (fArchitecture == NULL)
return B_NO_MEMORY;
status_t error = fArchitecture->Init();
if (error != B_OK)
return error;
// create debugger port
char buffer[128];
snprintf(buffer, sizeof(buffer), "team %ld debugger", fTeamID);
@ -271,7 +275,7 @@ DebuggerInterface::Init()
if (fDebugContextPool == NULL)
return B_NO_MEMORY;
status_t error = fDebugContextPool->Init();
error = fDebugContextPool->Init();
if (error != B_OK)
return error;
@ -425,13 +429,8 @@ DebuggerInterface::GetCpuState(thread_id thread, CpuState*& _state)
if (reply.error != B_OK)
return reply.error;
// TODO: Correctly create the state...
CpuState* state = new(std::nothrow) CpuState;
if (state == NULL)
return B_NO_MEMORY;
_state = state;
return B_OK;
return fArchitecture->CreateCpuState(&reply.cpu_state,
sizeof(debug_cpu_state), _state);
}