#include "ArchitectureX8664.h"
#include <new>
#include <String.h>
#include <AutoDeleter.h>
#include "CfaContext.h"
#include "CpuStateX8664.h"
#include "DisassembledCode.h"
#include "FunctionDebugInfo.h"
#include "InstructionInfo.h"
#include "NoOpStackFrameDebugInfo.h"
#include "RegisterMap.h"
#include "StackFrame.h"
#include "Statement.h"
#include "TeamMemory.h"
#include "ValueLocation.h"
#include "X86AssemblyLanguage.h"
#include "disasm/DisassemblerX8664.h"
#define X86_64_EXTENDED_FEATURE_AVX (1 << 28)
static const int32 kFromDwarfRegisters[] = {
X86_64_REGISTER_RAX,
X86_64_REGISTER_RDX,
X86_64_REGISTER_RCX,
X86_64_REGISTER_RBX,
X86_64_REGISTER_RSI,
X86_64_REGISTER_RDI,
X86_64_REGISTER_RBP,
X86_64_REGISTER_RSP,
X86_64_REGISTER_R8,
X86_64_REGISTER_R9,
X86_64_REGISTER_R10,
X86_64_REGISTER_R11,
X86_64_REGISTER_R12,
X86_64_REGISTER_R13,
X86_64_REGISTER_R14,
X86_64_REGISTER_R15,
X86_64_REGISTER_RIP,
X86_64_REGISTER_XMM0,
X86_64_REGISTER_XMM1,
X86_64_REGISTER_XMM2,
X86_64_REGISTER_XMM3,
X86_64_REGISTER_XMM4,
X86_64_REGISTER_XMM5,
X86_64_REGISTER_XMM6,
X86_64_REGISTER_XMM7,
X86_64_REGISTER_XMM8,
X86_64_REGISTER_XMM9,
X86_64_REGISTER_XMM10,
X86_64_REGISTER_XMM11,
X86_64_REGISTER_XMM12,
X86_64_REGISTER_XMM13,
X86_64_REGISTER_XMM14,
X86_64_REGISTER_XMM15,
X86_64_REGISTER_ST0,
X86_64_REGISTER_ST1,
X86_64_REGISTER_ST2,
X86_64_REGISTER_ST3,
X86_64_REGISTER_ST4,
X86_64_REGISTER_ST5,
X86_64_REGISTER_ST6,
X86_64_REGISTER_ST7,
X86_64_REGISTER_MM0,
X86_64_REGISTER_MM1,
X86_64_REGISTER_MM2,
X86_64_REGISTER_MM3,
X86_64_REGISTER_MM4,
X86_64_REGISTER_MM5,
X86_64_REGISTER_MM6,
X86_64_REGISTER_MM7,
-1,
X86_64_REGISTER_ES,
X86_64_REGISTER_CS,
X86_64_REGISTER_SS,
X86_64_REGISTER_DS,
X86_64_REGISTER_FS,
X86_64_REGISTER_GS,
};
static const int32 kFromDwarfRegisterCount = sizeof(kFromDwarfRegisters) / 4;
static const uint16 kFunctionPrologueSize = 4;
struct ArchitectureX8664::ToDwarfRegisterMap : RegisterMap {
ToDwarfRegisterMap()
{
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_64_REGISTER_COUNT;
}
virtual int32 MapRegisterIndex(int32 index) const
{
return index >= 0 && index < X86_64_REGISTER_COUNT ? fIndices[index] : -1;
}
private:
int32 fIndices[X86_64_REGISTER_COUNT];
};
struct ArchitectureX8664::FromDwarfRegisterMap : RegisterMap {
virtual int32 CountRegisters() const
{
return kFromDwarfRegisterCount;
}
virtual int32 MapRegisterIndex(int32 index) const
{
return index >= 0 && index < kFromDwarfRegisterCount
? kFromDwarfRegisters[index] : -1;
}
};
ArchitectureX8664::ArchitectureX8664(TeamMemory* teamMemory)
:
Architecture(teamMemory, 8, sizeof(x86_64_debug_cpu_state), false),
fAssemblyLanguage(NULL),
fToDwarfRegisterMap(NULL),
fFromDwarfRegisterMap(NULL)
{
}
ArchitectureX8664::~ArchitectureX8664()
{
if (fToDwarfRegisterMap != NULL)
fToDwarfRegisterMap->ReleaseReference();
if (fFromDwarfRegisterMap != NULL)
fFromDwarfRegisterMap->ReleaseReference();
if (fAssemblyLanguage != NULL)
fAssemblyLanguage->ReleaseReference();
}
status_t
ArchitectureX8664::Init()
{
fAssemblyLanguage = new(std::nothrow) X86AssemblyLanguage;
if (fAssemblyLanguage == NULL)
return B_NO_MEMORY;
int featureFlags = 0;
#ifdef __x86_64__
cpuid_info info;
status_t error = get_cpuid(&info, 1, 0);
if (error != B_OK)
return error;
if ((info.eax_1.extended_features & X86_64_EXTENDED_FEATURE_AVX) != 0)
featureFlags |= X86_64_CPU_FEATURE_FLAG_AVX;
#endif
try {
_AddIntegerRegister(X86_64_REGISTER_RIP, "rip", B_UINT64_TYPE,
REGISTER_TYPE_INSTRUCTION_POINTER, false);
_AddIntegerRegister(X86_64_REGISTER_RSP, "rsp", B_UINT64_TYPE,
REGISTER_TYPE_STACK_POINTER, true);
_AddIntegerRegister(X86_64_REGISTER_RBP, "rbp", B_UINT64_TYPE,
REGISTER_TYPE_GENERAL_PURPOSE, true);
_AddIntegerRegister(X86_64_REGISTER_RAX, "rax", B_UINT64_TYPE,
REGISTER_TYPE_GENERAL_PURPOSE, false);
_AddIntegerRegister(X86_64_REGISTER_RBX, "rbx", B_UINT64_TYPE,
REGISTER_TYPE_GENERAL_PURPOSE, true);
_AddIntegerRegister(X86_64_REGISTER_RCX, "rcx", B_UINT64_TYPE,
REGISTER_TYPE_GENERAL_PURPOSE, false);
_AddIntegerRegister(X86_64_REGISTER_RDX, "rdx", B_UINT64_TYPE,
REGISTER_TYPE_GENERAL_PURPOSE, false);
_AddIntegerRegister(X86_64_REGISTER_RSI, "rsi", B_UINT64_TYPE,
REGISTER_TYPE_GENERAL_PURPOSE, false);
_AddIntegerRegister(X86_64_REGISTER_RDI, "rdi", B_UINT64_TYPE,
REGISTER_TYPE_GENERAL_PURPOSE, false);
_AddIntegerRegister(X86_64_REGISTER_R8, "r8", B_UINT64_TYPE,
REGISTER_TYPE_GENERAL_PURPOSE, false);
_AddIntegerRegister(X86_64_REGISTER_R9, "r9", B_UINT64_TYPE,
REGISTER_TYPE_GENERAL_PURPOSE, false);
_AddIntegerRegister(X86_64_REGISTER_R10, "r10", B_UINT64_TYPE,
REGISTER_TYPE_GENERAL_PURPOSE, false);
_AddIntegerRegister(X86_64_REGISTER_R11, "r11", B_UINT64_TYPE,
REGISTER_TYPE_GENERAL_PURPOSE, false);
_AddIntegerRegister(X86_64_REGISTER_R12, "r12", B_UINT64_TYPE,
REGISTER_TYPE_GENERAL_PURPOSE, true);
_AddIntegerRegister(X86_64_REGISTER_R13, "r13", B_UINT64_TYPE,
REGISTER_TYPE_GENERAL_PURPOSE, true);
_AddIntegerRegister(X86_64_REGISTER_R14, "r14", B_UINT64_TYPE,
REGISTER_TYPE_GENERAL_PURPOSE, true);
_AddIntegerRegister(X86_64_REGISTER_R15, "r15", B_UINT64_TYPE,
REGISTER_TYPE_GENERAL_PURPOSE, true);
_AddIntegerRegister(X86_64_REGISTER_CS, "cs", B_UINT16_TYPE,
REGISTER_TYPE_SPECIAL_PURPOSE, true);
_AddIntegerRegister(X86_64_REGISTER_DS, "ds", B_UINT16_TYPE,
REGISTER_TYPE_SPECIAL_PURPOSE, true);
_AddIntegerRegister(X86_64_REGISTER_ES, "es", B_UINT16_TYPE,
REGISTER_TYPE_SPECIAL_PURPOSE, true);
_AddIntegerRegister(X86_64_REGISTER_FS, "fs", B_UINT16_TYPE,
REGISTER_TYPE_SPECIAL_PURPOSE, true);
_AddIntegerRegister(X86_64_REGISTER_GS, "gs", B_UINT16_TYPE,
REGISTER_TYPE_SPECIAL_PURPOSE, true);
_AddIntegerRegister(X86_64_REGISTER_SS, "ss", B_UINT16_TYPE,
REGISTER_TYPE_SPECIAL_PURPOSE, true);
_AddFPRegister(X86_64_REGISTER_ST0, "st0");
_AddFPRegister(X86_64_REGISTER_ST1, "st1");
_AddFPRegister(X86_64_REGISTER_ST2, "st2");
_AddFPRegister(X86_64_REGISTER_ST3, "st3");
_AddFPRegister(X86_64_REGISTER_ST4, "st4");
_AddFPRegister(X86_64_REGISTER_ST5, "st5");
_AddFPRegister(X86_64_REGISTER_ST6, "st6");
_AddFPRegister(X86_64_REGISTER_ST7, "st7");
_AddSIMDRegister(X86_64_REGISTER_MM0, "mm0", sizeof(uint64));
_AddSIMDRegister(X86_64_REGISTER_MM1, "mm1", sizeof(uint64));
_AddSIMDRegister(X86_64_REGISTER_MM2, "mm2", sizeof(uint64));
_AddSIMDRegister(X86_64_REGISTER_MM3, "mm3", sizeof(uint64));
_AddSIMDRegister(X86_64_REGISTER_MM4, "mm4", sizeof(uint64));
_AddSIMDRegister(X86_64_REGISTER_MM5, "mm5", sizeof(uint64));
_AddSIMDRegister(X86_64_REGISTER_MM6, "mm6", sizeof(uint64));
_AddSIMDRegister(X86_64_REGISTER_MM7, "mm7", sizeof(uint64));
if ((featureFlags & X86_64_CPU_FEATURE_FLAG_AVX) != 0) {
_AddSIMDRegister(X86_64_REGISTER_XMM0, "ymm0",
sizeof(x86_64_xmm_register) * 2);
_AddSIMDRegister(X86_64_REGISTER_XMM1, "ymm1",
sizeof(x86_64_xmm_register) * 2);
_AddSIMDRegister(X86_64_REGISTER_XMM2, "ymm2",
sizeof(x86_64_xmm_register) * 2);
_AddSIMDRegister(X86_64_REGISTER_XMM3, "ymm3",
sizeof(x86_64_xmm_register) * 2);
_AddSIMDRegister(X86_64_REGISTER_XMM4, "ymm4",
sizeof(x86_64_xmm_register) * 2);
_AddSIMDRegister(X86_64_REGISTER_XMM5, "ymm5",
sizeof(x86_64_xmm_register) * 2);
_AddSIMDRegister(X86_64_REGISTER_XMM6, "ymm6",
sizeof(x86_64_xmm_register) * 2);
_AddSIMDRegister(X86_64_REGISTER_XMM7, "ymm7",
sizeof(x86_64_xmm_register) * 2);
_AddSIMDRegister(X86_64_REGISTER_XMM8, "ymm8",
sizeof(x86_64_xmm_register) * 2);
_AddSIMDRegister(X86_64_REGISTER_XMM9, "ymm9",
sizeof(x86_64_xmm_register) * 2);
_AddSIMDRegister(X86_64_REGISTER_XMM10, "ymm10",
sizeof(x86_64_xmm_register) * 2);
_AddSIMDRegister(X86_64_REGISTER_XMM11, "ymm11",
sizeof(x86_64_xmm_register) * 2);
_AddSIMDRegister(X86_64_REGISTER_XMM12, "ymm12",
sizeof(x86_64_xmm_register) * 2);
_AddSIMDRegister(X86_64_REGISTER_XMM13, "ymm13",
sizeof(x86_64_xmm_register) * 2);
_AddSIMDRegister(X86_64_REGISTER_XMM14, "ymm14",
sizeof(x86_64_xmm_register) * 2);
_AddSIMDRegister(X86_64_REGISTER_XMM15, "ymm15",
sizeof(x86_64_xmm_register) * 2);
} else {
_AddSIMDRegister(X86_64_REGISTER_XMM0, "xmm0",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM1, "xmm1",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM2, "xmm2",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM3, "xmm3",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM4, "xmm4",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM5, "xmm5",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM6, "xmm6",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM7, "xmm7",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM8, "xmm8",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM9, "xmm9",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM10, "xmm10",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM11, "xmm11",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM12, "xmm12",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM13, "xmm13",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM14, "xmm14",
sizeof(x86_64_xmm_register));
_AddSIMDRegister(X86_64_REGISTER_XMM15, "xmm15",
sizeof(x86_64_xmm_register));
}
} 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;
}
int32
ArchitectureX8664::StackGrowthDirection() const
{
return STACK_GROWTH_DIRECTION_NEGATIVE;
}
int32
ArchitectureX8664::CountRegisters() const
{
return fRegisters.Count();
}
const Register*
ArchitectureX8664::Registers() const
{
return fRegisters.Elements();
}
status_t
ArchitectureX8664::InitRegisterRules(CfaContext& context) const
{
status_t error = Architecture::InitRegisterRules(context);
if (error != B_OK)
return error;
context.RegisterRule(fToDwarfRegisterMap->MapRegisterIndex(
X86_64_REGISTER_RIP))->SetToLocationOffset(0);
return B_OK;
}
status_t
ArchitectureX8664::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
ArchitectureX8664::GetCpuFeatures(uint32& flags)
{
flags = 0;
return B_OK;
}
status_t
ArchitectureX8664::CreateCpuState(CpuState*& _state)
{
CpuStateX8664* state = new(std::nothrow) CpuStateX8664;
if (state == NULL)
return B_NO_MEMORY;
_state = state;
return B_OK;
}
status_t
ArchitectureX8664::CreateCpuState(const void* cpuStateData, size_t size,
CpuState*& _state)
{
if (size != sizeof(x86_64_debug_cpu_state))
return B_BAD_VALUE;
CpuStateX8664* state = new(std::nothrow) CpuStateX8664(
*(const x86_64_debug_cpu_state*)cpuStateData);
if (state == NULL)
return B_NO_MEMORY;
_state = state;
return B_OK;
}
status_t
ArchitectureX8664::CreateStackFrame(Image* image, FunctionDebugInfo* function,
CpuState* _cpuState, bool isTopFrame, StackFrame*& _frame,
CpuState*& _previousCpuState)
{
CpuStateX8664* cpuState = dynamic_cast<CpuStateX8664*>(_cpuState);
uint64 framePointer = cpuState->IntRegisterValue(X86_64_REGISTER_RBP);
uint64 rip = cpuState->IntRegisterValue(X86_64_REGISTER_RIP);
bool readStandardFrame = true;
uint64 previousFramePointer = 0;
uint64 returnAddress = 0;
stack_frame_type frameType;
bool hasPrologue = false;
if (isTopFrame && cpuState->InterruptVector() == 99) {
frameType = STACK_FRAME_TYPE_SYSCALL;
rip -= 2;
uint64 rsp = cpuState->IntRegisterValue(X86_64_REGISTER_RSP);
uint64 address;
if (fTeamMemory->ReadMemory(rsp, &address, 8) == 8) {
returnAddress = address;
previousFramePointer = framePointer;
framePointer = 0;
readStandardFrame = false;
}
} else {
hasPrologue = _HasFunctionPrologue(function);
if (hasPrologue)
frameType = STACK_FRAME_TYPE_STANDARD;
else
frameType = STACK_FRAME_TYPE_FRAMELESS;
if (isTopFrame) {
uint64 stack = 0;
if (hasPrologue) {
if (rip < function->Address() + kFunctionPrologueSize) {
stack = cpuState->IntRegisterValue(X86_64_REGISTER_RSP);
if (rip > function->Address()) {
stack += 8;
}
} else {
uint8 code[1];
if (fTeamMemory->ReadMemory(rip, &code, 1) == 1
&& code[0] == 0xc3) {
stack = cpuState->IntRegisterValue(
X86_64_REGISTER_RSP);
}
}
} else {
uint8 data[1];
if (fTeamMemory->ReadMemory(rip, &data, 1) != 1)
stack = cpuState->IntRegisterValue(X86_64_REGISTER_RSP);
}
if (stack != 0) {
uint64 address;
if (fTeamMemory->ReadMemory(stack, &address, 8) == 8) {
returnAddress = address;
previousFramePointer = framePointer;
framePointer = 0;
readStandardFrame = false;
frameType = STACK_FRAME_TYPE_FRAMELESS;
}
}
}
}
StackFrameDebugInfo* stackFrameDebugInfo
= new(std::nothrow) NoOpStackFrameDebugInfo;
if (stackFrameDebugInfo == NULL)
return B_NO_MEMORY;
BReference<StackFrameDebugInfo> stackFrameDebugInfoReference(
stackFrameDebugInfo, true);
StackFrame* frame = new(std::nothrow) StackFrame(frameType, cpuState,
framePointer, rip, stackFrameDebugInfo);
if (frame == NULL)
return B_NO_MEMORY;
BReference<StackFrame> frameReference(frame, true);
status_t error = frame->Init();
if (error != B_OK)
return error;
if (readStandardFrame) {
uint64 frameData[2];
if (framePointer != 0
&& fTeamMemory->ReadMemory(framePointer, frameData, 16) == 16) {
previousFramePointer = frameData[0];
returnAddress = frameData[1];
}
}
CpuStateX8664* previousCpuState = NULL;
if (returnAddress != 0) {
previousCpuState = new(std::nothrow) CpuStateX8664;
if (previousCpuState == NULL)
return B_NO_MEMORY;
previousCpuState->SetIntRegister(X86_64_REGISTER_RBP,
previousFramePointer);
previousCpuState->SetIntRegister(X86_64_REGISTER_RIP, returnAddress);
frame->SetPreviousCpuState(previousCpuState);
}
frame->SetReturnAddress(returnAddress);
_frame = frameReference.Detach();
_previousCpuState = previousCpuState;
return B_OK;
}
void
ArchitectureX8664::UpdateStackFrameCpuState(const StackFrame* frame,
Image* previousImage, FunctionDebugInfo* previousFunction,
CpuState* previousCpuState)
{
CpuStateX8664* cpuState = dynamic_cast<CpuStateX8664*>(previousCpuState);
uint64 rip = cpuState->IntRegisterValue(X86_64_REGISTER_RIP);
if (previousFunction == NULL || rip <= previousFunction->Address())
return;
target_addr_t functionAddress = previousFunction->Address();
size_t bufferSize = rip - functionAddress;
void* buffer = malloc(bufferSize);
if (buffer == NULL)
return;
MemoryDeleter bufferDeleter(buffer);
ssize_t bytesRead = fTeamMemory->ReadMemory(functionAddress, buffer,
bufferSize);
if (bytesRead != (ssize_t)bufferSize)
return;
DisassemblerX8664 disassembler;
target_addr_t instructionAddress;
target_size_t instructionSize;
if (disassembler.Init(functionAddress, buffer, bufferSize) == B_OK
&& disassembler.GetPreviousInstruction(rip, instructionAddress,
instructionSize) == B_OK) {
rip -= instructionSize;
cpuState->SetIntRegister(X86_64_REGISTER_RIP, rip);
}
}
status_t
ArchitectureX8664::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;
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);
return B_OK;
case B_DOUBLE_TYPE:
_value.SetTo(*(double*)buffer);
return B_OK;
default:
return B_BAD_VALUE;
}
}
status_t
ArchitectureX8664::ReadValueFromMemory(target_addr_t addressSpace,
target_addr_t address, uint32 valueType, BVariant& _value) const
{
return B_BAD_VALUE;
}
status_t
ArchitectureX8664::DisassembleCode(FunctionDebugInfo* function,
const void* buffer, size_t bufferSize, DisassembledCode*& _sourceCode)
{
DisassembledCode* source = new(std::nothrow) DisassembledCode(
fAssemblyLanguage);
if (source == NULL)
return B_NO_MEMORY;
BReference<DisassembledCode> sourceReference(source, true);
DisassemblerX8664 disassembler;
status_t error = disassembler.Init(function->Address(), buffer, bufferSize);
if (error != B_OK)
return error;
BString functionName(function->PrettyName());
if (!source->AddCommentLine((functionName << ':').String()))
return B_NO_MEMORY;
BString line;
target_addr_t instructionAddress;
target_size_t instructionSize;
bool breakpointAllowed;
while (disassembler.GetNextInstruction(line, instructionAddress,
instructionSize, breakpointAllowed) == B_OK) {
if (!source->AddInstructionLine(line, instructionAddress,
instructionSize)) {
return B_NO_MEMORY;
}
}
_sourceCode = sourceReference.Detach();
return B_OK;
}
status_t
ArchitectureX8664::GetStatement(FunctionDebugInfo* function,
target_addr_t address, Statement*& _statement)
{
InstructionInfo info;
status_t error = GetInstructionInfo(address, info, NULL);
if (error != B_OK)
return error;
ContiguousStatement* statement = new(std::nothrow) ContiguousStatement(
SourceLocation(-1), TargetAddressRange(info.Address(), info.Size()));
if (statement == NULL)
return B_NO_MEMORY;
_statement = statement;
return B_OK;
}
status_t
ArchitectureX8664::GetInstructionInfo(target_addr_t address,
InstructionInfo& _info, CpuState* state)
{
uint8 buffer[16];
ssize_t bytesRead = fTeamMemory->ReadMemory(address, buffer,
sizeof(buffer));
if (bytesRead < 0)
return bytesRead;
DisassemblerX8664 disassembler;
status_t error = disassembler.Init(address, buffer, bytesRead);
if (error != B_OK)
return error;
return disassembler.GetNextInstructionInfo(_info, state);
}
status_t
ArchitectureX8664::ResolvePICFunctionAddress(target_addr_t instructionAddress,
CpuState* state, target_addr_t& _targetAddress)
{
target_addr_t previousIP = state->InstructionPointer();
InstructionInfo info;
if (GetInstructionInfo(instructionAddress, info, state) != B_OK)
return B_BAD_VALUE;
state->SetInstructionPointer(info.Address() + info.Size());
status_t result = GetInstructionInfo(info.Address(), info, state);
state->SetInstructionPointer(previousIP);
if (result != B_OK)
return result;
target_addr_t subroutineAddress;
ssize_t bytesRead = fTeamMemory->ReadMemory(info.TargetAddress(),
&subroutineAddress, fAddressSize);
if (bytesRead != fAddressSize)
return B_BAD_VALUE;
_targetAddress = subroutineAddress;
return B_OK;
}
status_t
ArchitectureX8664::GetWatchpointDebugCapabilities(int32& _maxRegisterCount,
int32& _maxBytesPerRegister, uint8& _watchpointCapabilityFlags)
{
_maxRegisterCount = 3;
_maxBytesPerRegister = 8;
_watchpointCapabilityFlags = WATCHPOINT_CAPABILITY_FLAG_WRITE
| WATCHPOINT_CAPABILITY_FLAG_READ_WRITE;
return B_OK;
}
status_t
ArchitectureX8664::GetReturnAddressLocation(StackFrame* frame,
target_size_t valueSize, ValueLocation*& _location)
{
ValueLocation* location = new(std::nothrow) ValueLocation(
IsBigEndian());
if (location == NULL)
return B_NO_MEMORY;
BReference<ValueLocation> locationReference(location,
true);
if (valueSize <= 8) {
ValuePieceLocation piece;
piece.SetSize(valueSize);
piece.SetToRegister(X86_64_REGISTER_RAX);
if (!location->AddPiece(piece))
return B_NO_MEMORY;
} else {
ValuePieceLocation piece;
CpuStateX8664* state = dynamic_cast<CpuStateX8664*>(frame->GetCpuState());
piece.SetToMemory(state->IntRegisterValue(X86_64_REGISTER_RAX));
piece.SetSize(valueSize);
if (!location->AddPiece(piece))
return B_NO_MEMORY;
}
_location = locationReference.Detach();
return B_OK;
}
void
ArchitectureX8664::_AddRegister(int32 index, const char* name,
uint32 bitSize, uint32 valueType, register_type type, bool calleePreserved)
{
if (!fRegisters.Add(Register(index, name, bitSize, valueType, type,
calleePreserved))) {
throw std::bad_alloc();
}
}
void
ArchitectureX8664::_AddIntegerRegister(int32 index, const char* name,
uint32 valueType, register_type type, bool calleePreserved)
{
_AddRegister(index, name, 8 * BVariant::SizeOfType(valueType), valueType,
type, calleePreserved);
}
void
ArchitectureX8664::_AddFPRegister(int32 index, const char* name)
{
_AddRegister(index, name, 8 * BVariant::SizeOfType(B_DOUBLE_TYPE),
B_DOUBLE_TYPE, REGISTER_TYPE_GENERAL_PURPOSE, true);
}
void
ArchitectureX8664::_AddSIMDRegister(int32 index, const char* name,
uint32 byteSize)
{
_AddRegister(index, name, byteSize * 8, B_RAW_TYPE,
REGISTER_TYPE_GENERAL_PURPOSE, true);
}
bool
ArchitectureX8664::_HasFunctionPrologue(FunctionDebugInfo* function) const
{
if (function == NULL)
return false;
if (function->Size() < kFunctionPrologueSize)
return false;
uint8 buffer[kFunctionPrologueSize];
if (fTeamMemory->ReadMemory(function->Address(), buffer,
kFunctionPrologueSize) != kFunctionPrologueSize) {
return false;
}
return buffer[0] == 0x55 && buffer[1] == 0x48 && buffer[2] == 0x89
&& buffer[3] == 0xe5;
}