#include <sstream>
#include "arch/instruction_set.h"
+#include "base/enums.h"
#include "debug/dwarf/dwarf_constants.h"
#include "debug/dwarf/dwarf_test.h"
#include "debug/dwarf/headers.h"
#include "disassembler/disassembler.h"
#include "gtest/gtest.h"
+#include "thread.h"
namespace art {
// Pretty-print assembly.
const uint8_t* asm_base = actual_asm.data();
const uint8_t* asm_end = asm_base + actual_asm.size();
- auto* opts = new DisassemblerOptions(false, asm_base, asm_end, true);
+ auto* opts = new DisassemblerOptions(false,
+ asm_base,
+ asm_end,
+ true,
+ is64bit
+ ? &Thread::DumpThreadOffset<PointerSize::k64>
+ : &Thread::DumpThreadOffset<PointerSize::k32>);
std::unique_ptr<Disassembler> disasm(Disassembler::Create(isa, opts));
std::stringstream stream;
const uint8_t* base = actual_asm.data() + (isa == kThumb2 ? 1 : 0);
new DisassemblerOptions(/* absolute_addresses */ false,
base_address,
end_address,
- /* can_read_literals */ true)));
+ /* can_read_literals */ true,
+ Is64BitInstructionSet(instruction_set)
+ ? &Thread::DumpThreadOffset<PointerSize::k64>
+ : &Thread::DumpThreadOffset<PointerSize::k32>)));
}
~HGraphVisualizerDisassembler() {
return new arm::DisassemblerArm(options);
} else if (instruction_set == kArm64) {
return new arm64::DisassemblerArm64(options);
- } else if (instruction_set == kMips) {
- return new mips::DisassemblerMips(options, false);
- } else if (instruction_set == kMips64) {
- return new mips::DisassemblerMips(options, true);
+ } else if (instruction_set == kMips || instruction_set == kMips64) {
+ return new mips::DisassemblerMips(options);
} else if (instruction_set == kX86) {
return new x86::DisassemblerX86(options, false);
} else if (instruction_set == kX86_64) {
class DisassemblerOptions {
public:
- // Should the disassembler print absolute or relative addresses.
- const bool absolute_addresses_;
+ using ThreadOffsetNameFunction = void (*)(std::ostream& os, uint32_t offset);
+
+ ThreadOffsetNameFunction thread_offset_name_function_;
// Base address for calculating relative code offsets when absolute_addresses_ is false.
const uint8_t* const base_address_;
// End address (exclusive);
const uint8_t* const end_address_;
+ // Should the disassembler print absolute or relative addresses.
+ const bool absolute_addresses_;
+
// If set, the disassembler is allowed to look at load targets in literal
// pools.
const bool can_read_literals_;
DisassemblerOptions(bool absolute_addresses,
const uint8_t* base_address,
const uint8_t* end_address,
- bool can_read_literals)
- : absolute_addresses_(absolute_addresses),
+ bool can_read_literals,
+ ThreadOffsetNameFunction fn)
+ : thread_offset_name_function_(fn),
base_address_(base_address),
end_address_(end_address),
+ absolute_addresses_(absolute_addresses),
can_read_literals_(can_read_literals) {}
private:
#include "base/bit_utils.h"
#include "base/logging.h"
#include "base/stringprintf.h"
-#include "thread.h"
namespace art {
namespace arm {
}
if (rn.r == 9) {
args << " ; ";
- Thread::DumpThreadOffset<kArmPointerSize>(args, offset);
+ GetDisassemblerOptions()->thread_offset_name_function_(args, offset);
}
}
}
args << Rt << ", [" << Rn << ", #" << (U != 0u ? "" : "-") << imm12 << "]";
if (Rn.r == TR && is_load) {
args << " ; ";
- Thread::DumpThreadOffset<kArmPointerSize>(args, imm12);
+ GetDisassemblerOptions()->thread_offset_name_function_(args, imm12);
} else if (Rn.r == PC) {
T2LitType lit_type[] = {
kT2LitUByte, kT2LitUHalf, kT2LitHexWord, kT2LitInvalid,
#include "base/logging.h"
#include "base/stringprintf.h"
-#include "thread.h"
using namespace vixl::aarch64; // NOLINT(build/namespaces)
if (instr->GetRn() == TR) {
int64_t offset = instr->GetImmLSUnsigned() << instr->GetSizeLS();
std::ostringstream tmp_stream;
- Thread::DumpThreadOffset<kArm64PointerSize>(tmp_stream, static_cast<uint32_t>(offset));
+ options_->thread_offset_name_function_(tmp_stream, static_cast<uint32_t>(offset));
AppendToOutput(" ; %s", tmp_stream.str().c_str());
}
}
: vixl::aarch64::Disassembler(),
read_literals_(options->can_read_literals_),
base_address_(options->base_address_),
- end_address_(options->end_address_) {
+ end_address_(options->end_address_),
+ options_(options) {
if (!options->absolute_addresses_) {
MapCodeAddress(0,
reinterpret_cast<const vixl::aarch64::Instruction*>(options->base_address_));
// Valid address range: [base_address_, end_address_)
const void* const base_address_;
const void* const end_address_;
+
+ DisassemblerOptions* options_;
};
class DisassemblerArm64 FINAL : public Disassembler {
#include "base/logging.h"
#include "base/stringprintf.h"
-#include "thread.h"
namespace art {
namespace mips {
args << StringPrintf("%+d(r%d)", offset, rs);
if (rs == 17) {
args << " ; ";
- if (is64bit_) {
- Thread::DumpThreadOffset<kMips64PointerSize>(args, offset);
- } else {
- Thread::DumpThreadOffset<kMipsPointerSize>(args, offset);
- }
+ GetDisassemblerOptions()->thread_offset_name_function_(args, offset);
}
}
break;
class DisassemblerMips FINAL : public Disassembler {
public:
- DisassemblerMips(DisassemblerOptions* options, bool is64bit)
+ explicit DisassemblerMips(DisassemblerOptions* options)
: Disassembler(options),
- is64bit_(is64bit),
last_ptr_(nullptr),
last_instr_(0) {}
void Dump(std::ostream& os, const uint8_t* begin, const uint8_t* end) OVERRIDE;
private:
- const bool is64bit_;
-
// Address and encoding of the last disassembled instruction.
// Needed to produce more readable disassembly of certain 2-instruction sequences.
const uint8_t* last_ptr_;
#include "base/logging.h"
#include "base/stringprintf.h"
-#include "thread.h"
namespace art {
namespace x86 {
}
if (prefix[1] == kFs && !supports_rex_) {
args << " ; ";
- Thread::DumpThreadOffset<kX86PointerSize>(args, address_bits);
+ GetDisassemblerOptions()->thread_offset_name_function_(args, address_bits);
}
if (prefix[1] == kGs && supports_rex_) {
args << " ; ";
- Thread::DumpThreadOffset<kX86_64PointerSize>(args, address_bits);
+ GetDisassemblerOptions()->thread_offset_name_function_(args, address_bits);
}
const char* prefix_str;
switch (prefix[0]) {
resolved_addr2instr_(0),
instruction_set_(oat_file_.GetOatHeader().GetInstructionSet()),
disassembler_(Disassembler::Create(instruction_set_,
- new DisassemblerOptions(options_.absolute_addresses_,
- oat_file.Begin(),
- oat_file.End(),
- true /* can_read_literals_ */))) {
+ new DisassemblerOptions(
+ options_.absolute_addresses_,
+ oat_file.Begin(),
+ oat_file.End(),
+ true /* can_read_literals_ */,
+ Is64BitInstructionSet(instruction_set_)
+ ? &Thread::DumpThreadOffset<PointerSize::k64>
+ : &Thread::DumpThreadOffset<PointerSize::k32>))) {
CHECK(options_.class_loader_ != nullptr);
CHECK(options_.class_filter_ != nullptr);
CHECK(options_.method_filter_ != nullptr);
const std::vector<const OatFile::OatDexFile*> oat_dex_files_;
const OatDumperOptions& options_;
uint32_t resolved_addr2instr_;
- InstructionSet instruction_set_;
+ const InstructionSet instruction_set_;
std::set<uintptr_t> offsets_;
Disassembler* disassembler_;
};