| //===-- DisassemblerLLVMC.h -------------------------------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef liblldb_DisassemblerLLVMC_h_ |
| #define liblldb_DisassemblerLLVMC_h_ |
| |
| // C Includes |
| // C++ Includes |
| #include <memory> |
| #include <mutex> |
| #include <string> |
| |
| // 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<llvm::MCContext> m_context_ap; |
| std::unique_ptr<llvm::MCAsmInfo> m_asm_info_ap; |
| std::unique_ptr<llvm::MCSubtargetInfo> m_subtarget_info_ap; |
| std::unique_ptr<llvm::MCInstrInfo> m_instr_info_ap; |
| std::unique_ptr<llvm::MCRegisterInfo> m_reg_info_ap; |
| std::unique_ptr<llvm::MCInstPrinter> m_instr_printer_ap; |
| std::unique_ptr<llvm::MCDisassembler> m_disasm_ap; |
| }; |
| |
| public: |
| DisassemblerLLVMC(const lldb_private::ArchSpec &arch, |
| const char *flavor /* = NULL */); |
| |
| ~DisassemblerLLVMC() override; |
| |
| //------------------------------------------------------------------ |
| // Static Functions |
| //------------------------------------------------------------------ |
| static void Initialize(); |
| |
| static void Terminate(); |
| |
| static lldb_private::ConstString GetPluginNameStatic(); |
| |
| static lldb_private::Disassembler * |
| CreateInstance(const lldb_private::ArchSpec &arch, const char *flavor); |
| |
| size_t DecodeInstructions(const lldb_private::Address &base_addr, |
| const lldb_private::DataExtractor &data, |
| lldb::offset_t data_offset, size_t num_instructions, |
| bool append, bool data_from_file) override; |
| |
| //------------------------------------------------------------------ |
| // PluginInterface protocol |
| //------------------------------------------------------------------ |
| lldb_private::ConstString GetPluginName() override; |
| |
| uint32_t GetPluginVersion() override; |
| |
| protected: |
| friend class InstructionLLVMC; |
| |
| bool FlavorValidForArchSpec(const lldb_private::ArchSpec &arch, |
| const char *flavor) override; |
| |
| bool IsValid() { |
| return (m_disasm_ap.get() != NULL && m_disasm_ap->IsValid()); |
| } |
| |
| int OpInfo(uint64_t PC, uint64_t Offset, uint64_t Size, int TagType, |
| void *TagBug); |
| |
| const char *SymbolLookup(uint64_t ReferenceValue, uint64_t *ReferenceType, |
| uint64_t ReferencePC, const char **ReferenceName); |
| |
| static int OpInfoCallback(void *DisInfo, uint64_t PC, uint64_t Offset, |
| uint64_t Size, int TagType, void *TagBug); |
| |
| static const char *SymbolLookupCallback(void *DisInfo, |
| uint64_t ReferenceValue, |
| uint64_t *ReferenceType, |
| uint64_t ReferencePC, |
| const char **ReferenceName); |
| |
| void Lock(InstructionLLVMC *inst, |
| const lldb_private::ExecutionContext *exe_ctx) { |
| m_mutex.lock(); |
| m_inst = inst; |
| m_exe_ctx = exe_ctx; |
| } |
| |
| void Unlock() { |
| m_inst = NULL; |
| m_exe_ctx = NULL; |
| m_mutex.unlock(); |
| } |
| |
| const lldb_private::ExecutionContext *m_exe_ctx; |
| InstructionLLVMC *m_inst; |
| std::mutex m_mutex; |
| bool m_data_from_file; |
| |
| std::unique_ptr<LLVMCDisassembler> m_disasm_ap; |
| std::unique_ptr<LLVMCDisassembler> m_alternate_disasm_ap; |
| }; |
| |
| #endif // liblldb_DisassemblerLLVM_h_ |