* Register:

- Added a type constant describing the format of the register value.
  - Added flag "is callee-preserved" indicating whether the ABI requires the
    register to be preserved by a called function.
* CpuState: Added SetRegisterValue(), made GetRegisterValue() const.
* Added RegisterMap interface for mapping register indices between different
  models.
* Architecture:
  - Added CreateCpuState() version to create a clean CpuState.
  - Added GetDwarfRegisterMaps(), which returns to RegisterMaps, converting
    from and to DWARF register indices.
  - Added ReadValueFromMemory() reading a value from the target team's memory.
    The value type is specified by a type constant and the value return via a
    BVariant.
  - CreateStackTrace: No longer decide whether to adjust the instruction pointer
    of the previous CPU state depending on who created the CPU state. Instead
    compare it with the return address of the next frame. If they are equal it
    obviously has to be adjusted.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31539 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2009-07-13 18:45:49 +00:00
parent 3b859de22e
commit 614e1dc42f
12 changed files with 349 additions and 63 deletions
+1
View File
@@ -44,6 +44,7 @@ Application Debugger :
CpuState.cpp
InstructionInfo.cpp
Register.cpp
RegisterMap.cpp
# arch/x86
ArchitectureX86.cpp
+5 -7
View File
@@ -52,7 +52,6 @@ Architecture::CreateStackTrace(Team* team,
return B_NO_MEMORY;
ObjectDeleter<StackTrace> stackTraceDeleter(stackTrace);
bool architectureFrame = false;
StackFrame* frame = NULL;
while (cpuState != NULL) {
@@ -85,9 +84,10 @@ Architecture::CreateStackTrace(Team* team,
Reference<FunctionInstance> functionReference(function);
teamLocker.Unlock();
// If the last frame had been created by the architecture, we update the
// CPU state.
if (architectureFrame) {
// If the CPU state's instruction pointer is actually the return address
// of the next frame, we let the architecture fix that.
if (frame != NULL
&& frame->ReturnAddress() == cpuState->InstructionPointer()) {
UpdateStackFrameCpuState(frame, image,
functionDebugInfo, cpuState);
}
@@ -109,9 +109,7 @@ Architecture::CreateStackTrace(Team* team,
cpuState, frame == NULL, previousFrame, previousCpuState);
if (error != B_OK)
break;
architectureFrame = true;
} else
architectureFrame = false;
}
cpuStateReference.SetTo(previousCpuState, true);
+12
View File
@@ -5,9 +5,11 @@
#ifndef ARCHITECTURE_H
#define ARCHITECTURE_H
#include <OS.h>
#include <Referenceable.h>
#include <Variant.h>
#include "Types.h"
@@ -19,6 +21,7 @@ class Image;
class ImageDebugInfoProvider;
class InstructionInfo;
class Register;
class RegisterMap;
class StackFrame;
class StackTrace;
class Statement;
@@ -36,6 +39,11 @@ public:
virtual int32 CountRegisters() const = 0;
virtual const Register* Registers() const = 0;
virtual status_t GetDwarfRegisterMaps(RegisterMap** _toDwarf,
RegisterMap** _fromDwarf) const = 0;
// returns references
virtual status_t CreateCpuState(CpuState*& _state) = 0;
virtual status_t CreateCpuState(const void* cpuStateData,
size_t size, CpuState*& _state) = 0;
virtual status_t CreateStackFrame(Image* image,
@@ -55,6 +63,10 @@ public:
// with the image/function corresponding
// to the CPU state.
virtual status_t ReadValueFromMemory(target_addr_t address,
uint32 valueType, BVariant& _value) const
= 0;
virtual status_t DisassembleCode(FunctionDebugInfo* function,
const void* buffer, size_t bufferSize,
DisassembledCode*& _sourceCode) = 0;
+3 -1
View File
@@ -22,7 +22,9 @@ public:
virtual target_addr_t InstructionPointer() const = 0;
virtual bool GetRegisterValue(const Register* reg,
BVariant& _value) = 0;
BVariant& _value) const = 0;
virtual bool SetRegisterValue(const Register* reg,
const BVariant& value) = 0;
};
+31 -6
View File
@@ -3,18 +3,41 @@
* Distributed under the terms of the MIT License.
*/
#include "Register.h"
#include <TypeConstants.h>
Register::Register(int32 index, const char* name, register_format format,
uint32 bitSize, register_type type)
Register::Register(int32 index, const char* name, uint32 bitSize,
uint32 valueType, register_type type, bool calleePreserved)
:
fIndex(index),
fName(name),
fFormat(format),
fBitSize(bitSize),
fType(type)
fValueType(valueType),
fType(type),
fCalleePreserved(calleePreserved)
{
switch (fValueType) {
case B_INT8_TYPE:
case B_UINT8_TYPE:
case B_INT16_TYPE:
case B_UINT16_TYPE:
case B_INT32_TYPE:
case B_UINT32_TYPE:
case B_INT64_TYPE:
case B_UINT64_TYPE:
fFormat = REGISTER_FORMAT_INTEGER;
break;
case B_FLOAT_TYPE:
case B_DOUBLE_TYPE:
fFormat = REGISTER_FORMAT_FLOAT;
break;
default:
fFormat = 0;
break;
}
}
@@ -22,8 +45,10 @@ Register::Register(const Register& other)
:
fIndex(other.fIndex),
fName(other.fName),
fFormat(other.fFormat),
fBitSize(other.fBitSize),
fType(other.fType)
fValueType(other.fValueType),
fFormat(other.fFormat),
fType(other.fType),
fCalleePreserved(other.fCalleePreserved)
{
}
+14 -8
View File
@@ -5,6 +5,7 @@
#ifndef REGISTER_H
#define REGISTER_H
#include <SupportDefs.h>
@@ -25,23 +26,28 @@ enum register_type {
class Register {
public:
Register(int32 index, const char* name,
register_format format, uint32 bitSize,
register_type type);
uint32 bitSize, uint32 valueType,
register_type type, bool calleePreserved);
// 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; }
int32 Index() const { return fIndex; }
const char* Name() const { return fName; }
uint32 ValueType() const { return fValueType; }
register_format Format() const { return fFormat; }
uint32 BitSize() const { return fBitSize; }
register_type Type() const { return fType; }
bool IsCalleePreserved() const
{ return fCalleePreserved; }
private:
int32 fIndex;
const char* fName;
register_format fFormat;
uint32 fBitSize;
uint32 fValueType;
register_format fFormat;
register_type fType;
bool fCalleePreserved;
};
+12
View File
@@ -0,0 +1,12 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "RegisterMap.h"
RegisterMap::~RegisterMap()
{
}
+21
View File
@@ -0,0 +1,21 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef REGISTER_MAP_H
#define REGISTER_MAP_H
#include <Referenceable.h>
class RegisterMap : public Referenceable {
public:
virtual ~RegisterMap();
virtual int32 CountRegisters() const = 0;
virtual int32 MapRegisterIndex(int32 index) const = 0;
};
#endif // REGISTER_MAP_H
+215 -35
View File
@@ -3,6 +3,7 @@
* Distributed under the terms of the MIT License.
*/
#include "ArchitectureX86.h"
#include <new>
@@ -15,6 +16,7 @@
#include "DisassembledCode.h"
#include "FunctionDebugInfo.h"
#include "InstructionInfo.h"
#include "RegisterMap.h"
#include "StackFrame.h"
#include "Statement.h"
#include "TeamMemory.h"
@@ -22,15 +24,98 @@
#include "disasm/DisassemblerX86.h"
static const int32 kFromDwarfRegisters[] = {
X86_REGISTER_EAX,
X86_REGISTER_ECX,
X86_REGISTER_EDX,
X86_REGISTER_EBX,
X86_REGISTER_ESP,
X86_REGISTER_EBP,
X86_REGISTER_ESI,
X86_REGISTER_EDI,
X86_REGISTER_EIP,
-1, // eflags
-1, // trap number
-1, // st(0)
-1, // st(1)
-1, // st(2)
-1, // st(3)
-1, // st(4)
-1, // st(5)
-1, // st(6)
-1, // st(7)
-1, // ?
-1, // ?
-1, -1, -1, -1, -1, -1, -1, -1, // SSE
-1, -1, -1, -1, -1, -1, -1, -1 // MMX
};
static const int32 kFromDwarfRegisterCount = sizeof(kFromDwarfRegisters) / 4;
// #pragma mark - ToDwarfRegisterMap
struct ArchitectureX86::ToDwarfRegisterMap : RegisterMap {
ToDwarfRegisterMap()
{
// init the index array from the reverse map
memset(fIndices, -1, sizeof(fIndices));
for (int32 i = 0; i < kFromDwarfRegisterCount; i++) {
if (kFromDwarfRegisters[i] >= 0)
fIndices[kFromDwarfRegisters[i]] = i;
}
}
virtual int32 CountRegisters() const
{
return X86_REGISTER_COUNT;
}
virtual int32 MapRegisterIndex(int32 index) const
{
return index >= 0 && index < X86_REGISTER_COUNT ? fIndices[index] : -1;
}
private:
int32 fIndices[X86_REGISTER_COUNT];
};
// #pragma mark - FromDwarfRegisterMap
struct ArchitectureX86::FromDwarfRegisterMap : RegisterMap {
virtual int32 CountRegisters() const
{
return kFromDwarfRegisterCount;
}
virtual int32 MapRegisterIndex(int32 index) const
{
return index >= 0 && index < kFromDwarfRegisterCount
? kFromDwarfRegisters[index] : -1;
}
};
// #pragma mark - ArchitectureX86
ArchitectureX86::ArchitectureX86(TeamMemory* teamMemory)
:
Architecture(teamMemory)
Architecture(teamMemory),
fToDwarfRegisterMap(NULL),
fFromDwarfRegisterMap(NULL)
{
}
ArchitectureX86::~ArchitectureX86()
{
if (fToDwarfRegisterMap != NULL)
fToDwarfRegisterMap->ReleaseReference();
if (fFromDwarfRegisterMap != NULL)
fFromDwarfRegisterMap->ReleaseReference();
}
@@ -38,43 +123,49 @@ status_t
ArchitectureX86::Init()
{
try {
_AddIntegerRegister(X86_REGISTER_EIP, "eip", 32,
REGISTER_TYPE_INSTRUCTION_POINTER);
_AddIntegerRegister(X86_REGISTER_ESP, "esp", 32,
REGISTER_TYPE_STACK_POINTER);
_AddIntegerRegister(X86_REGISTER_EBP, "ebp", 32,
REGISTER_TYPE_GENERAL_PURPOSE);
_AddIntegerRegister(X86_REGISTER_EIP, "eip", B_UINT32_TYPE,
REGISTER_TYPE_INSTRUCTION_POINTER, false);
_AddIntegerRegister(X86_REGISTER_ESP, "esp", B_UINT32_TYPE,
REGISTER_TYPE_STACK_POINTER, true);
_AddIntegerRegister(X86_REGISTER_EBP, "ebp", B_UINT32_TYPE,
REGISTER_TYPE_GENERAL_PURPOSE, true);
_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_EAX, "eax", B_UINT32_TYPE,
REGISTER_TYPE_GENERAL_PURPOSE, false);
_AddIntegerRegister(X86_REGISTER_EBX, "ebx", B_UINT32_TYPE,
REGISTER_TYPE_GENERAL_PURPOSE, true);
_AddIntegerRegister(X86_REGISTER_ECX, "ecx", B_UINT32_TYPE,
REGISTER_TYPE_GENERAL_PURPOSE, false);
_AddIntegerRegister(X86_REGISTER_EDX, "edx", B_UINT32_TYPE,
REGISTER_TYPE_GENERAL_PURPOSE, false);
_AddIntegerRegister(X86_REGISTER_ESI, "esi", 32,
REGISTER_TYPE_GENERAL_PURPOSE);
_AddIntegerRegister(X86_REGISTER_EDI, "edi", 32,
REGISTER_TYPE_GENERAL_PURPOSE);
_AddIntegerRegister(X86_REGISTER_ESI, "esi", B_UINT32_TYPE,
REGISTER_TYPE_GENERAL_PURPOSE, true);
_AddIntegerRegister(X86_REGISTER_EDI, "edi", B_UINT32_TYPE,
REGISTER_TYPE_GENERAL_PURPOSE, true);
_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);
_AddIntegerRegister(X86_REGISTER_CS, "cs", B_UINT16_TYPE,
REGISTER_TYPE_SPECIAL_PURPOSE, true);
_AddIntegerRegister(X86_REGISTER_DS, "ds", B_UINT16_TYPE,
REGISTER_TYPE_SPECIAL_PURPOSE, true);
_AddIntegerRegister(X86_REGISTER_ES, "es", B_UINT16_TYPE,
REGISTER_TYPE_SPECIAL_PURPOSE, true);
_AddIntegerRegister(X86_REGISTER_FS, "fs", B_UINT16_TYPE,
REGISTER_TYPE_SPECIAL_PURPOSE, true);
_AddIntegerRegister(X86_REGISTER_GS, "gs", B_UINT16_TYPE,
REGISTER_TYPE_SPECIAL_PURPOSE, true);
_AddIntegerRegister(X86_REGISTER_SS, "ss", B_UINT16_TYPE,
REGISTER_TYPE_SPECIAL_PURPOSE, true);
} catch (std::bad_alloc) {
return B_NO_MEMORY;
}
fToDwarfRegisterMap = new(std::nothrow) ToDwarfRegisterMap;
fFromDwarfRegisterMap = new(std::nothrow) FromDwarfRegisterMap;
if (fToDwarfRegisterMap == NULL || fFromDwarfRegisterMap == NULL)
return B_NO_MEMORY;
return B_OK;
}
@@ -93,6 +184,36 @@ ArchitectureX86::Registers() const
}
status_t
ArchitectureX86::GetDwarfRegisterMaps(RegisterMap** _toDwarf,
RegisterMap** _fromDwarf) const
{
if (_toDwarf != NULL) {
*_toDwarf = fToDwarfRegisterMap;
fToDwarfRegisterMap->AcquireReference();
}
if (_fromDwarf != NULL) {
*_fromDwarf = fFromDwarfRegisterMap;
fFromDwarfRegisterMap->AcquireReference();
}
return B_OK;
}
status_t
ArchitectureX86::CreateCpuState(CpuState*& _state)
{
CpuStateX86* state = new(std::nothrow) CpuStateX86;
if (state == NULL)
return B_NO_MEMORY;
_state = state;
return B_OK;
}
status_t
ArchitectureX86::CreateCpuState(const void* cpuStateData, size_t size,
CpuState*& _state)
@@ -269,6 +390,62 @@ ArchitectureX86::UpdateStackFrameCpuState(const StackFrame* frame,
}
status_t
ArchitectureX86::ReadValueFromMemory(target_addr_t address, uint32 valueType,
BVariant& _value) const
{
uint8 buffer[64];
size_t size = BVariant::SizeOfType(valueType);
if (size == 0 || size > sizeof(buffer))
return B_BAD_VALUE;
ssize_t bytesRead = fTeamMemory->ReadMemory(address, buffer, size);
if (bytesRead < 0)
return bytesRead;
if ((size_t)bytesRead != size)
return B_ERROR;
// TODO: We need to swap endianess, if the host is big endian!
switch (valueType) {
case B_INT8_TYPE:
_value.SetTo(*(int8*)buffer);
return B_OK;
case B_UINT8_TYPE:
_value.SetTo(*(uint8*)buffer);
return B_OK;
case B_INT16_TYPE:
_value.SetTo(*(int16*)buffer);
return B_OK;
case B_UINT16_TYPE:
_value.SetTo(*(uint16*)buffer);
return B_OK;
case B_INT32_TYPE:
_value.SetTo(*(int32*)buffer);
return B_OK;
case B_UINT32_TYPE:
_value.SetTo(*(uint32*)buffer);
return B_OK;
case B_INT64_TYPE:
_value.SetTo(*(int64*)buffer);
return B_OK;
case B_UINT64_TYPE:
_value.SetTo(*(uint64*)buffer);
return B_OK;
case B_FLOAT_TYPE:
_value.SetTo(*(float*)buffer);
// TODO: float on the host might work differently!
return B_OK;
case B_DOUBLE_TYPE:
_value.SetTo(*(double*)buffer);
// TODO: double on the host might work differently!
return B_OK;
default:
return B_BAD_VALUE;
}
}
status_t
ArchitectureX86::DisassembleCode(FunctionDebugInfo* function,
const void* buffer, size_t bufferSize, DisassembledCode*& _sourceCode)
@@ -382,18 +559,21 @@ ArchitectureX86::GetInstructionInfo(target_addr_t address,
void
ArchitectureX86::_AddRegister(int32 index, const char* name,
register_format format, uint32 bitSize, register_type type)
uint32 bitSize, uint32 valueType, register_type type, bool calleePreserved)
{
if (!fRegisters.Add(Register(index, name, format, bitSize, type)))
if (!fRegisters.Add(Register(index, name, bitSize, valueType, type,
calleePreserved))) {
throw std::bad_alloc();
}
}
void
ArchitectureX86::_AddIntegerRegister(int32 index, const char* name,
uint32 bitSize, register_type type)
uint32 valueType, register_type type, bool calleePreserved)
{
_AddRegister(index, name, REGISTER_FORMAT_INTEGER, bitSize, type);
_AddRegister(index, name, 8 * BVariant::SizeOfType(valueType), valueType,
type, calleePreserved);
}
+18 -4
View File
@@ -5,6 +5,7 @@
#ifndef ARCHITECTURE_X86_H
#define ARCHITECTURE_X86_H
#include "Architecture.h"
#include "Array.h"
#include "Register.h"
@@ -20,6 +21,10 @@ public:
virtual int32 CountRegisters() const;
virtual const Register* Registers() const;
virtual status_t GetDwarfRegisterMaps(RegisterMap** _toDwarf,
RegisterMap** _fromDwarf) const;
virtual status_t CreateCpuState(CpuState*& _state);
virtual status_t CreateCpuState(const void* cpuStateData,
size_t size, CpuState*& _state);
virtual status_t CreateStackFrame(Image* image,
@@ -33,6 +38,9 @@ public:
FunctionDebugInfo* previousFunction,
CpuState* previousCpuState);
virtual status_t ReadValueFromMemory(target_addr_t address,
uint32 valueType, BVariant& _value) const;
virtual status_t DisassembleCode(FunctionDebugInfo* function,
const void* buffer, size_t bufferSize,
DisassembledCode*& _sourceCode);
@@ -42,19 +50,25 @@ public:
virtual status_t GetInstructionInfo(target_addr_t address,
InstructionInfo& _info);
private:
struct ToDwarfRegisterMap;
struct FromDwarfRegisterMap;
private:
void _AddRegister(int32 index, const char* name,
register_format format, uint32 bitSize,
register_type type);
uint32 bitSize, uint32 valueType,
register_type type, bool calleePreserved);
void _AddIntegerRegister(int32 index,
const char* name, uint32 bitSize,
register_type type);
const char* name, uint32 valueType,
register_type type, bool calleePreserved);
bool _HasFunctionPrologue(
FunctionDebugInfo* function) const;
private:
Array<Register> fRegisters;
ToDwarfRegisterMap* fToDwarfRegisterMap;
FromDwarfRegisterMap* fFromDwarfRegisterMap;
};
+14 -1
View File
@@ -55,7 +55,7 @@ CpuStateX86::InstructionPointer() const
bool
CpuStateX86::GetRegisterValue(const Register* reg, BVariant& _value)
CpuStateX86::GetRegisterValue(const Register* reg, BVariant& _value) const
{
int32 index = reg->Index();
if (!IsRegisterSet(index))
@@ -73,6 +73,19 @@ CpuStateX86::GetRegisterValue(const Register* reg, BVariant& _value)
}
bool
CpuStateX86::SetRegisterValue(const Register* reg, const BVariant& value)
{
int32 index = reg->Index();
if (index >= X86_INT_REGISTER_END)
return false;
fIntRegisters[index] = value.ToUInt32();
fSetRegisters[index] = 1;
return true;
}
bool
CpuStateX86::IsRegisterSet(int32 index) const
{
+3 -1
View File
@@ -48,7 +48,9 @@ public:
virtual target_addr_t InstructionPointer() const;
virtual bool GetRegisterValue(const Register* reg,
BVariant& _value);
BVariant& _value) const;
virtual bool SetRegisterValue(const Register* reg,
const BVariant& value);
uint32 InterruptVector() const
{ return fInterruptVector; }