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