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