diff options
Diffstat (limited to 'disassembler/disassembler_arm64.cc')
-rw-r--r-- | disassembler/disassembler_arm64.cc | 80 |
1 files changed, 79 insertions, 1 deletions
diff --git a/disassembler/disassembler_arm64.cc b/disassembler/disassembler_arm64.cc index 229ac97..fe50421 100644 --- a/disassembler/disassembler_arm64.cc +++ b/disassembler/disassembler_arm64.cc @@ -27,10 +27,88 @@ namespace art { namespace arm64 { +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; + case TR: AppendToOutput(reg.Is64Bits() ? "tr" : "w18"); return; + case ETR: AppendToOutput(reg.Is64Bits() ? "etr" : "w21"); return; + case FP: AppendToOutput(reg.Is64Bits() ? "fp" : "w29"); return; + case LR: AppendToOutput(reg.Is64Bits() ? "lr" : "w30"); return; + default: + // Fall through. + break; + } + } + // Print other register names as usual. + Disassembler::AppendRegisterNameToOutput(instr, reg); +} + +void CustomDisassembler::VisitLoadLiteral(const vixl::Instruction* instr) { + Disassembler::VisitLoadLiteral(instr); + + if (!read_literals_) { + 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(); + ptrdiff_t buf_size_remaining = buffer_end - buffer; + vixl::Instr op = instr->Mask(vixl::LoadLiteralMask); + + switch (op) { + case vixl::LDR_w_lit: + case vixl::LDR_x_lit: + 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); + 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); + break; + } + default: + break; + } +} + size_t DisassemblerArm64::Dump(std::ostream& os, const uint8_t* begin) { const vixl::Instruction* instr = reinterpret_cast<const vixl::Instruction*>(begin); decoder.Decode(instr); - os << FormatInstructionPointer(begin) + // TODO: Use FormatInstructionPointer() once VIXL provides the appropriate + // features. + // VIXL does not yet allow remapping addresses disassembled. Using + // FormatInstructionPointer() would show incoherences between the instruction + // location addresses and the target addresses disassembled by VIXL (eg. for + // branch instructions). + os << StringPrintf("%p", instr) << StringPrintf(": %08x\t%s\n", instr->InstructionBits(), disasm.GetOutput()); return vixl::kInstructionSize; } |