From 8feddbc07bd1e05ed7aa5cf5fc66f7b2c3c24c31 Mon Sep 17 00:00:00 2001 From: Vladimir Marko Date: Thu, 3 Sep 2020 09:59:45 +0100 Subject: Improve disasembly of BL to thread entrypoint trampoline. Test: Manual, search for "\bbl\b" in `m dump-oat` output and oatdump of an individual oat file for arm and arm64. Change-Id: Idb6d8d1a21b2aa8c77e5b72f24faf7a4e655294c --- disassembler/disassembler_arm.cc | 16 ++++++++++++++++ disassembler/disassembler_arm64.cc | 30 ++++++++++++++++++++++++++---- disassembler/disassembler_arm64.h | 5 +++++ 3 files changed, 47 insertions(+), 4 deletions(-) (limited to 'disassembler') diff --git a/disassembler/disassembler_arm.cc b/disassembler/disassembler_arm.cc index 94ea0064e6..c2156ca5e1 100644 --- a/disassembler/disassembler_arm.cc +++ b/disassembler/disassembler_arm.cc @@ -68,6 +68,22 @@ class DisassemblerArm::CustomDisassembler final : public PrintDisassembler { PrintLiteral(type, offset); return *this; } + case kCodeLocation: + DisassemblerStream::operator<<(label); + // Improve the disassembly of branch to thunk jumping to pointer from thread entrypoint. + if (disasm_->GetIsT32() && GetCurrentInstructionType() == vixl::aarch32::kBl) { + const uintptr_t begin = reinterpret_cast(options_->base_address_); + const uintptr_t end = reinterpret_cast(options_->end_address_); + uintptr_t address = label.GetLocation() + (options_->absolute_addresses_ ? 0u : begin); + if ((address >= begin && address < end && end - address >= 4u) && + reinterpret_cast(address)[0] == 0xf8d9 && // LDR Rt, [tr, #imm12] + (reinterpret_cast(address)[1] >> 12) == 0xf) { // Rt == PC + uint32_t imm12 = reinterpret_cast(address)[1] & 0xfffu; + os() << " ; "; + options_->thread_offset_name_function_(os(), imm12); + } + } + return *this; default: return DisassemblerStream::operator<<(label); } diff --git a/disassembler/disassembler_arm64.cc b/disassembler/disassembler_arm64.cc index 49b9623f4f..0d51cfdc1a 100644 --- a/disassembler/disassembler_arm64.cc +++ b/disassembler/disassembler_arm64.cc @@ -101,13 +101,35 @@ void CustomDisassembler::VisitLoadStoreUnsignedOffset(const Instruction* instr) Disassembler::VisitLoadStoreUnsignedOffset(instr); if (instr->GetRn() == TR) { - int64_t offset = instr->GetImmLSUnsigned() << instr->GetSizeLS(); - std::ostringstream tmp_stream; - options_->thread_offset_name_function_(tmp_stream, static_cast(offset)); - AppendToOutput(" ; %s", tmp_stream.str().c_str()); + AppendThreadOfsetName(instr); } } +void CustomDisassembler::VisitUnconditionalBranch(const Instruction* instr) { + Disassembler::VisitUnconditionalBranch(instr); + + if (instr->Mask(UnconditionalBranchMask) == BL) { + const Instruction* target = instr->GetImmPCOffsetTarget(); + if (target >= base_address_ && + target < end_address_ && + target->Mask(LoadStoreMask) == LDR_x && + target->GetRn() == TR && + target->GetRt() == IP0 && + target->GetNextInstruction() < end_address_ && + target->GetNextInstruction()->Mask(UnconditionalBranchToRegisterMask) == BR && + target->GetNextInstruction()->GetRn() == IP0) { + AppendThreadOfsetName(target); + } + } +} + +void CustomDisassembler::AppendThreadOfsetName(const vixl::aarch64::Instruction* instr) { + int64_t offset = instr->GetImmLSUnsigned() << instr->GetSizeLS(); + std::ostringstream tmp_stream; + options_->thread_offset_name_function_(tmp_stream, static_cast(offset)); + AppendToOutput(" ; %s", tmp_stream.str().c_str()); +} + size_t DisassemblerArm64::Dump(std::ostream& os, const uint8_t* begin) { const Instruction* instr = reinterpret_cast(begin); decoder.Decode(instr); diff --git a/disassembler/disassembler_arm64.h b/disassembler/disassembler_arm64.h index 89beaa927b..a895dfe823 100644 --- a/disassembler/disassembler_arm64.h +++ b/disassembler/disassembler_arm64.h @@ -53,7 +53,12 @@ class CustomDisassembler final : public vixl::aarch64::Disassembler { // Improve the disassembly of thread offset. void VisitLoadStoreUnsignedOffset(const vixl::aarch64::Instruction* instr) override; + // Improve the disassembly of branch to thunk jumping to pointer from thread entrypoint. + void VisitUnconditionalBranch(const vixl::aarch64::Instruction* instr) override; + private: + void AppendThreadOfsetName(const vixl::aarch64::Instruction* instr); + // Indicate if the disassembler should read data loaded from literal pools. // This should only be enabled if reading the target of literal loads is safe. // Here are possible outputs when the option is on or off: -- cgit v1.2.3-59-g8ed1b