diff --git a/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp b/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp index 05ba2a43153..3c27c878e9a 100644 --- a/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp +++ b/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp @@ -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); } diff --git a/src/apps/debugger/arch/x86_64/disasm/DisassemblerX8664.cpp b/src/apps/debugger/arch/x86_64/disasm/DisassemblerX8664.cpp index 7122943d114..07424ce51b5 100644 --- a/src/apps/debugger/arch/x86_64/disasm/DisassemblerX8664.cpp +++ b/src/apps/debugger/arch/x86_64/disasm/DisassemblerX8664.cpp @@ -14,6 +14,46 @@ #include +#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(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; +} diff --git a/src/apps/debugger/arch/x86_64/disasm/DisassemblerX8664.h b/src/apps/debugger/arch/x86_64/disasm/DisassemblerX8664.h index af045f4b7ba..9a61a9508e0 100644 --- a/src/apps/debugger/arch/x86_64/disasm/DisassemblerX8664.h +++ b/src/apps/debugger/arch/x86_64/disasm/DisassemblerX8664.h @@ -11,6 +11,10 @@ #include "Types.h" +class CpuState; +class InstructionInfo; + + class DisassemblerX8664 { public: DisassemblerX8664(); @@ -27,7 +31,13 @@ class DisassemblerX8664 { 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; diff --git a/src/apps/debugger/arch/x86_64/disasm/Jamfile b/src/apps/debugger/arch/x86_64/disasm/Jamfile index 7abcbb21b78..7424d3d7804 100644 --- a/src/apps/debugger/arch/x86_64/disasm/Jamfile +++ b/src/apps/debugger/arch/x86_64/disasm/Jamfile @@ -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 ] ;