Skip to content

Commit

Permalink
Improve disasembly of BL to thread entrypoint trampoline.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
vmarko committed Sep 3, 2020
1 parent d111cd2 commit 8feddbc
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 4 deletions.
16 changes: 16 additions & 0 deletions disassembler/disassembler_arm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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<uintptr_t>(options_->base_address_);
const uintptr_t end = reinterpret_cast<uintptr_t>(options_->end_address_);
uintptr_t address = label.GetLocation() + (options_->absolute_addresses_ ? 0u : begin);
if ((address >= begin && address < end && end - address >= 4u) &&
reinterpret_cast<const uint16_t*>(address)[0] == 0xf8d9 && // LDR Rt, [tr, #imm12]
(reinterpret_cast<const uint16_t*>(address)[1] >> 12) == 0xf) { // Rt == PC
uint32_t imm12 = reinterpret_cast<const uint16_t*>(address)[1] & 0xfffu;
os() << " ; ";
options_->thread_offset_name_function_(os(), imm12);
}
}
return *this;
default:
return DisassemblerStream::operator<<(label);
}
Expand Down
30 changes: 26 additions & 4 deletions disassembler/disassembler_arm64.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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<uint32_t>(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<uint32_t>(offset));
AppendToOutput(" ; %s", tmp_stream.str().c_str());
}

size_t DisassemblerArm64::Dump(std::ostream& os, const uint8_t* begin) {
const Instruction* instr = reinterpret_cast<const Instruction*>(begin);
decoder.Decode(instr);
Expand Down
5 changes: 5 additions & 0 deletions disassembler/disassembler_arm64.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down

0 comments on commit 8feddbc

Please sign in to comment.