15ffd83dbSDimitry Andric //===-- DisassemblerLLVMC.cpp ---------------------------------------------===// 25ffd83dbSDimitry Andric // 35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65ffd83dbSDimitry Andric // 75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 85ffd83dbSDimitry Andric 95ffd83dbSDimitry Andric #include "DisassemblerLLVMC.h" 105ffd83dbSDimitry Andric 115ffd83dbSDimitry Andric #include "llvm-c/Disassembler.h" 125ffd83dbSDimitry Andric #include "llvm/ADT/SmallString.h" 135ffd83dbSDimitry Andric #include "llvm/MC/MCAsmInfo.h" 145ffd83dbSDimitry Andric #include "llvm/MC/MCContext.h" 155ffd83dbSDimitry Andric #include "llvm/MC/MCDisassembler/MCDisassembler.h" 165ffd83dbSDimitry Andric #include "llvm/MC/MCDisassembler/MCExternalSymbolizer.h" 175ffd83dbSDimitry Andric #include "llvm/MC/MCDisassembler/MCRelocationInfo.h" 185ffd83dbSDimitry Andric #include "llvm/MC/MCInst.h" 195ffd83dbSDimitry Andric #include "llvm/MC/MCInstPrinter.h" 205ffd83dbSDimitry Andric #include "llvm/MC/MCInstrInfo.h" 215ffd83dbSDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 225ffd83dbSDimitry Andric #include "llvm/MC/MCSubtargetInfo.h" 235ffd83dbSDimitry Andric #include "llvm/MC/MCTargetOptions.h" 245ffd83dbSDimitry Andric #include "llvm/Support/ErrorHandling.h" 255ffd83dbSDimitry Andric #include "llvm/Support/ScopedPrinter.h" 265ffd83dbSDimitry Andric #include "llvm/Support/TargetRegistry.h" 275ffd83dbSDimitry Andric #include "llvm/Support/TargetSelect.h" 285ffd83dbSDimitry Andric 295ffd83dbSDimitry Andric #include "lldb/Core/Address.h" 305ffd83dbSDimitry Andric #include "lldb/Core/Module.h" 315ffd83dbSDimitry Andric #include "lldb/Symbol/SymbolContext.h" 325ffd83dbSDimitry Andric #include "lldb/Target/ExecutionContext.h" 335ffd83dbSDimitry Andric #include "lldb/Target/Process.h" 345ffd83dbSDimitry Andric #include "lldb/Target/RegisterContext.h" 355ffd83dbSDimitry Andric #include "lldb/Target/SectionLoadList.h" 365ffd83dbSDimitry Andric #include "lldb/Target/StackFrame.h" 375ffd83dbSDimitry Andric #include "lldb/Target/Target.h" 385ffd83dbSDimitry Andric #include "lldb/Utility/DataExtractor.h" 395ffd83dbSDimitry Andric #include "lldb/Utility/Log.h" 405ffd83dbSDimitry Andric #include "lldb/Utility/RegularExpression.h" 415ffd83dbSDimitry Andric #include "lldb/Utility/Stream.h" 425ffd83dbSDimitry Andric 435ffd83dbSDimitry Andric using namespace lldb; 445ffd83dbSDimitry Andric using namespace lldb_private; 455ffd83dbSDimitry Andric 465ffd83dbSDimitry Andric LLDB_PLUGIN_DEFINE(DisassemblerLLVMC) 475ffd83dbSDimitry Andric 485ffd83dbSDimitry Andric class DisassemblerLLVMC::MCDisasmInstance { 495ffd83dbSDimitry Andric public: 505ffd83dbSDimitry Andric static std::unique_ptr<MCDisasmInstance> 515ffd83dbSDimitry Andric Create(const char *triple, const char *cpu, const char *features_str, 525ffd83dbSDimitry Andric unsigned flavor, DisassemblerLLVMC &owner); 535ffd83dbSDimitry Andric 545ffd83dbSDimitry Andric ~MCDisasmInstance() = default; 555ffd83dbSDimitry Andric 565ffd83dbSDimitry Andric uint64_t GetMCInst(const uint8_t *opcode_data, size_t opcode_data_len, 575ffd83dbSDimitry Andric lldb::addr_t pc, llvm::MCInst &mc_inst) const; 585ffd83dbSDimitry Andric void PrintMCInst(llvm::MCInst &mc_inst, std::string &inst_string, 595ffd83dbSDimitry Andric std::string &comments_string); 605ffd83dbSDimitry Andric void SetStyle(bool use_hex_immed, HexImmediateStyle hex_style); 615ffd83dbSDimitry Andric bool CanBranch(llvm::MCInst &mc_inst) const; 625ffd83dbSDimitry Andric bool HasDelaySlot(llvm::MCInst &mc_inst) const; 635ffd83dbSDimitry Andric bool IsCall(llvm::MCInst &mc_inst) const; 645ffd83dbSDimitry Andric 655ffd83dbSDimitry Andric private: 665ffd83dbSDimitry Andric MCDisasmInstance(std::unique_ptr<llvm::MCInstrInfo> &&instr_info_up, 675ffd83dbSDimitry Andric std::unique_ptr<llvm::MCRegisterInfo> &®_info_up, 685ffd83dbSDimitry Andric std::unique_ptr<llvm::MCSubtargetInfo> &&subtarget_info_up, 695ffd83dbSDimitry Andric std::unique_ptr<llvm::MCAsmInfo> &&asm_info_up, 705ffd83dbSDimitry Andric std::unique_ptr<llvm::MCContext> &&context_up, 715ffd83dbSDimitry Andric std::unique_ptr<llvm::MCDisassembler> &&disasm_up, 725ffd83dbSDimitry Andric std::unique_ptr<llvm::MCInstPrinter> &&instr_printer_up); 735ffd83dbSDimitry Andric 745ffd83dbSDimitry Andric std::unique_ptr<llvm::MCInstrInfo> m_instr_info_up; 755ffd83dbSDimitry Andric std::unique_ptr<llvm::MCRegisterInfo> m_reg_info_up; 765ffd83dbSDimitry Andric std::unique_ptr<llvm::MCSubtargetInfo> m_subtarget_info_up; 775ffd83dbSDimitry Andric std::unique_ptr<llvm::MCAsmInfo> m_asm_info_up; 785ffd83dbSDimitry Andric std::unique_ptr<llvm::MCContext> m_context_up; 795ffd83dbSDimitry Andric std::unique_ptr<llvm::MCDisassembler> m_disasm_up; 805ffd83dbSDimitry Andric std::unique_ptr<llvm::MCInstPrinter> m_instr_printer_up; 815ffd83dbSDimitry Andric }; 825ffd83dbSDimitry Andric 835ffd83dbSDimitry Andric class InstructionLLVMC : public lldb_private::Instruction { 845ffd83dbSDimitry Andric public: 855ffd83dbSDimitry Andric InstructionLLVMC(DisassemblerLLVMC &disasm, 865ffd83dbSDimitry Andric const lldb_private::Address &address, 875ffd83dbSDimitry Andric AddressClass addr_class) 885ffd83dbSDimitry Andric : Instruction(address, addr_class), 895ffd83dbSDimitry Andric m_disasm_wp(std::static_pointer_cast<DisassemblerLLVMC>( 905ffd83dbSDimitry Andric disasm.shared_from_this())), 915ffd83dbSDimitry Andric m_using_file_addr(false) {} 925ffd83dbSDimitry Andric 935ffd83dbSDimitry Andric ~InstructionLLVMC() override = default; 945ffd83dbSDimitry Andric 955ffd83dbSDimitry Andric bool DoesBranch() override { 965ffd83dbSDimitry Andric VisitInstruction(); 975ffd83dbSDimitry Andric return m_does_branch; 985ffd83dbSDimitry Andric } 995ffd83dbSDimitry Andric 1005ffd83dbSDimitry Andric bool HasDelaySlot() override { 1015ffd83dbSDimitry Andric VisitInstruction(); 1025ffd83dbSDimitry Andric return m_has_delay_slot; 1035ffd83dbSDimitry Andric } 1045ffd83dbSDimitry Andric 1055ffd83dbSDimitry Andric DisassemblerLLVMC::MCDisasmInstance *GetDisasmToUse(bool &is_alternate_isa) { 1065ffd83dbSDimitry Andric DisassemblerScope disasm(*this); 1075ffd83dbSDimitry Andric return GetDisasmToUse(is_alternate_isa, disasm); 1085ffd83dbSDimitry Andric } 1095ffd83dbSDimitry Andric 1105ffd83dbSDimitry Andric size_t Decode(const lldb_private::Disassembler &disassembler, 1115ffd83dbSDimitry Andric const lldb_private::DataExtractor &data, 1125ffd83dbSDimitry Andric lldb::offset_t data_offset) override { 1135ffd83dbSDimitry Andric // All we have to do is read the opcode which can be easy for some 1145ffd83dbSDimitry Andric // architectures 1155ffd83dbSDimitry Andric bool got_op = false; 1165ffd83dbSDimitry Andric DisassemblerScope disasm(*this); 1175ffd83dbSDimitry Andric if (disasm) { 1185ffd83dbSDimitry Andric const ArchSpec &arch = disasm->GetArchitecture(); 1195ffd83dbSDimitry Andric const lldb::ByteOrder byte_order = data.GetByteOrder(); 1205ffd83dbSDimitry Andric 1215ffd83dbSDimitry Andric const uint32_t min_op_byte_size = arch.GetMinimumOpcodeByteSize(); 1225ffd83dbSDimitry Andric const uint32_t max_op_byte_size = arch.GetMaximumOpcodeByteSize(); 1235ffd83dbSDimitry Andric if (min_op_byte_size == max_op_byte_size) { 1245ffd83dbSDimitry Andric // Fixed size instructions, just read that amount of data. 1255ffd83dbSDimitry Andric if (!data.ValidOffsetForDataOfSize(data_offset, min_op_byte_size)) 1265ffd83dbSDimitry Andric return false; 1275ffd83dbSDimitry Andric 1285ffd83dbSDimitry Andric switch (min_op_byte_size) { 1295ffd83dbSDimitry Andric case 1: 1305ffd83dbSDimitry Andric m_opcode.SetOpcode8(data.GetU8(&data_offset), byte_order); 1315ffd83dbSDimitry Andric got_op = true; 1325ffd83dbSDimitry Andric break; 1335ffd83dbSDimitry Andric 1345ffd83dbSDimitry Andric case 2: 1355ffd83dbSDimitry Andric m_opcode.SetOpcode16(data.GetU16(&data_offset), byte_order); 1365ffd83dbSDimitry Andric got_op = true; 1375ffd83dbSDimitry Andric break; 1385ffd83dbSDimitry Andric 1395ffd83dbSDimitry Andric case 4: 1405ffd83dbSDimitry Andric m_opcode.SetOpcode32(data.GetU32(&data_offset), byte_order); 1415ffd83dbSDimitry Andric got_op = true; 1425ffd83dbSDimitry Andric break; 1435ffd83dbSDimitry Andric 1445ffd83dbSDimitry Andric case 8: 1455ffd83dbSDimitry Andric m_opcode.SetOpcode64(data.GetU64(&data_offset), byte_order); 1465ffd83dbSDimitry Andric got_op = true; 1475ffd83dbSDimitry Andric break; 1485ffd83dbSDimitry Andric 1495ffd83dbSDimitry Andric default: 1505ffd83dbSDimitry Andric m_opcode.SetOpcodeBytes(data.PeekData(data_offset, min_op_byte_size), 1515ffd83dbSDimitry Andric min_op_byte_size); 1525ffd83dbSDimitry Andric got_op = true; 1535ffd83dbSDimitry Andric break; 1545ffd83dbSDimitry Andric } 1555ffd83dbSDimitry Andric } 1565ffd83dbSDimitry Andric if (!got_op) { 1575ffd83dbSDimitry Andric bool is_alternate_isa = false; 1585ffd83dbSDimitry Andric DisassemblerLLVMC::MCDisasmInstance *mc_disasm_ptr = 1595ffd83dbSDimitry Andric GetDisasmToUse(is_alternate_isa, disasm); 1605ffd83dbSDimitry Andric 1615ffd83dbSDimitry Andric const llvm::Triple::ArchType machine = arch.GetMachine(); 1625ffd83dbSDimitry Andric if (machine == llvm::Triple::arm || machine == llvm::Triple::thumb) { 1635ffd83dbSDimitry Andric if (machine == llvm::Triple::thumb || is_alternate_isa) { 1645ffd83dbSDimitry Andric uint32_t thumb_opcode = data.GetU16(&data_offset); 1655ffd83dbSDimitry Andric if ((thumb_opcode & 0xe000) != 0xe000 || 1665ffd83dbSDimitry Andric ((thumb_opcode & 0x1800u) == 0)) { 1675ffd83dbSDimitry Andric m_opcode.SetOpcode16(thumb_opcode, byte_order); 1685ffd83dbSDimitry Andric m_is_valid = true; 1695ffd83dbSDimitry Andric } else { 1705ffd83dbSDimitry Andric thumb_opcode <<= 16; 1715ffd83dbSDimitry Andric thumb_opcode |= data.GetU16(&data_offset); 1725ffd83dbSDimitry Andric m_opcode.SetOpcode16_2(thumb_opcode, byte_order); 1735ffd83dbSDimitry Andric m_is_valid = true; 1745ffd83dbSDimitry Andric } 1755ffd83dbSDimitry Andric } else { 1765ffd83dbSDimitry Andric m_opcode.SetOpcode32(data.GetU32(&data_offset), byte_order); 1775ffd83dbSDimitry Andric m_is_valid = true; 1785ffd83dbSDimitry Andric } 1795ffd83dbSDimitry Andric } else { 1805ffd83dbSDimitry Andric // The opcode isn't evenly sized, so we need to actually use the llvm 1815ffd83dbSDimitry Andric // disassembler to parse it and get the size. 1825ffd83dbSDimitry Andric uint8_t *opcode_data = 1835ffd83dbSDimitry Andric const_cast<uint8_t *>(data.PeekData(data_offset, 1)); 1845ffd83dbSDimitry Andric const size_t opcode_data_len = data.BytesLeft(data_offset); 1855ffd83dbSDimitry Andric const addr_t pc = m_address.GetFileAddress(); 1865ffd83dbSDimitry Andric llvm::MCInst inst; 1875ffd83dbSDimitry Andric 1885ffd83dbSDimitry Andric const size_t inst_size = 1895ffd83dbSDimitry Andric mc_disasm_ptr->GetMCInst(opcode_data, opcode_data_len, pc, inst); 1905ffd83dbSDimitry Andric if (inst_size == 0) 1915ffd83dbSDimitry Andric m_opcode.Clear(); 1925ffd83dbSDimitry Andric else { 1935ffd83dbSDimitry Andric m_opcode.SetOpcodeBytes(opcode_data, inst_size); 1945ffd83dbSDimitry Andric m_is_valid = true; 1955ffd83dbSDimitry Andric } 1965ffd83dbSDimitry Andric } 1975ffd83dbSDimitry Andric } 1985ffd83dbSDimitry Andric return m_opcode.GetByteSize(); 1995ffd83dbSDimitry Andric } 2005ffd83dbSDimitry Andric return 0; 2015ffd83dbSDimitry Andric } 2025ffd83dbSDimitry Andric 2035ffd83dbSDimitry Andric void AppendComment(std::string &description) { 2045ffd83dbSDimitry Andric if (m_comment.empty()) 2055ffd83dbSDimitry Andric m_comment.swap(description); 2065ffd83dbSDimitry Andric else { 2075ffd83dbSDimitry Andric m_comment.append(", "); 2085ffd83dbSDimitry Andric m_comment.append(description); 2095ffd83dbSDimitry Andric } 2105ffd83dbSDimitry Andric } 2115ffd83dbSDimitry Andric 2125ffd83dbSDimitry Andric void CalculateMnemonicOperandsAndComment( 2135ffd83dbSDimitry Andric const lldb_private::ExecutionContext *exe_ctx) override { 2145ffd83dbSDimitry Andric DataExtractor data; 2155ffd83dbSDimitry Andric const AddressClass address_class = GetAddressClass(); 2165ffd83dbSDimitry Andric 2175ffd83dbSDimitry Andric if (m_opcode.GetData(data)) { 2185ffd83dbSDimitry Andric std::string out_string; 2195ffd83dbSDimitry Andric std::string comment_string; 2205ffd83dbSDimitry Andric 2215ffd83dbSDimitry Andric DisassemblerScope disasm(*this, exe_ctx); 2225ffd83dbSDimitry Andric if (disasm) { 2235ffd83dbSDimitry Andric DisassemblerLLVMC::MCDisasmInstance *mc_disasm_ptr; 2245ffd83dbSDimitry Andric 2255ffd83dbSDimitry Andric if (address_class == AddressClass::eCodeAlternateISA) 2265ffd83dbSDimitry Andric mc_disasm_ptr = disasm->m_alternate_disasm_up.get(); 2275ffd83dbSDimitry Andric else 2285ffd83dbSDimitry Andric mc_disasm_ptr = disasm->m_disasm_up.get(); 2295ffd83dbSDimitry Andric 2305ffd83dbSDimitry Andric lldb::addr_t pc = m_address.GetFileAddress(); 2315ffd83dbSDimitry Andric m_using_file_addr = true; 2325ffd83dbSDimitry Andric 2335ffd83dbSDimitry Andric const bool data_from_file = disasm->m_data_from_file; 2345ffd83dbSDimitry Andric bool use_hex_immediates = true; 2355ffd83dbSDimitry Andric Disassembler::HexImmediateStyle hex_style = Disassembler::eHexStyleC; 2365ffd83dbSDimitry Andric 2375ffd83dbSDimitry Andric if (exe_ctx) { 2385ffd83dbSDimitry Andric Target *target = exe_ctx->GetTargetPtr(); 2395ffd83dbSDimitry Andric if (target) { 2405ffd83dbSDimitry Andric use_hex_immediates = target->GetUseHexImmediates(); 2415ffd83dbSDimitry Andric hex_style = target->GetHexImmediateStyle(); 2425ffd83dbSDimitry Andric 2435ffd83dbSDimitry Andric if (!data_from_file) { 2445ffd83dbSDimitry Andric const lldb::addr_t load_addr = m_address.GetLoadAddress(target); 2455ffd83dbSDimitry Andric if (load_addr != LLDB_INVALID_ADDRESS) { 2465ffd83dbSDimitry Andric pc = load_addr; 2475ffd83dbSDimitry Andric m_using_file_addr = false; 2485ffd83dbSDimitry Andric } 2495ffd83dbSDimitry Andric } 2505ffd83dbSDimitry Andric } 2515ffd83dbSDimitry Andric } 2525ffd83dbSDimitry Andric 2535ffd83dbSDimitry Andric const uint8_t *opcode_data = data.GetDataStart(); 2545ffd83dbSDimitry Andric const size_t opcode_data_len = data.GetByteSize(); 2555ffd83dbSDimitry Andric llvm::MCInst inst; 2565ffd83dbSDimitry Andric size_t inst_size = 2575ffd83dbSDimitry Andric mc_disasm_ptr->GetMCInst(opcode_data, opcode_data_len, pc, inst); 2585ffd83dbSDimitry Andric 2595ffd83dbSDimitry Andric if (inst_size > 0) { 2605ffd83dbSDimitry Andric mc_disasm_ptr->SetStyle(use_hex_immediates, hex_style); 2615ffd83dbSDimitry Andric mc_disasm_ptr->PrintMCInst(inst, out_string, comment_string); 2625ffd83dbSDimitry Andric 2635ffd83dbSDimitry Andric if (!comment_string.empty()) { 2645ffd83dbSDimitry Andric AppendComment(comment_string); 2655ffd83dbSDimitry Andric } 2665ffd83dbSDimitry Andric } 2675ffd83dbSDimitry Andric 2685ffd83dbSDimitry Andric if (inst_size == 0) { 2695ffd83dbSDimitry Andric m_comment.assign("unknown opcode"); 2705ffd83dbSDimitry Andric inst_size = m_opcode.GetByteSize(); 2715ffd83dbSDimitry Andric StreamString mnemonic_strm; 2725ffd83dbSDimitry Andric lldb::offset_t offset = 0; 2735ffd83dbSDimitry Andric lldb::ByteOrder byte_order = data.GetByteOrder(); 2745ffd83dbSDimitry Andric switch (inst_size) { 2755ffd83dbSDimitry Andric case 1: { 2765ffd83dbSDimitry Andric const uint8_t uval8 = data.GetU8(&offset); 2775ffd83dbSDimitry Andric m_opcode.SetOpcode8(uval8, byte_order); 2785ffd83dbSDimitry Andric m_opcode_name.assign(".byte"); 2795ffd83dbSDimitry Andric mnemonic_strm.Printf("0x%2.2x", uval8); 2805ffd83dbSDimitry Andric } break; 2815ffd83dbSDimitry Andric case 2: { 2825ffd83dbSDimitry Andric const uint16_t uval16 = data.GetU16(&offset); 2835ffd83dbSDimitry Andric m_opcode.SetOpcode16(uval16, byte_order); 2845ffd83dbSDimitry Andric m_opcode_name.assign(".short"); 2855ffd83dbSDimitry Andric mnemonic_strm.Printf("0x%4.4x", uval16); 2865ffd83dbSDimitry Andric } break; 2875ffd83dbSDimitry Andric case 4: { 2885ffd83dbSDimitry Andric const uint32_t uval32 = data.GetU32(&offset); 2895ffd83dbSDimitry Andric m_opcode.SetOpcode32(uval32, byte_order); 2905ffd83dbSDimitry Andric m_opcode_name.assign(".long"); 2915ffd83dbSDimitry Andric mnemonic_strm.Printf("0x%8.8x", uval32); 2925ffd83dbSDimitry Andric } break; 2935ffd83dbSDimitry Andric case 8: { 2945ffd83dbSDimitry Andric const uint64_t uval64 = data.GetU64(&offset); 2955ffd83dbSDimitry Andric m_opcode.SetOpcode64(uval64, byte_order); 2965ffd83dbSDimitry Andric m_opcode_name.assign(".quad"); 2975ffd83dbSDimitry Andric mnemonic_strm.Printf("0x%16.16" PRIx64, uval64); 2985ffd83dbSDimitry Andric } break; 2995ffd83dbSDimitry Andric default: 3005ffd83dbSDimitry Andric if (inst_size == 0) 3015ffd83dbSDimitry Andric return; 3025ffd83dbSDimitry Andric else { 3035ffd83dbSDimitry Andric const uint8_t *bytes = data.PeekData(offset, inst_size); 3045ffd83dbSDimitry Andric if (bytes == nullptr) 3055ffd83dbSDimitry Andric return; 3065ffd83dbSDimitry Andric m_opcode_name.assign(".byte"); 3075ffd83dbSDimitry Andric m_opcode.SetOpcodeBytes(bytes, inst_size); 3085ffd83dbSDimitry Andric mnemonic_strm.Printf("0x%2.2x", bytes[0]); 3095ffd83dbSDimitry Andric for (uint32_t i = 1; i < inst_size; ++i) 3105ffd83dbSDimitry Andric mnemonic_strm.Printf(" 0x%2.2x", bytes[i]); 3115ffd83dbSDimitry Andric } 3125ffd83dbSDimitry Andric break; 3135ffd83dbSDimitry Andric } 3145ffd83dbSDimitry Andric m_mnemonics = std::string(mnemonic_strm.GetString()); 3155ffd83dbSDimitry Andric return; 3165ffd83dbSDimitry Andric } 3175ffd83dbSDimitry Andric 3185ffd83dbSDimitry Andric static RegularExpression s_regex( 3195ffd83dbSDimitry Andric llvm::StringRef("[ \t]*([^ ^\t]+)[ \t]*([^ ^\t].*)?")); 3205ffd83dbSDimitry Andric 3215ffd83dbSDimitry Andric llvm::SmallVector<llvm::StringRef, 4> matches; 3225ffd83dbSDimitry Andric if (s_regex.Execute(out_string, &matches)) { 3235ffd83dbSDimitry Andric m_opcode_name = matches[1].str(); 3245ffd83dbSDimitry Andric m_mnemonics = matches[2].str(); 3255ffd83dbSDimitry Andric } 3265ffd83dbSDimitry Andric } 3275ffd83dbSDimitry Andric } 3285ffd83dbSDimitry Andric } 3295ffd83dbSDimitry Andric 3305ffd83dbSDimitry Andric bool IsValid() const { return m_is_valid; } 3315ffd83dbSDimitry Andric 3325ffd83dbSDimitry Andric bool UsingFileAddress() const { return m_using_file_addr; } 3335ffd83dbSDimitry Andric size_t GetByteSize() const { return m_opcode.GetByteSize(); } 3345ffd83dbSDimitry Andric 3355ffd83dbSDimitry Andric /// Grants exclusive access to the disassembler and initializes it with the 3365ffd83dbSDimitry Andric /// given InstructionLLVMC and an optional ExecutionContext. 3375ffd83dbSDimitry Andric class DisassemblerScope { 3385ffd83dbSDimitry Andric std::shared_ptr<DisassemblerLLVMC> m_disasm; 3395ffd83dbSDimitry Andric 3405ffd83dbSDimitry Andric public: 3415ffd83dbSDimitry Andric explicit DisassemblerScope( 3425ffd83dbSDimitry Andric InstructionLLVMC &i, 3435ffd83dbSDimitry Andric const lldb_private::ExecutionContext *exe_ctx = nullptr) 3445ffd83dbSDimitry Andric : m_disasm(i.m_disasm_wp.lock()) { 3455ffd83dbSDimitry Andric m_disasm->m_mutex.lock(); 3465ffd83dbSDimitry Andric m_disasm->m_inst = &i; 3475ffd83dbSDimitry Andric m_disasm->m_exe_ctx = exe_ctx; 3485ffd83dbSDimitry Andric } 3495ffd83dbSDimitry Andric ~DisassemblerScope() { m_disasm->m_mutex.unlock(); } 3505ffd83dbSDimitry Andric 3515ffd83dbSDimitry Andric /// Evaluates to true if this scope contains a valid disassembler. 3525ffd83dbSDimitry Andric operator bool() const { return static_cast<bool>(m_disasm); } 3535ffd83dbSDimitry Andric 3545ffd83dbSDimitry Andric std::shared_ptr<DisassemblerLLVMC> operator->() { return m_disasm; } 3555ffd83dbSDimitry Andric }; 3565ffd83dbSDimitry Andric 3575ffd83dbSDimitry Andric static llvm::StringRef::const_iterator 3585ffd83dbSDimitry Andric ConsumeWhitespace(llvm::StringRef::const_iterator osi, 3595ffd83dbSDimitry Andric llvm::StringRef::const_iterator ose) { 3605ffd83dbSDimitry Andric while (osi != ose) { 3615ffd83dbSDimitry Andric switch (*osi) { 3625ffd83dbSDimitry Andric default: 3635ffd83dbSDimitry Andric return osi; 3645ffd83dbSDimitry Andric case ' ': 3655ffd83dbSDimitry Andric case '\t': 3665ffd83dbSDimitry Andric break; 3675ffd83dbSDimitry Andric } 3685ffd83dbSDimitry Andric ++osi; 3695ffd83dbSDimitry Andric } 3705ffd83dbSDimitry Andric 3715ffd83dbSDimitry Andric return osi; 3725ffd83dbSDimitry Andric } 3735ffd83dbSDimitry Andric 3745ffd83dbSDimitry Andric static std::pair<bool, llvm::StringRef::const_iterator> 3755ffd83dbSDimitry Andric ConsumeChar(llvm::StringRef::const_iterator osi, const char c, 3765ffd83dbSDimitry Andric llvm::StringRef::const_iterator ose) { 3775ffd83dbSDimitry Andric bool found = false; 3785ffd83dbSDimitry Andric 3795ffd83dbSDimitry Andric osi = ConsumeWhitespace(osi, ose); 3805ffd83dbSDimitry Andric if (osi != ose && *osi == c) { 3815ffd83dbSDimitry Andric found = true; 3825ffd83dbSDimitry Andric ++osi; 3835ffd83dbSDimitry Andric } 3845ffd83dbSDimitry Andric 3855ffd83dbSDimitry Andric return std::make_pair(found, osi); 3865ffd83dbSDimitry Andric } 3875ffd83dbSDimitry Andric 3885ffd83dbSDimitry Andric static std::pair<Operand, llvm::StringRef::const_iterator> 3895ffd83dbSDimitry Andric ParseRegisterName(llvm::StringRef::const_iterator osi, 3905ffd83dbSDimitry Andric llvm::StringRef::const_iterator ose) { 3915ffd83dbSDimitry Andric Operand ret; 3925ffd83dbSDimitry Andric ret.m_type = Operand::Type::Register; 3935ffd83dbSDimitry Andric std::string str; 3945ffd83dbSDimitry Andric 3955ffd83dbSDimitry Andric osi = ConsumeWhitespace(osi, ose); 3965ffd83dbSDimitry Andric 3975ffd83dbSDimitry Andric while (osi != ose) { 3985ffd83dbSDimitry Andric if (*osi >= '0' && *osi <= '9') { 3995ffd83dbSDimitry Andric if (str.empty()) { 4005ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 4015ffd83dbSDimitry Andric } else { 4025ffd83dbSDimitry Andric str.push_back(*osi); 4035ffd83dbSDimitry Andric } 4045ffd83dbSDimitry Andric } else if (*osi >= 'a' && *osi <= 'z') { 4055ffd83dbSDimitry Andric str.push_back(*osi); 4065ffd83dbSDimitry Andric } else { 4075ffd83dbSDimitry Andric switch (*osi) { 4085ffd83dbSDimitry Andric default: 4095ffd83dbSDimitry Andric if (str.empty()) { 4105ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 4115ffd83dbSDimitry Andric } else { 4125ffd83dbSDimitry Andric ret.m_register = ConstString(str); 4135ffd83dbSDimitry Andric return std::make_pair(ret, osi); 4145ffd83dbSDimitry Andric } 4155ffd83dbSDimitry Andric case '%': 4165ffd83dbSDimitry Andric if (!str.empty()) { 4175ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 4185ffd83dbSDimitry Andric } 4195ffd83dbSDimitry Andric break; 4205ffd83dbSDimitry Andric } 4215ffd83dbSDimitry Andric } 4225ffd83dbSDimitry Andric ++osi; 4235ffd83dbSDimitry Andric } 4245ffd83dbSDimitry Andric 4255ffd83dbSDimitry Andric ret.m_register = ConstString(str); 4265ffd83dbSDimitry Andric return std::make_pair(ret, osi); 4275ffd83dbSDimitry Andric } 4285ffd83dbSDimitry Andric 4295ffd83dbSDimitry Andric static std::pair<Operand, llvm::StringRef::const_iterator> 4305ffd83dbSDimitry Andric ParseImmediate(llvm::StringRef::const_iterator osi, 4315ffd83dbSDimitry Andric llvm::StringRef::const_iterator ose) { 4325ffd83dbSDimitry Andric Operand ret; 4335ffd83dbSDimitry Andric ret.m_type = Operand::Type::Immediate; 4345ffd83dbSDimitry Andric std::string str; 4355ffd83dbSDimitry Andric bool is_hex = false; 4365ffd83dbSDimitry Andric 4375ffd83dbSDimitry Andric osi = ConsumeWhitespace(osi, ose); 4385ffd83dbSDimitry Andric 4395ffd83dbSDimitry Andric while (osi != ose) { 4405ffd83dbSDimitry Andric if (*osi >= '0' && *osi <= '9') { 4415ffd83dbSDimitry Andric str.push_back(*osi); 4425ffd83dbSDimitry Andric } else if (*osi >= 'a' && *osi <= 'f') { 4435ffd83dbSDimitry Andric if (is_hex) { 4445ffd83dbSDimitry Andric str.push_back(*osi); 4455ffd83dbSDimitry Andric } else { 4465ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 4475ffd83dbSDimitry Andric } 4485ffd83dbSDimitry Andric } else { 4495ffd83dbSDimitry Andric switch (*osi) { 4505ffd83dbSDimitry Andric default: 4515ffd83dbSDimitry Andric if (str.empty()) { 4525ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 4535ffd83dbSDimitry Andric } else { 4545ffd83dbSDimitry Andric ret.m_immediate = strtoull(str.c_str(), nullptr, 0); 4555ffd83dbSDimitry Andric return std::make_pair(ret, osi); 4565ffd83dbSDimitry Andric } 4575ffd83dbSDimitry Andric case 'x': 4585ffd83dbSDimitry Andric if (!str.compare("0")) { 4595ffd83dbSDimitry Andric is_hex = true; 4605ffd83dbSDimitry Andric str.push_back(*osi); 4615ffd83dbSDimitry Andric } else { 4625ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 4635ffd83dbSDimitry Andric } 4645ffd83dbSDimitry Andric break; 4655ffd83dbSDimitry Andric case '#': 4665ffd83dbSDimitry Andric case '$': 4675ffd83dbSDimitry Andric if (!str.empty()) { 4685ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 4695ffd83dbSDimitry Andric } 4705ffd83dbSDimitry Andric break; 4715ffd83dbSDimitry Andric case '-': 4725ffd83dbSDimitry Andric if (str.empty()) { 4735ffd83dbSDimitry Andric ret.m_negative = true; 4745ffd83dbSDimitry Andric } else { 4755ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 4765ffd83dbSDimitry Andric } 4775ffd83dbSDimitry Andric } 4785ffd83dbSDimitry Andric } 4795ffd83dbSDimitry Andric ++osi; 4805ffd83dbSDimitry Andric } 4815ffd83dbSDimitry Andric 4825ffd83dbSDimitry Andric ret.m_immediate = strtoull(str.c_str(), nullptr, 0); 4835ffd83dbSDimitry Andric return std::make_pair(ret, osi); 4845ffd83dbSDimitry Andric } 4855ffd83dbSDimitry Andric 4865ffd83dbSDimitry Andric // -0x5(%rax,%rax,2) 4875ffd83dbSDimitry Andric static std::pair<Operand, llvm::StringRef::const_iterator> 4885ffd83dbSDimitry Andric ParseIntelIndexedAccess(llvm::StringRef::const_iterator osi, 4895ffd83dbSDimitry Andric llvm::StringRef::const_iterator ose) { 4905ffd83dbSDimitry Andric std::pair<Operand, llvm::StringRef::const_iterator> offset_and_iterator = 4915ffd83dbSDimitry Andric ParseImmediate(osi, ose); 4925ffd83dbSDimitry Andric if (offset_and_iterator.first.IsValid()) { 4935ffd83dbSDimitry Andric osi = offset_and_iterator.second; 4945ffd83dbSDimitry Andric } 4955ffd83dbSDimitry Andric 4965ffd83dbSDimitry Andric bool found = false; 4975ffd83dbSDimitry Andric std::tie(found, osi) = ConsumeChar(osi, '(', ose); 4985ffd83dbSDimitry Andric if (!found) { 4995ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 5005ffd83dbSDimitry Andric } 5015ffd83dbSDimitry Andric 5025ffd83dbSDimitry Andric std::pair<Operand, llvm::StringRef::const_iterator> base_and_iterator = 5035ffd83dbSDimitry Andric ParseRegisterName(osi, ose); 5045ffd83dbSDimitry Andric if (base_and_iterator.first.IsValid()) { 5055ffd83dbSDimitry Andric osi = base_and_iterator.second; 5065ffd83dbSDimitry Andric } else { 5075ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 5085ffd83dbSDimitry Andric } 5095ffd83dbSDimitry Andric 5105ffd83dbSDimitry Andric std::tie(found, osi) = ConsumeChar(osi, ',', ose); 5115ffd83dbSDimitry Andric if (!found) { 5125ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 5135ffd83dbSDimitry Andric } 5145ffd83dbSDimitry Andric 5155ffd83dbSDimitry Andric std::pair<Operand, llvm::StringRef::const_iterator> index_and_iterator = 5165ffd83dbSDimitry Andric ParseRegisterName(osi, ose); 5175ffd83dbSDimitry Andric if (index_and_iterator.first.IsValid()) { 5185ffd83dbSDimitry Andric osi = index_and_iterator.second; 5195ffd83dbSDimitry Andric } else { 5205ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 5215ffd83dbSDimitry Andric } 5225ffd83dbSDimitry Andric 5235ffd83dbSDimitry Andric std::tie(found, osi) = ConsumeChar(osi, ',', ose); 5245ffd83dbSDimitry Andric if (!found) { 5255ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 5265ffd83dbSDimitry Andric } 5275ffd83dbSDimitry Andric 5285ffd83dbSDimitry Andric std::pair<Operand, llvm::StringRef::const_iterator> 5295ffd83dbSDimitry Andric multiplier_and_iterator = ParseImmediate(osi, ose); 5305ffd83dbSDimitry Andric if (index_and_iterator.first.IsValid()) { 5315ffd83dbSDimitry Andric osi = index_and_iterator.second; 5325ffd83dbSDimitry Andric } else { 5335ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 5345ffd83dbSDimitry Andric } 5355ffd83dbSDimitry Andric 5365ffd83dbSDimitry Andric std::tie(found, osi) = ConsumeChar(osi, ')', ose); 5375ffd83dbSDimitry Andric if (!found) { 5385ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 5395ffd83dbSDimitry Andric } 5405ffd83dbSDimitry Andric 5415ffd83dbSDimitry Andric Operand product; 5425ffd83dbSDimitry Andric product.m_type = Operand::Type::Product; 5435ffd83dbSDimitry Andric product.m_children.push_back(index_and_iterator.first); 5445ffd83dbSDimitry Andric product.m_children.push_back(multiplier_and_iterator.first); 5455ffd83dbSDimitry Andric 5465ffd83dbSDimitry Andric Operand index; 5475ffd83dbSDimitry Andric index.m_type = Operand::Type::Sum; 5485ffd83dbSDimitry Andric index.m_children.push_back(base_and_iterator.first); 5495ffd83dbSDimitry Andric index.m_children.push_back(product); 5505ffd83dbSDimitry Andric 5515ffd83dbSDimitry Andric if (offset_and_iterator.first.IsValid()) { 5525ffd83dbSDimitry Andric Operand offset; 5535ffd83dbSDimitry Andric offset.m_type = Operand::Type::Sum; 5545ffd83dbSDimitry Andric offset.m_children.push_back(offset_and_iterator.first); 5555ffd83dbSDimitry Andric offset.m_children.push_back(index); 5565ffd83dbSDimitry Andric 5575ffd83dbSDimitry Andric Operand deref; 5585ffd83dbSDimitry Andric deref.m_type = Operand::Type::Dereference; 5595ffd83dbSDimitry Andric deref.m_children.push_back(offset); 5605ffd83dbSDimitry Andric return std::make_pair(deref, osi); 5615ffd83dbSDimitry Andric } else { 5625ffd83dbSDimitry Andric Operand deref; 5635ffd83dbSDimitry Andric deref.m_type = Operand::Type::Dereference; 5645ffd83dbSDimitry Andric deref.m_children.push_back(index); 5655ffd83dbSDimitry Andric return std::make_pair(deref, osi); 5665ffd83dbSDimitry Andric } 5675ffd83dbSDimitry Andric } 5685ffd83dbSDimitry Andric 5695ffd83dbSDimitry Andric // -0x10(%rbp) 5705ffd83dbSDimitry Andric static std::pair<Operand, llvm::StringRef::const_iterator> 5715ffd83dbSDimitry Andric ParseIntelDerefAccess(llvm::StringRef::const_iterator osi, 5725ffd83dbSDimitry Andric llvm::StringRef::const_iterator ose) { 5735ffd83dbSDimitry Andric std::pair<Operand, llvm::StringRef::const_iterator> offset_and_iterator = 5745ffd83dbSDimitry Andric ParseImmediate(osi, ose); 5755ffd83dbSDimitry Andric if (offset_and_iterator.first.IsValid()) { 5765ffd83dbSDimitry Andric osi = offset_and_iterator.second; 5775ffd83dbSDimitry Andric } 5785ffd83dbSDimitry Andric 5795ffd83dbSDimitry Andric bool found = false; 5805ffd83dbSDimitry Andric std::tie(found, osi) = ConsumeChar(osi, '(', ose); 5815ffd83dbSDimitry Andric if (!found) { 5825ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 5835ffd83dbSDimitry Andric } 5845ffd83dbSDimitry Andric 5855ffd83dbSDimitry Andric std::pair<Operand, llvm::StringRef::const_iterator> base_and_iterator = 5865ffd83dbSDimitry Andric ParseRegisterName(osi, ose); 5875ffd83dbSDimitry Andric if (base_and_iterator.first.IsValid()) { 5885ffd83dbSDimitry Andric osi = base_and_iterator.second; 5895ffd83dbSDimitry Andric } else { 5905ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 5915ffd83dbSDimitry Andric } 5925ffd83dbSDimitry Andric 5935ffd83dbSDimitry Andric std::tie(found, osi) = ConsumeChar(osi, ')', ose); 5945ffd83dbSDimitry Andric if (!found) { 5955ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 5965ffd83dbSDimitry Andric } 5975ffd83dbSDimitry Andric 5985ffd83dbSDimitry Andric if (offset_and_iterator.first.IsValid()) { 5995ffd83dbSDimitry Andric Operand offset; 6005ffd83dbSDimitry Andric offset.m_type = Operand::Type::Sum; 6015ffd83dbSDimitry Andric offset.m_children.push_back(offset_and_iterator.first); 6025ffd83dbSDimitry Andric offset.m_children.push_back(base_and_iterator.first); 6035ffd83dbSDimitry Andric 6045ffd83dbSDimitry Andric Operand deref; 6055ffd83dbSDimitry Andric deref.m_type = Operand::Type::Dereference; 6065ffd83dbSDimitry Andric deref.m_children.push_back(offset); 6075ffd83dbSDimitry Andric return std::make_pair(deref, osi); 6085ffd83dbSDimitry Andric } else { 6095ffd83dbSDimitry Andric Operand deref; 6105ffd83dbSDimitry Andric deref.m_type = Operand::Type::Dereference; 6115ffd83dbSDimitry Andric deref.m_children.push_back(base_and_iterator.first); 6125ffd83dbSDimitry Andric return std::make_pair(deref, osi); 6135ffd83dbSDimitry Andric } 6145ffd83dbSDimitry Andric } 6155ffd83dbSDimitry Andric 6165ffd83dbSDimitry Andric // [sp, #8]! 6175ffd83dbSDimitry Andric static std::pair<Operand, llvm::StringRef::const_iterator> 6185ffd83dbSDimitry Andric ParseARMOffsetAccess(llvm::StringRef::const_iterator osi, 6195ffd83dbSDimitry Andric llvm::StringRef::const_iterator ose) { 6205ffd83dbSDimitry Andric bool found = false; 6215ffd83dbSDimitry Andric std::tie(found, osi) = ConsumeChar(osi, '[', ose); 6225ffd83dbSDimitry Andric if (!found) { 6235ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 6245ffd83dbSDimitry Andric } 6255ffd83dbSDimitry Andric 6265ffd83dbSDimitry Andric std::pair<Operand, llvm::StringRef::const_iterator> base_and_iterator = 6275ffd83dbSDimitry Andric ParseRegisterName(osi, ose); 6285ffd83dbSDimitry Andric if (base_and_iterator.first.IsValid()) { 6295ffd83dbSDimitry Andric osi = base_and_iterator.second; 6305ffd83dbSDimitry Andric } else { 6315ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 6325ffd83dbSDimitry Andric } 6335ffd83dbSDimitry Andric 6345ffd83dbSDimitry Andric std::tie(found, osi) = ConsumeChar(osi, ',', ose); 6355ffd83dbSDimitry Andric if (!found) { 6365ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 6375ffd83dbSDimitry Andric } 6385ffd83dbSDimitry Andric 6395ffd83dbSDimitry Andric std::pair<Operand, llvm::StringRef::const_iterator> offset_and_iterator = 6405ffd83dbSDimitry Andric ParseImmediate(osi, ose); 6415ffd83dbSDimitry Andric if (offset_and_iterator.first.IsValid()) { 6425ffd83dbSDimitry Andric osi = offset_and_iterator.second; 6435ffd83dbSDimitry Andric } 6445ffd83dbSDimitry Andric 6455ffd83dbSDimitry Andric std::tie(found, osi) = ConsumeChar(osi, ']', ose); 6465ffd83dbSDimitry Andric if (!found) { 6475ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 6485ffd83dbSDimitry Andric } 6495ffd83dbSDimitry Andric 6505ffd83dbSDimitry Andric Operand offset; 6515ffd83dbSDimitry Andric offset.m_type = Operand::Type::Sum; 6525ffd83dbSDimitry Andric offset.m_children.push_back(offset_and_iterator.first); 6535ffd83dbSDimitry Andric offset.m_children.push_back(base_and_iterator.first); 6545ffd83dbSDimitry Andric 6555ffd83dbSDimitry Andric Operand deref; 6565ffd83dbSDimitry Andric deref.m_type = Operand::Type::Dereference; 6575ffd83dbSDimitry Andric deref.m_children.push_back(offset); 6585ffd83dbSDimitry Andric return std::make_pair(deref, osi); 6595ffd83dbSDimitry Andric } 6605ffd83dbSDimitry Andric 6615ffd83dbSDimitry Andric // [sp] 6625ffd83dbSDimitry Andric static std::pair<Operand, llvm::StringRef::const_iterator> 6635ffd83dbSDimitry Andric ParseARMDerefAccess(llvm::StringRef::const_iterator osi, 6645ffd83dbSDimitry Andric llvm::StringRef::const_iterator ose) { 6655ffd83dbSDimitry Andric bool found = false; 6665ffd83dbSDimitry Andric std::tie(found, osi) = ConsumeChar(osi, '[', ose); 6675ffd83dbSDimitry Andric if (!found) { 6685ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 6695ffd83dbSDimitry Andric } 6705ffd83dbSDimitry Andric 6715ffd83dbSDimitry Andric std::pair<Operand, llvm::StringRef::const_iterator> base_and_iterator = 6725ffd83dbSDimitry Andric ParseRegisterName(osi, ose); 6735ffd83dbSDimitry Andric if (base_and_iterator.first.IsValid()) { 6745ffd83dbSDimitry Andric osi = base_and_iterator.second; 6755ffd83dbSDimitry Andric } else { 6765ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 6775ffd83dbSDimitry Andric } 6785ffd83dbSDimitry Andric 6795ffd83dbSDimitry Andric std::tie(found, osi) = ConsumeChar(osi, ']', ose); 6805ffd83dbSDimitry Andric if (!found) { 6815ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 6825ffd83dbSDimitry Andric } 6835ffd83dbSDimitry Andric 6845ffd83dbSDimitry Andric Operand deref; 6855ffd83dbSDimitry Andric deref.m_type = Operand::Type::Dereference; 6865ffd83dbSDimitry Andric deref.m_children.push_back(base_and_iterator.first); 6875ffd83dbSDimitry Andric return std::make_pair(deref, osi); 6885ffd83dbSDimitry Andric } 6895ffd83dbSDimitry Andric 6905ffd83dbSDimitry Andric static void DumpOperand(const Operand &op, Stream &s) { 6915ffd83dbSDimitry Andric switch (op.m_type) { 6925ffd83dbSDimitry Andric case Operand::Type::Dereference: 6935ffd83dbSDimitry Andric s.PutCString("*"); 6945ffd83dbSDimitry Andric DumpOperand(op.m_children[0], s); 6955ffd83dbSDimitry Andric break; 6965ffd83dbSDimitry Andric case Operand::Type::Immediate: 6975ffd83dbSDimitry Andric if (op.m_negative) { 6985ffd83dbSDimitry Andric s.PutCString("-"); 6995ffd83dbSDimitry Andric } 7005ffd83dbSDimitry Andric s.PutCString(llvm::to_string(op.m_immediate)); 7015ffd83dbSDimitry Andric break; 7025ffd83dbSDimitry Andric case Operand::Type::Invalid: 7035ffd83dbSDimitry Andric s.PutCString("Invalid"); 7045ffd83dbSDimitry Andric break; 7055ffd83dbSDimitry Andric case Operand::Type::Product: 7065ffd83dbSDimitry Andric s.PutCString("("); 7075ffd83dbSDimitry Andric DumpOperand(op.m_children[0], s); 7085ffd83dbSDimitry Andric s.PutCString("*"); 7095ffd83dbSDimitry Andric DumpOperand(op.m_children[1], s); 7105ffd83dbSDimitry Andric s.PutCString(")"); 7115ffd83dbSDimitry Andric break; 7125ffd83dbSDimitry Andric case Operand::Type::Register: 7135ffd83dbSDimitry Andric s.PutCString(op.m_register.GetStringRef()); 7145ffd83dbSDimitry Andric break; 7155ffd83dbSDimitry Andric case Operand::Type::Sum: 7165ffd83dbSDimitry Andric s.PutCString("("); 7175ffd83dbSDimitry Andric DumpOperand(op.m_children[0], s); 7185ffd83dbSDimitry Andric s.PutCString("+"); 7195ffd83dbSDimitry Andric DumpOperand(op.m_children[1], s); 7205ffd83dbSDimitry Andric s.PutCString(")"); 7215ffd83dbSDimitry Andric break; 7225ffd83dbSDimitry Andric } 7235ffd83dbSDimitry Andric } 7245ffd83dbSDimitry Andric 7255ffd83dbSDimitry Andric bool ParseOperands( 7265ffd83dbSDimitry Andric llvm::SmallVectorImpl<Instruction::Operand> &operands) override { 7275ffd83dbSDimitry Andric const char *operands_string = GetOperands(nullptr); 7285ffd83dbSDimitry Andric 7295ffd83dbSDimitry Andric if (!operands_string) { 7305ffd83dbSDimitry Andric return false; 7315ffd83dbSDimitry Andric } 7325ffd83dbSDimitry Andric 7335ffd83dbSDimitry Andric llvm::StringRef operands_ref(operands_string); 7345ffd83dbSDimitry Andric 7355ffd83dbSDimitry Andric llvm::StringRef::const_iterator osi = operands_ref.begin(); 7365ffd83dbSDimitry Andric llvm::StringRef::const_iterator ose = operands_ref.end(); 7375ffd83dbSDimitry Andric 7385ffd83dbSDimitry Andric while (osi != ose) { 7395ffd83dbSDimitry Andric Operand operand; 7405ffd83dbSDimitry Andric llvm::StringRef::const_iterator iter; 7415ffd83dbSDimitry Andric 7425ffd83dbSDimitry Andric if ((std::tie(operand, iter) = ParseIntelIndexedAccess(osi, ose), 7435ffd83dbSDimitry Andric operand.IsValid()) || 7445ffd83dbSDimitry Andric (std::tie(operand, iter) = ParseIntelDerefAccess(osi, ose), 7455ffd83dbSDimitry Andric operand.IsValid()) || 7465ffd83dbSDimitry Andric (std::tie(operand, iter) = ParseARMOffsetAccess(osi, ose), 7475ffd83dbSDimitry Andric operand.IsValid()) || 7485ffd83dbSDimitry Andric (std::tie(operand, iter) = ParseARMDerefAccess(osi, ose), 7495ffd83dbSDimitry Andric operand.IsValid()) || 7505ffd83dbSDimitry Andric (std::tie(operand, iter) = ParseRegisterName(osi, ose), 7515ffd83dbSDimitry Andric operand.IsValid()) || 7525ffd83dbSDimitry Andric (std::tie(operand, iter) = ParseImmediate(osi, ose), 7535ffd83dbSDimitry Andric operand.IsValid())) { 7545ffd83dbSDimitry Andric osi = iter; 7555ffd83dbSDimitry Andric operands.push_back(operand); 7565ffd83dbSDimitry Andric } else { 7575ffd83dbSDimitry Andric return false; 7585ffd83dbSDimitry Andric } 7595ffd83dbSDimitry Andric 7605ffd83dbSDimitry Andric std::pair<bool, llvm::StringRef::const_iterator> found_and_iter = 7615ffd83dbSDimitry Andric ConsumeChar(osi, ',', ose); 7625ffd83dbSDimitry Andric if (found_and_iter.first) { 7635ffd83dbSDimitry Andric osi = found_and_iter.second; 7645ffd83dbSDimitry Andric } 7655ffd83dbSDimitry Andric 7665ffd83dbSDimitry Andric osi = ConsumeWhitespace(osi, ose); 7675ffd83dbSDimitry Andric } 7685ffd83dbSDimitry Andric 7695ffd83dbSDimitry Andric DisassemblerSP disasm_sp = m_disasm_wp.lock(); 7705ffd83dbSDimitry Andric 7715ffd83dbSDimitry Andric if (disasm_sp && operands.size() > 1) { 7725ffd83dbSDimitry Andric // TODO tie this into the MC Disassembler's notion of clobbers. 7735ffd83dbSDimitry Andric switch (disasm_sp->GetArchitecture().GetMachine()) { 7745ffd83dbSDimitry Andric default: 7755ffd83dbSDimitry Andric break; 7765ffd83dbSDimitry Andric case llvm::Triple::x86: 7775ffd83dbSDimitry Andric case llvm::Triple::x86_64: 7785ffd83dbSDimitry Andric operands[operands.size() - 1].m_clobbered = true; 7795ffd83dbSDimitry Andric break; 7805ffd83dbSDimitry Andric case llvm::Triple::arm: 7815ffd83dbSDimitry Andric operands[0].m_clobbered = true; 7825ffd83dbSDimitry Andric break; 7835ffd83dbSDimitry Andric } 7845ffd83dbSDimitry Andric } 7855ffd83dbSDimitry Andric 7865ffd83dbSDimitry Andric if (Log *log = 7875ffd83dbSDimitry Andric lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)) { 7885ffd83dbSDimitry Andric StreamString ss; 7895ffd83dbSDimitry Andric 7905ffd83dbSDimitry Andric ss.Printf("[%s] expands to %zu operands:\n", operands_string, 7915ffd83dbSDimitry Andric operands.size()); 7925ffd83dbSDimitry Andric for (const Operand &operand : operands) { 7935ffd83dbSDimitry Andric ss.PutCString(" "); 7945ffd83dbSDimitry Andric DumpOperand(operand, ss); 7955ffd83dbSDimitry Andric ss.PutCString("\n"); 7965ffd83dbSDimitry Andric } 7975ffd83dbSDimitry Andric 7985ffd83dbSDimitry Andric log->PutString(ss.GetString()); 7995ffd83dbSDimitry Andric } 8005ffd83dbSDimitry Andric 8015ffd83dbSDimitry Andric return true; 8025ffd83dbSDimitry Andric } 8035ffd83dbSDimitry Andric 8045ffd83dbSDimitry Andric bool IsCall() override { 8055ffd83dbSDimitry Andric VisitInstruction(); 8065ffd83dbSDimitry Andric return m_is_call; 8075ffd83dbSDimitry Andric } 8085ffd83dbSDimitry Andric 8095ffd83dbSDimitry Andric protected: 8105ffd83dbSDimitry Andric std::weak_ptr<DisassemblerLLVMC> m_disasm_wp; 8115ffd83dbSDimitry Andric 8125ffd83dbSDimitry Andric bool m_is_valid = false; 8135ffd83dbSDimitry Andric bool m_using_file_addr; 8145ffd83dbSDimitry Andric bool m_has_visited_instruction = false; 8155ffd83dbSDimitry Andric 8165ffd83dbSDimitry Andric // Be conservative. If we didn't understand the instruction, say it: 8175ffd83dbSDimitry Andric // - Might branch 8185ffd83dbSDimitry Andric // - Does not have a delay slot 8195ffd83dbSDimitry Andric // - Is not a call 8205ffd83dbSDimitry Andric bool m_does_branch = true; 8215ffd83dbSDimitry Andric bool m_has_delay_slot = false; 8225ffd83dbSDimitry Andric bool m_is_call = false; 8235ffd83dbSDimitry Andric 8245ffd83dbSDimitry Andric void VisitInstruction() { 8255ffd83dbSDimitry Andric if (m_has_visited_instruction) 8265ffd83dbSDimitry Andric return; 8275ffd83dbSDimitry Andric 8285ffd83dbSDimitry Andric DisassemblerScope disasm(*this); 8295ffd83dbSDimitry Andric if (!disasm) 8305ffd83dbSDimitry Andric return; 8315ffd83dbSDimitry Andric 8325ffd83dbSDimitry Andric DataExtractor data; 8335ffd83dbSDimitry Andric if (!m_opcode.GetData(data)) 8345ffd83dbSDimitry Andric return; 8355ffd83dbSDimitry Andric 8365ffd83dbSDimitry Andric bool is_alternate_isa; 8375ffd83dbSDimitry Andric lldb::addr_t pc = m_address.GetFileAddress(); 8385ffd83dbSDimitry Andric DisassemblerLLVMC::MCDisasmInstance *mc_disasm_ptr = 8395ffd83dbSDimitry Andric GetDisasmToUse(is_alternate_isa, disasm); 8405ffd83dbSDimitry Andric const uint8_t *opcode_data = data.GetDataStart(); 8415ffd83dbSDimitry Andric const size_t opcode_data_len = data.GetByteSize(); 8425ffd83dbSDimitry Andric llvm::MCInst inst; 8435ffd83dbSDimitry Andric const size_t inst_size = 8445ffd83dbSDimitry Andric mc_disasm_ptr->GetMCInst(opcode_data, opcode_data_len, pc, inst); 8455ffd83dbSDimitry Andric if (inst_size == 0) 8465ffd83dbSDimitry Andric return; 8475ffd83dbSDimitry Andric 8485ffd83dbSDimitry Andric m_has_visited_instruction = true; 8495ffd83dbSDimitry Andric m_does_branch = mc_disasm_ptr->CanBranch(inst); 8505ffd83dbSDimitry Andric m_has_delay_slot = mc_disasm_ptr->HasDelaySlot(inst); 8515ffd83dbSDimitry Andric m_is_call = mc_disasm_ptr->IsCall(inst); 8525ffd83dbSDimitry Andric } 8535ffd83dbSDimitry Andric 8545ffd83dbSDimitry Andric private: 8555ffd83dbSDimitry Andric DisassemblerLLVMC::MCDisasmInstance * 8565ffd83dbSDimitry Andric GetDisasmToUse(bool &is_alternate_isa, DisassemblerScope &disasm) { 8575ffd83dbSDimitry Andric is_alternate_isa = false; 8585ffd83dbSDimitry Andric if (disasm) { 8595ffd83dbSDimitry Andric if (disasm->m_alternate_disasm_up) { 8605ffd83dbSDimitry Andric const AddressClass address_class = GetAddressClass(); 8615ffd83dbSDimitry Andric 8625ffd83dbSDimitry Andric if (address_class == AddressClass::eCodeAlternateISA) { 8635ffd83dbSDimitry Andric is_alternate_isa = true; 8645ffd83dbSDimitry Andric return disasm->m_alternate_disasm_up.get(); 8655ffd83dbSDimitry Andric } 8665ffd83dbSDimitry Andric } 8675ffd83dbSDimitry Andric return disasm->m_disasm_up.get(); 8685ffd83dbSDimitry Andric } 8695ffd83dbSDimitry Andric return nullptr; 8705ffd83dbSDimitry Andric } 8715ffd83dbSDimitry Andric }; 8725ffd83dbSDimitry Andric 8735ffd83dbSDimitry Andric std::unique_ptr<DisassemblerLLVMC::MCDisasmInstance> 8745ffd83dbSDimitry Andric DisassemblerLLVMC::MCDisasmInstance::Create(const char *triple, const char *cpu, 8755ffd83dbSDimitry Andric const char *features_str, 8765ffd83dbSDimitry Andric unsigned flavor, 8775ffd83dbSDimitry Andric DisassemblerLLVMC &owner) { 8785ffd83dbSDimitry Andric using Instance = std::unique_ptr<DisassemblerLLVMC::MCDisasmInstance>; 8795ffd83dbSDimitry Andric 8805ffd83dbSDimitry Andric std::string Status; 8815ffd83dbSDimitry Andric const llvm::Target *curr_target = 8825ffd83dbSDimitry Andric llvm::TargetRegistry::lookupTarget(triple, Status); 8835ffd83dbSDimitry Andric if (!curr_target) 8845ffd83dbSDimitry Andric return Instance(); 8855ffd83dbSDimitry Andric 8865ffd83dbSDimitry Andric std::unique_ptr<llvm::MCInstrInfo> instr_info_up( 8875ffd83dbSDimitry Andric curr_target->createMCInstrInfo()); 8885ffd83dbSDimitry Andric if (!instr_info_up) 8895ffd83dbSDimitry Andric return Instance(); 8905ffd83dbSDimitry Andric 8915ffd83dbSDimitry Andric std::unique_ptr<llvm::MCRegisterInfo> reg_info_up( 8925ffd83dbSDimitry Andric curr_target->createMCRegInfo(triple)); 8935ffd83dbSDimitry Andric if (!reg_info_up) 8945ffd83dbSDimitry Andric return Instance(); 8955ffd83dbSDimitry Andric 8965ffd83dbSDimitry Andric std::unique_ptr<llvm::MCSubtargetInfo> subtarget_info_up( 8975ffd83dbSDimitry Andric curr_target->createMCSubtargetInfo(triple, cpu, features_str)); 8985ffd83dbSDimitry Andric if (!subtarget_info_up) 8995ffd83dbSDimitry Andric return Instance(); 9005ffd83dbSDimitry Andric 9015ffd83dbSDimitry Andric llvm::MCTargetOptions MCOptions; 9025ffd83dbSDimitry Andric std::unique_ptr<llvm::MCAsmInfo> asm_info_up( 9035ffd83dbSDimitry Andric curr_target->createMCAsmInfo(*reg_info_up, triple, MCOptions)); 9045ffd83dbSDimitry Andric if (!asm_info_up) 9055ffd83dbSDimitry Andric return Instance(); 9065ffd83dbSDimitry Andric 9075ffd83dbSDimitry Andric std::unique_ptr<llvm::MCContext> context_up( 908*fe6060f1SDimitry Andric new llvm::MCContext(llvm::Triple(triple), asm_info_up.get(), 909*fe6060f1SDimitry Andric reg_info_up.get(), subtarget_info_up.get())); 9105ffd83dbSDimitry Andric if (!context_up) 9115ffd83dbSDimitry Andric return Instance(); 9125ffd83dbSDimitry Andric 9135ffd83dbSDimitry Andric std::unique_ptr<llvm::MCDisassembler> disasm_up( 9145ffd83dbSDimitry Andric curr_target->createMCDisassembler(*subtarget_info_up, *context_up)); 9155ffd83dbSDimitry Andric if (!disasm_up) 9165ffd83dbSDimitry Andric return Instance(); 9175ffd83dbSDimitry Andric 9185ffd83dbSDimitry Andric std::unique_ptr<llvm::MCRelocationInfo> rel_info_up( 9195ffd83dbSDimitry Andric curr_target->createMCRelocationInfo(triple, *context_up)); 9205ffd83dbSDimitry Andric if (!rel_info_up) 9215ffd83dbSDimitry Andric return Instance(); 9225ffd83dbSDimitry Andric 9235ffd83dbSDimitry Andric std::unique_ptr<llvm::MCSymbolizer> symbolizer_up( 9245ffd83dbSDimitry Andric curr_target->createMCSymbolizer( 9255ffd83dbSDimitry Andric triple, nullptr, DisassemblerLLVMC::SymbolLookupCallback, &owner, 9265ffd83dbSDimitry Andric context_up.get(), std::move(rel_info_up))); 9275ffd83dbSDimitry Andric disasm_up->setSymbolizer(std::move(symbolizer_up)); 9285ffd83dbSDimitry Andric 9295ffd83dbSDimitry Andric unsigned asm_printer_variant = 9305ffd83dbSDimitry Andric flavor == ~0U ? asm_info_up->getAssemblerDialect() : flavor; 9315ffd83dbSDimitry Andric 9325ffd83dbSDimitry Andric std::unique_ptr<llvm::MCInstPrinter> instr_printer_up( 9335ffd83dbSDimitry Andric curr_target->createMCInstPrinter(llvm::Triple{triple}, 9345ffd83dbSDimitry Andric asm_printer_variant, *asm_info_up, 9355ffd83dbSDimitry Andric *instr_info_up, *reg_info_up)); 9365ffd83dbSDimitry Andric if (!instr_printer_up) 9375ffd83dbSDimitry Andric return Instance(); 9385ffd83dbSDimitry Andric 9395ffd83dbSDimitry Andric return Instance( 9405ffd83dbSDimitry Andric new MCDisasmInstance(std::move(instr_info_up), std::move(reg_info_up), 9415ffd83dbSDimitry Andric std::move(subtarget_info_up), std::move(asm_info_up), 9425ffd83dbSDimitry Andric std::move(context_up), std::move(disasm_up), 9435ffd83dbSDimitry Andric std::move(instr_printer_up))); 9445ffd83dbSDimitry Andric } 9455ffd83dbSDimitry Andric 9465ffd83dbSDimitry Andric DisassemblerLLVMC::MCDisasmInstance::MCDisasmInstance( 9475ffd83dbSDimitry Andric std::unique_ptr<llvm::MCInstrInfo> &&instr_info_up, 9485ffd83dbSDimitry Andric std::unique_ptr<llvm::MCRegisterInfo> &®_info_up, 9495ffd83dbSDimitry Andric std::unique_ptr<llvm::MCSubtargetInfo> &&subtarget_info_up, 9505ffd83dbSDimitry Andric std::unique_ptr<llvm::MCAsmInfo> &&asm_info_up, 9515ffd83dbSDimitry Andric std::unique_ptr<llvm::MCContext> &&context_up, 9525ffd83dbSDimitry Andric std::unique_ptr<llvm::MCDisassembler> &&disasm_up, 9535ffd83dbSDimitry Andric std::unique_ptr<llvm::MCInstPrinter> &&instr_printer_up) 9545ffd83dbSDimitry Andric : m_instr_info_up(std::move(instr_info_up)), 9555ffd83dbSDimitry Andric m_reg_info_up(std::move(reg_info_up)), 9565ffd83dbSDimitry Andric m_subtarget_info_up(std::move(subtarget_info_up)), 9575ffd83dbSDimitry Andric m_asm_info_up(std::move(asm_info_up)), 9585ffd83dbSDimitry Andric m_context_up(std::move(context_up)), m_disasm_up(std::move(disasm_up)), 9595ffd83dbSDimitry Andric m_instr_printer_up(std::move(instr_printer_up)) { 9605ffd83dbSDimitry Andric assert(m_instr_info_up && m_reg_info_up && m_subtarget_info_up && 9615ffd83dbSDimitry Andric m_asm_info_up && m_context_up && m_disasm_up && m_instr_printer_up); 9625ffd83dbSDimitry Andric } 9635ffd83dbSDimitry Andric 9645ffd83dbSDimitry Andric uint64_t DisassemblerLLVMC::MCDisasmInstance::GetMCInst( 9655ffd83dbSDimitry Andric const uint8_t *opcode_data, size_t opcode_data_len, lldb::addr_t pc, 9665ffd83dbSDimitry Andric llvm::MCInst &mc_inst) const { 9675ffd83dbSDimitry Andric llvm::ArrayRef<uint8_t> data(opcode_data, opcode_data_len); 9685ffd83dbSDimitry Andric llvm::MCDisassembler::DecodeStatus status; 9695ffd83dbSDimitry Andric 9705ffd83dbSDimitry Andric uint64_t new_inst_size; 9715ffd83dbSDimitry Andric status = m_disasm_up->getInstruction(mc_inst, new_inst_size, data, pc, 9725ffd83dbSDimitry Andric llvm::nulls()); 9735ffd83dbSDimitry Andric if (status == llvm::MCDisassembler::Success) 9745ffd83dbSDimitry Andric return new_inst_size; 9755ffd83dbSDimitry Andric else 9765ffd83dbSDimitry Andric return 0; 9775ffd83dbSDimitry Andric } 9785ffd83dbSDimitry Andric 9795ffd83dbSDimitry Andric void DisassemblerLLVMC::MCDisasmInstance::PrintMCInst( 9805ffd83dbSDimitry Andric llvm::MCInst &mc_inst, std::string &inst_string, 9815ffd83dbSDimitry Andric std::string &comments_string) { 9825ffd83dbSDimitry Andric llvm::raw_string_ostream inst_stream(inst_string); 9835ffd83dbSDimitry Andric llvm::raw_string_ostream comments_stream(comments_string); 9845ffd83dbSDimitry Andric 9855ffd83dbSDimitry Andric m_instr_printer_up->setCommentStream(comments_stream); 9865ffd83dbSDimitry Andric m_instr_printer_up->printInst(&mc_inst, 0, llvm::StringRef(), 9875ffd83dbSDimitry Andric *m_subtarget_info_up, inst_stream); 9885ffd83dbSDimitry Andric m_instr_printer_up->setCommentStream(llvm::nulls()); 9895ffd83dbSDimitry Andric comments_stream.flush(); 9905ffd83dbSDimitry Andric 9915ffd83dbSDimitry Andric static std::string g_newlines("\r\n"); 9925ffd83dbSDimitry Andric 9935ffd83dbSDimitry Andric for (size_t newline_pos = 0; 9945ffd83dbSDimitry Andric (newline_pos = comments_string.find_first_of(g_newlines, newline_pos)) != 9955ffd83dbSDimitry Andric comments_string.npos; 9965ffd83dbSDimitry Andric /**/) { 9975ffd83dbSDimitry Andric comments_string.replace(comments_string.begin() + newline_pos, 9985ffd83dbSDimitry Andric comments_string.begin() + newline_pos + 1, 1, ' '); 9995ffd83dbSDimitry Andric } 10005ffd83dbSDimitry Andric } 10015ffd83dbSDimitry Andric 10025ffd83dbSDimitry Andric void DisassemblerLLVMC::MCDisasmInstance::SetStyle( 10035ffd83dbSDimitry Andric bool use_hex_immed, HexImmediateStyle hex_style) { 10045ffd83dbSDimitry Andric m_instr_printer_up->setPrintImmHex(use_hex_immed); 10055ffd83dbSDimitry Andric switch (hex_style) { 10065ffd83dbSDimitry Andric case eHexStyleC: 10075ffd83dbSDimitry Andric m_instr_printer_up->setPrintHexStyle(llvm::HexStyle::C); 10085ffd83dbSDimitry Andric break; 10095ffd83dbSDimitry Andric case eHexStyleAsm: 10105ffd83dbSDimitry Andric m_instr_printer_up->setPrintHexStyle(llvm::HexStyle::Asm); 10115ffd83dbSDimitry Andric break; 10125ffd83dbSDimitry Andric } 10135ffd83dbSDimitry Andric } 10145ffd83dbSDimitry Andric 10155ffd83dbSDimitry Andric bool DisassemblerLLVMC::MCDisasmInstance::CanBranch( 10165ffd83dbSDimitry Andric llvm::MCInst &mc_inst) const { 10175ffd83dbSDimitry Andric return m_instr_info_up->get(mc_inst.getOpcode()) 10185ffd83dbSDimitry Andric .mayAffectControlFlow(mc_inst, *m_reg_info_up); 10195ffd83dbSDimitry Andric } 10205ffd83dbSDimitry Andric 10215ffd83dbSDimitry Andric bool DisassemblerLLVMC::MCDisasmInstance::HasDelaySlot( 10225ffd83dbSDimitry Andric llvm::MCInst &mc_inst) const { 10235ffd83dbSDimitry Andric return m_instr_info_up->get(mc_inst.getOpcode()).hasDelaySlot(); 10245ffd83dbSDimitry Andric } 10255ffd83dbSDimitry Andric 10265ffd83dbSDimitry Andric bool DisassemblerLLVMC::MCDisasmInstance::IsCall(llvm::MCInst &mc_inst) const { 10275ffd83dbSDimitry Andric return m_instr_info_up->get(mc_inst.getOpcode()).isCall(); 10285ffd83dbSDimitry Andric } 10295ffd83dbSDimitry Andric 10305ffd83dbSDimitry Andric DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch, 10315ffd83dbSDimitry Andric const char *flavor_string) 10325ffd83dbSDimitry Andric : Disassembler(arch, flavor_string), m_exe_ctx(nullptr), m_inst(nullptr), 10335ffd83dbSDimitry Andric m_data_from_file(false) { 10345ffd83dbSDimitry Andric if (!FlavorValidForArchSpec(arch, m_flavor.c_str())) { 10355ffd83dbSDimitry Andric m_flavor.assign("default"); 10365ffd83dbSDimitry Andric } 10375ffd83dbSDimitry Andric 10385ffd83dbSDimitry Andric unsigned flavor = ~0U; 10395ffd83dbSDimitry Andric llvm::Triple triple = arch.GetTriple(); 10405ffd83dbSDimitry Andric 10415ffd83dbSDimitry Andric // So far the only supported flavor is "intel" on x86. The base class will 10425ffd83dbSDimitry Andric // set this correctly coming in. 10435ffd83dbSDimitry Andric if (triple.getArch() == llvm::Triple::x86 || 10445ffd83dbSDimitry Andric triple.getArch() == llvm::Triple::x86_64) { 10455ffd83dbSDimitry Andric if (m_flavor == "intel") { 10465ffd83dbSDimitry Andric flavor = 1; 10475ffd83dbSDimitry Andric } else if (m_flavor == "att") { 10485ffd83dbSDimitry Andric flavor = 0; 10495ffd83dbSDimitry Andric } 10505ffd83dbSDimitry Andric } 10515ffd83dbSDimitry Andric 10525ffd83dbSDimitry Andric ArchSpec thumb_arch(arch); 10535ffd83dbSDimitry Andric if (triple.getArch() == llvm::Triple::arm) { 10545ffd83dbSDimitry Andric std::string thumb_arch_name(thumb_arch.GetTriple().getArchName().str()); 10555ffd83dbSDimitry Andric // Replace "arm" with "thumb" so we get all thumb variants correct 10565ffd83dbSDimitry Andric if (thumb_arch_name.size() > 3) { 10575ffd83dbSDimitry Andric thumb_arch_name.erase(0, 3); 10585ffd83dbSDimitry Andric thumb_arch_name.insert(0, "thumb"); 10595ffd83dbSDimitry Andric } else { 1060e8d8bef9SDimitry Andric thumb_arch_name = "thumbv8.7a"; 10615ffd83dbSDimitry Andric } 10625ffd83dbSDimitry Andric thumb_arch.GetTriple().setArchName(llvm::StringRef(thumb_arch_name)); 10635ffd83dbSDimitry Andric } 10645ffd83dbSDimitry Andric 10655ffd83dbSDimitry Andric // If no sub architecture specified then use the most recent arm architecture 10665ffd83dbSDimitry Andric // so the disassembler will return all instruction. Without it we will see a 10675ffd83dbSDimitry Andric // lot of unknow opcode in case the code uses instructions which are not 10685ffd83dbSDimitry Andric // available in the oldest arm version (used when no sub architecture is 10695ffd83dbSDimitry Andric // specified) 10705ffd83dbSDimitry Andric if (triple.getArch() == llvm::Triple::arm && 10715ffd83dbSDimitry Andric triple.getSubArch() == llvm::Triple::NoSubArch) 1072e8d8bef9SDimitry Andric triple.setArchName("armv8.7a"); 10735ffd83dbSDimitry Andric 10745ffd83dbSDimitry Andric std::string features_str = ""; 10755ffd83dbSDimitry Andric const char *triple_str = triple.getTriple().c_str(); 10765ffd83dbSDimitry Andric 10775ffd83dbSDimitry Andric // ARM Cortex M0-M7 devices only execute thumb instructions 10785ffd83dbSDimitry Andric if (arch.IsAlwaysThumbInstructions()) { 10795ffd83dbSDimitry Andric triple_str = thumb_arch.GetTriple().getTriple().c_str(); 10805ffd83dbSDimitry Andric features_str += "+fp-armv8,"; 10815ffd83dbSDimitry Andric } 10825ffd83dbSDimitry Andric 10835ffd83dbSDimitry Andric const char *cpu = ""; 10845ffd83dbSDimitry Andric 10855ffd83dbSDimitry Andric switch (arch.GetCore()) { 10865ffd83dbSDimitry Andric case ArchSpec::eCore_mips32: 10875ffd83dbSDimitry Andric case ArchSpec::eCore_mips32el: 10885ffd83dbSDimitry Andric cpu = "mips32"; 10895ffd83dbSDimitry Andric break; 10905ffd83dbSDimitry Andric case ArchSpec::eCore_mips32r2: 10915ffd83dbSDimitry Andric case ArchSpec::eCore_mips32r2el: 10925ffd83dbSDimitry Andric cpu = "mips32r2"; 10935ffd83dbSDimitry Andric break; 10945ffd83dbSDimitry Andric case ArchSpec::eCore_mips32r3: 10955ffd83dbSDimitry Andric case ArchSpec::eCore_mips32r3el: 10965ffd83dbSDimitry Andric cpu = "mips32r3"; 10975ffd83dbSDimitry Andric break; 10985ffd83dbSDimitry Andric case ArchSpec::eCore_mips32r5: 10995ffd83dbSDimitry Andric case ArchSpec::eCore_mips32r5el: 11005ffd83dbSDimitry Andric cpu = "mips32r5"; 11015ffd83dbSDimitry Andric break; 11025ffd83dbSDimitry Andric case ArchSpec::eCore_mips32r6: 11035ffd83dbSDimitry Andric case ArchSpec::eCore_mips32r6el: 11045ffd83dbSDimitry Andric cpu = "mips32r6"; 11055ffd83dbSDimitry Andric break; 11065ffd83dbSDimitry Andric case ArchSpec::eCore_mips64: 11075ffd83dbSDimitry Andric case ArchSpec::eCore_mips64el: 11085ffd83dbSDimitry Andric cpu = "mips64"; 11095ffd83dbSDimitry Andric break; 11105ffd83dbSDimitry Andric case ArchSpec::eCore_mips64r2: 11115ffd83dbSDimitry Andric case ArchSpec::eCore_mips64r2el: 11125ffd83dbSDimitry Andric cpu = "mips64r2"; 11135ffd83dbSDimitry Andric break; 11145ffd83dbSDimitry Andric case ArchSpec::eCore_mips64r3: 11155ffd83dbSDimitry Andric case ArchSpec::eCore_mips64r3el: 11165ffd83dbSDimitry Andric cpu = "mips64r3"; 11175ffd83dbSDimitry Andric break; 11185ffd83dbSDimitry Andric case ArchSpec::eCore_mips64r5: 11195ffd83dbSDimitry Andric case ArchSpec::eCore_mips64r5el: 11205ffd83dbSDimitry Andric cpu = "mips64r5"; 11215ffd83dbSDimitry Andric break; 11225ffd83dbSDimitry Andric case ArchSpec::eCore_mips64r6: 11235ffd83dbSDimitry Andric case ArchSpec::eCore_mips64r6el: 11245ffd83dbSDimitry Andric cpu = "mips64r6"; 11255ffd83dbSDimitry Andric break; 11265ffd83dbSDimitry Andric default: 11275ffd83dbSDimitry Andric cpu = ""; 11285ffd83dbSDimitry Andric break; 11295ffd83dbSDimitry Andric } 11305ffd83dbSDimitry Andric 11315ffd83dbSDimitry Andric if (arch.IsMIPS()) { 11325ffd83dbSDimitry Andric uint32_t arch_flags = arch.GetFlags(); 11335ffd83dbSDimitry Andric if (arch_flags & ArchSpec::eMIPSAse_msa) 11345ffd83dbSDimitry Andric features_str += "+msa,"; 11355ffd83dbSDimitry Andric if (arch_flags & ArchSpec::eMIPSAse_dsp) 11365ffd83dbSDimitry Andric features_str += "+dsp,"; 11375ffd83dbSDimitry Andric if (arch_flags & ArchSpec::eMIPSAse_dspr2) 11385ffd83dbSDimitry Andric features_str += "+dspr2,"; 11395ffd83dbSDimitry Andric } 11405ffd83dbSDimitry Andric 1141e8d8bef9SDimitry Andric // If any AArch64 variant, enable latest ISA with any optional 1142e8d8bef9SDimitry Andric // extensions like SVE. 1143e8d8bef9SDimitry Andric if (triple.isAArch64()) { 1144e8d8bef9SDimitry Andric features_str += "+v8.7a,+sve2,+mte"; 11455ffd83dbSDimitry Andric 1146e8d8bef9SDimitry Andric if (triple.getVendor() == llvm::Triple::Apple) 11475ffd83dbSDimitry Andric cpu = "apple-latest"; 11485ffd83dbSDimitry Andric } 11495ffd83dbSDimitry Andric 11505ffd83dbSDimitry Andric // We use m_disasm_up.get() to tell whether we are valid or not, so if this 11515ffd83dbSDimitry Andric // isn't good for some reason, we won't be valid and FindPlugin will fail and 11525ffd83dbSDimitry Andric // we won't get used. 11535ffd83dbSDimitry Andric m_disasm_up = MCDisasmInstance::Create(triple_str, cpu, features_str.c_str(), 11545ffd83dbSDimitry Andric flavor, *this); 11555ffd83dbSDimitry Andric 11565ffd83dbSDimitry Andric llvm::Triple::ArchType llvm_arch = triple.getArch(); 11575ffd83dbSDimitry Andric 11585ffd83dbSDimitry Andric // For arm CPUs that can execute arm or thumb instructions, also create a 11595ffd83dbSDimitry Andric // thumb instruction disassembler. 11605ffd83dbSDimitry Andric if (llvm_arch == llvm::Triple::arm) { 11615ffd83dbSDimitry Andric std::string thumb_triple(thumb_arch.GetTriple().getTriple()); 11625ffd83dbSDimitry Andric m_alternate_disasm_up = 11635ffd83dbSDimitry Andric MCDisasmInstance::Create(thumb_triple.c_str(), "", features_str.c_str(), 11645ffd83dbSDimitry Andric flavor, *this); 11655ffd83dbSDimitry Andric if (!m_alternate_disasm_up) 11665ffd83dbSDimitry Andric m_disasm_up.reset(); 11675ffd83dbSDimitry Andric 11685ffd83dbSDimitry Andric } else if (arch.IsMIPS()) { 11695ffd83dbSDimitry Andric /* Create alternate disassembler for MIPS16 and microMIPS */ 11705ffd83dbSDimitry Andric uint32_t arch_flags = arch.GetFlags(); 11715ffd83dbSDimitry Andric if (arch_flags & ArchSpec::eMIPSAse_mips16) 11725ffd83dbSDimitry Andric features_str += "+mips16,"; 11735ffd83dbSDimitry Andric else if (arch_flags & ArchSpec::eMIPSAse_micromips) 11745ffd83dbSDimitry Andric features_str += "+micromips,"; 11755ffd83dbSDimitry Andric 11765ffd83dbSDimitry Andric m_alternate_disasm_up = MCDisasmInstance::Create( 11775ffd83dbSDimitry Andric triple_str, cpu, features_str.c_str(), flavor, *this); 11785ffd83dbSDimitry Andric if (!m_alternate_disasm_up) 11795ffd83dbSDimitry Andric m_disasm_up.reset(); 11805ffd83dbSDimitry Andric } 11815ffd83dbSDimitry Andric } 11825ffd83dbSDimitry Andric 11835ffd83dbSDimitry Andric DisassemblerLLVMC::~DisassemblerLLVMC() = default; 11845ffd83dbSDimitry Andric 11855ffd83dbSDimitry Andric Disassembler *DisassemblerLLVMC::CreateInstance(const ArchSpec &arch, 11865ffd83dbSDimitry Andric const char *flavor) { 11875ffd83dbSDimitry Andric if (arch.GetTriple().getArch() != llvm::Triple::UnknownArch) { 11885ffd83dbSDimitry Andric std::unique_ptr<DisassemblerLLVMC> disasm_up( 11895ffd83dbSDimitry Andric new DisassemblerLLVMC(arch, flavor)); 11905ffd83dbSDimitry Andric 11915ffd83dbSDimitry Andric if (disasm_up.get() && disasm_up->IsValid()) 11925ffd83dbSDimitry Andric return disasm_up.release(); 11935ffd83dbSDimitry Andric } 11945ffd83dbSDimitry Andric return nullptr; 11955ffd83dbSDimitry Andric } 11965ffd83dbSDimitry Andric 11975ffd83dbSDimitry Andric size_t DisassemblerLLVMC::DecodeInstructions(const Address &base_addr, 11985ffd83dbSDimitry Andric const DataExtractor &data, 11995ffd83dbSDimitry Andric lldb::offset_t data_offset, 12005ffd83dbSDimitry Andric size_t num_instructions, 12015ffd83dbSDimitry Andric bool append, bool data_from_file) { 12025ffd83dbSDimitry Andric if (!append) 12035ffd83dbSDimitry Andric m_instruction_list.Clear(); 12045ffd83dbSDimitry Andric 12055ffd83dbSDimitry Andric if (!IsValid()) 12065ffd83dbSDimitry Andric return 0; 12075ffd83dbSDimitry Andric 12085ffd83dbSDimitry Andric m_data_from_file = data_from_file; 12095ffd83dbSDimitry Andric uint32_t data_cursor = data_offset; 12105ffd83dbSDimitry Andric const size_t data_byte_size = data.GetByteSize(); 12115ffd83dbSDimitry Andric uint32_t instructions_parsed = 0; 12125ffd83dbSDimitry Andric Address inst_addr(base_addr); 12135ffd83dbSDimitry Andric 12145ffd83dbSDimitry Andric while (data_cursor < data_byte_size && 12155ffd83dbSDimitry Andric instructions_parsed < num_instructions) { 12165ffd83dbSDimitry Andric 12175ffd83dbSDimitry Andric AddressClass address_class = AddressClass::eCode; 12185ffd83dbSDimitry Andric 12195ffd83dbSDimitry Andric if (m_alternate_disasm_up) 12205ffd83dbSDimitry Andric address_class = inst_addr.GetAddressClass(); 12215ffd83dbSDimitry Andric 12225ffd83dbSDimitry Andric InstructionSP inst_sp( 12235ffd83dbSDimitry Andric new InstructionLLVMC(*this, inst_addr, address_class)); 12245ffd83dbSDimitry Andric 12255ffd83dbSDimitry Andric if (!inst_sp) 12265ffd83dbSDimitry Andric break; 12275ffd83dbSDimitry Andric 12285ffd83dbSDimitry Andric uint32_t inst_size = inst_sp->Decode(*this, data, data_cursor); 12295ffd83dbSDimitry Andric 12305ffd83dbSDimitry Andric if (inst_size == 0) 12315ffd83dbSDimitry Andric break; 12325ffd83dbSDimitry Andric 12335ffd83dbSDimitry Andric m_instruction_list.Append(inst_sp); 12345ffd83dbSDimitry Andric data_cursor += inst_size; 12355ffd83dbSDimitry Andric inst_addr.Slide(inst_size); 12365ffd83dbSDimitry Andric instructions_parsed++; 12375ffd83dbSDimitry Andric } 12385ffd83dbSDimitry Andric 12395ffd83dbSDimitry Andric return data_cursor - data_offset; 12405ffd83dbSDimitry Andric } 12415ffd83dbSDimitry Andric 12425ffd83dbSDimitry Andric void DisassemblerLLVMC::Initialize() { 12435ffd83dbSDimitry Andric PluginManager::RegisterPlugin(GetPluginNameStatic(), 12445ffd83dbSDimitry Andric "Disassembler that uses LLVM MC to disassemble " 12455ffd83dbSDimitry Andric "i386, x86_64, ARM, and ARM64.", 12465ffd83dbSDimitry Andric CreateInstance); 12475ffd83dbSDimitry Andric 12485ffd83dbSDimitry Andric llvm::InitializeAllTargetInfos(); 12495ffd83dbSDimitry Andric llvm::InitializeAllTargetMCs(); 12505ffd83dbSDimitry Andric llvm::InitializeAllAsmParsers(); 12515ffd83dbSDimitry Andric llvm::InitializeAllDisassemblers(); 12525ffd83dbSDimitry Andric } 12535ffd83dbSDimitry Andric 12545ffd83dbSDimitry Andric void DisassemblerLLVMC::Terminate() { 12555ffd83dbSDimitry Andric PluginManager::UnregisterPlugin(CreateInstance); 12565ffd83dbSDimitry Andric } 12575ffd83dbSDimitry Andric 12585ffd83dbSDimitry Andric ConstString DisassemblerLLVMC::GetPluginNameStatic() { 12595ffd83dbSDimitry Andric static ConstString g_name("llvm-mc"); 12605ffd83dbSDimitry Andric return g_name; 12615ffd83dbSDimitry Andric } 12625ffd83dbSDimitry Andric 12635ffd83dbSDimitry Andric int DisassemblerLLVMC::OpInfoCallback(void *disassembler, uint64_t pc, 12645ffd83dbSDimitry Andric uint64_t offset, uint64_t size, 12655ffd83dbSDimitry Andric int tag_type, void *tag_bug) { 12665ffd83dbSDimitry Andric return static_cast<DisassemblerLLVMC *>(disassembler) 12675ffd83dbSDimitry Andric ->OpInfo(pc, offset, size, tag_type, tag_bug); 12685ffd83dbSDimitry Andric } 12695ffd83dbSDimitry Andric 12705ffd83dbSDimitry Andric const char *DisassemblerLLVMC::SymbolLookupCallback(void *disassembler, 12715ffd83dbSDimitry Andric uint64_t value, 12725ffd83dbSDimitry Andric uint64_t *type, uint64_t pc, 12735ffd83dbSDimitry Andric const char **name) { 12745ffd83dbSDimitry Andric return static_cast<DisassemblerLLVMC *>(disassembler) 12755ffd83dbSDimitry Andric ->SymbolLookup(value, type, pc, name); 12765ffd83dbSDimitry Andric } 12775ffd83dbSDimitry Andric 12785ffd83dbSDimitry Andric bool DisassemblerLLVMC::FlavorValidForArchSpec( 12795ffd83dbSDimitry Andric const lldb_private::ArchSpec &arch, const char *flavor) { 12805ffd83dbSDimitry Andric llvm::Triple triple = arch.GetTriple(); 12815ffd83dbSDimitry Andric if (flavor == nullptr || strcmp(flavor, "default") == 0) 12825ffd83dbSDimitry Andric return true; 12835ffd83dbSDimitry Andric 12845ffd83dbSDimitry Andric if (triple.getArch() == llvm::Triple::x86 || 12855ffd83dbSDimitry Andric triple.getArch() == llvm::Triple::x86_64) { 12865ffd83dbSDimitry Andric return strcmp(flavor, "intel") == 0 || strcmp(flavor, "att") == 0; 12875ffd83dbSDimitry Andric } else 12885ffd83dbSDimitry Andric return false; 12895ffd83dbSDimitry Andric } 12905ffd83dbSDimitry Andric 12915ffd83dbSDimitry Andric bool DisassemblerLLVMC::IsValid() const { return m_disasm_up.operator bool(); } 12925ffd83dbSDimitry Andric 12935ffd83dbSDimitry Andric int DisassemblerLLVMC::OpInfo(uint64_t PC, uint64_t Offset, uint64_t Size, 12945ffd83dbSDimitry Andric int tag_type, void *tag_bug) { 12955ffd83dbSDimitry Andric switch (tag_type) { 12965ffd83dbSDimitry Andric default: 12975ffd83dbSDimitry Andric break; 12985ffd83dbSDimitry Andric case 1: 12995ffd83dbSDimitry Andric memset(tag_bug, 0, sizeof(::LLVMOpInfo1)); 13005ffd83dbSDimitry Andric break; 13015ffd83dbSDimitry Andric } 13025ffd83dbSDimitry Andric return 0; 13035ffd83dbSDimitry Andric } 13045ffd83dbSDimitry Andric 13055ffd83dbSDimitry Andric const char *DisassemblerLLVMC::SymbolLookup(uint64_t value, uint64_t *type_ptr, 13065ffd83dbSDimitry Andric uint64_t pc, const char **name) { 13075ffd83dbSDimitry Andric if (*type_ptr) { 13085ffd83dbSDimitry Andric if (m_exe_ctx && m_inst) { 13095ffd83dbSDimitry Andric // std::string remove_this_prior_to_checkin; 13105ffd83dbSDimitry Andric Target *target = m_exe_ctx ? m_exe_ctx->GetTargetPtr() : nullptr; 13115ffd83dbSDimitry Andric Address value_so_addr; 13125ffd83dbSDimitry Andric Address pc_so_addr; 13135ffd83dbSDimitry Andric if (m_inst->UsingFileAddress()) { 13145ffd83dbSDimitry Andric ModuleSP module_sp(m_inst->GetAddress().GetModule()); 13155ffd83dbSDimitry Andric if (module_sp) { 13165ffd83dbSDimitry Andric module_sp->ResolveFileAddress(value, value_so_addr); 13175ffd83dbSDimitry Andric module_sp->ResolveFileAddress(pc, pc_so_addr); 13185ffd83dbSDimitry Andric } 13195ffd83dbSDimitry Andric } else if (target && !target->GetSectionLoadList().IsEmpty()) { 13205ffd83dbSDimitry Andric target->GetSectionLoadList().ResolveLoadAddress(value, value_so_addr); 13215ffd83dbSDimitry Andric target->GetSectionLoadList().ResolveLoadAddress(pc, pc_so_addr); 13225ffd83dbSDimitry Andric } 13235ffd83dbSDimitry Andric 13245ffd83dbSDimitry Andric SymbolContext sym_ctx; 13255ffd83dbSDimitry Andric const SymbolContextItem resolve_scope = 13265ffd83dbSDimitry Andric eSymbolContextFunction | eSymbolContextSymbol; 13275ffd83dbSDimitry Andric if (pc_so_addr.IsValid() && pc_so_addr.GetModule()) { 13285ffd83dbSDimitry Andric pc_so_addr.GetModule()->ResolveSymbolContextForAddress( 13295ffd83dbSDimitry Andric pc_so_addr, resolve_scope, sym_ctx); 13305ffd83dbSDimitry Andric } 13315ffd83dbSDimitry Andric 13325ffd83dbSDimitry Andric if (value_so_addr.IsValid() && value_so_addr.GetSection()) { 13335ffd83dbSDimitry Andric StreamString ss; 13345ffd83dbSDimitry Andric 13355ffd83dbSDimitry Andric bool format_omitting_current_func_name = false; 13365ffd83dbSDimitry Andric if (sym_ctx.symbol || sym_ctx.function) { 13375ffd83dbSDimitry Andric AddressRange range; 13385ffd83dbSDimitry Andric if (sym_ctx.GetAddressRange(resolve_scope, 0, false, range) && 13395ffd83dbSDimitry Andric range.GetBaseAddress().IsValid() && 13405ffd83dbSDimitry Andric range.ContainsLoadAddress(value_so_addr, target)) { 13415ffd83dbSDimitry Andric format_omitting_current_func_name = true; 13425ffd83dbSDimitry Andric } 13435ffd83dbSDimitry Andric } 13445ffd83dbSDimitry Andric 13455ffd83dbSDimitry Andric // If the "value" address (the target address we're symbolicating) is 13465ffd83dbSDimitry Andric // inside the same SymbolContext as the current instruction pc 13475ffd83dbSDimitry Andric // (pc_so_addr), don't print the full function name - just print it 13485ffd83dbSDimitry Andric // with DumpStyleNoFunctionName style, e.g. "<+36>". 13495ffd83dbSDimitry Andric if (format_omitting_current_func_name) { 13505ffd83dbSDimitry Andric value_so_addr.Dump(&ss, target, Address::DumpStyleNoFunctionName, 13515ffd83dbSDimitry Andric Address::DumpStyleSectionNameOffset); 13525ffd83dbSDimitry Andric } else { 13535ffd83dbSDimitry Andric value_so_addr.Dump( 13545ffd83dbSDimitry Andric &ss, target, 13555ffd83dbSDimitry Andric Address::DumpStyleResolvedDescriptionNoFunctionArguments, 13565ffd83dbSDimitry Andric Address::DumpStyleSectionNameOffset); 13575ffd83dbSDimitry Andric } 13585ffd83dbSDimitry Andric 13595ffd83dbSDimitry Andric if (!ss.GetString().empty()) { 13605ffd83dbSDimitry Andric // If Address::Dump returned a multi-line description, most commonly 13615ffd83dbSDimitry Andric // seen when we have multiple levels of inlined functions at an 13625ffd83dbSDimitry Andric // address, only show the first line. 13635ffd83dbSDimitry Andric std::string str = std::string(ss.GetString()); 13645ffd83dbSDimitry Andric size_t first_eol_char = str.find_first_of("\r\n"); 13655ffd83dbSDimitry Andric if (first_eol_char != std::string::npos) { 13665ffd83dbSDimitry Andric str.erase(first_eol_char); 13675ffd83dbSDimitry Andric } 13685ffd83dbSDimitry Andric m_inst->AppendComment(str); 13695ffd83dbSDimitry Andric } 13705ffd83dbSDimitry Andric } 13715ffd83dbSDimitry Andric } 13725ffd83dbSDimitry Andric } 13735ffd83dbSDimitry Andric 13745ffd83dbSDimitry Andric *type_ptr = LLVMDisassembler_ReferenceType_InOut_None; 13755ffd83dbSDimitry Andric *name = nullptr; 13765ffd83dbSDimitry Andric return nullptr; 13775ffd83dbSDimitry Andric } 13785ffd83dbSDimitry Andric 13795ffd83dbSDimitry Andric // PluginInterface protocol 13805ffd83dbSDimitry Andric ConstString DisassemblerLLVMC::GetPluginName() { return GetPluginNameStatic(); } 13815ffd83dbSDimitry Andric 13825ffd83dbSDimitry Andric uint32_t DisassemblerLLVMC::GetPluginVersion() { return 1; } 1383