summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVladimir Kostyukov <vladimir.kostyukov@intel.com>2014-04-18 17:06:15 +0700
committerIan Rogers <irogers@google.com>2014-04-25 10:42:13 -0700
commite8861b30ac8b2b1ca49386f9c9218f1d6fedc511 (patch)
tree70ec1c5dc2b917211b9bf0428f2806694f725744
parent3f4dcdf6c99f90a2301304d26ce29dc637b4be7f (diff)
downloadart-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.cc32
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) {