Skip to content

Commit

Permalink
Adapt x86-64 to also use udis86-based instruction analysis.
Browse files Browse the repository at this point in the history
  • Loading branch information
anevilyak committed Jan 6, 2013
1 parent 59fcd81 commit dcce0a0
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 33 deletions.
35 changes: 2 additions & 33 deletions src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp
Expand Up @@ -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)
Expand All @@ -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);
}


Expand Down
122 changes: 122 additions & 0 deletions src/apps/debugger/arch/x86_64/disasm/DisassemblerX8664.cpp
Expand Up @@ -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 {
};

Expand Down Expand Up @@ -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;
}
10 changes: 10 additions & 0 deletions src/apps/debugger/arch/x86_64/disasm/DisassemblerX8664.h
Expand Up @@ -11,6 +11,10 @@
#include "Types.h"


class CpuState;
class InstructionInfo;


class DisassemblerX8664 {
public:
DisassemblerX8664();
Expand All @@ -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;

Expand Down
3 changes: 3 additions & 0 deletions src/apps/debugger/arch/x86_64/disasm/Jamfile
Expand Up @@ -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 ] ;

Expand Down

0 comments on commit dcce0a0

Please sign in to comment.