Index: source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h =================================================================== --- source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h +++ source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h @@ -16,62 +16,14 @@ #include #include -// Other libraries and framework includes -#include "llvm-c/Disassembler.h" - // Project includes #include "lldb/Core/Address.h" #include "lldb/Core/Disassembler.h" #include "lldb/Core/PluginManager.h" -// Opaque references to C++ Objects in LLVM's MC. -namespace llvm { -class MCContext; -class MCInst; -class MCInstrInfo; -class MCRegisterInfo; -class MCDisassembler; -class MCInstPrinter; -class MCAsmInfo; -class MCSubtargetInfo; -} // namespace llvm - class InstructionLLVMC; class DisassemblerLLVMC : public lldb_private::Disassembler { - // Since we need to make two actual MC Disassemblers for ARM (ARM & THUMB), - // and there's a bit of goo to set up and own - // in the MC disassembler world, I added this class to manage the actual - // disassemblers. - class LLVMCDisassembler { - public: - LLVMCDisassembler(const char *triple, const char *cpu, - const char *features_str, unsigned flavor, - DisassemblerLLVMC &owner); - - ~LLVMCDisassembler(); - - uint64_t GetMCInst(const uint8_t *opcode_data, size_t opcode_data_len, - lldb::addr_t pc, llvm::MCInst &mc_inst); - void PrintMCInst(llvm::MCInst &mc_inst, std::string &inst_string, - std::string &comments_string); - void SetStyle(bool use_hex_immed, HexImmediateStyle hex_style); - bool CanBranch(llvm::MCInst &mc_inst); - bool HasDelaySlot(llvm::MCInst &mc_inst); - bool IsCall(llvm::MCInst &mc_inst); - bool IsValid() { return m_is_valid; } - - private: - bool m_is_valid; - std::unique_ptr m_context_ap; - std::unique_ptr m_asm_info_ap; - std::unique_ptr m_subtarget_info_ap; - std::unique_ptr m_instr_info_ap; - std::unique_ptr m_reg_info_ap; - std::unique_ptr m_instr_printer_ap; - std::unique_ptr m_disasm_ap; - }; - public: DisassemblerLLVMC(const lldb_private::ArchSpec &arch, const char *flavor /* = NULL */); @@ -108,9 +60,7 @@ bool FlavorValidForArchSpec(const lldb_private::ArchSpec &arch, const char *flavor) override; - bool IsValid() { - return (m_disasm_ap.get() != NULL && m_disasm_ap->IsValid()); - } + bool IsValid() const; int OpInfo(uint64_t PC, uint64_t Offset, uint64_t Size, int TagType, void *TagBug); @@ -145,8 +95,13 @@ std::mutex m_mutex; bool m_data_from_file; - std::unique_ptr m_disasm_ap; - std::unique_ptr m_alternate_disasm_ap; + // Since we need to make two actual MC Disassemblers for ARM (ARM & THUMB), + // and there's a bit of goo to set up and own + // in the MC disassembler world, I added this class to manage the actual + // disassemblers. + class MCDisasmToolset; + std::unique_ptr m_disasm; + std::unique_ptr m_alternate_disasm; }; #endif // liblldb_DisassemblerLLVM_h_ Index: source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp =================================================================== --- source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp +++ source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp @@ -48,6 +48,41 @@ using namespace lldb; using namespace lldb_private; +class DisassemblerLLVMC::MCDisasmToolset { +public: + static std::unique_ptr + Create(const char *triple, const char *cpu, const char *features_str, + unsigned flavor, DisassemblerLLVMC &owner); + + ~MCDisasmToolset() = default; + + uint64_t GetMCInst(const uint8_t *opcode_data, size_t opcode_data_len, + lldb::addr_t pc, llvm::MCInst &mc_inst) const; + void PrintMCInst(llvm::MCInst &mc_inst, std::string &inst_string, + std::string &comments_string); + void SetStyle(bool use_hex_immed, HexImmediateStyle hex_style); + bool CanBranch(llvm::MCInst &mc_inst) const; + bool HasDelaySlot(llvm::MCInst &mc_inst) const; + bool IsCall(llvm::MCInst &mc_inst) const; + +private: + MCDisasmToolset(std::unique_ptr &&instr_info, + std::unique_ptr &®_info, + std::unique_ptr &&subtarget_info, + std::unique_ptr &&asm_info, + std::unique_ptr &&context, + std::unique_ptr &&disasm, + std::unique_ptr &&instr_printer); + + std::unique_ptr m_instr_info; + std::unique_ptr m_reg_info; + std::unique_ptr m_subtarget_info; + std::unique_ptr m_asm_info; + std::unique_ptr m_context; + std::unique_ptr m_disasm; + std::unique_ptr m_instr_printer; +}; + class InstructionLLVMC : public lldb_private::Instruction { public: InstructionLLVMC(DisassemblerLLVMC &disasm, @@ -72,7 +107,7 @@ bool is_alternate_isa; lldb::addr_t pc = m_address.GetFileAddress(); - DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = + DisassemblerLLVMC::MCDisasmToolset *mc_disasm_ptr = GetDisasmToUse(is_alternate_isa); const uint8_t *opcode_data = data.GetDataStart(); const size_t opcode_data_len = data.GetByteSize(); @@ -107,7 +142,7 @@ bool is_alternate_isa; lldb::addr_t pc = m_address.GetFileAddress(); - DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = + DisassemblerLLVMC::MCDisasmToolset *mc_disasm_ptr = GetDisasmToUse(is_alternate_isa); const uint8_t *opcode_data = data.GetDataStart(); const size_t opcode_data_len = data.GetByteSize(); @@ -132,19 +167,19 @@ return m_has_delay_slot == eLazyBoolYes; } - DisassemblerLLVMC::LLVMCDisassembler *GetDisasmToUse(bool &is_alternate_isa) { + DisassemblerLLVMC::MCDisasmToolset *GetDisasmToUse(bool &is_alternate_isa) { is_alternate_isa = false; std::shared_ptr disasm_sp(GetDisassembler()); if (disasm_sp) { - if (disasm_sp->m_alternate_disasm_ap.get() != NULL) { + if (disasm_sp->m_alternate_disasm) { const AddressClass address_class = GetAddressClass(); if (address_class == eAddressClassCodeAlternateISA) { is_alternate_isa = true; - return disasm_sp->m_alternate_disasm_ap.get(); + return disasm_sp->m_alternate_disasm.get(); } } - return disasm_sp->m_disasm_ap.get(); + return disasm_sp->m_disasm.get(); } return nullptr; } @@ -197,7 +232,7 @@ } if (!got_op) { bool is_alternate_isa = false; - DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = + DisassemblerLLVMC::MCDisasmToolset *mc_disasm_ptr = GetDisasmToUse(is_alternate_isa); const llvm::Triple::ArchType machine = arch.GetMachine(); @@ -264,12 +299,12 @@ std::shared_ptr disasm_sp(GetDisassembler()); if (disasm_sp) { - DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr; + DisassemblerLLVMC::MCDisasmToolset *mc_disasm_ptr; if (address_class == eAddressClassCodeAlternateISA) - mc_disasm_ptr = disasm_sp->m_alternate_disasm_ap.get(); + mc_disasm_ptr = disasm_sp->m_alternate_disasm.get(); else - mc_disasm_ptr = disasm_sp->m_disasm_ap.get(); + mc_disasm_ptr = disasm_sp->m_disasm.get(); lldb::addr_t pc = m_address.GetFileAddress(); m_using_file_addr = true; @@ -850,7 +885,7 @@ bool is_alternate_isa; lldb::addr_t pc = m_address.GetFileAddress(); - DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = + DisassemblerLLVMC::MCDisasmToolset *mc_disasm_ptr = GetDisasmToUse(is_alternate_isa); const uint8_t *opcode_data = data.GetDataStart(); const size_t opcode_data_len = data.GetByteSize(); @@ -881,81 +916,101 @@ bool m_using_file_addr; }; -DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler( - const char *triple, const char *cpu, const char *features_str, - unsigned flavor, DisassemblerLLVMC &owner) - : m_is_valid(true) { +std::unique_ptr +DisassemblerLLVMC::MCDisasmToolset::Create(const char *triple, const char *cpu, + const char *features_str, + unsigned flavor, + DisassemblerLLVMC &owner) { + using Instance = std::unique_ptr; + std::string Status; const llvm::Target *curr_target = llvm::TargetRegistry::lookupTarget(triple, Status); - if (!curr_target) { - m_is_valid = false; - return; - } + if (!curr_target) + return Instance(); - m_instr_info_ap.reset(curr_target->createMCInstrInfo()); - m_reg_info_ap.reset(curr_target->createMCRegInfo(triple)); + std::unique_ptr instr_info( + curr_target->createMCInstrInfo()); + if (!instr_info) + return Instance(); - m_subtarget_info_ap.reset( - curr_target->createMCSubtargetInfo(triple, cpu, features_str)); - std::unique_ptr reg_info( curr_target->createMCRegInfo(triple)); - m_asm_info_ap.reset(curr_target->createMCAsmInfo(*reg_info, triple)); + if (!reg_info) + return Instance(); - if (m_instr_info_ap.get() == NULL || m_reg_info_ap.get() == NULL || - m_subtarget_info_ap.get() == NULL || m_asm_info_ap.get() == NULL) { - m_is_valid = false; - return; - } + std::unique_ptr subtarget_info( + curr_target->createMCSubtargetInfo(triple, cpu, features_str)); + if (!subtarget_info) + return Instance(); - m_context_ap.reset( - new llvm::MCContext(m_asm_info_ap.get(), m_reg_info_ap.get(), 0)); + std::unique_ptr asm_info( + curr_target->createMCAsmInfo(*reg_info, triple)); + if (!asm_info) + return Instance(); - m_disasm_ap.reset(curr_target->createMCDisassembler( - *m_subtarget_info_ap.get(), *m_context_ap.get())); - if (m_disasm_ap.get() && m_context_ap.get()) { - std::unique_ptr RelInfo( - curr_target->createMCRelocationInfo(triple, *m_context_ap.get())); - if (!RelInfo) { - m_is_valid = false; - return; - } - std::unique_ptr symbolizer_up( - curr_target->createMCSymbolizer( - triple, NULL, DisassemblerLLVMC::SymbolLookupCallback, - (void *)&owner, m_context_ap.get(), std::move(RelInfo))); - m_disasm_ap->setSymbolizer(std::move(symbolizer_up)); + std::unique_ptr context( + new llvm::MCContext(asm_info.get(), reg_info.get(), 0)); + if (!context) + return Instance(); - unsigned asm_printer_variant; - if (flavor == ~0U) - asm_printer_variant = m_asm_info_ap->getAssemblerDialect(); - else { - asm_printer_variant = flavor; - } + std::unique_ptr disasm( + curr_target->createMCDisassembler(*subtarget_info, *context)); + if (!disasm) + return Instance(); - m_instr_printer_ap.reset(curr_target->createMCInstPrinter( - llvm::Triple{triple}, asm_printer_variant, *m_asm_info_ap.get(), - *m_instr_info_ap.get(), *m_reg_info_ap.get())); - if (m_instr_printer_ap.get() == NULL) { - m_disasm_ap.reset(); - m_is_valid = false; - } - } else - m_is_valid = false; + std::unique_ptr rel_info( + curr_target->createMCRelocationInfo(triple, *context)); + if (!rel_info) + return Instance(); + + std::unique_ptr symbolizer( + curr_target->createMCSymbolizer( + triple, NULL, DisassemblerLLVMC::SymbolLookupCallback, (void *)&owner, + context.get(), std::move(rel_info))); + disasm->setSymbolizer(std::move(symbolizer)); + + unsigned asm_printer_variant = + flavor == ~0U ? asm_info->getAssemblerDialect() : flavor; + + std::unique_ptr instr_printer( + curr_target->createMCInstPrinter(llvm::Triple{triple}, + asm_printer_variant, *asm_info, + *instr_info, *reg_info)); + if (!instr_printer) + return Instance(); + + return Instance(new MCDisasmToolset( + std::move(instr_info), std::move(reg_info), std::move(subtarget_info), + std::move(asm_info), std::move(context), std::move(disasm), + std::move(instr_printer))); } -DisassemblerLLVMC::LLVMCDisassembler::~LLVMCDisassembler() = default; +DisassemblerLLVMC::MCDisasmToolset::MCDisasmToolset( + std::unique_ptr &&instr_info, + std::unique_ptr &®_info, + std::unique_ptr &&subtarget_info, + std::unique_ptr &&asm_info, + std::unique_ptr &&context, + std::unique_ptr &&disasm, + std::unique_ptr &&instr_printer) + : m_instr_info(std::move(instr_info)), m_reg_info(std::move(reg_info)), + m_subtarget_info(std::move(subtarget_info)), + m_asm_info(std::move(asm_info)), m_context(std::move(context)), + m_disasm(std::move(disasm)), m_instr_printer(std::move(instr_printer)) { + assert(m_instr_info && m_reg_info && m_subtarget_info && m_asm_info && + m_context && disasm && instr_printer); +} -uint64_t DisassemblerLLVMC::LLVMCDisassembler::GetMCInst( +uint64_t DisassemblerLLVMC::MCDisasmToolset::GetMCInst( const uint8_t *opcode_data, size_t opcode_data_len, lldb::addr_t pc, - llvm::MCInst &mc_inst) { + llvm::MCInst &mc_inst) const { llvm::ArrayRef data(opcode_data, opcode_data_len); llvm::MCDisassembler::DecodeStatus status; uint64_t new_inst_size; - status = m_disasm_ap->getInstruction(mc_inst, new_inst_size, data, pc, - llvm::nulls(), llvm::nulls()); + status = m_disasm->getInstruction(mc_inst, new_inst_size, data, pc, + llvm::nulls(), llvm::nulls()); if (status == llvm::MCDisassembler::Success) return new_inst_size; else @@ -962,16 +1017,16 @@ return 0; } -void DisassemblerLLVMC::LLVMCDisassembler::PrintMCInst( +void DisassemblerLLVMC::MCDisasmToolset::PrintMCInst( llvm::MCInst &mc_inst, std::string &inst_string, std::string &comments_string) { llvm::raw_string_ostream inst_stream(inst_string); llvm::raw_string_ostream comments_stream(comments_string); - m_instr_printer_ap->setCommentStream(comments_stream); - m_instr_printer_ap->printInst(&mc_inst, inst_stream, llvm::StringRef(), - *m_subtarget_info_ap); - m_instr_printer_ap->setCommentStream(llvm::nulls()); + m_instr_printer->setCommentStream(comments_stream); + m_instr_printer->printInst(&mc_inst, inst_stream, llvm::StringRef(), + *m_subtarget_info); + m_instr_printer->setCommentStream(llvm::nulls()); comments_stream.flush(); static std::string g_newlines("\r\n"); @@ -985,30 +1040,32 @@ } } -void DisassemblerLLVMC::LLVMCDisassembler::SetStyle( - bool use_hex_immed, HexImmediateStyle hex_style) { - m_instr_printer_ap->setPrintImmHex(use_hex_immed); +void DisassemblerLLVMC::MCDisasmToolset::SetStyle(bool use_hex_immed, + HexImmediateStyle hex_style) { + m_instr_printer->setPrintImmHex(use_hex_immed); switch (hex_style) { case eHexStyleC: - m_instr_printer_ap->setPrintHexStyle(llvm::HexStyle::C); + m_instr_printer->setPrintHexStyle(llvm::HexStyle::C); break; case eHexStyleAsm: - m_instr_printer_ap->setPrintHexStyle(llvm::HexStyle::Asm); + m_instr_printer->setPrintHexStyle(llvm::HexStyle::Asm); break; } } -bool DisassemblerLLVMC::LLVMCDisassembler::CanBranch(llvm::MCInst &mc_inst) { - return m_instr_info_ap->get(mc_inst.getOpcode()) - .mayAffectControlFlow(mc_inst, *m_reg_info_ap.get()); +bool DisassemblerLLVMC::MCDisasmToolset::CanBranch( + llvm::MCInst &mc_inst) const { + return m_instr_info->get(mc_inst.getOpcode()) + .mayAffectControlFlow(mc_inst, *m_reg_info); } -bool DisassemblerLLVMC::LLVMCDisassembler::HasDelaySlot(llvm::MCInst &mc_inst) { - return m_instr_info_ap->get(mc_inst.getOpcode()).hasDelaySlot(); +bool DisassemblerLLVMC::MCDisasmToolset::HasDelaySlot( + llvm::MCInst &mc_inst) const { + return m_instr_info->get(mc_inst.getOpcode()).hasDelaySlot(); } -bool DisassemblerLLVMC::LLVMCDisassembler::IsCall(llvm::MCInst &mc_inst) { - return m_instr_info_ap->get(mc_inst.getOpcode()).isCall(); +bool DisassemblerLLVMC::MCDisasmToolset::IsCall(llvm::MCInst &mc_inst) const { + return m_instr_info->get(mc_inst.getOpcode()).isCall(); } DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch, @@ -1132,15 +1189,11 @@ if (triple.getArch() == llvm::Triple::aarch64) features_str += "+v8.2a"; - m_disasm_ap.reset(new LLVMCDisassembler(triple_str, cpu, features_str.c_str(), - flavor, *this)); - if (!m_disasm_ap->IsValid()) { - // We use m_disasm_ap.get() to tell whether we are valid or not, so if this - // isn't good for some reason, - // we reset it, and then we won't be valid and FindPlugin will fail and we - // won't get used. - m_disasm_ap.reset(); - } + // We use m_disasm_ap.get() to tell whether we are valid or not, + // so if this isn't good for some reason, + // we won't be valid and FindPlugin will fail and we won't get used. + m_disasm = MCDisasmToolset::Create(triple_str, cpu, features_str.c_str(), + flavor, *this); llvm::Triple::ArchType llvm_arch = triple.getArch(); @@ -1148,12 +1201,11 @@ // thumb instruction disassembler. if (llvm_arch == llvm::Triple::arm) { std::string thumb_triple(thumb_arch.GetTriple().getTriple()); - m_alternate_disasm_ap.reset( - new LLVMCDisassembler(thumb_triple.c_str(), "", "", flavor, *this)); - if (!m_alternate_disasm_ap->IsValid()) { - m_disasm_ap.reset(); - m_alternate_disasm_ap.reset(); - } + m_alternate_disasm = + MCDisasmToolset::Create(thumb_triple.c_str(), "", "", flavor, *this); + if (!m_alternate_disasm) + m_disasm.reset(); + } else if (llvm_arch == llvm::Triple::mips || llvm_arch == llvm::Triple::mipsel || llvm_arch == llvm::Triple::mips64 || @@ -1165,12 +1217,10 @@ else if (arch_flags & ArchSpec::eMIPSAse_micromips) features_str += "+micromips,"; - m_alternate_disasm_ap.reset(new LLVMCDisassembler( - triple_str, cpu, features_str.c_str(), flavor, *this)); - if (!m_alternate_disasm_ap->IsValid()) { - m_disasm_ap.reset(); - m_alternate_disasm_ap.reset(); - } + m_alternate_disasm = MCDisasmToolset::Create( + triple_str, cpu, features_str.c_str(), flavor, *this); + if (!m_alternate_disasm) + m_disasm.reset(); } } @@ -1210,7 +1260,7 @@ AddressClass address_class = eAddressClassCode; - if (m_alternate_disasm_ap.get() != NULL) + if (m_alternate_disasm) address_class = inst_addr.GetAddressClass(); InstructionSP inst_sp( @@ -1285,6 +1335,8 @@ return false; } +bool DisassemblerLLVMC::IsValid() const { return m_disasm.operator bool(); } + int DisassemblerLLVMC::OpInfo(uint64_t PC, uint64_t Offset, uint64_t Size, int tag_type, void *tag_bug) { switch (tag_type) {