Adapt x86-64 to also use udis86-based instruction analysis.
This commit is contained in:
parent
59fcd81013
commit
dcce0a030b
@ -470,9 +470,8 @@ status_t
|
||||
ArchitectureX8664::GetInstructionInfo(target_addr_t address,
|
||||
InstructionInfo& _info, CpuState* state)
|
||||
{
|
||||
// read the code
|
||||
// read the code - maximum x86{-64} instruction size = 15 bytes
|
||||
uint8 buffer[16];
|
||||
// TODO: What's the maximum instruction size?
|
||||
ssize_t bytesRead = fTeamMemory->ReadMemory(address, buffer,
|
||||
sizeof(buffer));
|
||||
if (bytesRead < 0)
|
||||
@ -484,37 +483,7 @@ ArchitectureX8664::GetInstructionInfo(target_addr_t address,
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
// disassemble the instruction
|
||||
BString line;
|
||||
target_addr_t instructionAddress;
|
||||
target_addr_t targetAddress = 0;
|
||||
target_size_t instructionSize;
|
||||
bool breakpointAllowed;
|
||||
error = disassembler.GetNextInstruction(line, instructionAddress,
|
||||
instructionSize, breakpointAllowed);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
// FIXME: Is this correct for x86_64? I'm not entirely sure.
|
||||
instruction_type instructionType = INSTRUCTION_TYPE_OTHER;
|
||||
if (buffer[0] == 0xff && (buffer[1] & 0x34) == 0x10) {
|
||||
// absolute call with r/m32
|
||||
instructionType = INSTRUCTION_TYPE_SUBROUTINE_CALL;
|
||||
} else if (buffer[0] == 0xe8 && instructionSize == 5) {
|
||||
// relative call with rel32 -- don't categorize the call with 0 as
|
||||
// subroutine call, since it is only used to get the address of the GOT
|
||||
if (buffer[1] != 0 || buffer[2] != 0 || buffer[3] != 0
|
||||
|| buffer[4] != 0) {
|
||||
instructionType = INSTRUCTION_TYPE_SUBROUTINE_CALL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_info.SetTo(instructionAddress, targetAddress, instructionSize,
|
||||
instructionType, breakpointAllowed, line)) {
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
return disassembler.GetNextInstructionInfo(_info, state);
|
||||
}
|
||||
|
||||
|
||||
|
@ -14,6 +14,46 @@
|
||||
#include <OS.h>
|
||||
|
||||
|
||||
#include "CpuStateX8664.h"
|
||||
#include "InstructionInfo.h"
|
||||
|
||||
|
||||
static uint8 RegisterNumberFromUdisIndex(int32 udisIndex)
|
||||
{
|
||||
switch (udisIndex) {
|
||||
case UD_R_RIP: return X86_64_REGISTER_RIP;
|
||||
case UD_R_RSP: return X86_64_REGISTER_RSP;
|
||||
case UD_R_RBP: return X86_64_REGISTER_RBP;
|
||||
|
||||
case UD_R_RAX: return X86_64_REGISTER_RAX;
|
||||
case UD_R_RBX: return X86_64_REGISTER_RBX;
|
||||
case UD_R_RCX: return X86_64_REGISTER_RCX;
|
||||
case UD_R_RDX: return X86_64_REGISTER_RDX;
|
||||
|
||||
case UD_R_RSI: return X86_64_REGISTER_RSI;
|
||||
case UD_R_RDI: return X86_64_REGISTER_RDI;
|
||||
|
||||
case UD_R_R8: return X86_64_REGISTER_R8;
|
||||
case UD_R_R9: return X86_64_REGISTER_R9;
|
||||
case UD_R_R10: return X86_64_REGISTER_R10;
|
||||
case UD_R_R11: return X86_64_REGISTER_R11;
|
||||
case UD_R_R12: return X86_64_REGISTER_R12;
|
||||
case UD_R_R13: return X86_64_REGISTER_R13;
|
||||
case UD_R_R14: return X86_64_REGISTER_R14;
|
||||
case UD_R_R15: return X86_64_REGISTER_R15;
|
||||
|
||||
case UD_R_CS: return X86_64_REGISTER_CS;
|
||||
case UD_R_DS: return X86_64_REGISTER_DS;
|
||||
case UD_R_ES: return X86_64_REGISTER_ES;
|
||||
case UD_R_FS: return X86_64_REGISTER_FS;
|
||||
case UD_R_GS: return X86_64_REGISTER_GS;
|
||||
case UD_R_SS: return X86_64_REGISTER_SS;
|
||||
}
|
||||
|
||||
return X86_64_INT_REGISTER_END;
|
||||
}
|
||||
|
||||
|
||||
struct DisassemblerX8664::UdisData : ud_t {
|
||||
};
|
||||
|
||||
@ -109,3 +149,85 @@ DisassemblerX8664::GetPreviousInstruction(target_addr_t nextAddress,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
DisassemblerX8664::GetNextInstructionInfo(InstructionInfo& _info,
|
||||
CpuState* state)
|
||||
{
|
||||
unsigned int size = ud_disassemble(fUdisData);
|
||||
if (size < 1)
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
|
||||
uint32 address = (uint32)ud_insn_off(fUdisData);
|
||||
|
||||
instruction_type type = INSTRUCTION_TYPE_OTHER;
|
||||
target_addr_t targetAddress = 0;
|
||||
|
||||
if (fUdisData->mnemonic == UD_Icall)
|
||||
type = INSTRUCTION_TYPE_SUBROUTINE_CALL;
|
||||
else if (fUdisData->mnemonic == UD_Ijmp)
|
||||
type = INSTRUCTION_TYPE_JUMP;
|
||||
if (state != NULL)
|
||||
targetAddress = GetInstructionTargetAddress(state);
|
||||
|
||||
char buffer[256];
|
||||
snprintf(buffer, sizeof(buffer), "0x%08" B_PRIx32 ": %16.16s %s", address,
|
||||
ud_insn_hex(fUdisData), ud_insn_asm(fUdisData));
|
||||
// TODO: Resolve symbols!
|
||||
|
||||
if (!_info.SetTo(address, targetAddress, size, type, true, buffer))
|
||||
return B_NO_MEMORY;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
target_addr_t
|
||||
DisassemblerX8664::GetInstructionTargetAddress(CpuState* state) const
|
||||
{
|
||||
if (fUdisData->mnemonic != UD_Icall && fUdisData->mnemonic != UD_Ijmp)
|
||||
return 0;
|
||||
|
||||
CpuStateX8664* x64State = dynamic_cast<CpuStateX8664*>(state);
|
||||
if (x64State == NULL)
|
||||
return 0;
|
||||
|
||||
target_addr_t targetAddress = 0;
|
||||
switch (fUdisData->operand[0].type) {
|
||||
case UD_OP_REG:
|
||||
{
|
||||
targetAddress = x64State->IntRegisterValue(
|
||||
RegisterNumberFromUdisIndex(fUdisData->operand[0].base));
|
||||
targetAddress += fUdisData->operand[0].offset;
|
||||
}
|
||||
break;
|
||||
case UD_OP_MEM:
|
||||
{
|
||||
targetAddress = x64State->IntRegisterValue(
|
||||
RegisterNumberFromUdisIndex(fUdisData->operand[0].base));
|
||||
targetAddress += x64State->IntRegisterValue(
|
||||
RegisterNumberFromUdisIndex(fUdisData->operand[0].index))
|
||||
* fUdisData->operand[0].scale;
|
||||
}
|
||||
break;
|
||||
case UD_OP_JIMM:
|
||||
{
|
||||
targetAddress = ud_insn_off(fUdisData)
|
||||
+ fUdisData->operand[0].lval.sdword + ud_insn_len(fUdisData);
|
||||
}
|
||||
break;
|
||||
|
||||
case UD_OP_IMM:
|
||||
case UD_OP_CONST:
|
||||
{
|
||||
targetAddress = fUdisData->operand[0].lval.udword;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return targetAddress;
|
||||
}
|
||||
|
@ -11,6 +11,10 @@
|
||||
#include "Types.h"
|
||||
|
||||
|
||||
class CpuState;
|
||||
class InstructionInfo;
|
||||
|
||||
|
||||
class DisassemblerX8664 {
|
||||
public:
|
||||
DisassemblerX8664();
|
||||
@ -27,7 +31,13 @@ public:
|
||||
target_addr_t nextAddress,
|
||||
target_addr_t& _address,
|
||||
target_size_t& _size);
|
||||
virtual status_t GetNextInstructionInfo(
|
||||
InstructionInfo& _info,
|
||||
CpuState* state);
|
||||
|
||||
private:
|
||||
target_addr_t GetInstructionTargetAddress(
|
||||
CpuState* state) const;
|
||||
private:
|
||||
struct UdisData;
|
||||
|
||||
|
@ -3,9 +3,12 @@ SubDir HAIKU_TOP src apps debugger arch x86_64 disasm ;
|
||||
CCFLAGS += -Werror ;
|
||||
C++FLAGS += -Werror ;
|
||||
|
||||
UsePrivateHeaders shared ;
|
||||
|
||||
UseHeaders [ LibraryHeaders udis86 ] ;
|
||||
UseHeaders [ LibraryHeaders [ FDirName udis86 libudis86 ] ] ;
|
||||
|
||||
SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) ] ;
|
||||
SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) ] ;
|
||||
SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) $(DOTDOT) types ] ;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user