summaryrefslogtreecommitdiff
path: root/disassembler
diff options
context:
space:
mode:
Diffstat (limited to 'disassembler')
-rw-r--r--disassembler/disassembler_arm64.cc49
-rw-r--r--disassembler/disassembler_arm64.h9
-rw-r--r--disassembler/disassembler_x86.cc26
3 files changed, 48 insertions, 36 deletions
diff --git a/disassembler/disassembler_arm64.cc b/disassembler/disassembler_arm64.cc
index bd3bebf20f..4ff44b47c2 100644
--- a/disassembler/disassembler_arm64.cc
+++ b/disassembler/disassembler_arm64.cc
@@ -18,7 +18,7 @@
#include <inttypes.h>
-#include <ostream>
+#include <sstream>
#include "base/logging.h"
#include "base/stringprintf.h"
@@ -27,22 +27,23 @@
namespace art {
namespace arm64 {
+// This enumeration should mirror the declarations in
+// runtime/arch/arm64/registers_arm64.h. We do not include that file to
+// avoid a dependency on libart.
+enum {
+ TR = 18,
+ ETR = 21,
+ IP0 = 16,
+ IP1 = 17,
+ FP = 29,
+ LR = 30
+};
+
void CustomDisassembler::AppendRegisterNameToOutput(
const vixl::Instruction* instr,
const vixl::CPURegister& reg) {
USE(instr);
if (reg.IsRegister()) {
- // This enumeration should mirror the declarations in
- // runtime/arch/arm64/registers_arm64.h. We do not include that file to
- // avoid a dependency on libart.
- enum {
- TR = 18,
- ETR = 21,
- IP0 = 16,
- IP1 = 17,
- FP = 29,
- LR = 30
- };
switch (reg.code()) {
case IP0: AppendToOutput(reg.Is64Bits() ? "ip0" : "wip0"); return;
case IP1: AppendToOutput(reg.Is64Bits() ? "ip1" : "wip1"); return;
@@ -66,16 +67,7 @@ void CustomDisassembler::VisitLoadLiteral(const vixl::Instruction* instr) {
return;
}
- char* buffer = buffer_;
- char* buffer_end = buffer_ + buffer_size_;
-
- // Find the end position in the buffer.
- while ((*buffer != 0) && (buffer < buffer_end)) {
- ++buffer;
- }
-
void* data_address = instr->LiteralAddress<void*>();
- ptrdiff_t buf_size_remaining = buffer_end - buffer;
vixl::Instr op = instr->Mask(vixl::LoadLiteralMask);
switch (op) {
@@ -84,14 +76,14 @@ void CustomDisassembler::VisitLoadLiteral(const vixl::Instruction* instr) {
case vixl::LDRSW_x_lit: {
int64_t data = op == vixl::LDR_x_lit ? *reinterpret_cast<int64_t*>(data_address)
: *reinterpret_cast<int32_t*>(data_address);
- snprintf(buffer, buf_size_remaining, " (0x%" PRIx64 " / %" PRId64 ")", data, data);
+ AppendToOutput(" (0x%" PRIx64 " / %" PRId64 ")", data, data);
break;
}
case vixl::LDR_s_lit:
case vixl::LDR_d_lit: {
double data = (op == vixl::LDR_s_lit) ? *reinterpret_cast<float*>(data_address)
: *reinterpret_cast<double*>(data_address);
- snprintf(buffer, buf_size_remaining, " (%g)", data);
+ AppendToOutput(" (%g)", data);
break;
}
default:
@@ -99,6 +91,17 @@ void CustomDisassembler::VisitLoadLiteral(const vixl::Instruction* instr) {
}
}
+void CustomDisassembler::VisitLoadStoreUnsignedOffset(const vixl::Instruction* instr) {
+ Disassembler::VisitLoadStoreUnsignedOffset(instr);
+
+ if (instr->Rn() == TR) {
+ int64_t offset = instr->ImmLSUnsigned() << instr->SizeLS();
+ std::ostringstream tmp_stream;
+ Thread::DumpThreadOffset<8>(tmp_stream, static_cast<uint32_t>(offset));
+ AppendToOutput(" (%s)", tmp_stream.str().c_str());
+ }
+}
+
size_t DisassemblerArm64::Dump(std::ostream& os, const uint8_t* begin) {
const vixl::Instruction* instr = reinterpret_cast<const vixl::Instruction*>(begin);
decoder.Decode(instr);
diff --git a/disassembler/disassembler_arm64.h b/disassembler/disassembler_arm64.h
index a370b8ded9..57f11c822f 100644
--- a/disassembler/disassembler_arm64.h
+++ b/disassembler/disassembler_arm64.h
@@ -34,11 +34,14 @@ class CustomDisassembler FINAL : public vixl::Disassembler {
vixl::Disassembler(), read_literals_(read_literals) {}
// Use register aliases in the disassembly.
- virtual void AppendRegisterNameToOutput(const vixl::Instruction* instr,
- const vixl::CPURegister& reg) OVERRIDE;
+ void AppendRegisterNameToOutput(const vixl::Instruction* instr,
+ const vixl::CPURegister& reg) OVERRIDE;
// Improve the disassembly of literal load instructions.
- virtual void VisitLoadLiteral(const vixl::Instruction* instr) OVERRIDE;
+ void VisitLoadLiteral(const vixl::Instruction* instr) OVERRIDE;
+
+ // Improve the disassembly of thread offset.
+ void VisitLoadStoreUnsignedOffset(const vixl::Instruction* instr) OVERRIDE;
private:
// Indicate if the disassembler should read data loaded from literal pools.
diff --git a/disassembler/disassembler_x86.cc b/disassembler/disassembler_x86.cc
index 1a768c8b86..203488d2fb 100644
--- a/disassembler/disassembler_x86.cc
+++ b/disassembler/disassembler_x86.cc
@@ -119,12 +119,6 @@ static void DumpBaseReg(std::ostream& os, uint8_t rex, uint8_t reg) {
DumpAddrReg(os, rex, reg_num);
}
-static void DumpIndexReg(std::ostream& os, uint8_t rex, uint8_t reg) {
- bool rex_x = (rex & REX_X) != 0;
- uint8_t reg_num = rex_x ? (reg + 8) : reg;
- DumpAddrReg(os, rex, reg_num);
-}
-
static void DumpOpcodeReg(std::ostream& os, uint8_t rex, uint8_t reg,
bool byte_operand, uint8_t size_override) {
bool rex_b = (rex & REX_B) != 0;
@@ -184,18 +178,30 @@ std::string DisassemblerX86::DumpAddress(uint8_t mod, uint8_t rm, uint8_t rex64,
uint8_t index = (sib >> 3) & 7;
uint8_t base = sib & 7;
address << "[";
+
+ // REX.x is bit 3 of index.
+ if ((rex64 & REX_X) != 0) {
+ index += 8;
+ }
+
+ // Mod = 0 && base = 5 (ebp): no base (ignores REX.b).
+ bool has_base = false;
if (base != 5 || mod != 0) {
+ has_base = true;
DumpBaseReg(address, rex64, base);
- if (index != 4) {
- address << " + ";
- }
}
+
+ // Index = 4 (esp/rsp) is disallowed.
if (index != 4) {
- DumpIndexReg(address, rex64, index);
+ if (has_base) {
+ address << " + ";
+ }
+ DumpAddrReg(address, rex64, index);
if (scale != 0) {
address << StringPrintf(" * %d", 1 << scale);
}
}
+
if (mod == 0) {
if (base == 5) {
if (index != 4) {