summaryrefslogtreecommitdiffstats
path: root/disassembler
diff options
context:
space:
mode:
authorIan Rogers <irogers@google.com>2014-03-14 14:06:14 -0700
committerIan Rogers <irogers@google.com>2014-03-14 14:16:04 -0700
commit38e12034f1ef2b32e98b6e49cb36b7cc37a7f1be (patch)
tree9a879d4034bce742c8b5ef0680c2da2d8da5139d /disassembler
parentfb5b21d1d598b6b42e5d5ca1dac4a040832558fb (diff)
downloadandroid_art-38e12034f1ef2b32e98b6e49cb36b7cc37a7f1be.tar.gz
android_art-38e12034f1ef2b32e98b6e49cb36b7cc37a7f1be.tar.bz2
android_art-38e12034f1ef2b32e98b6e49cb36b7cc37a7f1be.zip
x86-64 disassembler support.
Change-Id: I0ae39ae1ffdae2500ff368354f9e4702445176f0
Diffstat (limited to 'disassembler')
-rw-r--r--disassembler/disassembler.cc4
-rw-r--r--disassembler/disassembler_arm.cc3
-rw-r--r--disassembler/disassembler_arm.h9
-rw-r--r--disassembler/disassembler_arm64.h6
-rw-r--r--disassembler/disassembler_mips.cc3
-rw-r--r--disassembler/disassembler_mips.h10
-rw-r--r--disassembler/disassembler_x86.cc26
-rw-r--r--disassembler/disassembler_x86.h14
8 files changed, 43 insertions, 32 deletions
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<intptr_t>(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