From 38e12034f1ef2b32e98b6e49cb36b7cc37a7f1be Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Fri, 14 Mar 2014 14:06:14 -0700 Subject: x86-64 disassembler support. Change-Id: I0ae39ae1ffdae2500ff368354f9e4702445176f0 --- disassembler/disassembler.cc | 4 +++- disassembler/disassembler_arm.cc | 3 --- disassembler/disassembler_arm.h | 9 +++++---- disassembler/disassembler_arm64.h | 6 +++--- disassembler/disassembler_mips.cc | 3 --- disassembler/disassembler_mips.h | 10 ++++++---- disassembler/disassembler_x86.cc | 26 ++++++++++++++++---------- disassembler/disassembler_x86.h | 14 ++++++++++---- 8 files changed, 43 insertions(+), 32 deletions(-) (limited to 'disassembler') diff --git a/disassembler/disassembler.cc b/disassembler/disassembler.cc index 5c17a830e9..41ee21365e 100644 --- a/disassembler/disassembler.cc +++ b/disassembler/disassembler.cc @@ -34,7 +34,9 @@ Disassembler* Disassembler::Create(InstructionSet instruction_set) { } else if (instruction_set == kMips) { return new mips::DisassemblerMips(); } else if (instruction_set == kX86) { - return new x86::DisassemblerX86(); + return new x86::DisassemblerX86(false); + } else if (instruction_set == kX86_64) { + return new x86::DisassemblerX86(true); } else { UNIMPLEMENTED(FATAL) << "no disassembler for " << instruction_set; return NULL; diff --git a/disassembler/disassembler_arm.cc b/disassembler/disassembler_arm.cc index 2a966a3512..161a7265ac 100644 --- a/disassembler/disassembler_arm.cc +++ b/disassembler/disassembler_arm.cc @@ -27,9 +27,6 @@ namespace art { namespace arm { -DisassemblerArm::DisassemblerArm() { -} - size_t DisassemblerArm::Dump(std::ostream& os, const uint8_t* begin) { if ((reinterpret_cast(begin) & 1) == 0) { DumpArm(os, begin); diff --git a/disassembler/disassembler_arm.h b/disassembler/disassembler_arm.h index e34274e126..f6d7fdad52 100644 --- a/disassembler/disassembler_arm.h +++ b/disassembler/disassembler_arm.h @@ -24,12 +24,13 @@ namespace art { namespace arm { -class DisassemblerArm : public Disassembler { +class DisassemblerArm FINAL : public Disassembler { public: - DisassemblerArm(); + DisassemblerArm() { + } - virtual size_t Dump(std::ostream& os, const uint8_t* begin); - virtual void Dump(std::ostream& os, const uint8_t* begin, const uint8_t* end); + size_t Dump(std::ostream& os, const uint8_t* begin) OVERRIDE; + void Dump(std::ostream& os, const uint8_t* begin, const uint8_t* end) OVERRIDE; private: void DumpArm(std::ostream& os, const uint8_t* instr); diff --git a/disassembler/disassembler_arm64.h b/disassembler/disassembler_arm64.h index d759df661c..28c0fa7556 100644 --- a/disassembler/disassembler_arm64.h +++ b/disassembler/disassembler_arm64.h @@ -25,14 +25,14 @@ namespace art { namespace arm64 { -class DisassemblerArm64 : public Disassembler { +class DisassemblerArm64 FINAL : public Disassembler { public: DisassemblerArm64() { decoder.AppendVisitor(&disasm); } - size_t Dump(std::ostream& os, const uint8_t* begin); - void Dump(std::ostream& os, const uint8_t* begin, const uint8_t* end); + size_t Dump(std::ostream& os, const uint8_t* begin) OVERRIDE; + void Dump(std::ostream& os, const uint8_t* begin, const uint8_t* end) OVERRIDE; private: vixl::Decoder decoder; diff --git a/disassembler/disassembler_mips.cc b/disassembler/disassembler_mips.cc index 25bbae68ef..72ff761426 100644 --- a/disassembler/disassembler_mips.cc +++ b/disassembler/disassembler_mips.cc @@ -257,9 +257,6 @@ static void DumpMips(std::ostream& os, const uint8_t* instr_ptr) { os << StringPrintf("%p: %08x\t%-7s ", instr_ptr, instruction, opcode.c_str()) << args.str() << '\n'; } -DisassemblerMips::DisassemblerMips() { -} - size_t DisassemblerMips::Dump(std::ostream& os, const uint8_t* begin) { DumpMips(os, begin); return 4; diff --git a/disassembler/disassembler_mips.h b/disassembler/disassembler_mips.h index d3862676a0..e1fb0340ab 100644 --- a/disassembler/disassembler_mips.h +++ b/disassembler/disassembler_mips.h @@ -24,11 +24,13 @@ namespace art { namespace mips { -class DisassemblerMips : public Disassembler { +class DisassemblerMips FINAL : public Disassembler { public: - DisassemblerMips(); - virtual size_t Dump(std::ostream& os, const uint8_t* begin); - virtual void Dump(std::ostream& os, const uint8_t* begin, const uint8_t* end); + DisassemblerMips() { + } + + size_t Dump(std::ostream& os, const uint8_t* begin) OVERRIDE; + void Dump(std::ostream& os, const uint8_t* begin, const uint8_t* end) OVERRIDE; private: DISALLOW_COPY_AND_ASSIGN(DisassemblerMips); diff --git a/disassembler/disassembler_x86.cc b/disassembler/disassembler_x86.cc index d86ba7b77a..ab0ee52205 100644 --- a/disassembler/disassembler_x86.cc +++ b/disassembler/disassembler_x86.cc @@ -25,8 +25,6 @@ namespace art { namespace x86 { -DisassemblerX86::DisassemblerX86() {} - size_t DisassemblerX86::Dump(std::ostream& os, const uint8_t* begin) { return DumpInstruction(os, begin); } @@ -41,16 +39,21 @@ void DisassemblerX86::Dump(std::ostream& os, const uint8_t* begin, const uint8_t static const char* gReg8Names[] = { "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh" }; static const char* gReg16Names[] = { "ax", "cx", "dx", "bx", "sp", "bp", "si", "di" }; static const char* gReg32Names[] = { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" }; +static const char* gReg64Names[] = { + "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" +}; -static void DumpReg0(std::ostream& os, uint8_t /*rex*/, size_t reg, +static void DumpReg0(std::ostream& os, uint8_t rex, size_t reg, bool byte_operand, uint8_t size_override) { - DCHECK_LT(reg, 8u); - // TODO: combine rex into size - size_t size = byte_operand ? 1 : (size_override == 0x66 ? 2 : 4); + DCHECK_LT(reg, (rex == 0) ? 8u : 16u); + bool rex_w = (rex & 0b1000) != 0; + size_t size = byte_operand ? 1 : (size_override == 0x66 ? 2 : (rex_w ? 8 :4)); switch (size) { case 1: os << gReg8Names[reg]; break; case 2: os << gReg16Names[reg]; break; case 4: os << gReg32Names[reg]; break; + case 8: os << gReg64Names[reg]; break; default: LOG(FATAL) << "unexpected size " << size; } } @@ -59,7 +62,8 @@ enum RegFile { GPR, MMX, SSE }; static void DumpReg(std::ostream& os, uint8_t rex, uint8_t reg, bool byte_operand, uint8_t size_override, RegFile reg_file) { - size_t reg_num = reg; // TODO: combine with REX.R on 64bit + bool rex_r = (rex & 0b0100) != 0; + size_t reg_num = rex_r ? (reg + 8) : reg; if (reg_file == GPR) { DumpReg0(os, rex, reg_num, byte_operand, size_override); } else if (reg_file == SSE) { @@ -70,12 +74,14 @@ static void DumpReg(std::ostream& os, uint8_t rex, uint8_t reg, } static void DumpBaseReg(std::ostream& os, uint8_t rex, uint8_t reg) { - size_t reg_num = reg; // TODO: combine with REX.B on 64bit + bool rex_b = (rex & 0b0001) != 0; + size_t reg_num = rex_b ? (reg + 8) : reg; DumpReg0(os, rex, reg_num, false, 0); } static void DumpIndexReg(std::ostream& os, uint8_t rex, uint8_t reg) { - int reg_num = reg; // TODO: combine with REX.X on 64bit + bool rex_x = (rex & 0b0010) != 0; + uint8_t reg_num = rex_x ? (reg + 8) : reg; DumpReg0(os, rex, reg_num, false, 0); } @@ -138,7 +144,7 @@ size_t DisassemblerX86::DumpInstruction(std::ostream& os, const uint8_t* instr) instr++; } } while (have_prefixes); - uint8_t rex = (*instr >= 0x40 && *instr <= 0x4F) ? *instr : 0; + uint8_t rex = (supports_rex_ && (*instr >= 0x40) && (*instr <= 0x4F)) ? *instr : 0; bool has_modrm = false; bool reg_is_opcode = false; size_t immediate_bytes = 0; diff --git a/disassembler/disassembler_x86.h b/disassembler/disassembler_x86.h index 9adaff7048..2565bb1ee7 100644 --- a/disassembler/disassembler_x86.h +++ b/disassembler/disassembler_x86.h @@ -22,14 +22,20 @@ namespace art { namespace x86 { -class DisassemblerX86 : public Disassembler { +class DisassemblerX86 FINAL : public Disassembler { public: - DisassemblerX86(); + explicit DisassemblerX86(bool supports_rex) : supports_rex_(supports_rex) { + } + + size_t Dump(std::ostream& os, const uint8_t* begin) OVERRIDE; + void Dump(std::ostream& os, const uint8_t* begin, const uint8_t* end) OVERRIDE; - virtual size_t Dump(std::ostream& os, const uint8_t* begin); - virtual void Dump(std::ostream& os, const uint8_t* begin, const uint8_t* end); private: size_t DumpInstruction(std::ostream& os, const uint8_t* instr); + + const bool supports_rex_; + + DISALLOW_COPY_AND_ASSIGN(DisassemblerX86); }; } // namespace x86 -- cgit v1.2.3