180814287SRaphael Isemann //===-- DisassemblerLLVMC.cpp ---------------------------------------------===// 2be960424SJonas Devlieghere // 3be960424SJonas Devlieghere // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4be960424SJonas Devlieghere // See https://llvm.org/LICENSE.txt for license information. 5be960424SJonas Devlieghere // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6be960424SJonas Devlieghere // 7be960424SJonas Devlieghere //===----------------------------------------------------------------------===// 8be960424SJonas Devlieghere 9be960424SJonas Devlieghere #include "DisassemblerLLVMC.h" 10be960424SJonas Devlieghere 11be960424SJonas Devlieghere #include "llvm-c/Disassembler.h" 12be960424SJonas Devlieghere #include "llvm/ADT/SmallString.h" 130231a90bSDavid Spickett #include "llvm/ADT/StringExtras.h" 14be960424SJonas Devlieghere #include "llvm/MC/MCAsmInfo.h" 15be960424SJonas Devlieghere #include "llvm/MC/MCContext.h" 16be960424SJonas Devlieghere #include "llvm/MC/MCDisassembler/MCDisassembler.h" 17be960424SJonas Devlieghere #include "llvm/MC/MCDisassembler/MCExternalSymbolizer.h" 18be960424SJonas Devlieghere #include "llvm/MC/MCDisassembler/MCRelocationInfo.h" 19be960424SJonas Devlieghere #include "llvm/MC/MCInst.h" 20be960424SJonas Devlieghere #include "llvm/MC/MCInstPrinter.h" 21254a3127SVenkata Ramanaiah Nalamothu #include "llvm/MC/MCInstrAnalysis.h" 22be960424SJonas Devlieghere #include "llvm/MC/MCInstrInfo.h" 23be960424SJonas Devlieghere #include "llvm/MC/MCRegisterInfo.h" 24be960424SJonas Devlieghere #include "llvm/MC/MCSubtargetInfo.h" 25be960424SJonas Devlieghere #include "llvm/MC/MCTargetOptions.h" 2689b57061SReid Kleckner #include "llvm/MC/TargetRegistry.h" 27be960424SJonas Devlieghere #include "llvm/Support/ErrorHandling.h" 28be960424SJonas Devlieghere #include "llvm/Support/ScopedPrinter.h" 29be960424SJonas Devlieghere #include "llvm/Support/TargetSelect.h" 308c712296SArchibald Elliott #include "llvm/TargetParser/AArch64TargetParser.h" 31be960424SJonas Devlieghere 32be960424SJonas Devlieghere #include "lldb/Core/Address.h" 33be960424SJonas Devlieghere #include "lldb/Core/Module.h" 34be960424SJonas Devlieghere #include "lldb/Symbol/SymbolContext.h" 35be960424SJonas Devlieghere #include "lldb/Target/ExecutionContext.h" 36be960424SJonas Devlieghere #include "lldb/Target/Process.h" 37be960424SJonas Devlieghere #include "lldb/Target/RegisterContext.h" 38be960424SJonas Devlieghere #include "lldb/Target/SectionLoadList.h" 39be960424SJonas Devlieghere #include "lldb/Target/StackFrame.h" 40be960424SJonas Devlieghere #include "lldb/Target/Target.h" 41be960424SJonas Devlieghere #include "lldb/Utility/DataExtractor.h" 42c34698a8SPavel Labath #include "lldb/Utility/LLDBLog.h" 43be960424SJonas Devlieghere #include "lldb/Utility/Log.h" 44be960424SJonas Devlieghere #include "lldb/Utility/RegularExpression.h" 45be960424SJonas Devlieghere #include "lldb/Utility/Stream.h" 46f190ce62SKazu Hirata #include <optional> 47be960424SJonas Devlieghere 48be960424SJonas Devlieghere using namespace lldb; 49be960424SJonas Devlieghere using namespace lldb_private; 50be960424SJonas Devlieghere 51bba9ba8dSJonas Devlieghere LLDB_PLUGIN_DEFINE(DisassemblerLLVMC) 52fbb4d1e4SJonas Devlieghere 53be960424SJonas Devlieghere class DisassemblerLLVMC::MCDisasmInstance { 54be960424SJonas Devlieghere public: 55be960424SJonas Devlieghere static std::unique_ptr<MCDisasmInstance> 56be960424SJonas Devlieghere Create(const char *triple, const char *cpu, const char *features_str, 57be960424SJonas Devlieghere unsigned flavor, DisassemblerLLVMC &owner); 58be960424SJonas Devlieghere 59be960424SJonas Devlieghere ~MCDisasmInstance() = default; 60be960424SJonas Devlieghere 61be960424SJonas Devlieghere uint64_t GetMCInst(const uint8_t *opcode_data, size_t opcode_data_len, 62be960424SJonas Devlieghere lldb::addr_t pc, llvm::MCInst &mc_inst) const; 63523110d6STed Woodward void PrintMCInst(llvm::MCInst &mc_inst, lldb::addr_t pc, 64523110d6STed Woodward std::string &inst_string, std::string &comments_string); 65be960424SJonas Devlieghere void SetStyle(bool use_hex_immed, HexImmediateStyle hex_style); 66a69f78b0SJonas Devlieghere void SetUseColor(bool use_color); 67a69f78b0SJonas Devlieghere bool GetUseColor() const; 68be960424SJonas Devlieghere bool CanBranch(llvm::MCInst &mc_inst) const; 69be960424SJonas Devlieghere bool HasDelaySlot(llvm::MCInst &mc_inst) const; 70be960424SJonas Devlieghere bool IsCall(llvm::MCInst &mc_inst) const; 7166902a32SVedant Kumar bool IsLoad(llvm::MCInst &mc_inst) const; 7266902a32SVedant Kumar bool IsAuthenticated(llvm::MCInst &mc_inst) const; 73be960424SJonas Devlieghere 74be960424SJonas Devlieghere private: 75be960424SJonas Devlieghere MCDisasmInstance(std::unique_ptr<llvm::MCInstrInfo> &&instr_info_up, 76be960424SJonas Devlieghere std::unique_ptr<llvm::MCRegisterInfo> &®_info_up, 77be960424SJonas Devlieghere std::unique_ptr<llvm::MCSubtargetInfo> &&subtarget_info_up, 78be960424SJonas Devlieghere std::unique_ptr<llvm::MCAsmInfo> &&asm_info_up, 79be960424SJonas Devlieghere std::unique_ptr<llvm::MCContext> &&context_up, 80be960424SJonas Devlieghere std::unique_ptr<llvm::MCDisassembler> &&disasm_up, 81254a3127SVenkata Ramanaiah Nalamothu std::unique_ptr<llvm::MCInstPrinter> &&instr_printer_up, 82254a3127SVenkata Ramanaiah Nalamothu std::unique_ptr<llvm::MCInstrAnalysis> &&instr_analysis_up); 83be960424SJonas Devlieghere 84be960424SJonas Devlieghere std::unique_ptr<llvm::MCInstrInfo> m_instr_info_up; 85be960424SJonas Devlieghere std::unique_ptr<llvm::MCRegisterInfo> m_reg_info_up; 86be960424SJonas Devlieghere std::unique_ptr<llvm::MCSubtargetInfo> m_subtarget_info_up; 87be960424SJonas Devlieghere std::unique_ptr<llvm::MCAsmInfo> m_asm_info_up; 88be960424SJonas Devlieghere std::unique_ptr<llvm::MCContext> m_context_up; 89be960424SJonas Devlieghere std::unique_ptr<llvm::MCDisassembler> m_disasm_up; 90be960424SJonas Devlieghere std::unique_ptr<llvm::MCInstPrinter> m_instr_printer_up; 91254a3127SVenkata Ramanaiah Nalamothu std::unique_ptr<llvm::MCInstrAnalysis> m_instr_analysis_up; 92be960424SJonas Devlieghere }; 93be960424SJonas Devlieghere 940538e543SWalter Erquinigo namespace x86 { 950538e543SWalter Erquinigo 960538e543SWalter Erquinigo /// These are the three values deciding instruction control flow kind. 970538e543SWalter Erquinigo /// InstructionLengthDecode function decodes an instruction and get this struct. 980538e543SWalter Erquinigo /// 990538e543SWalter Erquinigo /// primary_opcode 1000538e543SWalter Erquinigo /// Primary opcode of the instruction. 1010538e543SWalter Erquinigo /// For one-byte opcode instruction, it's the first byte after prefix. 1020538e543SWalter Erquinigo /// For two- and three-byte opcodes, it's the second byte. 1030538e543SWalter Erquinigo /// 1040538e543SWalter Erquinigo /// opcode_len 1050538e543SWalter Erquinigo /// The length of opcode in bytes. Valid opcode lengths are 1, 2, or 3. 1060538e543SWalter Erquinigo /// 1070538e543SWalter Erquinigo /// modrm 1080538e543SWalter Erquinigo /// ModR/M byte of the instruction. 1090538e543SWalter Erquinigo /// Bits[7:6] indicate MOD. Bits[5:3] specify a register and R/M bits[2:0] 1100538e543SWalter Erquinigo /// may contain a register or specify an addressing mode, depending on MOD. 1110538e543SWalter Erquinigo struct InstructionOpcodeAndModrm { 1120538e543SWalter Erquinigo uint8_t primary_opcode; 1130538e543SWalter Erquinigo uint8_t opcode_len; 1140538e543SWalter Erquinigo uint8_t modrm; 1150538e543SWalter Erquinigo }; 1160538e543SWalter Erquinigo 1170538e543SWalter Erquinigo /// Determine the InstructionControlFlowKind based on opcode and modrm bytes. 1180538e543SWalter Erquinigo /// Refer to http://ref.x86asm.net/coder.html for the full list of opcode and 1190538e543SWalter Erquinigo /// instruction set. 1200538e543SWalter Erquinigo /// 1210538e543SWalter Erquinigo /// \param[in] opcode_and_modrm 1220538e543SWalter Erquinigo /// Contains primary_opcode byte, its length, and ModR/M byte. 1230538e543SWalter Erquinigo /// Refer to the struct InstructionOpcodeAndModrm for details. 1240538e543SWalter Erquinigo /// 1250538e543SWalter Erquinigo /// \return 1260538e543SWalter Erquinigo /// The control flow kind of the instruction or 1270538e543SWalter Erquinigo /// eInstructionControlFlowKindOther if the instruction doesn't affect 1280538e543SWalter Erquinigo /// the control flow of the program. 1290538e543SWalter Erquinigo lldb::InstructionControlFlowKind 1300538e543SWalter Erquinigo MapOpcodeIntoControlFlowKind(InstructionOpcodeAndModrm opcode_and_modrm) { 1310538e543SWalter Erquinigo uint8_t opcode = opcode_and_modrm.primary_opcode; 1320538e543SWalter Erquinigo uint8_t opcode_len = opcode_and_modrm.opcode_len; 1330538e543SWalter Erquinigo uint8_t modrm = opcode_and_modrm.modrm; 1340538e543SWalter Erquinigo 1350538e543SWalter Erquinigo if (opcode_len > 2) 1360538e543SWalter Erquinigo return lldb::eInstructionControlFlowKindOther; 1370538e543SWalter Erquinigo 1380538e543SWalter Erquinigo if (opcode >= 0x70 && opcode <= 0x7F) { 1390538e543SWalter Erquinigo if (opcode_len == 1) 1400538e543SWalter Erquinigo return lldb::eInstructionControlFlowKindCondJump; 1410538e543SWalter Erquinigo else 1420538e543SWalter Erquinigo return lldb::eInstructionControlFlowKindOther; 1430538e543SWalter Erquinigo } 1440538e543SWalter Erquinigo 1450538e543SWalter Erquinigo if (opcode >= 0x80 && opcode <= 0x8F) { 1460538e543SWalter Erquinigo if (opcode_len == 2) 1470538e543SWalter Erquinigo return lldb::eInstructionControlFlowKindCondJump; 1480538e543SWalter Erquinigo else 1490538e543SWalter Erquinigo return lldb::eInstructionControlFlowKindOther; 1500538e543SWalter Erquinigo } 1510538e543SWalter Erquinigo 1520538e543SWalter Erquinigo switch (opcode) { 1530538e543SWalter Erquinigo case 0x9A: 1540538e543SWalter Erquinigo if (opcode_len == 1) 1550538e543SWalter Erquinigo return lldb::eInstructionControlFlowKindFarCall; 1560538e543SWalter Erquinigo break; 1570538e543SWalter Erquinigo case 0xFF: 1580538e543SWalter Erquinigo if (opcode_len == 1) { 1590538e543SWalter Erquinigo uint8_t modrm_reg = (modrm >> 3) & 7; 1600538e543SWalter Erquinigo if (modrm_reg == 2) 1610538e543SWalter Erquinigo return lldb::eInstructionControlFlowKindCall; 1620538e543SWalter Erquinigo else if (modrm_reg == 3) 1630538e543SWalter Erquinigo return lldb::eInstructionControlFlowKindFarCall; 1640538e543SWalter Erquinigo else if (modrm_reg == 4) 1650538e543SWalter Erquinigo return lldb::eInstructionControlFlowKindJump; 1660538e543SWalter Erquinigo else if (modrm_reg == 5) 1670538e543SWalter Erquinigo return lldb::eInstructionControlFlowKindFarJump; 1680538e543SWalter Erquinigo } 1690538e543SWalter Erquinigo break; 1700538e543SWalter Erquinigo case 0xE8: 1710538e543SWalter Erquinigo if (opcode_len == 1) 1720538e543SWalter Erquinigo return lldb::eInstructionControlFlowKindCall; 1730538e543SWalter Erquinigo break; 1740538e543SWalter Erquinigo case 0xCD: 1750538e543SWalter Erquinigo case 0xCC: 1760538e543SWalter Erquinigo case 0xCE: 1770538e543SWalter Erquinigo case 0xF1: 1780538e543SWalter Erquinigo if (opcode_len == 1) 1790538e543SWalter Erquinigo return lldb::eInstructionControlFlowKindFarCall; 1800538e543SWalter Erquinigo break; 1810538e543SWalter Erquinigo case 0xCF: 1820538e543SWalter Erquinigo if (opcode_len == 1) 1830538e543SWalter Erquinigo return lldb::eInstructionControlFlowKindFarReturn; 1840538e543SWalter Erquinigo break; 1850538e543SWalter Erquinigo case 0xE9: 1860538e543SWalter Erquinigo case 0xEB: 1870538e543SWalter Erquinigo if (opcode_len == 1) 1880538e543SWalter Erquinigo return lldb::eInstructionControlFlowKindJump; 1890538e543SWalter Erquinigo break; 1900538e543SWalter Erquinigo case 0xEA: 1910538e543SWalter Erquinigo if (opcode_len == 1) 1920538e543SWalter Erquinigo return lldb::eInstructionControlFlowKindFarJump; 1930538e543SWalter Erquinigo break; 1940538e543SWalter Erquinigo case 0xE3: 1950538e543SWalter Erquinigo case 0xE0: 1960538e543SWalter Erquinigo case 0xE1: 1970538e543SWalter Erquinigo case 0xE2: 1980538e543SWalter Erquinigo if (opcode_len == 1) 1990538e543SWalter Erquinigo return lldb::eInstructionControlFlowKindCondJump; 2000538e543SWalter Erquinigo break; 2010538e543SWalter Erquinigo case 0xC3: 2020538e543SWalter Erquinigo case 0xC2: 2030538e543SWalter Erquinigo if (opcode_len == 1) 2040538e543SWalter Erquinigo return lldb::eInstructionControlFlowKindReturn; 2050538e543SWalter Erquinigo break; 2060538e543SWalter Erquinigo case 0xCB: 2070538e543SWalter Erquinigo case 0xCA: 2080538e543SWalter Erquinigo if (opcode_len == 1) 2090538e543SWalter Erquinigo return lldb::eInstructionControlFlowKindFarReturn; 2100538e543SWalter Erquinigo break; 2110538e543SWalter Erquinigo case 0x05: 2120538e543SWalter Erquinigo case 0x34: 2130538e543SWalter Erquinigo if (opcode_len == 2) 2140538e543SWalter Erquinigo return lldb::eInstructionControlFlowKindFarCall; 2150538e543SWalter Erquinigo break; 2160538e543SWalter Erquinigo case 0x35: 2170538e543SWalter Erquinigo case 0x07: 2180538e543SWalter Erquinigo if (opcode_len == 2) 2190538e543SWalter Erquinigo return lldb::eInstructionControlFlowKindFarReturn; 2200538e543SWalter Erquinigo break; 2210538e543SWalter Erquinigo case 0x01: 2220538e543SWalter Erquinigo if (opcode_len == 2) { 2230538e543SWalter Erquinigo switch (modrm) { 2240538e543SWalter Erquinigo case 0xc1: 2250538e543SWalter Erquinigo return lldb::eInstructionControlFlowKindFarCall; 2260538e543SWalter Erquinigo case 0xc2: 2270538e543SWalter Erquinigo case 0xc3: 2280538e543SWalter Erquinigo return lldb::eInstructionControlFlowKindFarReturn; 2290538e543SWalter Erquinigo default: 2300538e543SWalter Erquinigo break; 2310538e543SWalter Erquinigo } 2320538e543SWalter Erquinigo } 2330538e543SWalter Erquinigo break; 2340538e543SWalter Erquinigo default: 2350538e543SWalter Erquinigo break; 2360538e543SWalter Erquinigo } 2370538e543SWalter Erquinigo 2380538e543SWalter Erquinigo return lldb::eInstructionControlFlowKindOther; 2390538e543SWalter Erquinigo } 2400538e543SWalter Erquinigo 2410538e543SWalter Erquinigo /// Decode an instruction into opcode, modrm and opcode_len. 2420538e543SWalter Erquinigo /// Refer to http://ref.x86asm.net/coder.html for the instruction bytes layout. 2430538e543SWalter Erquinigo /// Opcodes in x86 are generally the first byte of instruction, though two-byte 2440538e543SWalter Erquinigo /// instructions and prefixes exist. ModR/M is the byte following the opcode 2450538e543SWalter Erquinigo /// and adds additional information for how the instruction is executed. 2460538e543SWalter Erquinigo /// 2470538e543SWalter Erquinigo /// \param[in] inst_bytes 2480538e543SWalter Erquinigo /// Raw bytes of the instruction 2490538e543SWalter Erquinigo /// 2500538e543SWalter Erquinigo /// 2510538e543SWalter Erquinigo /// \param[in] bytes_len 2520538e543SWalter Erquinigo /// The length of the inst_bytes array. 2530538e543SWalter Erquinigo /// 2540538e543SWalter Erquinigo /// \param[in] is_exec_mode_64b 2550538e543SWalter Erquinigo /// If true, the execution mode is 64 bit. 2560538e543SWalter Erquinigo /// 2570538e543SWalter Erquinigo /// \return 2580538e543SWalter Erquinigo /// Returns decoded instruction as struct InstructionOpcodeAndModrm, holding 2590538e543SWalter Erquinigo /// primary_opcode, opcode_len and modrm byte. Refer to the struct definition 2600538e543SWalter Erquinigo /// for more details. 261768cae4aSKazu Hirata /// Otherwise if the given instruction is invalid, returns std::nullopt. 2622fe83274SKazu Hirata std::optional<InstructionOpcodeAndModrm> 2630538e543SWalter Erquinigo InstructionLengthDecode(const uint8_t *inst_bytes, int bytes_len, 2640538e543SWalter Erquinigo bool is_exec_mode_64b) { 2650538e543SWalter Erquinigo int op_idx = 0; 2660538e543SWalter Erquinigo bool prefix_done = false; 2670538e543SWalter Erquinigo InstructionOpcodeAndModrm ret = {0, 0, 0}; 2680538e543SWalter Erquinigo 2690538e543SWalter Erquinigo // In most cases, the primary_opcode is the first byte of the instruction 2700538e543SWalter Erquinigo // but some instructions have a prefix to be skipped for these calculations. 2710538e543SWalter Erquinigo // The following mapping is inspired from libipt's instruction decoding logic 2720538e543SWalter Erquinigo // in `src/pt_ild.c` 2730538e543SWalter Erquinigo while (!prefix_done) { 2740538e543SWalter Erquinigo if (op_idx >= bytes_len) 275343523d0SKazu Hirata return std::nullopt; 2760538e543SWalter Erquinigo 2770538e543SWalter Erquinigo ret.primary_opcode = inst_bytes[op_idx]; 2780538e543SWalter Erquinigo switch (ret.primary_opcode) { 2790538e543SWalter Erquinigo // prefix_ignore 2800538e543SWalter Erquinigo case 0x26: 2810538e543SWalter Erquinigo case 0x2e: 2820538e543SWalter Erquinigo case 0x36: 2830538e543SWalter Erquinigo case 0x3e: 2840538e543SWalter Erquinigo case 0x64: 2850538e543SWalter Erquinigo case 0x65: 2860538e543SWalter Erquinigo // prefix_osz, prefix_asz 2870538e543SWalter Erquinigo case 0x66: 2880538e543SWalter Erquinigo case 0x67: 2890538e543SWalter Erquinigo // prefix_lock, prefix_f2, prefix_f3 2900538e543SWalter Erquinigo case 0xf0: 2910538e543SWalter Erquinigo case 0xf2: 2920538e543SWalter Erquinigo case 0xf3: 2930538e543SWalter Erquinigo op_idx++; 2940538e543SWalter Erquinigo break; 2950538e543SWalter Erquinigo 2960538e543SWalter Erquinigo // prefix_rex 2970538e543SWalter Erquinigo case 0x40: 2980538e543SWalter Erquinigo case 0x41: 2990538e543SWalter Erquinigo case 0x42: 3000538e543SWalter Erquinigo case 0x43: 3010538e543SWalter Erquinigo case 0x44: 3020538e543SWalter Erquinigo case 0x45: 3030538e543SWalter Erquinigo case 0x46: 3040538e543SWalter Erquinigo case 0x47: 3050538e543SWalter Erquinigo case 0x48: 3060538e543SWalter Erquinigo case 0x49: 3070538e543SWalter Erquinigo case 0x4a: 3080538e543SWalter Erquinigo case 0x4b: 3090538e543SWalter Erquinigo case 0x4c: 3100538e543SWalter Erquinigo case 0x4d: 3110538e543SWalter Erquinigo case 0x4e: 3120538e543SWalter Erquinigo case 0x4f: 3130538e543SWalter Erquinigo if (is_exec_mode_64b) 3140538e543SWalter Erquinigo op_idx++; 3150538e543SWalter Erquinigo else 3160538e543SWalter Erquinigo prefix_done = true; 3170538e543SWalter Erquinigo break; 3180538e543SWalter Erquinigo 3190538e543SWalter Erquinigo // prefix_vex_c4, c5 3200538e543SWalter Erquinigo case 0xc5: 3210538e543SWalter Erquinigo if (!is_exec_mode_64b && (inst_bytes[op_idx + 1] & 0xc0) != 0xc0) { 3220538e543SWalter Erquinigo prefix_done = true; 3230538e543SWalter Erquinigo break; 3240538e543SWalter Erquinigo } 3250538e543SWalter Erquinigo 3260538e543SWalter Erquinigo ret.opcode_len = 2; 3270538e543SWalter Erquinigo ret.primary_opcode = inst_bytes[op_idx + 2]; 3280538e543SWalter Erquinigo ret.modrm = inst_bytes[op_idx + 3]; 3290538e543SWalter Erquinigo return ret; 3300538e543SWalter Erquinigo 3310538e543SWalter Erquinigo case 0xc4: 3320538e543SWalter Erquinigo if (!is_exec_mode_64b && (inst_bytes[op_idx + 1] & 0xc0) != 0xc0) { 3330538e543SWalter Erquinigo prefix_done = true; 3340538e543SWalter Erquinigo break; 3350538e543SWalter Erquinigo } 3360538e543SWalter Erquinigo ret.opcode_len = inst_bytes[op_idx + 1] & 0x1f; 3370538e543SWalter Erquinigo ret.primary_opcode = inst_bytes[op_idx + 3]; 3380538e543SWalter Erquinigo ret.modrm = inst_bytes[op_idx + 4]; 3390538e543SWalter Erquinigo return ret; 3400538e543SWalter Erquinigo 3410538e543SWalter Erquinigo // prefix_evex 3420538e543SWalter Erquinigo case 0x62: 3430538e543SWalter Erquinigo if (!is_exec_mode_64b && (inst_bytes[op_idx + 1] & 0xc0) != 0xc0) { 3440538e543SWalter Erquinigo prefix_done = true; 3450538e543SWalter Erquinigo break; 3460538e543SWalter Erquinigo } 3470538e543SWalter Erquinigo ret.opcode_len = inst_bytes[op_idx + 1] & 0x03; 3480538e543SWalter Erquinigo ret.primary_opcode = inst_bytes[op_idx + 4]; 3490538e543SWalter Erquinigo ret.modrm = inst_bytes[op_idx + 5]; 3500538e543SWalter Erquinigo return ret; 3510538e543SWalter Erquinigo 3520538e543SWalter Erquinigo default: 3530538e543SWalter Erquinigo prefix_done = true; 3540538e543SWalter Erquinigo break; 3550538e543SWalter Erquinigo } 3560538e543SWalter Erquinigo } // prefix done 3570538e543SWalter Erquinigo 3580538e543SWalter Erquinigo ret.primary_opcode = inst_bytes[op_idx]; 3590538e543SWalter Erquinigo ret.modrm = inst_bytes[op_idx + 1]; 3600538e543SWalter Erquinigo ret.opcode_len = 1; 3610538e543SWalter Erquinigo 3620538e543SWalter Erquinigo // If the first opcode is 0F, it's two- or three- byte opcodes. 3630538e543SWalter Erquinigo if (ret.primary_opcode == 0x0F) { 3640538e543SWalter Erquinigo ret.primary_opcode = inst_bytes[++op_idx]; // get the next byte 3650538e543SWalter Erquinigo 3660538e543SWalter Erquinigo if (ret.primary_opcode == 0x38) { 3670538e543SWalter Erquinigo ret.opcode_len = 3; 3680538e543SWalter Erquinigo ret.primary_opcode = inst_bytes[++op_idx]; // get the next byte 3690538e543SWalter Erquinigo ret.modrm = inst_bytes[op_idx + 1]; 3700538e543SWalter Erquinigo } else if (ret.primary_opcode == 0x3A) { 3710538e543SWalter Erquinigo ret.opcode_len = 3; 3720538e543SWalter Erquinigo ret.primary_opcode = inst_bytes[++op_idx]; 3730538e543SWalter Erquinigo ret.modrm = inst_bytes[op_idx + 1]; 3740538e543SWalter Erquinigo } else if ((ret.primary_opcode & 0xf8) == 0x38) { 3750538e543SWalter Erquinigo ret.opcode_len = 0; 3760538e543SWalter Erquinigo ret.primary_opcode = inst_bytes[++op_idx]; 3770538e543SWalter Erquinigo ret.modrm = inst_bytes[op_idx + 1]; 3780538e543SWalter Erquinigo } else if (ret.primary_opcode == 0x0F) { 3790538e543SWalter Erquinigo ret.opcode_len = 3; 3800538e543SWalter Erquinigo // opcode is 0x0F, no needs to update 3810538e543SWalter Erquinigo ret.modrm = inst_bytes[op_idx + 1]; 3820538e543SWalter Erquinigo } else { 3830538e543SWalter Erquinigo ret.opcode_len = 2; 3840538e543SWalter Erquinigo ret.modrm = inst_bytes[op_idx + 1]; 3850538e543SWalter Erquinigo } 3860538e543SWalter Erquinigo } 3870538e543SWalter Erquinigo 3880538e543SWalter Erquinigo return ret; 3890538e543SWalter Erquinigo } 3900538e543SWalter Erquinigo 3910538e543SWalter Erquinigo lldb::InstructionControlFlowKind GetControlFlowKind(bool is_exec_mode_64b, 3920538e543SWalter Erquinigo Opcode m_opcode) { 3932fe83274SKazu Hirata std::optional<InstructionOpcodeAndModrm> ret; 3940538e543SWalter Erquinigo 3950538e543SWalter Erquinigo if (m_opcode.GetOpcodeBytes() == nullptr || m_opcode.GetByteSize() <= 0) { 3960538e543SWalter Erquinigo // x86_64 and i386 instructions are categorized as Opcode::Type::eTypeBytes 3970538e543SWalter Erquinigo return lldb::eInstructionControlFlowKindUnknown; 3980538e543SWalter Erquinigo } 3990538e543SWalter Erquinigo 4000538e543SWalter Erquinigo // Opcode bytes will be decoded into primary_opcode, modrm and opcode length. 4010538e543SWalter Erquinigo // These are the three values deciding instruction control flow kind. 4020538e543SWalter Erquinigo ret = InstructionLengthDecode((const uint8_t *)m_opcode.GetOpcodeBytes(), 4030538e543SWalter Erquinigo m_opcode.GetByteSize(), is_exec_mode_64b); 4040538e543SWalter Erquinigo if (!ret) 4050538e543SWalter Erquinigo return lldb::eInstructionControlFlowKindUnknown; 4060538e543SWalter Erquinigo else 4079464bd8cSFangrui Song return MapOpcodeIntoControlFlowKind(*ret); 4080538e543SWalter Erquinigo } 4090538e543SWalter Erquinigo 4100538e543SWalter Erquinigo } // namespace x86 4110538e543SWalter Erquinigo 412be960424SJonas Devlieghere class InstructionLLVMC : public lldb_private::Instruction { 413be960424SJonas Devlieghere public: 414be960424SJonas Devlieghere InstructionLLVMC(DisassemblerLLVMC &disasm, 415be960424SJonas Devlieghere const lldb_private::Address &address, 416be960424SJonas Devlieghere AddressClass addr_class) 417be960424SJonas Devlieghere : Instruction(address, addr_class), 418be960424SJonas Devlieghere m_disasm_wp(std::static_pointer_cast<DisassemblerLLVMC>( 41928c878aeSShafik Yaghmour disasm.shared_from_this())) {} 420be960424SJonas Devlieghere 421be960424SJonas Devlieghere ~InstructionLLVMC() override = default; 422be960424SJonas Devlieghere 423be960424SJonas Devlieghere bool DoesBranch() override { 424009e3e53SVedant Kumar VisitInstruction(); 425009e3e53SVedant Kumar return m_does_branch; 426be960424SJonas Devlieghere } 427be960424SJonas Devlieghere 428be960424SJonas Devlieghere bool HasDelaySlot() override { 429009e3e53SVedant Kumar VisitInstruction(); 430009e3e53SVedant Kumar return m_has_delay_slot; 431be960424SJonas Devlieghere } 432be960424SJonas Devlieghere 43366902a32SVedant Kumar bool IsLoad() override { 43466902a32SVedant Kumar VisitInstruction(); 43566902a32SVedant Kumar return m_is_load; 43666902a32SVedant Kumar } 43766902a32SVedant Kumar 43866902a32SVedant Kumar bool IsAuthenticated() override { 43966902a32SVedant Kumar VisitInstruction(); 44066902a32SVedant Kumar return m_is_authenticated; 44166902a32SVedant Kumar } 44266902a32SVedant Kumar 443be960424SJonas Devlieghere DisassemblerLLVMC::MCDisasmInstance *GetDisasmToUse(bool &is_alternate_isa) { 444be960424SJonas Devlieghere DisassemblerScope disasm(*this); 445be960424SJonas Devlieghere return GetDisasmToUse(is_alternate_isa, disasm); 446be960424SJonas Devlieghere } 447be960424SJonas Devlieghere 448be960424SJonas Devlieghere size_t Decode(const lldb_private::Disassembler &disassembler, 449be960424SJonas Devlieghere const lldb_private::DataExtractor &data, 450be960424SJonas Devlieghere lldb::offset_t data_offset) override { 451be960424SJonas Devlieghere // All we have to do is read the opcode which can be easy for some 452be960424SJonas Devlieghere // architectures 453be960424SJonas Devlieghere bool got_op = false; 454be960424SJonas Devlieghere DisassemblerScope disasm(*this); 455be960424SJonas Devlieghere if (disasm) { 456be960424SJonas Devlieghere const ArchSpec &arch = disasm->GetArchitecture(); 457be960424SJonas Devlieghere const lldb::ByteOrder byte_order = data.GetByteOrder(); 458be960424SJonas Devlieghere 459be960424SJonas Devlieghere const uint32_t min_op_byte_size = arch.GetMinimumOpcodeByteSize(); 460be960424SJonas Devlieghere const uint32_t max_op_byte_size = arch.GetMaximumOpcodeByteSize(); 461be960424SJonas Devlieghere if (min_op_byte_size == max_op_byte_size) { 462be960424SJonas Devlieghere // Fixed size instructions, just read that amount of data. 463be960424SJonas Devlieghere if (!data.ValidOffsetForDataOfSize(data_offset, min_op_byte_size)) 464be960424SJonas Devlieghere return false; 465be960424SJonas Devlieghere 466be960424SJonas Devlieghere switch (min_op_byte_size) { 467be960424SJonas Devlieghere case 1: 468be960424SJonas Devlieghere m_opcode.SetOpcode8(data.GetU8(&data_offset), byte_order); 469be960424SJonas Devlieghere got_op = true; 470be960424SJonas Devlieghere break; 471be960424SJonas Devlieghere 472be960424SJonas Devlieghere case 2: 473be960424SJonas Devlieghere m_opcode.SetOpcode16(data.GetU16(&data_offset), byte_order); 474be960424SJonas Devlieghere got_op = true; 475be960424SJonas Devlieghere break; 476be960424SJonas Devlieghere 477be960424SJonas Devlieghere case 4: 478be960424SJonas Devlieghere m_opcode.SetOpcode32(data.GetU32(&data_offset), byte_order); 479be960424SJonas Devlieghere got_op = true; 480be960424SJonas Devlieghere break; 481be960424SJonas Devlieghere 482be960424SJonas Devlieghere case 8: 483be960424SJonas Devlieghere m_opcode.SetOpcode64(data.GetU64(&data_offset), byte_order); 484be960424SJonas Devlieghere got_op = true; 485be960424SJonas Devlieghere break; 486be960424SJonas Devlieghere 487be960424SJonas Devlieghere default: 488be960424SJonas Devlieghere m_opcode.SetOpcodeBytes(data.PeekData(data_offset, min_op_byte_size), 489be960424SJonas Devlieghere min_op_byte_size); 490be960424SJonas Devlieghere got_op = true; 491be960424SJonas Devlieghere break; 492be960424SJonas Devlieghere } 493be960424SJonas Devlieghere } 494be960424SJonas Devlieghere if (!got_op) { 495be960424SJonas Devlieghere bool is_alternate_isa = false; 496be960424SJonas Devlieghere DisassemblerLLVMC::MCDisasmInstance *mc_disasm_ptr = 497be960424SJonas Devlieghere GetDisasmToUse(is_alternate_isa, disasm); 498be960424SJonas Devlieghere 499be960424SJonas Devlieghere const llvm::Triple::ArchType machine = arch.GetMachine(); 500be960424SJonas Devlieghere if (machine == llvm::Triple::arm || machine == llvm::Triple::thumb) { 501be960424SJonas Devlieghere if (machine == llvm::Triple::thumb || is_alternate_isa) { 502be960424SJonas Devlieghere uint32_t thumb_opcode = data.GetU16(&data_offset); 503be960424SJonas Devlieghere if ((thumb_opcode & 0xe000) != 0xe000 || 504be960424SJonas Devlieghere ((thumb_opcode & 0x1800u) == 0)) { 505be960424SJonas Devlieghere m_opcode.SetOpcode16(thumb_opcode, byte_order); 506be960424SJonas Devlieghere m_is_valid = true; 507be960424SJonas Devlieghere } else { 508be960424SJonas Devlieghere thumb_opcode <<= 16; 509be960424SJonas Devlieghere thumb_opcode |= data.GetU16(&data_offset); 510be960424SJonas Devlieghere m_opcode.SetOpcode16_2(thumb_opcode, byte_order); 511be960424SJonas Devlieghere m_is_valid = true; 512be960424SJonas Devlieghere } 513be960424SJonas Devlieghere } else { 514be960424SJonas Devlieghere m_opcode.SetOpcode32(data.GetU32(&data_offset), byte_order); 515be960424SJonas Devlieghere m_is_valid = true; 516be960424SJonas Devlieghere } 517be960424SJonas Devlieghere } else { 518be960424SJonas Devlieghere // The opcode isn't evenly sized, so we need to actually use the llvm 519be960424SJonas Devlieghere // disassembler to parse it and get the size. 520be960424SJonas Devlieghere uint8_t *opcode_data = 521be960424SJonas Devlieghere const_cast<uint8_t *>(data.PeekData(data_offset, 1)); 522be960424SJonas Devlieghere const size_t opcode_data_len = data.BytesLeft(data_offset); 523be960424SJonas Devlieghere const addr_t pc = m_address.GetFileAddress(); 524be960424SJonas Devlieghere llvm::MCInst inst; 525be960424SJonas Devlieghere 526be960424SJonas Devlieghere const size_t inst_size = 527be960424SJonas Devlieghere mc_disasm_ptr->GetMCInst(opcode_data, opcode_data_len, pc, inst); 528be960424SJonas Devlieghere if (inst_size == 0) 529be960424SJonas Devlieghere m_opcode.Clear(); 530be960424SJonas Devlieghere else { 531be960424SJonas Devlieghere m_opcode.SetOpcodeBytes(opcode_data, inst_size); 532be960424SJonas Devlieghere m_is_valid = true; 533be960424SJonas Devlieghere } 534be960424SJonas Devlieghere } 535be960424SJonas Devlieghere } 536be960424SJonas Devlieghere return m_opcode.GetByteSize(); 537be960424SJonas Devlieghere } 538be960424SJonas Devlieghere return 0; 539be960424SJonas Devlieghere } 540be960424SJonas Devlieghere 541be960424SJonas Devlieghere void AppendComment(std::string &description) { 542be960424SJonas Devlieghere if (m_comment.empty()) 543be960424SJonas Devlieghere m_comment.swap(description); 544be960424SJonas Devlieghere else { 545be960424SJonas Devlieghere m_comment.append(", "); 546be960424SJonas Devlieghere m_comment.append(description); 547be960424SJonas Devlieghere } 548be960424SJonas Devlieghere } 549be960424SJonas Devlieghere 5500538e543SWalter Erquinigo lldb::InstructionControlFlowKind 5510538e543SWalter Erquinigo GetControlFlowKind(const lldb_private::ExecutionContext *exe_ctx) override { 5520538e543SWalter Erquinigo DisassemblerScope disasm(*this, exe_ctx); 5530538e543SWalter Erquinigo if (disasm){ 5540538e543SWalter Erquinigo if (disasm->GetArchitecture().GetMachine() == llvm::Triple::x86) 5550538e543SWalter Erquinigo return x86::GetControlFlowKind(/*is_64b=*/false, m_opcode); 5560538e543SWalter Erquinigo else if (disasm->GetArchitecture().GetMachine() == llvm::Triple::x86_64) 5570538e543SWalter Erquinigo return x86::GetControlFlowKind(/*is_64b=*/true, m_opcode); 5580538e543SWalter Erquinigo } 5590538e543SWalter Erquinigo 5600538e543SWalter Erquinigo return eInstructionControlFlowKindUnknown; 5610538e543SWalter Erquinigo } 5620538e543SWalter Erquinigo 563be960424SJonas Devlieghere void CalculateMnemonicOperandsAndComment( 564be960424SJonas Devlieghere const lldb_private::ExecutionContext *exe_ctx) override { 565be960424SJonas Devlieghere DataExtractor data; 566be960424SJonas Devlieghere const AddressClass address_class = GetAddressClass(); 567be960424SJonas Devlieghere 568be960424SJonas Devlieghere if (m_opcode.GetData(data)) { 569be960424SJonas Devlieghere std::string out_string; 570a69f78b0SJonas Devlieghere std::string markup_out_string; 571be960424SJonas Devlieghere std::string comment_string; 572a69f78b0SJonas Devlieghere std::string markup_comment_string; 573be960424SJonas Devlieghere 574be960424SJonas Devlieghere DisassemblerScope disasm(*this, exe_ctx); 575be960424SJonas Devlieghere if (disasm) { 576be960424SJonas Devlieghere DisassemblerLLVMC::MCDisasmInstance *mc_disasm_ptr; 577be960424SJonas Devlieghere 578be960424SJonas Devlieghere if (address_class == AddressClass::eCodeAlternateISA) 579be960424SJonas Devlieghere mc_disasm_ptr = disasm->m_alternate_disasm_up.get(); 580be960424SJonas Devlieghere else 581be960424SJonas Devlieghere mc_disasm_ptr = disasm->m_disasm_up.get(); 582be960424SJonas Devlieghere 583be960424SJonas Devlieghere lldb::addr_t pc = m_address.GetFileAddress(); 584be960424SJonas Devlieghere m_using_file_addr = true; 585be960424SJonas Devlieghere 586be960424SJonas Devlieghere bool use_hex_immediates = true; 587be960424SJonas Devlieghere Disassembler::HexImmediateStyle hex_style = Disassembler::eHexStyleC; 588be960424SJonas Devlieghere 589be960424SJonas Devlieghere if (exe_ctx) { 590be960424SJonas Devlieghere Target *target = exe_ctx->GetTargetPtr(); 591be960424SJonas Devlieghere if (target) { 592be960424SJonas Devlieghere use_hex_immediates = target->GetUseHexImmediates(); 593be960424SJonas Devlieghere hex_style = target->GetHexImmediateStyle(); 594be960424SJonas Devlieghere 595be960424SJonas Devlieghere const lldb::addr_t load_addr = m_address.GetLoadAddress(target); 596be960424SJonas Devlieghere if (load_addr != LLDB_INVALID_ADDRESS) { 597be960424SJonas Devlieghere pc = load_addr; 598be960424SJonas Devlieghere m_using_file_addr = false; 599be960424SJonas Devlieghere } 600be960424SJonas Devlieghere } 601be960424SJonas Devlieghere } 602be960424SJonas Devlieghere 603be960424SJonas Devlieghere const uint8_t *opcode_data = data.GetDataStart(); 604be960424SJonas Devlieghere const size_t opcode_data_len = data.GetByteSize(); 605be960424SJonas Devlieghere llvm::MCInst inst; 606be960424SJonas Devlieghere size_t inst_size = 607be960424SJonas Devlieghere mc_disasm_ptr->GetMCInst(opcode_data, opcode_data_len, pc, inst); 608be960424SJonas Devlieghere 609be960424SJonas Devlieghere if (inst_size > 0) { 610be960424SJonas Devlieghere mc_disasm_ptr->SetStyle(use_hex_immediates, hex_style); 611a69f78b0SJonas Devlieghere 612a69f78b0SJonas Devlieghere const bool saved_use_color = mc_disasm_ptr->GetUseColor(); 613a69f78b0SJonas Devlieghere mc_disasm_ptr->SetUseColor(false); 614523110d6STed Woodward mc_disasm_ptr->PrintMCInst(inst, pc, out_string, comment_string); 615a69f78b0SJonas Devlieghere mc_disasm_ptr->SetUseColor(true); 616a69f78b0SJonas Devlieghere mc_disasm_ptr->PrintMCInst(inst, pc, markup_out_string, 617a69f78b0SJonas Devlieghere markup_comment_string); 618a69f78b0SJonas Devlieghere mc_disasm_ptr->SetUseColor(saved_use_color); 619be960424SJonas Devlieghere 620be960424SJonas Devlieghere if (!comment_string.empty()) { 621be960424SJonas Devlieghere AppendComment(comment_string); 622be960424SJonas Devlieghere } 623be960424SJonas Devlieghere } 624be960424SJonas Devlieghere 625be960424SJonas Devlieghere if (inst_size == 0) { 626be960424SJonas Devlieghere m_comment.assign("unknown opcode"); 627be960424SJonas Devlieghere inst_size = m_opcode.GetByteSize(); 628be960424SJonas Devlieghere StreamString mnemonic_strm; 629be960424SJonas Devlieghere lldb::offset_t offset = 0; 630be960424SJonas Devlieghere lldb::ByteOrder byte_order = data.GetByteOrder(); 631be960424SJonas Devlieghere switch (inst_size) { 632be960424SJonas Devlieghere case 1: { 633be960424SJonas Devlieghere const uint8_t uval8 = data.GetU8(&offset); 634be960424SJonas Devlieghere m_opcode.SetOpcode8(uval8, byte_order); 635be960424SJonas Devlieghere m_opcode_name.assign(".byte"); 636be960424SJonas Devlieghere mnemonic_strm.Printf("0x%2.2x", uval8); 637be960424SJonas Devlieghere } break; 638be960424SJonas Devlieghere case 2: { 639be960424SJonas Devlieghere const uint16_t uval16 = data.GetU16(&offset); 640be960424SJonas Devlieghere m_opcode.SetOpcode16(uval16, byte_order); 641be960424SJonas Devlieghere m_opcode_name.assign(".short"); 642be960424SJonas Devlieghere mnemonic_strm.Printf("0x%4.4x", uval16); 643be960424SJonas Devlieghere } break; 644be960424SJonas Devlieghere case 4: { 645be960424SJonas Devlieghere const uint32_t uval32 = data.GetU32(&offset); 646be960424SJonas Devlieghere m_opcode.SetOpcode32(uval32, byte_order); 647be960424SJonas Devlieghere m_opcode_name.assign(".long"); 648be960424SJonas Devlieghere mnemonic_strm.Printf("0x%8.8x", uval32); 649be960424SJonas Devlieghere } break; 650be960424SJonas Devlieghere case 8: { 651be960424SJonas Devlieghere const uint64_t uval64 = data.GetU64(&offset); 652be960424SJonas Devlieghere m_opcode.SetOpcode64(uval64, byte_order); 653be960424SJonas Devlieghere m_opcode_name.assign(".quad"); 654be960424SJonas Devlieghere mnemonic_strm.Printf("0x%16.16" PRIx64, uval64); 655be960424SJonas Devlieghere } break; 656be960424SJonas Devlieghere default: 657be960424SJonas Devlieghere if (inst_size == 0) 658be960424SJonas Devlieghere return; 659be960424SJonas Devlieghere else { 660be960424SJonas Devlieghere const uint8_t *bytes = data.PeekData(offset, inst_size); 661be960424SJonas Devlieghere if (bytes == nullptr) 662be960424SJonas Devlieghere return; 663be960424SJonas Devlieghere m_opcode_name.assign(".byte"); 664be960424SJonas Devlieghere m_opcode.SetOpcodeBytes(bytes, inst_size); 665be960424SJonas Devlieghere mnemonic_strm.Printf("0x%2.2x", bytes[0]); 666be960424SJonas Devlieghere for (uint32_t i = 1; i < inst_size; ++i) 667be960424SJonas Devlieghere mnemonic_strm.Printf(" 0x%2.2x", bytes[i]); 668be960424SJonas Devlieghere } 669be960424SJonas Devlieghere break; 670be960424SJonas Devlieghere } 671adcd0268SBenjamin Kramer m_mnemonics = std::string(mnemonic_strm.GetString()); 672be960424SJonas Devlieghere return; 673be960424SJonas Devlieghere } 674be960424SJonas Devlieghere 675be960424SJonas Devlieghere static RegularExpression s_regex( 676be960424SJonas Devlieghere llvm::StringRef("[ \t]*([^ ^\t]+)[ \t]*([^ ^\t].*)?")); 677be960424SJonas Devlieghere 678be960424SJonas Devlieghere llvm::SmallVector<llvm::StringRef, 4> matches; 679be960424SJonas Devlieghere if (s_regex.Execute(out_string, &matches)) { 680be960424SJonas Devlieghere m_opcode_name = matches[1].str(); 681be960424SJonas Devlieghere m_mnemonics = matches[2].str(); 682be960424SJonas Devlieghere } 683a69f78b0SJonas Devlieghere matches.clear(); 684a69f78b0SJonas Devlieghere if (s_regex.Execute(markup_out_string, &matches)) { 685a69f78b0SJonas Devlieghere m_markup_opcode_name = matches[1].str(); 686a69f78b0SJonas Devlieghere m_markup_mnemonics = matches[2].str(); 687a69f78b0SJonas Devlieghere } 688be960424SJonas Devlieghere } 689be960424SJonas Devlieghere } 690be960424SJonas Devlieghere } 691be960424SJonas Devlieghere 692be960424SJonas Devlieghere bool IsValid() const { return m_is_valid; } 693be960424SJonas Devlieghere 694be960424SJonas Devlieghere bool UsingFileAddress() const { return m_using_file_addr; } 695be960424SJonas Devlieghere size_t GetByteSize() const { return m_opcode.GetByteSize(); } 696be960424SJonas Devlieghere 697be960424SJonas Devlieghere /// Grants exclusive access to the disassembler and initializes it with the 698be960424SJonas Devlieghere /// given InstructionLLVMC and an optional ExecutionContext. 699be960424SJonas Devlieghere class DisassemblerScope { 700be960424SJonas Devlieghere std::shared_ptr<DisassemblerLLVMC> m_disasm; 701be960424SJonas Devlieghere 702be960424SJonas Devlieghere public: 703be960424SJonas Devlieghere explicit DisassemblerScope( 704be960424SJonas Devlieghere InstructionLLVMC &i, 705be960424SJonas Devlieghere const lldb_private::ExecutionContext *exe_ctx = nullptr) 706be960424SJonas Devlieghere : m_disasm(i.m_disasm_wp.lock()) { 707be960424SJonas Devlieghere m_disasm->m_mutex.lock(); 708be960424SJonas Devlieghere m_disasm->m_inst = &i; 709be960424SJonas Devlieghere m_disasm->m_exe_ctx = exe_ctx; 710be960424SJonas Devlieghere } 711be960424SJonas Devlieghere ~DisassemblerScope() { m_disasm->m_mutex.unlock(); } 712be960424SJonas Devlieghere 713be960424SJonas Devlieghere /// Evaluates to true if this scope contains a valid disassembler. 714be960424SJonas Devlieghere operator bool() const { return static_cast<bool>(m_disasm); } 715be960424SJonas Devlieghere 716be960424SJonas Devlieghere std::shared_ptr<DisassemblerLLVMC> operator->() { return m_disasm; } 717be960424SJonas Devlieghere }; 718be960424SJonas Devlieghere 719be960424SJonas Devlieghere static llvm::StringRef::const_iterator 720be960424SJonas Devlieghere ConsumeWhitespace(llvm::StringRef::const_iterator osi, 721be960424SJonas Devlieghere llvm::StringRef::const_iterator ose) { 722be960424SJonas Devlieghere while (osi != ose) { 723be960424SJonas Devlieghere switch (*osi) { 724be960424SJonas Devlieghere default: 725be960424SJonas Devlieghere return osi; 726be960424SJonas Devlieghere case ' ': 727be960424SJonas Devlieghere case '\t': 728be960424SJonas Devlieghere break; 729be960424SJonas Devlieghere } 730be960424SJonas Devlieghere ++osi; 731be960424SJonas Devlieghere } 732be960424SJonas Devlieghere 733be960424SJonas Devlieghere return osi; 734be960424SJonas Devlieghere } 735be960424SJonas Devlieghere 736be960424SJonas Devlieghere static std::pair<bool, llvm::StringRef::const_iterator> 737be960424SJonas Devlieghere ConsumeChar(llvm::StringRef::const_iterator osi, const char c, 738be960424SJonas Devlieghere llvm::StringRef::const_iterator ose) { 739be960424SJonas Devlieghere bool found = false; 740be960424SJonas Devlieghere 741be960424SJonas Devlieghere osi = ConsumeWhitespace(osi, ose); 742be960424SJonas Devlieghere if (osi != ose && *osi == c) { 743be960424SJonas Devlieghere found = true; 744be960424SJonas Devlieghere ++osi; 745be960424SJonas Devlieghere } 746be960424SJonas Devlieghere 747be960424SJonas Devlieghere return std::make_pair(found, osi); 748be960424SJonas Devlieghere } 749be960424SJonas Devlieghere 750be960424SJonas Devlieghere static std::pair<Operand, llvm::StringRef::const_iterator> 751be960424SJonas Devlieghere ParseRegisterName(llvm::StringRef::const_iterator osi, 752be960424SJonas Devlieghere llvm::StringRef::const_iterator ose) { 753be960424SJonas Devlieghere Operand ret; 754be960424SJonas Devlieghere ret.m_type = Operand::Type::Register; 755be960424SJonas Devlieghere std::string str; 756be960424SJonas Devlieghere 757be960424SJonas Devlieghere osi = ConsumeWhitespace(osi, ose); 758be960424SJonas Devlieghere 759be960424SJonas Devlieghere while (osi != ose) { 760be960424SJonas Devlieghere if (*osi >= '0' && *osi <= '9') { 761be960424SJonas Devlieghere if (str.empty()) { 762be960424SJonas Devlieghere return std::make_pair(Operand(), osi); 763be960424SJonas Devlieghere } else { 764be960424SJonas Devlieghere str.push_back(*osi); 765be960424SJonas Devlieghere } 766be960424SJonas Devlieghere } else if (*osi >= 'a' && *osi <= 'z') { 767be960424SJonas Devlieghere str.push_back(*osi); 768be960424SJonas Devlieghere } else { 769be960424SJonas Devlieghere switch (*osi) { 770be960424SJonas Devlieghere default: 771be960424SJonas Devlieghere if (str.empty()) { 772be960424SJonas Devlieghere return std::make_pair(Operand(), osi); 773be960424SJonas Devlieghere } else { 774be960424SJonas Devlieghere ret.m_register = ConstString(str); 775be960424SJonas Devlieghere return std::make_pair(ret, osi); 776be960424SJonas Devlieghere } 777be960424SJonas Devlieghere case '%': 778be960424SJonas Devlieghere if (!str.empty()) { 779be960424SJonas Devlieghere return std::make_pair(Operand(), osi); 780be960424SJonas Devlieghere } 781be960424SJonas Devlieghere break; 782be960424SJonas Devlieghere } 783be960424SJonas Devlieghere } 784be960424SJonas Devlieghere ++osi; 785be960424SJonas Devlieghere } 786be960424SJonas Devlieghere 787be960424SJonas Devlieghere ret.m_register = ConstString(str); 788be960424SJonas Devlieghere return std::make_pair(ret, osi); 789be960424SJonas Devlieghere } 790be960424SJonas Devlieghere 791be960424SJonas Devlieghere static std::pair<Operand, llvm::StringRef::const_iterator> 792be960424SJonas Devlieghere ParseImmediate(llvm::StringRef::const_iterator osi, 793be960424SJonas Devlieghere llvm::StringRef::const_iterator ose) { 794be960424SJonas Devlieghere Operand ret; 795be960424SJonas Devlieghere ret.m_type = Operand::Type::Immediate; 796be960424SJonas Devlieghere std::string str; 797be960424SJonas Devlieghere bool is_hex = false; 798be960424SJonas Devlieghere 799be960424SJonas Devlieghere osi = ConsumeWhitespace(osi, ose); 800be960424SJonas Devlieghere 801be960424SJonas Devlieghere while (osi != ose) { 802be960424SJonas Devlieghere if (*osi >= '0' && *osi <= '9') { 803be960424SJonas Devlieghere str.push_back(*osi); 804be960424SJonas Devlieghere } else if (*osi >= 'a' && *osi <= 'f') { 805be960424SJonas Devlieghere if (is_hex) { 806be960424SJonas Devlieghere str.push_back(*osi); 807be960424SJonas Devlieghere } else { 808be960424SJonas Devlieghere return std::make_pair(Operand(), osi); 809be960424SJonas Devlieghere } 810be960424SJonas Devlieghere } else { 811be960424SJonas Devlieghere switch (*osi) { 812be960424SJonas Devlieghere default: 813be960424SJonas Devlieghere if (str.empty()) { 814be960424SJonas Devlieghere return std::make_pair(Operand(), osi); 815be960424SJonas Devlieghere } else { 816be960424SJonas Devlieghere ret.m_immediate = strtoull(str.c_str(), nullptr, 0); 817be960424SJonas Devlieghere return std::make_pair(ret, osi); 818be960424SJonas Devlieghere } 819be960424SJonas Devlieghere case 'x': 820be960424SJonas Devlieghere if (!str.compare("0")) { 821be960424SJonas Devlieghere is_hex = true; 822be960424SJonas Devlieghere str.push_back(*osi); 823be960424SJonas Devlieghere } else { 824be960424SJonas Devlieghere return std::make_pair(Operand(), osi); 825be960424SJonas Devlieghere } 826be960424SJonas Devlieghere break; 827be960424SJonas Devlieghere case '#': 828be960424SJonas Devlieghere case '$': 829be960424SJonas Devlieghere if (!str.empty()) { 830be960424SJonas Devlieghere return std::make_pair(Operand(), osi); 831be960424SJonas Devlieghere } 832be960424SJonas Devlieghere break; 833be960424SJonas Devlieghere case '-': 834be960424SJonas Devlieghere if (str.empty()) { 835be960424SJonas Devlieghere ret.m_negative = true; 836be960424SJonas Devlieghere } else { 837be960424SJonas Devlieghere return std::make_pair(Operand(), osi); 838be960424SJonas Devlieghere } 839be960424SJonas Devlieghere } 840be960424SJonas Devlieghere } 841be960424SJonas Devlieghere ++osi; 842be960424SJonas Devlieghere } 843be960424SJonas Devlieghere 844be960424SJonas Devlieghere ret.m_immediate = strtoull(str.c_str(), nullptr, 0); 845be960424SJonas Devlieghere return std::make_pair(ret, osi); 846be960424SJonas Devlieghere } 847be960424SJonas Devlieghere 848be960424SJonas Devlieghere // -0x5(%rax,%rax,2) 849be960424SJonas Devlieghere static std::pair<Operand, llvm::StringRef::const_iterator> 850be960424SJonas Devlieghere ParseIntelIndexedAccess(llvm::StringRef::const_iterator osi, 851be960424SJonas Devlieghere llvm::StringRef::const_iterator ose) { 852be960424SJonas Devlieghere std::pair<Operand, llvm::StringRef::const_iterator> offset_and_iterator = 853be960424SJonas Devlieghere ParseImmediate(osi, ose); 854be960424SJonas Devlieghere if (offset_and_iterator.first.IsValid()) { 855be960424SJonas Devlieghere osi = offset_and_iterator.second; 856be960424SJonas Devlieghere } 857be960424SJonas Devlieghere 858be960424SJonas Devlieghere bool found = false; 859be960424SJonas Devlieghere std::tie(found, osi) = ConsumeChar(osi, '(', ose); 860be960424SJonas Devlieghere if (!found) { 861be960424SJonas Devlieghere return std::make_pair(Operand(), osi); 862be960424SJonas Devlieghere } 863be960424SJonas Devlieghere 864be960424SJonas Devlieghere std::pair<Operand, llvm::StringRef::const_iterator> base_and_iterator = 865be960424SJonas Devlieghere ParseRegisterName(osi, ose); 866be960424SJonas Devlieghere if (base_and_iterator.first.IsValid()) { 867be960424SJonas Devlieghere osi = base_and_iterator.second; 868be960424SJonas Devlieghere } else { 869be960424SJonas Devlieghere return std::make_pair(Operand(), osi); 870be960424SJonas Devlieghere } 871be960424SJonas Devlieghere 872be960424SJonas Devlieghere std::tie(found, osi) = ConsumeChar(osi, ',', ose); 873be960424SJonas Devlieghere if (!found) { 874be960424SJonas Devlieghere return std::make_pair(Operand(), osi); 875be960424SJonas Devlieghere } 876be960424SJonas Devlieghere 877be960424SJonas Devlieghere std::pair<Operand, llvm::StringRef::const_iterator> index_and_iterator = 878be960424SJonas Devlieghere ParseRegisterName(osi, ose); 879be960424SJonas Devlieghere if (index_and_iterator.first.IsValid()) { 880be960424SJonas Devlieghere osi = index_and_iterator.second; 881be960424SJonas Devlieghere } else { 882be960424SJonas Devlieghere return std::make_pair(Operand(), osi); 883be960424SJonas Devlieghere } 884be960424SJonas Devlieghere 885be960424SJonas Devlieghere std::tie(found, osi) = ConsumeChar(osi, ',', ose); 886be960424SJonas Devlieghere if (!found) { 887be960424SJonas Devlieghere return std::make_pair(Operand(), osi); 888be960424SJonas Devlieghere } 889be960424SJonas Devlieghere 890be960424SJonas Devlieghere std::pair<Operand, llvm::StringRef::const_iterator> 891be960424SJonas Devlieghere multiplier_and_iterator = ParseImmediate(osi, ose); 892be960424SJonas Devlieghere if (index_and_iterator.first.IsValid()) { 893be960424SJonas Devlieghere osi = index_and_iterator.second; 894be960424SJonas Devlieghere } else { 895be960424SJonas Devlieghere return std::make_pair(Operand(), osi); 896be960424SJonas Devlieghere } 897be960424SJonas Devlieghere 898be960424SJonas Devlieghere std::tie(found, osi) = ConsumeChar(osi, ')', ose); 899be960424SJonas Devlieghere if (!found) { 900be960424SJonas Devlieghere return std::make_pair(Operand(), osi); 901be960424SJonas Devlieghere } 902be960424SJonas Devlieghere 903be960424SJonas Devlieghere Operand product; 904be960424SJonas Devlieghere product.m_type = Operand::Type::Product; 905be960424SJonas Devlieghere product.m_children.push_back(index_and_iterator.first); 906be960424SJonas Devlieghere product.m_children.push_back(multiplier_and_iterator.first); 907be960424SJonas Devlieghere 908be960424SJonas Devlieghere Operand index; 909be960424SJonas Devlieghere index.m_type = Operand::Type::Sum; 910be960424SJonas Devlieghere index.m_children.push_back(base_and_iterator.first); 911be960424SJonas Devlieghere index.m_children.push_back(product); 912be960424SJonas Devlieghere 913be960424SJonas Devlieghere if (offset_and_iterator.first.IsValid()) { 914be960424SJonas Devlieghere Operand offset; 915be960424SJonas Devlieghere offset.m_type = Operand::Type::Sum; 916be960424SJonas Devlieghere offset.m_children.push_back(offset_and_iterator.first); 917be960424SJonas Devlieghere offset.m_children.push_back(index); 918be960424SJonas Devlieghere 919be960424SJonas Devlieghere Operand deref; 920be960424SJonas Devlieghere deref.m_type = Operand::Type::Dereference; 921be960424SJonas Devlieghere deref.m_children.push_back(offset); 922be960424SJonas Devlieghere return std::make_pair(deref, osi); 923be960424SJonas Devlieghere } else { 924be960424SJonas Devlieghere Operand deref; 925be960424SJonas Devlieghere deref.m_type = Operand::Type::Dereference; 926be960424SJonas Devlieghere deref.m_children.push_back(index); 927be960424SJonas Devlieghere return std::make_pair(deref, osi); 928be960424SJonas Devlieghere } 929be960424SJonas Devlieghere } 930be960424SJonas Devlieghere 931be960424SJonas Devlieghere // -0x10(%rbp) 932be960424SJonas Devlieghere static std::pair<Operand, llvm::StringRef::const_iterator> 933be960424SJonas Devlieghere ParseIntelDerefAccess(llvm::StringRef::const_iterator osi, 934be960424SJonas Devlieghere llvm::StringRef::const_iterator ose) { 935be960424SJonas Devlieghere std::pair<Operand, llvm::StringRef::const_iterator> offset_and_iterator = 936be960424SJonas Devlieghere ParseImmediate(osi, ose); 937be960424SJonas Devlieghere if (offset_and_iterator.first.IsValid()) { 938be960424SJonas Devlieghere osi = offset_and_iterator.second; 939be960424SJonas Devlieghere } 940be960424SJonas Devlieghere 941be960424SJonas Devlieghere bool found = false; 942be960424SJonas Devlieghere std::tie(found, osi) = ConsumeChar(osi, '(', ose); 943be960424SJonas Devlieghere if (!found) { 944be960424SJonas Devlieghere return std::make_pair(Operand(), osi); 945be960424SJonas Devlieghere } 946be960424SJonas Devlieghere 947be960424SJonas Devlieghere std::pair<Operand, llvm::StringRef::const_iterator> base_and_iterator = 948be960424SJonas Devlieghere ParseRegisterName(osi, ose); 949be960424SJonas Devlieghere if (base_and_iterator.first.IsValid()) { 950be960424SJonas Devlieghere osi = base_and_iterator.second; 951be960424SJonas Devlieghere } else { 952be960424SJonas Devlieghere return std::make_pair(Operand(), osi); 953be960424SJonas Devlieghere } 954be960424SJonas Devlieghere 955be960424SJonas Devlieghere std::tie(found, osi) = ConsumeChar(osi, ')', ose); 956be960424SJonas Devlieghere if (!found) { 957be960424SJonas Devlieghere return std::make_pair(Operand(), osi); 958be960424SJonas Devlieghere } 959be960424SJonas Devlieghere 960be960424SJonas Devlieghere if (offset_and_iterator.first.IsValid()) { 961be960424SJonas Devlieghere Operand offset; 962be960424SJonas Devlieghere offset.m_type = Operand::Type::Sum; 963be960424SJonas Devlieghere offset.m_children.push_back(offset_and_iterator.first); 964be960424SJonas Devlieghere offset.m_children.push_back(base_and_iterator.first); 965be960424SJonas Devlieghere 966be960424SJonas Devlieghere Operand deref; 967be960424SJonas Devlieghere deref.m_type = Operand::Type::Dereference; 968be960424SJonas Devlieghere deref.m_children.push_back(offset); 969be960424SJonas Devlieghere return std::make_pair(deref, osi); 970be960424SJonas Devlieghere } else { 971be960424SJonas Devlieghere Operand deref; 972be960424SJonas Devlieghere deref.m_type = Operand::Type::Dereference; 973be960424SJonas Devlieghere deref.m_children.push_back(base_and_iterator.first); 974be960424SJonas Devlieghere return std::make_pair(deref, osi); 975be960424SJonas Devlieghere } 976be960424SJonas Devlieghere } 977be960424SJonas Devlieghere 978be960424SJonas Devlieghere // [sp, #8]! 979be960424SJonas Devlieghere static std::pair<Operand, llvm::StringRef::const_iterator> 980be960424SJonas Devlieghere ParseARMOffsetAccess(llvm::StringRef::const_iterator osi, 981be960424SJonas Devlieghere llvm::StringRef::const_iterator ose) { 982be960424SJonas Devlieghere bool found = false; 983be960424SJonas Devlieghere std::tie(found, osi) = ConsumeChar(osi, '[', ose); 984be960424SJonas Devlieghere if (!found) { 985be960424SJonas Devlieghere return std::make_pair(Operand(), osi); 986be960424SJonas Devlieghere } 987be960424SJonas Devlieghere 988be960424SJonas Devlieghere std::pair<Operand, llvm::StringRef::const_iterator> base_and_iterator = 989be960424SJonas Devlieghere ParseRegisterName(osi, ose); 990be960424SJonas Devlieghere if (base_and_iterator.first.IsValid()) { 991be960424SJonas Devlieghere osi = base_and_iterator.second; 992be960424SJonas Devlieghere } else { 993be960424SJonas Devlieghere return std::make_pair(Operand(), osi); 994be960424SJonas Devlieghere } 995be960424SJonas Devlieghere 996be960424SJonas Devlieghere std::tie(found, osi) = ConsumeChar(osi, ',', ose); 997be960424SJonas Devlieghere if (!found) { 998be960424SJonas Devlieghere return std::make_pair(Operand(), osi); 999be960424SJonas Devlieghere } 1000be960424SJonas Devlieghere 1001be960424SJonas Devlieghere std::pair<Operand, llvm::StringRef::const_iterator> offset_and_iterator = 1002be960424SJonas Devlieghere ParseImmediate(osi, ose); 1003be960424SJonas Devlieghere if (offset_and_iterator.first.IsValid()) { 1004be960424SJonas Devlieghere osi = offset_and_iterator.second; 1005be960424SJonas Devlieghere } 1006be960424SJonas Devlieghere 1007be960424SJonas Devlieghere std::tie(found, osi) = ConsumeChar(osi, ']', ose); 1008be960424SJonas Devlieghere if (!found) { 1009be960424SJonas Devlieghere return std::make_pair(Operand(), osi); 1010be960424SJonas Devlieghere } 1011be960424SJonas Devlieghere 1012be960424SJonas Devlieghere Operand offset; 1013be960424SJonas Devlieghere offset.m_type = Operand::Type::Sum; 1014be960424SJonas Devlieghere offset.m_children.push_back(offset_and_iterator.first); 1015be960424SJonas Devlieghere offset.m_children.push_back(base_and_iterator.first); 1016be960424SJonas Devlieghere 1017be960424SJonas Devlieghere Operand deref; 1018be960424SJonas Devlieghere deref.m_type = Operand::Type::Dereference; 1019be960424SJonas Devlieghere deref.m_children.push_back(offset); 1020be960424SJonas Devlieghere return std::make_pair(deref, osi); 1021be960424SJonas Devlieghere } 1022be960424SJonas Devlieghere 1023be960424SJonas Devlieghere // [sp] 1024be960424SJonas Devlieghere static std::pair<Operand, llvm::StringRef::const_iterator> 1025be960424SJonas Devlieghere ParseARMDerefAccess(llvm::StringRef::const_iterator osi, 1026be960424SJonas Devlieghere llvm::StringRef::const_iterator ose) { 1027be960424SJonas Devlieghere bool found = false; 1028be960424SJonas Devlieghere std::tie(found, osi) = ConsumeChar(osi, '[', ose); 1029be960424SJonas Devlieghere if (!found) { 1030be960424SJonas Devlieghere return std::make_pair(Operand(), osi); 1031be960424SJonas Devlieghere } 1032be960424SJonas Devlieghere 1033be960424SJonas Devlieghere std::pair<Operand, llvm::StringRef::const_iterator> base_and_iterator = 1034be960424SJonas Devlieghere ParseRegisterName(osi, ose); 1035be960424SJonas Devlieghere if (base_and_iterator.first.IsValid()) { 1036be960424SJonas Devlieghere osi = base_and_iterator.second; 1037be960424SJonas Devlieghere } else { 1038be960424SJonas Devlieghere return std::make_pair(Operand(), osi); 1039be960424SJonas Devlieghere } 1040be960424SJonas Devlieghere 1041be960424SJonas Devlieghere std::tie(found, osi) = ConsumeChar(osi, ']', ose); 1042be960424SJonas Devlieghere if (!found) { 1043be960424SJonas Devlieghere return std::make_pair(Operand(), osi); 1044be960424SJonas Devlieghere } 1045be960424SJonas Devlieghere 1046be960424SJonas Devlieghere Operand deref; 1047be960424SJonas Devlieghere deref.m_type = Operand::Type::Dereference; 1048be960424SJonas Devlieghere deref.m_children.push_back(base_and_iterator.first); 1049be960424SJonas Devlieghere return std::make_pair(deref, osi); 1050be960424SJonas Devlieghere } 1051be960424SJonas Devlieghere 1052be960424SJonas Devlieghere static void DumpOperand(const Operand &op, Stream &s) { 1053be960424SJonas Devlieghere switch (op.m_type) { 1054be960424SJonas Devlieghere case Operand::Type::Dereference: 1055be960424SJonas Devlieghere s.PutCString("*"); 1056be960424SJonas Devlieghere DumpOperand(op.m_children[0], s); 1057be960424SJonas Devlieghere break; 1058be960424SJonas Devlieghere case Operand::Type::Immediate: 1059be960424SJonas Devlieghere if (op.m_negative) { 1060be960424SJonas Devlieghere s.PutCString("-"); 1061be960424SJonas Devlieghere } 1062be960424SJonas Devlieghere s.PutCString(llvm::to_string(op.m_immediate)); 1063be960424SJonas Devlieghere break; 1064be960424SJonas Devlieghere case Operand::Type::Invalid: 1065be960424SJonas Devlieghere s.PutCString("Invalid"); 1066be960424SJonas Devlieghere break; 1067be960424SJonas Devlieghere case Operand::Type::Product: 1068be960424SJonas Devlieghere s.PutCString("("); 1069be960424SJonas Devlieghere DumpOperand(op.m_children[0], s); 1070be960424SJonas Devlieghere s.PutCString("*"); 1071be960424SJonas Devlieghere DumpOperand(op.m_children[1], s); 1072be960424SJonas Devlieghere s.PutCString(")"); 1073be960424SJonas Devlieghere break; 1074be960424SJonas Devlieghere case Operand::Type::Register: 1075642bc15dSRaphael Isemann s.PutCString(op.m_register.GetStringRef()); 1076be960424SJonas Devlieghere break; 1077be960424SJonas Devlieghere case Operand::Type::Sum: 1078be960424SJonas Devlieghere s.PutCString("("); 1079be960424SJonas Devlieghere DumpOperand(op.m_children[0], s); 1080be960424SJonas Devlieghere s.PutCString("+"); 1081be960424SJonas Devlieghere DumpOperand(op.m_children[1], s); 1082be960424SJonas Devlieghere s.PutCString(")"); 1083be960424SJonas Devlieghere break; 1084be960424SJonas Devlieghere } 1085be960424SJonas Devlieghere } 1086be960424SJonas Devlieghere 1087be960424SJonas Devlieghere bool ParseOperands( 1088be960424SJonas Devlieghere llvm::SmallVectorImpl<Instruction::Operand> &operands) override { 1089be960424SJonas Devlieghere const char *operands_string = GetOperands(nullptr); 1090be960424SJonas Devlieghere 1091be960424SJonas Devlieghere if (!operands_string) { 1092be960424SJonas Devlieghere return false; 1093be960424SJonas Devlieghere } 1094be960424SJonas Devlieghere 1095be960424SJonas Devlieghere llvm::StringRef operands_ref(operands_string); 1096be960424SJonas Devlieghere 1097be960424SJonas Devlieghere llvm::StringRef::const_iterator osi = operands_ref.begin(); 1098be960424SJonas Devlieghere llvm::StringRef::const_iterator ose = operands_ref.end(); 1099be960424SJonas Devlieghere 1100be960424SJonas Devlieghere while (osi != ose) { 1101be960424SJonas Devlieghere Operand operand; 1102be960424SJonas Devlieghere llvm::StringRef::const_iterator iter; 1103be960424SJonas Devlieghere 1104be960424SJonas Devlieghere if ((std::tie(operand, iter) = ParseIntelIndexedAccess(osi, ose), 1105be960424SJonas Devlieghere operand.IsValid()) || 1106be960424SJonas Devlieghere (std::tie(operand, iter) = ParseIntelDerefAccess(osi, ose), 1107be960424SJonas Devlieghere operand.IsValid()) || 1108be960424SJonas Devlieghere (std::tie(operand, iter) = ParseARMOffsetAccess(osi, ose), 1109be960424SJonas Devlieghere operand.IsValid()) || 1110be960424SJonas Devlieghere (std::tie(operand, iter) = ParseARMDerefAccess(osi, ose), 1111be960424SJonas Devlieghere operand.IsValid()) || 1112be960424SJonas Devlieghere (std::tie(operand, iter) = ParseRegisterName(osi, ose), 1113be960424SJonas Devlieghere operand.IsValid()) || 1114be960424SJonas Devlieghere (std::tie(operand, iter) = ParseImmediate(osi, ose), 1115be960424SJonas Devlieghere operand.IsValid())) { 1116be960424SJonas Devlieghere osi = iter; 1117be960424SJonas Devlieghere operands.push_back(operand); 1118be960424SJonas Devlieghere } else { 1119be960424SJonas Devlieghere return false; 1120be960424SJonas Devlieghere } 1121be960424SJonas Devlieghere 1122be960424SJonas Devlieghere std::pair<bool, llvm::StringRef::const_iterator> found_and_iter = 1123be960424SJonas Devlieghere ConsumeChar(osi, ',', ose); 1124be960424SJonas Devlieghere if (found_and_iter.first) { 1125be960424SJonas Devlieghere osi = found_and_iter.second; 1126be960424SJonas Devlieghere } 1127be960424SJonas Devlieghere 1128be960424SJonas Devlieghere osi = ConsumeWhitespace(osi, ose); 1129be960424SJonas Devlieghere } 1130be960424SJonas Devlieghere 1131be960424SJonas Devlieghere DisassemblerSP disasm_sp = m_disasm_wp.lock(); 1132be960424SJonas Devlieghere 1133be960424SJonas Devlieghere if (disasm_sp && operands.size() > 1) { 1134be960424SJonas Devlieghere // TODO tie this into the MC Disassembler's notion of clobbers. 1135be960424SJonas Devlieghere switch (disasm_sp->GetArchitecture().GetMachine()) { 1136be960424SJonas Devlieghere default: 1137be960424SJonas Devlieghere break; 1138be960424SJonas Devlieghere case llvm::Triple::x86: 1139be960424SJonas Devlieghere case llvm::Triple::x86_64: 1140be960424SJonas Devlieghere operands[operands.size() - 1].m_clobbered = true; 1141be960424SJonas Devlieghere break; 1142be960424SJonas Devlieghere case llvm::Triple::arm: 1143be960424SJonas Devlieghere operands[0].m_clobbered = true; 1144be960424SJonas Devlieghere break; 1145be960424SJonas Devlieghere } 1146be960424SJonas Devlieghere } 1147be960424SJonas Devlieghere 1148a007a6d8SPavel Labath if (Log *log = GetLog(LLDBLog::Process)) { 1149be960424SJonas Devlieghere StreamString ss; 1150be960424SJonas Devlieghere 1151be960424SJonas Devlieghere ss.Printf("[%s] expands to %zu operands:\n", operands_string, 1152be960424SJonas Devlieghere operands.size()); 1153be960424SJonas Devlieghere for (const Operand &operand : operands) { 1154be960424SJonas Devlieghere ss.PutCString(" "); 1155be960424SJonas Devlieghere DumpOperand(operand, ss); 1156be960424SJonas Devlieghere ss.PutCString("\n"); 1157be960424SJonas Devlieghere } 1158be960424SJonas Devlieghere 1159be960424SJonas Devlieghere log->PutString(ss.GetString()); 1160be960424SJonas Devlieghere } 1161be960424SJonas Devlieghere 1162be960424SJonas Devlieghere return true; 1163be960424SJonas Devlieghere } 1164be960424SJonas Devlieghere 1165be960424SJonas Devlieghere bool IsCall() override { 1166009e3e53SVedant Kumar VisitInstruction(); 1167009e3e53SVedant Kumar return m_is_call; 1168009e3e53SVedant Kumar } 1169009e3e53SVedant Kumar 1170009e3e53SVedant Kumar protected: 1171009e3e53SVedant Kumar std::weak_ptr<DisassemblerLLVMC> m_disasm_wp; 1172009e3e53SVedant Kumar 1173009e3e53SVedant Kumar bool m_is_valid = false; 117428c878aeSShafik Yaghmour bool m_using_file_addr = false; 1175009e3e53SVedant Kumar bool m_has_visited_instruction = false; 1176009e3e53SVedant Kumar 1177009e3e53SVedant Kumar // Be conservative. If we didn't understand the instruction, say it: 1178009e3e53SVedant Kumar // - Might branch 1179009e3e53SVedant Kumar // - Does not have a delay slot 1180009e3e53SVedant Kumar // - Is not a call 118166902a32SVedant Kumar // - Is not a load 118266902a32SVedant Kumar // - Is not an authenticated instruction 1183009e3e53SVedant Kumar bool m_does_branch = true; 1184009e3e53SVedant Kumar bool m_has_delay_slot = false; 1185009e3e53SVedant Kumar bool m_is_call = false; 118666902a32SVedant Kumar bool m_is_load = false; 118766902a32SVedant Kumar bool m_is_authenticated = false; 1188009e3e53SVedant Kumar 1189009e3e53SVedant Kumar void VisitInstruction() { 1190009e3e53SVedant Kumar if (m_has_visited_instruction) 1191009e3e53SVedant Kumar return; 1192009e3e53SVedant Kumar 1193be960424SJonas Devlieghere DisassemblerScope disasm(*this); 1194009e3e53SVedant Kumar if (!disasm) 1195009e3e53SVedant Kumar return; 1196009e3e53SVedant Kumar 1197be960424SJonas Devlieghere DataExtractor data; 1198009e3e53SVedant Kumar if (!m_opcode.GetData(data)) 1199009e3e53SVedant Kumar return; 1200009e3e53SVedant Kumar 1201be960424SJonas Devlieghere bool is_alternate_isa; 1202be960424SJonas Devlieghere lldb::addr_t pc = m_address.GetFileAddress(); 1203be960424SJonas Devlieghere DisassemblerLLVMC::MCDisasmInstance *mc_disasm_ptr = 1204be960424SJonas Devlieghere GetDisasmToUse(is_alternate_isa, disasm); 1205be960424SJonas Devlieghere const uint8_t *opcode_data = data.GetDataStart(); 1206be960424SJonas Devlieghere const size_t opcode_data_len = data.GetByteSize(); 1207be960424SJonas Devlieghere llvm::MCInst inst; 1208be960424SJonas Devlieghere const size_t inst_size = 1209be960424SJonas Devlieghere mc_disasm_ptr->GetMCInst(opcode_data, opcode_data_len, pc, inst); 1210009e3e53SVedant Kumar if (inst_size == 0) 1211009e3e53SVedant Kumar return; 1212be960424SJonas Devlieghere 1213009e3e53SVedant Kumar m_has_visited_instruction = true; 1214009e3e53SVedant Kumar m_does_branch = mc_disasm_ptr->CanBranch(inst); 1215009e3e53SVedant Kumar m_has_delay_slot = mc_disasm_ptr->HasDelaySlot(inst); 1216009e3e53SVedant Kumar m_is_call = mc_disasm_ptr->IsCall(inst); 121766902a32SVedant Kumar m_is_load = mc_disasm_ptr->IsLoad(inst); 121866902a32SVedant Kumar m_is_authenticated = mc_disasm_ptr->IsAuthenticated(inst); 1219009e3e53SVedant Kumar } 1220be960424SJonas Devlieghere 1221be960424SJonas Devlieghere private: 1222be960424SJonas Devlieghere DisassemblerLLVMC::MCDisasmInstance * 1223be960424SJonas Devlieghere GetDisasmToUse(bool &is_alternate_isa, DisassemblerScope &disasm) { 1224be960424SJonas Devlieghere is_alternate_isa = false; 1225be960424SJonas Devlieghere if (disasm) { 1226be960424SJonas Devlieghere if (disasm->m_alternate_disasm_up) { 1227be960424SJonas Devlieghere const AddressClass address_class = GetAddressClass(); 1228be960424SJonas Devlieghere 1229be960424SJonas Devlieghere if (address_class == AddressClass::eCodeAlternateISA) { 1230be960424SJonas Devlieghere is_alternate_isa = true; 1231be960424SJonas Devlieghere return disasm->m_alternate_disasm_up.get(); 1232be960424SJonas Devlieghere } 1233be960424SJonas Devlieghere } 1234be960424SJonas Devlieghere return disasm->m_disasm_up.get(); 1235be960424SJonas Devlieghere } 1236be960424SJonas Devlieghere return nullptr; 1237be960424SJonas Devlieghere } 1238be960424SJonas Devlieghere }; 1239be960424SJonas Devlieghere 1240be960424SJonas Devlieghere std::unique_ptr<DisassemblerLLVMC::MCDisasmInstance> 1241be960424SJonas Devlieghere DisassemblerLLVMC::MCDisasmInstance::Create(const char *triple, const char *cpu, 1242be960424SJonas Devlieghere const char *features_str, 1243be960424SJonas Devlieghere unsigned flavor, 1244be960424SJonas Devlieghere DisassemblerLLVMC &owner) { 1245be960424SJonas Devlieghere using Instance = std::unique_ptr<DisassemblerLLVMC::MCDisasmInstance>; 1246be960424SJonas Devlieghere 1247be960424SJonas Devlieghere std::string Status; 1248be960424SJonas Devlieghere const llvm::Target *curr_target = 1249be960424SJonas Devlieghere llvm::TargetRegistry::lookupTarget(triple, Status); 1250be960424SJonas Devlieghere if (!curr_target) 1251be960424SJonas Devlieghere return Instance(); 1252be960424SJonas Devlieghere 1253be960424SJonas Devlieghere std::unique_ptr<llvm::MCInstrInfo> instr_info_up( 1254be960424SJonas Devlieghere curr_target->createMCInstrInfo()); 1255be960424SJonas Devlieghere if (!instr_info_up) 1256be960424SJonas Devlieghere return Instance(); 1257be960424SJonas Devlieghere 1258be960424SJonas Devlieghere std::unique_ptr<llvm::MCRegisterInfo> reg_info_up( 1259be960424SJonas Devlieghere curr_target->createMCRegInfo(triple)); 1260be960424SJonas Devlieghere if (!reg_info_up) 1261be960424SJonas Devlieghere return Instance(); 1262be960424SJonas Devlieghere 1263be960424SJonas Devlieghere std::unique_ptr<llvm::MCSubtargetInfo> subtarget_info_up( 1264be960424SJonas Devlieghere curr_target->createMCSubtargetInfo(triple, cpu, features_str)); 1265be960424SJonas Devlieghere if (!subtarget_info_up) 1266be960424SJonas Devlieghere return Instance(); 1267be960424SJonas Devlieghere 1268be960424SJonas Devlieghere llvm::MCTargetOptions MCOptions; 1269be960424SJonas Devlieghere std::unique_ptr<llvm::MCAsmInfo> asm_info_up( 1270be960424SJonas Devlieghere curr_target->createMCAsmInfo(*reg_info_up, triple, MCOptions)); 1271be960424SJonas Devlieghere if (!asm_info_up) 1272be960424SJonas Devlieghere return Instance(); 1273be960424SJonas Devlieghere 1274c2f819afSPhilipp Krones std::unique_ptr<llvm::MCContext> context_up( 1275c2f819afSPhilipp Krones new llvm::MCContext(llvm::Triple(triple), asm_info_up.get(), 1276c2f819afSPhilipp Krones reg_info_up.get(), subtarget_info_up.get())); 1277be960424SJonas Devlieghere if (!context_up) 1278be960424SJonas Devlieghere return Instance(); 1279be960424SJonas Devlieghere 1280be960424SJonas Devlieghere std::unique_ptr<llvm::MCDisassembler> disasm_up( 1281be960424SJonas Devlieghere curr_target->createMCDisassembler(*subtarget_info_up, *context_up)); 1282be960424SJonas Devlieghere if (!disasm_up) 1283be960424SJonas Devlieghere return Instance(); 1284be960424SJonas Devlieghere 1285be960424SJonas Devlieghere std::unique_ptr<llvm::MCRelocationInfo> rel_info_up( 1286be960424SJonas Devlieghere curr_target->createMCRelocationInfo(triple, *context_up)); 1287be960424SJonas Devlieghere if (!rel_info_up) 1288be960424SJonas Devlieghere return Instance(); 1289be960424SJonas Devlieghere 1290be960424SJonas Devlieghere std::unique_ptr<llvm::MCSymbolizer> symbolizer_up( 1291be960424SJonas Devlieghere curr_target->createMCSymbolizer( 1292be960424SJonas Devlieghere triple, nullptr, DisassemblerLLVMC::SymbolLookupCallback, &owner, 1293be960424SJonas Devlieghere context_up.get(), std::move(rel_info_up))); 1294be960424SJonas Devlieghere disasm_up->setSymbolizer(std::move(symbolizer_up)); 1295be960424SJonas Devlieghere 1296be960424SJonas Devlieghere unsigned asm_printer_variant = 1297be960424SJonas Devlieghere flavor == ~0U ? asm_info_up->getAssemblerDialect() : flavor; 1298be960424SJonas Devlieghere 1299be960424SJonas Devlieghere std::unique_ptr<llvm::MCInstPrinter> instr_printer_up( 1300be960424SJonas Devlieghere curr_target->createMCInstPrinter(llvm::Triple{triple}, 1301be960424SJonas Devlieghere asm_printer_variant, *asm_info_up, 1302be960424SJonas Devlieghere *instr_info_up, *reg_info_up)); 1303be960424SJonas Devlieghere if (!instr_printer_up) 1304be960424SJonas Devlieghere return Instance(); 1305be960424SJonas Devlieghere 1306523110d6STed Woodward instr_printer_up->setPrintBranchImmAsAddress(true); 1307523110d6STed Woodward 1308254a3127SVenkata Ramanaiah Nalamothu // Not all targets may have registered createMCInstrAnalysis(). 1309254a3127SVenkata Ramanaiah Nalamothu std::unique_ptr<llvm::MCInstrAnalysis> instr_analysis_up( 1310254a3127SVenkata Ramanaiah Nalamothu curr_target->createMCInstrAnalysis(instr_info_up.get())); 1311254a3127SVenkata Ramanaiah Nalamothu 1312254a3127SVenkata Ramanaiah Nalamothu return Instance(new MCDisasmInstance( 1313254a3127SVenkata Ramanaiah Nalamothu std::move(instr_info_up), std::move(reg_info_up), 1314be960424SJonas Devlieghere std::move(subtarget_info_up), std::move(asm_info_up), 1315254a3127SVenkata Ramanaiah Nalamothu std::move(context_up), std::move(disasm_up), std::move(instr_printer_up), 1316254a3127SVenkata Ramanaiah Nalamothu std::move(instr_analysis_up))); 1317be960424SJonas Devlieghere } 1318be960424SJonas Devlieghere 1319be960424SJonas Devlieghere DisassemblerLLVMC::MCDisasmInstance::MCDisasmInstance( 1320be960424SJonas Devlieghere std::unique_ptr<llvm::MCInstrInfo> &&instr_info_up, 1321be960424SJonas Devlieghere std::unique_ptr<llvm::MCRegisterInfo> &®_info_up, 1322be960424SJonas Devlieghere std::unique_ptr<llvm::MCSubtargetInfo> &&subtarget_info_up, 1323be960424SJonas Devlieghere std::unique_ptr<llvm::MCAsmInfo> &&asm_info_up, 1324be960424SJonas Devlieghere std::unique_ptr<llvm::MCContext> &&context_up, 1325be960424SJonas Devlieghere std::unique_ptr<llvm::MCDisassembler> &&disasm_up, 1326254a3127SVenkata Ramanaiah Nalamothu std::unique_ptr<llvm::MCInstPrinter> &&instr_printer_up, 1327254a3127SVenkata Ramanaiah Nalamothu std::unique_ptr<llvm::MCInstrAnalysis> &&instr_analysis_up) 1328be960424SJonas Devlieghere : m_instr_info_up(std::move(instr_info_up)), 1329be960424SJonas Devlieghere m_reg_info_up(std::move(reg_info_up)), 1330be960424SJonas Devlieghere m_subtarget_info_up(std::move(subtarget_info_up)), 1331be960424SJonas Devlieghere m_asm_info_up(std::move(asm_info_up)), 1332be960424SJonas Devlieghere m_context_up(std::move(context_up)), m_disasm_up(std::move(disasm_up)), 1333254a3127SVenkata Ramanaiah Nalamothu m_instr_printer_up(std::move(instr_printer_up)), 1334254a3127SVenkata Ramanaiah Nalamothu m_instr_analysis_up(std::move(instr_analysis_up)) { 1335be960424SJonas Devlieghere assert(m_instr_info_up && m_reg_info_up && m_subtarget_info_up && 1336be960424SJonas Devlieghere m_asm_info_up && m_context_up && m_disasm_up && m_instr_printer_up); 1337be960424SJonas Devlieghere } 1338be960424SJonas Devlieghere 1339be960424SJonas Devlieghere uint64_t DisassemblerLLVMC::MCDisasmInstance::GetMCInst( 1340be960424SJonas Devlieghere const uint8_t *opcode_data, size_t opcode_data_len, lldb::addr_t pc, 1341be960424SJonas Devlieghere llvm::MCInst &mc_inst) const { 1342be960424SJonas Devlieghere llvm::ArrayRef<uint8_t> data(opcode_data, opcode_data_len); 1343be960424SJonas Devlieghere llvm::MCDisassembler::DecodeStatus status; 1344be960424SJonas Devlieghere 1345be960424SJonas Devlieghere uint64_t new_inst_size; 1346be960424SJonas Devlieghere status = m_disasm_up->getInstruction(mc_inst, new_inst_size, data, pc, 1347be960424SJonas Devlieghere llvm::nulls()); 1348be960424SJonas Devlieghere if (status == llvm::MCDisassembler::Success) 1349be960424SJonas Devlieghere return new_inst_size; 1350be960424SJonas Devlieghere else 1351be960424SJonas Devlieghere return 0; 1352be960424SJonas Devlieghere } 1353be960424SJonas Devlieghere 1354be960424SJonas Devlieghere void DisassemblerLLVMC::MCDisasmInstance::PrintMCInst( 1355523110d6STed Woodward llvm::MCInst &mc_inst, lldb::addr_t pc, std::string &inst_string, 1356be960424SJonas Devlieghere std::string &comments_string) { 1357be960424SJonas Devlieghere llvm::raw_string_ostream inst_stream(inst_string); 1358be960424SJonas Devlieghere llvm::raw_string_ostream comments_stream(comments_string); 1359be960424SJonas Devlieghere 1360a69f78b0SJonas Devlieghere inst_stream.enable_colors(m_instr_printer_up->getUseColor()); 1361be960424SJonas Devlieghere m_instr_printer_up->setCommentStream(comments_stream); 1362523110d6STed Woodward m_instr_printer_up->printInst(&mc_inst, pc, llvm::StringRef(), 1363be960424SJonas Devlieghere *m_subtarget_info_up, inst_stream); 1364be960424SJonas Devlieghere m_instr_printer_up->setCommentStream(llvm::nulls()); 1365a69f78b0SJonas Devlieghere 1366be960424SJonas Devlieghere static std::string g_newlines("\r\n"); 1367be960424SJonas Devlieghere 1368be960424SJonas Devlieghere for (size_t newline_pos = 0; 1369be960424SJonas Devlieghere (newline_pos = comments_string.find_first_of(g_newlines, newline_pos)) != 1370be960424SJonas Devlieghere comments_string.npos; 1371be960424SJonas Devlieghere /**/) { 1372be960424SJonas Devlieghere comments_string.replace(comments_string.begin() + newline_pos, 1373be960424SJonas Devlieghere comments_string.begin() + newline_pos + 1, 1, ' '); 1374be960424SJonas Devlieghere } 1375be960424SJonas Devlieghere } 1376be960424SJonas Devlieghere 1377be960424SJonas Devlieghere void DisassemblerLLVMC::MCDisasmInstance::SetStyle( 1378be960424SJonas Devlieghere bool use_hex_immed, HexImmediateStyle hex_style) { 1379be960424SJonas Devlieghere m_instr_printer_up->setPrintImmHex(use_hex_immed); 1380be960424SJonas Devlieghere switch (hex_style) { 1381be960424SJonas Devlieghere case eHexStyleC: 1382be960424SJonas Devlieghere m_instr_printer_up->setPrintHexStyle(llvm::HexStyle::C); 1383be960424SJonas Devlieghere break; 1384be960424SJonas Devlieghere case eHexStyleAsm: 1385be960424SJonas Devlieghere m_instr_printer_up->setPrintHexStyle(llvm::HexStyle::Asm); 1386be960424SJonas Devlieghere break; 1387be960424SJonas Devlieghere } 1388be960424SJonas Devlieghere } 1389be960424SJonas Devlieghere 1390a69f78b0SJonas Devlieghere void DisassemblerLLVMC::MCDisasmInstance::SetUseColor(bool use_color) { 1391a69f78b0SJonas Devlieghere m_instr_printer_up->setUseColor(use_color); 1392a69f78b0SJonas Devlieghere } 1393a69f78b0SJonas Devlieghere 1394a69f78b0SJonas Devlieghere bool DisassemblerLLVMC::MCDisasmInstance::GetUseColor() const { 1395a69f78b0SJonas Devlieghere return m_instr_printer_up->getUseColor(); 1396a69f78b0SJonas Devlieghere } 1397a69f78b0SJonas Devlieghere 1398be960424SJonas Devlieghere bool DisassemblerLLVMC::MCDisasmInstance::CanBranch( 1399be960424SJonas Devlieghere llvm::MCInst &mc_inst) const { 1400254a3127SVenkata Ramanaiah Nalamothu if (m_instr_analysis_up) 1401254a3127SVenkata Ramanaiah Nalamothu return m_instr_analysis_up->mayAffectControlFlow(mc_inst, *m_reg_info_up); 1402be960424SJonas Devlieghere return m_instr_info_up->get(mc_inst.getOpcode()) 1403be960424SJonas Devlieghere .mayAffectControlFlow(mc_inst, *m_reg_info_up); 1404be960424SJonas Devlieghere } 1405be960424SJonas Devlieghere 1406be960424SJonas Devlieghere bool DisassemblerLLVMC::MCDisasmInstance::HasDelaySlot( 1407be960424SJonas Devlieghere llvm::MCInst &mc_inst) const { 1408be960424SJonas Devlieghere return m_instr_info_up->get(mc_inst.getOpcode()).hasDelaySlot(); 1409be960424SJonas Devlieghere } 1410be960424SJonas Devlieghere 1411be960424SJonas Devlieghere bool DisassemblerLLVMC::MCDisasmInstance::IsCall(llvm::MCInst &mc_inst) const { 1412254a3127SVenkata Ramanaiah Nalamothu if (m_instr_analysis_up) 1413254a3127SVenkata Ramanaiah Nalamothu return m_instr_analysis_up->isCall(mc_inst); 1414be960424SJonas Devlieghere return m_instr_info_up->get(mc_inst.getOpcode()).isCall(); 1415be960424SJonas Devlieghere } 1416be960424SJonas Devlieghere 141766902a32SVedant Kumar bool DisassemblerLLVMC::MCDisasmInstance::IsLoad(llvm::MCInst &mc_inst) const { 141866902a32SVedant Kumar return m_instr_info_up->get(mc_inst.getOpcode()).mayLoad(); 141966902a32SVedant Kumar } 142066902a32SVedant Kumar 142166902a32SVedant Kumar bool DisassemblerLLVMC::MCDisasmInstance::IsAuthenticated( 142266902a32SVedant Kumar llvm::MCInst &mc_inst) const { 1423291a7fcfSJay Foad const auto &InstrDesc = m_instr_info_up->get(mc_inst.getOpcode()); 142466902a32SVedant Kumar 142566902a32SVedant Kumar // Treat software auth traps (brk 0xc470 + aut key, where 0x70 == 'p', 0xc4 142666902a32SVedant Kumar // == 'a' + 'c') as authenticated instructions for reporting purposes, in 142766902a32SVedant Kumar // addition to the standard authenticated instructions specified in ARMv8.3. 142866902a32SVedant Kumar bool IsBrkC47x = false; 142966902a32SVedant Kumar if (InstrDesc.isTrap() && mc_inst.getNumOperands() == 1) { 143066902a32SVedant Kumar const llvm::MCOperand &Op0 = mc_inst.getOperand(0); 143166902a32SVedant Kumar if (Op0.isImm() && Op0.getImm() >= 0xc470 && Op0.getImm() <= 0xc474) 143266902a32SVedant Kumar IsBrkC47x = true; 143366902a32SVedant Kumar } 143466902a32SVedant Kumar 143566902a32SVedant Kumar return InstrDesc.isAuthenticated() || IsBrkC47x; 143666902a32SVedant Kumar } 143766902a32SVedant Kumar 1438be960424SJonas Devlieghere DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch, 1439f109517dSJonas Devlieghere const char *flavor_string, 1440f109517dSJonas Devlieghere const char *cpu_string, 1441f109517dSJonas Devlieghere const char *features_string) 1442be960424SJonas Devlieghere : Disassembler(arch, flavor_string), m_exe_ctx(nullptr), m_inst(nullptr), 14437150b562SJason Molenda m_data_from_file(false), m_adrp_address(LLDB_INVALID_ADDRESS), 14447150b562SJason Molenda m_adrp_insn() { 1445be960424SJonas Devlieghere if (!FlavorValidForArchSpec(arch, m_flavor.c_str())) { 1446be960424SJonas Devlieghere m_flavor.assign("default"); 1447be960424SJonas Devlieghere } 1448be960424SJonas Devlieghere 1449f109517dSJonas Devlieghere const bool cpu_or_features_overriden = cpu_string || features_string; 1450be960424SJonas Devlieghere unsigned flavor = ~0U; 1451be960424SJonas Devlieghere llvm::Triple triple = arch.GetTriple(); 1452be960424SJonas Devlieghere 1453be960424SJonas Devlieghere // So far the only supported flavor is "intel" on x86. The base class will 1454be960424SJonas Devlieghere // set this correctly coming in. 1455be960424SJonas Devlieghere if (triple.getArch() == llvm::Triple::x86 || 1456be960424SJonas Devlieghere triple.getArch() == llvm::Triple::x86_64) { 1457be960424SJonas Devlieghere if (m_flavor == "intel") { 1458be960424SJonas Devlieghere flavor = 1; 1459be960424SJonas Devlieghere } else if (m_flavor == "att") { 1460be960424SJonas Devlieghere flavor = 0; 1461be960424SJonas Devlieghere } 1462be960424SJonas Devlieghere } 1463be960424SJonas Devlieghere 1464be960424SJonas Devlieghere ArchSpec thumb_arch(arch); 1465be960424SJonas Devlieghere if (triple.getArch() == llvm::Triple::arm) { 1466be960424SJonas Devlieghere std::string thumb_arch_name(thumb_arch.GetTriple().getArchName().str()); 1467be960424SJonas Devlieghere // Replace "arm" with "thumb" so we get all thumb variants correct 1468be960424SJonas Devlieghere if (thumb_arch_name.size() > 3) { 1469be960424SJonas Devlieghere thumb_arch_name.erase(0, 3); 1470be960424SJonas Devlieghere thumb_arch_name.insert(0, "thumb"); 1471be960424SJonas Devlieghere } else { 1472d1c124e6SDavid Spickett thumb_arch_name = "thumbv9.3a"; 1473be960424SJonas Devlieghere } 1474be960424SJonas Devlieghere thumb_arch.GetTriple().setArchName(llvm::StringRef(thumb_arch_name)); 1475be960424SJonas Devlieghere } 1476be960424SJonas Devlieghere 1477be960424SJonas Devlieghere // If no sub architecture specified then use the most recent arm architecture 1478d1c124e6SDavid Spickett // so the disassembler will return all instructions. Without it we will see a 1479d1c124e6SDavid Spickett // lot of unknown opcodes if the code uses instructions which are not 1480d1c124e6SDavid Spickett // available in the oldest arm version (which is used when no sub architecture 1481d1c124e6SDavid Spickett // is specified). 1482be960424SJonas Devlieghere if (triple.getArch() == llvm::Triple::arm && 1483be960424SJonas Devlieghere triple.getSubArch() == llvm::Triple::NoSubArch) 1484d1c124e6SDavid Spickett triple.setArchName("armv9.3a"); 1485be960424SJonas Devlieghere 1486f109517dSJonas Devlieghere std::string features_str = 1487f109517dSJonas Devlieghere features_string ? std::string(features_string) : ""; 1488be960424SJonas Devlieghere const char *triple_str = triple.getTriple().c_str(); 1489be960424SJonas Devlieghere 1490be960424SJonas Devlieghere // ARM Cortex M0-M7 devices only execute thumb instructions 1491be960424SJonas Devlieghere if (arch.IsAlwaysThumbInstructions()) { 1492be960424SJonas Devlieghere triple_str = thumb_arch.GetTriple().getTriple().c_str(); 1493f109517dSJonas Devlieghere if (!features_string) 1494be960424SJonas Devlieghere features_str += "+fp-armv8,"; 1495be960424SJonas Devlieghere } 1496be960424SJonas Devlieghere 1497f109517dSJonas Devlieghere const char *cpu = cpu_string; 1498be960424SJonas Devlieghere 1499f109517dSJonas Devlieghere if (!cpu_or_features_overriden) { 1500be960424SJonas Devlieghere switch (arch.GetCore()) { 1501be960424SJonas Devlieghere case ArchSpec::eCore_mips32: 1502be960424SJonas Devlieghere case ArchSpec::eCore_mips32el: 1503be960424SJonas Devlieghere cpu = "mips32"; 1504be960424SJonas Devlieghere break; 1505be960424SJonas Devlieghere case ArchSpec::eCore_mips32r2: 1506be960424SJonas Devlieghere case ArchSpec::eCore_mips32r2el: 1507be960424SJonas Devlieghere cpu = "mips32r2"; 1508be960424SJonas Devlieghere break; 1509be960424SJonas Devlieghere case ArchSpec::eCore_mips32r3: 1510be960424SJonas Devlieghere case ArchSpec::eCore_mips32r3el: 1511be960424SJonas Devlieghere cpu = "mips32r3"; 1512be960424SJonas Devlieghere break; 1513be960424SJonas Devlieghere case ArchSpec::eCore_mips32r5: 1514be960424SJonas Devlieghere case ArchSpec::eCore_mips32r5el: 1515be960424SJonas Devlieghere cpu = "mips32r5"; 1516be960424SJonas Devlieghere break; 1517be960424SJonas Devlieghere case ArchSpec::eCore_mips32r6: 1518be960424SJonas Devlieghere case ArchSpec::eCore_mips32r6el: 1519be960424SJonas Devlieghere cpu = "mips32r6"; 1520be960424SJonas Devlieghere break; 1521be960424SJonas Devlieghere case ArchSpec::eCore_mips64: 1522be960424SJonas Devlieghere case ArchSpec::eCore_mips64el: 1523be960424SJonas Devlieghere cpu = "mips64"; 1524be960424SJonas Devlieghere break; 1525be960424SJonas Devlieghere case ArchSpec::eCore_mips64r2: 1526be960424SJonas Devlieghere case ArchSpec::eCore_mips64r2el: 1527be960424SJonas Devlieghere cpu = "mips64r2"; 1528be960424SJonas Devlieghere break; 1529be960424SJonas Devlieghere case ArchSpec::eCore_mips64r3: 1530be960424SJonas Devlieghere case ArchSpec::eCore_mips64r3el: 1531be960424SJonas Devlieghere cpu = "mips64r3"; 1532be960424SJonas Devlieghere break; 1533be960424SJonas Devlieghere case ArchSpec::eCore_mips64r5: 1534be960424SJonas Devlieghere case ArchSpec::eCore_mips64r5el: 1535be960424SJonas Devlieghere cpu = "mips64r5"; 1536be960424SJonas Devlieghere break; 1537be960424SJonas Devlieghere case ArchSpec::eCore_mips64r6: 1538be960424SJonas Devlieghere case ArchSpec::eCore_mips64r6el: 1539be960424SJonas Devlieghere cpu = "mips64r6"; 1540be960424SJonas Devlieghere break; 1541be960424SJonas Devlieghere default: 1542be960424SJonas Devlieghere cpu = ""; 1543be960424SJonas Devlieghere break; 1544be960424SJonas Devlieghere } 1545f109517dSJonas Devlieghere } 1546be960424SJonas Devlieghere 1547f109517dSJonas Devlieghere if (arch.IsMIPS() && !cpu_or_features_overriden) { 1548be960424SJonas Devlieghere uint32_t arch_flags = arch.GetFlags(); 1549be960424SJonas Devlieghere if (arch_flags & ArchSpec::eMIPSAse_msa) 1550be960424SJonas Devlieghere features_str += "+msa,"; 1551be960424SJonas Devlieghere if (arch_flags & ArchSpec::eMIPSAse_dsp) 1552be960424SJonas Devlieghere features_str += "+dsp,"; 1553be960424SJonas Devlieghere if (arch_flags & ArchSpec::eMIPSAse_dspr2) 1554be960424SJonas Devlieghere features_str += "+dspr2,"; 1555be960424SJonas Devlieghere } 1556be960424SJonas Devlieghere 1557f109517dSJonas Devlieghere // If any AArch64 variant, enable latest ISA with all extensions unless the 1558f109517dSJonas Devlieghere // CPU or features were overridden. 1559f109517dSJonas Devlieghere if (triple.isAArch64() && !cpu_or_features_overriden) { 1560e5fdcfacSDavid Spickett features_str += "+all,"; 1561801c7866SDavid Spickett if (triple.getVendor() == llvm::Triple::Apple) 1562be960424SJonas Devlieghere cpu = "apple-latest"; 1563be960424SJonas Devlieghere } 1564be960424SJonas Devlieghere 1565f109517dSJonas Devlieghere if (triple.isRISCV() && !cpu_or_features_overriden) { 1566c6042076SSaleem Abdulrasool uint32_t arch_flags = arch.GetFlags(); 1567c6042076SSaleem Abdulrasool if (arch_flags & ArchSpec::eRISCV_rvc) 1568c6042076SSaleem Abdulrasool features_str += "+c,"; 1569c6042076SSaleem Abdulrasool if (arch_flags & ArchSpec::eRISCV_rve) 1570c6042076SSaleem Abdulrasool features_str += "+e,"; 1571c6042076SSaleem Abdulrasool if ((arch_flags & ArchSpec::eRISCV_float_abi_single) == 1572c6042076SSaleem Abdulrasool ArchSpec::eRISCV_float_abi_single) 1573c6042076SSaleem Abdulrasool features_str += "+f,"; 1574c6042076SSaleem Abdulrasool if ((arch_flags & ArchSpec::eRISCV_float_abi_double) == 1575c6042076SSaleem Abdulrasool ArchSpec::eRISCV_float_abi_double) 1576c6042076SSaleem Abdulrasool features_str += "+f,+d,"; 1577c6042076SSaleem Abdulrasool if ((arch_flags & ArchSpec::eRISCV_float_abi_quad) == 1578c6042076SSaleem Abdulrasool ArchSpec::eRISCV_float_abi_quad) 1579c6042076SSaleem Abdulrasool features_str += "+f,+d,+q,"; 1580c6042076SSaleem Abdulrasool // FIXME: how do we detect features such as `+a`, `+m`? 1581847de9c3STed Woodward // Turn them on by default now, since everyone seems to use them 1582847de9c3STed Woodward features_str += "+a,+m,"; 1583c6042076SSaleem Abdulrasool } 1584c6042076SSaleem Abdulrasool 1585be960424SJonas Devlieghere // We use m_disasm_up.get() to tell whether we are valid or not, so if this 1586be960424SJonas Devlieghere // isn't good for some reason, we won't be valid and FindPlugin will fail and 1587be960424SJonas Devlieghere // we won't get used. 1588be960424SJonas Devlieghere m_disasm_up = MCDisasmInstance::Create(triple_str, cpu, features_str.c_str(), 1589be960424SJonas Devlieghere flavor, *this); 1590be960424SJonas Devlieghere 1591be960424SJonas Devlieghere llvm::Triple::ArchType llvm_arch = triple.getArch(); 1592be960424SJonas Devlieghere 1593be960424SJonas Devlieghere // For arm CPUs that can execute arm or thumb instructions, also create a 1594be960424SJonas Devlieghere // thumb instruction disassembler. 1595be960424SJonas Devlieghere if (llvm_arch == llvm::Triple::arm) { 1596be960424SJonas Devlieghere std::string thumb_triple(thumb_arch.GetTriple().getTriple()); 1597be960424SJonas Devlieghere m_alternate_disasm_up = 1598be960424SJonas Devlieghere MCDisasmInstance::Create(thumb_triple.c_str(), "", features_str.c_str(), 1599be960424SJonas Devlieghere flavor, *this); 1600be960424SJonas Devlieghere if (!m_alternate_disasm_up) 1601be960424SJonas Devlieghere m_disasm_up.reset(); 1602be960424SJonas Devlieghere 1603be960424SJonas Devlieghere } else if (arch.IsMIPS()) { 1604be960424SJonas Devlieghere /* Create alternate disassembler for MIPS16 and microMIPS */ 1605be960424SJonas Devlieghere uint32_t arch_flags = arch.GetFlags(); 1606be960424SJonas Devlieghere if (arch_flags & ArchSpec::eMIPSAse_mips16) 1607be960424SJonas Devlieghere features_str += "+mips16,"; 1608be960424SJonas Devlieghere else if (arch_flags & ArchSpec::eMIPSAse_micromips) 1609be960424SJonas Devlieghere features_str += "+micromips,"; 1610be960424SJonas Devlieghere 1611be960424SJonas Devlieghere m_alternate_disasm_up = MCDisasmInstance::Create( 1612be960424SJonas Devlieghere triple_str, cpu, features_str.c_str(), flavor, *this); 1613be960424SJonas Devlieghere if (!m_alternate_disasm_up) 1614be960424SJonas Devlieghere m_disasm_up.reset(); 1615be960424SJonas Devlieghere } 1616be960424SJonas Devlieghere } 1617be960424SJonas Devlieghere 1618be960424SJonas Devlieghere DisassemblerLLVMC::~DisassemblerLLVMC() = default; 1619be960424SJonas Devlieghere 1620f464b7c7SAlex Langford lldb::DisassemblerSP DisassemblerLLVMC::CreateInstance(const ArchSpec &arch, 1621f109517dSJonas Devlieghere const char *flavor, 1622f109517dSJonas Devlieghere const char *cpu, 1623f109517dSJonas Devlieghere const char *features) { 1624be960424SJonas Devlieghere if (arch.GetTriple().getArch() != llvm::Triple::UnknownArch) { 1625f109517dSJonas Devlieghere auto disasm_sp = 1626f109517dSJonas Devlieghere std::make_shared<DisassemblerLLVMC>(arch, flavor, cpu, features); 1627f464b7c7SAlex Langford if (disasm_sp && disasm_sp->IsValid()) 1628f464b7c7SAlex Langford return disasm_sp; 1629be960424SJonas Devlieghere } 1630f464b7c7SAlex Langford return lldb::DisassemblerSP(); 1631be960424SJonas Devlieghere } 1632be960424SJonas Devlieghere 1633be960424SJonas Devlieghere size_t DisassemblerLLVMC::DecodeInstructions(const Address &base_addr, 1634be960424SJonas Devlieghere const DataExtractor &data, 1635be960424SJonas Devlieghere lldb::offset_t data_offset, 1636be960424SJonas Devlieghere size_t num_instructions, 1637be960424SJonas Devlieghere bool append, bool data_from_file) { 1638be960424SJonas Devlieghere if (!append) 1639be960424SJonas Devlieghere m_instruction_list.Clear(); 1640be960424SJonas Devlieghere 1641be960424SJonas Devlieghere if (!IsValid()) 1642be960424SJonas Devlieghere return 0; 1643be960424SJonas Devlieghere 1644be960424SJonas Devlieghere m_data_from_file = data_from_file; 1645be960424SJonas Devlieghere uint32_t data_cursor = data_offset; 1646be960424SJonas Devlieghere const size_t data_byte_size = data.GetByteSize(); 1647be960424SJonas Devlieghere uint32_t instructions_parsed = 0; 1648be960424SJonas Devlieghere Address inst_addr(base_addr); 1649be960424SJonas Devlieghere 1650be960424SJonas Devlieghere while (data_cursor < data_byte_size && 1651be960424SJonas Devlieghere instructions_parsed < num_instructions) { 1652be960424SJonas Devlieghere 1653be960424SJonas Devlieghere AddressClass address_class = AddressClass::eCode; 1654be960424SJonas Devlieghere 1655be960424SJonas Devlieghere if (m_alternate_disasm_up) 1656be960424SJonas Devlieghere address_class = inst_addr.GetAddressClass(); 1657be960424SJonas Devlieghere 1658be960424SJonas Devlieghere InstructionSP inst_sp( 1659be960424SJonas Devlieghere new InstructionLLVMC(*this, inst_addr, address_class)); 1660be960424SJonas Devlieghere 1661be960424SJonas Devlieghere if (!inst_sp) 1662be960424SJonas Devlieghere break; 1663be960424SJonas Devlieghere 1664be960424SJonas Devlieghere uint32_t inst_size = inst_sp->Decode(*this, data, data_cursor); 1665be960424SJonas Devlieghere 1666be960424SJonas Devlieghere if (inst_size == 0) 1667be960424SJonas Devlieghere break; 1668be960424SJonas Devlieghere 1669be960424SJonas Devlieghere m_instruction_list.Append(inst_sp); 1670be960424SJonas Devlieghere data_cursor += inst_size; 1671be960424SJonas Devlieghere inst_addr.Slide(inst_size); 1672be960424SJonas Devlieghere instructions_parsed++; 1673be960424SJonas Devlieghere } 1674be960424SJonas Devlieghere 1675be960424SJonas Devlieghere return data_cursor - data_offset; 1676be960424SJonas Devlieghere } 1677be960424SJonas Devlieghere 1678be960424SJonas Devlieghere void DisassemblerLLVMC::Initialize() { 1679be960424SJonas Devlieghere PluginManager::RegisterPlugin(GetPluginNameStatic(), 1680be960424SJonas Devlieghere "Disassembler that uses LLVM MC to disassemble " 1681be960424SJonas Devlieghere "i386, x86_64, ARM, and ARM64.", 1682be960424SJonas Devlieghere CreateInstance); 1683be960424SJonas Devlieghere 1684be960424SJonas Devlieghere llvm::InitializeAllTargetInfos(); 1685be960424SJonas Devlieghere llvm::InitializeAllTargetMCs(); 1686be960424SJonas Devlieghere llvm::InitializeAllAsmParsers(); 1687be960424SJonas Devlieghere llvm::InitializeAllDisassemblers(); 1688be960424SJonas Devlieghere } 1689be960424SJonas Devlieghere 1690be960424SJonas Devlieghere void DisassemblerLLVMC::Terminate() { 1691be960424SJonas Devlieghere PluginManager::UnregisterPlugin(CreateInstance); 1692be960424SJonas Devlieghere } 1693be960424SJonas Devlieghere 1694be960424SJonas Devlieghere int DisassemblerLLVMC::OpInfoCallback(void *disassembler, uint64_t pc, 1695be960424SJonas Devlieghere uint64_t offset, uint64_t size, 1696be960424SJonas Devlieghere int tag_type, void *tag_bug) { 1697be960424SJonas Devlieghere return static_cast<DisassemblerLLVMC *>(disassembler) 1698be960424SJonas Devlieghere ->OpInfo(pc, offset, size, tag_type, tag_bug); 1699be960424SJonas Devlieghere } 1700be960424SJonas Devlieghere 1701be960424SJonas Devlieghere const char *DisassemblerLLVMC::SymbolLookupCallback(void *disassembler, 1702be960424SJonas Devlieghere uint64_t value, 1703be960424SJonas Devlieghere uint64_t *type, uint64_t pc, 1704be960424SJonas Devlieghere const char **name) { 1705be960424SJonas Devlieghere return static_cast<DisassemblerLLVMC *>(disassembler) 1706be960424SJonas Devlieghere ->SymbolLookup(value, type, pc, name); 1707be960424SJonas Devlieghere } 1708be960424SJonas Devlieghere 1709be960424SJonas Devlieghere bool DisassemblerLLVMC::FlavorValidForArchSpec( 1710be960424SJonas Devlieghere const lldb_private::ArchSpec &arch, const char *flavor) { 1711be960424SJonas Devlieghere llvm::Triple triple = arch.GetTriple(); 1712be960424SJonas Devlieghere if (flavor == nullptr || strcmp(flavor, "default") == 0) 1713be960424SJonas Devlieghere return true; 1714be960424SJonas Devlieghere 1715be960424SJonas Devlieghere if (triple.getArch() == llvm::Triple::x86 || 1716be960424SJonas Devlieghere triple.getArch() == llvm::Triple::x86_64) { 1717be960424SJonas Devlieghere return strcmp(flavor, "intel") == 0 || strcmp(flavor, "att") == 0; 1718be960424SJonas Devlieghere } else 1719be960424SJonas Devlieghere return false; 1720be960424SJonas Devlieghere } 1721be960424SJonas Devlieghere 1722be960424SJonas Devlieghere bool DisassemblerLLVMC::IsValid() const { return m_disasm_up.operator bool(); } 1723be960424SJonas Devlieghere 1724be960424SJonas Devlieghere int DisassemblerLLVMC::OpInfo(uint64_t PC, uint64_t Offset, uint64_t Size, 1725be960424SJonas Devlieghere int tag_type, void *tag_bug) { 1726be960424SJonas Devlieghere switch (tag_type) { 1727be960424SJonas Devlieghere default: 1728be960424SJonas Devlieghere break; 1729be960424SJonas Devlieghere case 1: 1730be960424SJonas Devlieghere memset(tag_bug, 0, sizeof(::LLVMOpInfo1)); 1731be960424SJonas Devlieghere break; 1732be960424SJonas Devlieghere } 1733be960424SJonas Devlieghere return 0; 1734be960424SJonas Devlieghere } 1735be960424SJonas Devlieghere 1736be960424SJonas Devlieghere const char *DisassemblerLLVMC::SymbolLookup(uint64_t value, uint64_t *type_ptr, 1737be960424SJonas Devlieghere uint64_t pc, const char **name) { 1738be960424SJonas Devlieghere if (*type_ptr) { 1739be960424SJonas Devlieghere if (m_exe_ctx && m_inst) { 1740be960424SJonas Devlieghere // std::string remove_this_prior_to_checkin; 1741be960424SJonas Devlieghere Target *target = m_exe_ctx ? m_exe_ctx->GetTargetPtr() : nullptr; 1742be960424SJonas Devlieghere Address value_so_addr; 1743be960424SJonas Devlieghere Address pc_so_addr; 17447150b562SJason Molenda if (target->GetArchitecture().GetMachine() == llvm::Triple::aarch64 || 17457150b562SJason Molenda target->GetArchitecture().GetMachine() == llvm::Triple::aarch64_be || 17467150b562SJason Molenda target->GetArchitecture().GetMachine() == llvm::Triple::aarch64_32) { 17477150b562SJason Molenda if (*type_ptr == LLVMDisassembler_ReferenceType_In_ARM64_ADRP) { 17487150b562SJason Molenda m_adrp_address = pc; 17497150b562SJason Molenda m_adrp_insn = value; 17507150b562SJason Molenda *name = nullptr; 17517150b562SJason Molenda *type_ptr = LLVMDisassembler_ReferenceType_InOut_None; 17527150b562SJason Molenda return nullptr; 17537150b562SJason Molenda } 17547150b562SJason Molenda // If this instruction is an ADD and 17557150b562SJason Molenda // the previous instruction was an ADRP and 17567150b562SJason Molenda // the ADRP's register and this ADD's register are the same, 17577150b562SJason Molenda // then this is a pc-relative address calculation. 17587150b562SJason Molenda if (*type_ptr == LLVMDisassembler_ReferenceType_In_ARM64_ADDXri && 175996d1b4ddSKazu Hirata m_adrp_insn && m_adrp_address == pc - 4 && 17609464bd8cSFangrui Song (*m_adrp_insn & 0x1f) == ((value >> 5) & 0x1f)) { 17617150b562SJason Molenda uint32_t addxri_inst; 17627150b562SJason Molenda uint64_t adrp_imm, addxri_imm; 17637150b562SJason Molenda // Get immlo and immhi bits, OR them together to get the ADRP imm 17647150b562SJason Molenda // value. 17659464bd8cSFangrui Song adrp_imm = 17669464bd8cSFangrui Song ((*m_adrp_insn & 0x00ffffe0) >> 3) | ((*m_adrp_insn >> 29) & 0x3); 17677150b562SJason Molenda // if high bit of immhi after right-shifting set, sign extend 17687150b562SJason Molenda if (adrp_imm & (1ULL << 20)) 17697150b562SJason Molenda adrp_imm |= ~((1ULL << 21) - 1); 17707150b562SJason Molenda 17717150b562SJason Molenda addxri_inst = value; 17727150b562SJason Molenda addxri_imm = (addxri_inst >> 10) & 0xfff; 17737150b562SJason Molenda // check if 'sh' bit is set, shift imm value up if so 17747150b562SJason Molenda // (this would make no sense, ADRP already gave us this part) 17757150b562SJason Molenda if ((addxri_inst >> (12 + 5 + 5)) & 1) 17767150b562SJason Molenda addxri_imm <<= 12; 17777150b562SJason Molenda value = (m_adrp_address & 0xfffffffffffff000LL) + (adrp_imm << 12) + 17787150b562SJason Molenda addxri_imm; 17797150b562SJason Molenda } 17807150b562SJason Molenda m_adrp_address = LLDB_INVALID_ADDRESS; 17817150b562SJason Molenda m_adrp_insn.reset(); 17827150b562SJason Molenda } 17837150b562SJason Molenda 1784be960424SJonas Devlieghere if (m_inst->UsingFileAddress()) { 1785be960424SJonas Devlieghere ModuleSP module_sp(m_inst->GetAddress().GetModule()); 1786be960424SJonas Devlieghere if (module_sp) { 1787be960424SJonas Devlieghere module_sp->ResolveFileAddress(value, value_so_addr); 1788be960424SJonas Devlieghere module_sp->ResolveFileAddress(pc, pc_so_addr); 1789be960424SJonas Devlieghere } 1790*c4fb7180SGreg Clayton } else if (target && target->HasLoadedSections()) { 1791*c4fb7180SGreg Clayton target->ResolveLoadAddress(value, value_so_addr); 1792*c4fb7180SGreg Clayton target->ResolveLoadAddress(pc, pc_so_addr); 1793be960424SJonas Devlieghere } 1794be960424SJonas Devlieghere 1795be960424SJonas Devlieghere SymbolContext sym_ctx; 1796be960424SJonas Devlieghere const SymbolContextItem resolve_scope = 1797be960424SJonas Devlieghere eSymbolContextFunction | eSymbolContextSymbol; 1798be960424SJonas Devlieghere if (pc_so_addr.IsValid() && pc_so_addr.GetModule()) { 1799be960424SJonas Devlieghere pc_so_addr.GetModule()->ResolveSymbolContextForAddress( 1800be960424SJonas Devlieghere pc_so_addr, resolve_scope, sym_ctx); 1801be960424SJonas Devlieghere } 1802be960424SJonas Devlieghere 1803be960424SJonas Devlieghere if (value_so_addr.IsValid() && value_so_addr.GetSection()) { 1804be960424SJonas Devlieghere StreamString ss; 1805be960424SJonas Devlieghere 1806be960424SJonas Devlieghere bool format_omitting_current_func_name = false; 1807be960424SJonas Devlieghere if (sym_ctx.symbol || sym_ctx.function) { 1808be960424SJonas Devlieghere AddressRange range; 1809be960424SJonas Devlieghere if (sym_ctx.GetAddressRange(resolve_scope, 0, false, range) && 1810be960424SJonas Devlieghere range.GetBaseAddress().IsValid() && 1811be960424SJonas Devlieghere range.ContainsLoadAddress(value_so_addr, target)) { 1812be960424SJonas Devlieghere format_omitting_current_func_name = true; 1813be960424SJonas Devlieghere } 1814be960424SJonas Devlieghere } 1815be960424SJonas Devlieghere 1816be960424SJonas Devlieghere // If the "value" address (the target address we're symbolicating) is 1817be960424SJonas Devlieghere // inside the same SymbolContext as the current instruction pc 1818be960424SJonas Devlieghere // (pc_so_addr), don't print the full function name - just print it 1819be960424SJonas Devlieghere // with DumpStyleNoFunctionName style, e.g. "<+36>". 1820be960424SJonas Devlieghere if (format_omitting_current_func_name) { 1821be960424SJonas Devlieghere value_so_addr.Dump(&ss, target, Address::DumpStyleNoFunctionName, 1822be960424SJonas Devlieghere Address::DumpStyleSectionNameOffset); 1823be960424SJonas Devlieghere } else { 1824be960424SJonas Devlieghere value_so_addr.Dump( 1825be960424SJonas Devlieghere &ss, target, 1826be960424SJonas Devlieghere Address::DumpStyleResolvedDescriptionNoFunctionArguments, 1827be960424SJonas Devlieghere Address::DumpStyleSectionNameOffset); 1828be960424SJonas Devlieghere } 1829be960424SJonas Devlieghere 1830be960424SJonas Devlieghere if (!ss.GetString().empty()) { 1831be960424SJonas Devlieghere // If Address::Dump returned a multi-line description, most commonly 1832be960424SJonas Devlieghere // seen when we have multiple levels of inlined functions at an 1833be960424SJonas Devlieghere // address, only show the first line. 1834adcd0268SBenjamin Kramer std::string str = std::string(ss.GetString()); 1835be960424SJonas Devlieghere size_t first_eol_char = str.find_first_of("\r\n"); 1836be960424SJonas Devlieghere if (first_eol_char != std::string::npos) { 1837be960424SJonas Devlieghere str.erase(first_eol_char); 1838be960424SJonas Devlieghere } 1839be960424SJonas Devlieghere m_inst->AppendComment(str); 1840be960424SJonas Devlieghere } 1841be960424SJonas Devlieghere } 1842be960424SJonas Devlieghere } 1843be960424SJonas Devlieghere } 1844be960424SJonas Devlieghere 18457150b562SJason Molenda // TODO: llvm-objdump sets the type_ptr to the 18467150b562SJason Molenda // LLVMDisassembler_ReferenceType_Out_* values 18477150b562SJason Molenda // based on where value_so_addr is pointing, with 18487150b562SJason Molenda // Mach-O specific augmentations in MachODump.cpp. e.g. 18497150b562SJason Molenda // see what AArch64ExternalSymbolizer::tryAddingSymbolicOperand 18507150b562SJason Molenda // handles. 1851be960424SJonas Devlieghere *type_ptr = LLVMDisassembler_ReferenceType_InOut_None; 1852be960424SJonas Devlieghere *name = nullptr; 1853be960424SJonas Devlieghere return nullptr; 1854be960424SJonas Devlieghere } 1855