diff options
author | Vladimir Kostyukov <vladimir.kostyukov@intel.com> | 2014-04-18 17:06:15 +0700 |
---|---|---|
committer | Ian Rogers <irogers@google.com> | 2014-04-25 10:42:13 -0700 |
commit | e8861b30ac8b2b1ca49386f9c9218f1d6fedc511 (patch) | |
tree | 70ec1c5dc2b917211b9bf0428f2806694f725744 | |
parent | 3f4dcdf6c99f90a2301304d26ce29dc637b4be7f (diff) | |
download | art-e8861b30ac8b2b1ca49386f9c9218f1d6fedc511.zip art-e8861b30ac8b2b1ca49386f9c9218f1d6fedc511.tar.gz art-e8861b30ac8b2b1ca49386f9c9218f1d6fedc511.tar.bz2 |
ART: Enables x86_64 disassembly
This patch
(a) cuts a REX prefix from the instruction and
(b) adds missed 32bit disp to instructions with ModR/M and SIB bytes.
Change-Id: I2674678224ca27746b33d4006ed38d497972309f
Signed-off-by: Vladimir Kostyukov <vladimir.kostyukov@intel.com>
-rw-r--r-- | disassembler/disassembler_x86.cc | 32 |
1 files changed, 25 insertions, 7 deletions
diff --git a/disassembler/disassembler_x86.cc b/disassembler/disassembler_x86.cc index 1b96a2b..5cc6acf 100644 --- a/disassembler/disassembler_x86.cc +++ b/disassembler/disassembler_x86.cc @@ -145,6 +145,9 @@ size_t DisassemblerX86::DumpInstruction(std::ostream& os, const uint8_t* instr) } } while (have_prefixes); uint8_t rex = (supports_rex_ && (*instr >= 0x40) && (*instr <= 0x4F)) ? *instr : 0; + if (rex != 0) { + instr++; + } bool has_modrm = false; bool reg_is_opcode = false; size_t immediate_bytes = 0; @@ -746,14 +749,18 @@ DISASSEMBLER_ENTRY(cmp, uint8_t reg_or_opcode = (modrm >> 3) & 7; uint8_t rm = modrm & 7; std::ostringstream address; - if (mod == 0 && rm == 5) { // fixed address - address_bits = *reinterpret_cast<const uint32_t*>(instr); - address << StringPrintf("[0x%x]", address_bits); + if (mod == 0 && rm == 5) { + if (!supports_rex_) { // Absolute address. + address_bits = *reinterpret_cast<const uint32_t*>(instr); + address << StringPrintf("[0x%x]", address_bits); + } else { // 64-bit RIP relative addressing. + address << StringPrintf("[RIP + 0x%x]", *reinterpret_cast<const uint32_t*>(instr)); + } instr += 4; } else if (rm == 4 && mod != 3) { // SIB uint8_t sib = *instr; instr++; - uint8_t ss = (sib >> 6) & 3; + uint8_t scale = (sib >> 6) & 3; uint8_t index = (sib >> 3) & 7; uint8_t base = sib & 7; address << "["; @@ -765,11 +772,22 @@ DISASSEMBLER_ENTRY(cmp, } if (index != 4) { DumpIndexReg(address, rex, index); - if (ss != 0) { - address << StringPrintf(" * %d", 1 << ss); + if (scale != 0) { + address << StringPrintf(" * %d", 1 << scale); } } - if (mod == 1) { + if (mod == 0) { + if (base == 5) { + if (index != 4) { + address << StringPrintf(" + %d", *reinterpret_cast<const int32_t*>(instr)); + } else { + // 64-bit low 32-bit absolute address, redundant absolute address encoding on 32-bit. + address_bits = *reinterpret_cast<const uint32_t*>(instr); + address << StringPrintf("%d", address_bits); + } + instr += 4; + } + } else if (mod == 1) { address << StringPrintf(" + %d", *reinterpret_cast<const int8_t*>(instr)); instr++; } else if (mod == 2) { |