15ffd83dbSDimitry Andric //===-- DisassemblerLLVMC.cpp ---------------------------------------------===// 25ffd83dbSDimitry Andric // 35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65ffd83dbSDimitry Andric // 75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 85ffd83dbSDimitry Andric 95ffd83dbSDimitry Andric #include "DisassemblerLLVMC.h" 105ffd83dbSDimitry Andric 115ffd83dbSDimitry Andric #include "llvm-c/Disassembler.h" 125ffd83dbSDimitry Andric #include "llvm/ADT/SmallString.h" 1381ad6265SDimitry Andric #include "llvm/ADT/StringExtras.h" 145ffd83dbSDimitry Andric #include "llvm/MC/MCAsmInfo.h" 155ffd83dbSDimitry Andric #include "llvm/MC/MCContext.h" 165ffd83dbSDimitry Andric #include "llvm/MC/MCDisassembler/MCDisassembler.h" 175ffd83dbSDimitry Andric #include "llvm/MC/MCDisassembler/MCExternalSymbolizer.h" 185ffd83dbSDimitry Andric #include "llvm/MC/MCDisassembler/MCRelocationInfo.h" 195ffd83dbSDimitry Andric #include "llvm/MC/MCInst.h" 205ffd83dbSDimitry Andric #include "llvm/MC/MCInstPrinter.h" 21*5f757f3fSDimitry Andric #include "llvm/MC/MCInstrAnalysis.h" 225ffd83dbSDimitry Andric #include "llvm/MC/MCInstrInfo.h" 235ffd83dbSDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 245ffd83dbSDimitry Andric #include "llvm/MC/MCSubtargetInfo.h" 255ffd83dbSDimitry Andric #include "llvm/MC/MCTargetOptions.h" 26349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h" 275ffd83dbSDimitry Andric #include "llvm/Support/ErrorHandling.h" 285ffd83dbSDimitry Andric #include "llvm/Support/ScopedPrinter.h" 295ffd83dbSDimitry Andric #include "llvm/Support/TargetSelect.h" 3006c3fb27SDimitry Andric #include "llvm/TargetParser/AArch64TargetParser.h" 315ffd83dbSDimitry Andric 325ffd83dbSDimitry Andric #include "lldb/Core/Address.h" 335ffd83dbSDimitry Andric #include "lldb/Core/Module.h" 345ffd83dbSDimitry Andric #include "lldb/Symbol/SymbolContext.h" 355ffd83dbSDimitry Andric #include "lldb/Target/ExecutionContext.h" 365ffd83dbSDimitry Andric #include "lldb/Target/Process.h" 375ffd83dbSDimitry Andric #include "lldb/Target/RegisterContext.h" 385ffd83dbSDimitry Andric #include "lldb/Target/SectionLoadList.h" 395ffd83dbSDimitry Andric #include "lldb/Target/StackFrame.h" 405ffd83dbSDimitry Andric #include "lldb/Target/Target.h" 415ffd83dbSDimitry Andric #include "lldb/Utility/DataExtractor.h" 4281ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h" 435ffd83dbSDimitry Andric #include "lldb/Utility/Log.h" 445ffd83dbSDimitry Andric #include "lldb/Utility/RegularExpression.h" 455ffd83dbSDimitry Andric #include "lldb/Utility/Stream.h" 46bdd1243dSDimitry Andric #include <optional> 475ffd83dbSDimitry Andric 485ffd83dbSDimitry Andric using namespace lldb; 495ffd83dbSDimitry Andric using namespace lldb_private; 505ffd83dbSDimitry Andric 515ffd83dbSDimitry Andric LLDB_PLUGIN_DEFINE(DisassemblerLLVMC) 525ffd83dbSDimitry Andric 535ffd83dbSDimitry Andric class DisassemblerLLVMC::MCDisasmInstance { 545ffd83dbSDimitry Andric public: 555ffd83dbSDimitry Andric static std::unique_ptr<MCDisasmInstance> 565ffd83dbSDimitry Andric Create(const char *triple, const char *cpu, const char *features_str, 575ffd83dbSDimitry Andric unsigned flavor, DisassemblerLLVMC &owner); 585ffd83dbSDimitry Andric 595ffd83dbSDimitry Andric ~MCDisasmInstance() = default; 605ffd83dbSDimitry Andric 615ffd83dbSDimitry Andric uint64_t GetMCInst(const uint8_t *opcode_data, size_t opcode_data_len, 625ffd83dbSDimitry Andric lldb::addr_t pc, llvm::MCInst &mc_inst) const; 63*5f757f3fSDimitry Andric void PrintMCInst(llvm::MCInst &mc_inst, lldb::addr_t pc, 64*5f757f3fSDimitry Andric std::string &inst_string, std::string &comments_string); 655ffd83dbSDimitry Andric void SetStyle(bool use_hex_immed, HexImmediateStyle hex_style); 66*5f757f3fSDimitry Andric void SetUseColor(bool use_color); 67*5f757f3fSDimitry Andric bool GetUseColor() const; 685ffd83dbSDimitry Andric bool CanBranch(llvm::MCInst &mc_inst) const; 695ffd83dbSDimitry Andric bool HasDelaySlot(llvm::MCInst &mc_inst) const; 705ffd83dbSDimitry Andric bool IsCall(llvm::MCInst &mc_inst) const; 71349cc55cSDimitry Andric bool IsLoad(llvm::MCInst &mc_inst) const; 72349cc55cSDimitry Andric bool IsAuthenticated(llvm::MCInst &mc_inst) const; 735ffd83dbSDimitry Andric 745ffd83dbSDimitry Andric private: 755ffd83dbSDimitry Andric MCDisasmInstance(std::unique_ptr<llvm::MCInstrInfo> &&instr_info_up, 765ffd83dbSDimitry Andric std::unique_ptr<llvm::MCRegisterInfo> &®_info_up, 775ffd83dbSDimitry Andric std::unique_ptr<llvm::MCSubtargetInfo> &&subtarget_info_up, 785ffd83dbSDimitry Andric std::unique_ptr<llvm::MCAsmInfo> &&asm_info_up, 795ffd83dbSDimitry Andric std::unique_ptr<llvm::MCContext> &&context_up, 805ffd83dbSDimitry Andric std::unique_ptr<llvm::MCDisassembler> &&disasm_up, 81*5f757f3fSDimitry Andric std::unique_ptr<llvm::MCInstPrinter> &&instr_printer_up, 82*5f757f3fSDimitry Andric std::unique_ptr<llvm::MCInstrAnalysis> &&instr_analysis_up); 835ffd83dbSDimitry Andric 845ffd83dbSDimitry Andric std::unique_ptr<llvm::MCInstrInfo> m_instr_info_up; 855ffd83dbSDimitry Andric std::unique_ptr<llvm::MCRegisterInfo> m_reg_info_up; 865ffd83dbSDimitry Andric std::unique_ptr<llvm::MCSubtargetInfo> m_subtarget_info_up; 875ffd83dbSDimitry Andric std::unique_ptr<llvm::MCAsmInfo> m_asm_info_up; 885ffd83dbSDimitry Andric std::unique_ptr<llvm::MCContext> m_context_up; 895ffd83dbSDimitry Andric std::unique_ptr<llvm::MCDisassembler> m_disasm_up; 905ffd83dbSDimitry Andric std::unique_ptr<llvm::MCInstPrinter> m_instr_printer_up; 91*5f757f3fSDimitry Andric std::unique_ptr<llvm::MCInstrAnalysis> m_instr_analysis_up; 925ffd83dbSDimitry Andric }; 935ffd83dbSDimitry Andric 94972a253aSDimitry Andric namespace x86 { 95972a253aSDimitry Andric 96972a253aSDimitry Andric /// These are the three values deciding instruction control flow kind. 97972a253aSDimitry Andric /// InstructionLengthDecode function decodes an instruction and get this struct. 98972a253aSDimitry Andric /// 99972a253aSDimitry Andric /// primary_opcode 100972a253aSDimitry Andric /// Primary opcode of the instruction. 101972a253aSDimitry Andric /// For one-byte opcode instruction, it's the first byte after prefix. 102972a253aSDimitry Andric /// For two- and three-byte opcodes, it's the second byte. 103972a253aSDimitry Andric /// 104972a253aSDimitry Andric /// opcode_len 105972a253aSDimitry Andric /// The length of opcode in bytes. Valid opcode lengths are 1, 2, or 3. 106972a253aSDimitry Andric /// 107972a253aSDimitry Andric /// modrm 108972a253aSDimitry Andric /// ModR/M byte of the instruction. 109972a253aSDimitry Andric /// Bits[7:6] indicate MOD. Bits[5:3] specify a register and R/M bits[2:0] 110972a253aSDimitry Andric /// may contain a register or specify an addressing mode, depending on MOD. 111972a253aSDimitry Andric struct InstructionOpcodeAndModrm { 112972a253aSDimitry Andric uint8_t primary_opcode; 113972a253aSDimitry Andric uint8_t opcode_len; 114972a253aSDimitry Andric uint8_t modrm; 115972a253aSDimitry Andric }; 116972a253aSDimitry Andric 117972a253aSDimitry Andric /// Determine the InstructionControlFlowKind based on opcode and modrm bytes. 118972a253aSDimitry Andric /// Refer to http://ref.x86asm.net/coder.html for the full list of opcode and 119972a253aSDimitry Andric /// instruction set. 120972a253aSDimitry Andric /// 121972a253aSDimitry Andric /// \param[in] opcode_and_modrm 122972a253aSDimitry Andric /// Contains primary_opcode byte, its length, and ModR/M byte. 123972a253aSDimitry Andric /// Refer to the struct InstructionOpcodeAndModrm for details. 124972a253aSDimitry Andric /// 125972a253aSDimitry Andric /// \return 126972a253aSDimitry Andric /// The control flow kind of the instruction or 127972a253aSDimitry Andric /// eInstructionControlFlowKindOther if the instruction doesn't affect 128972a253aSDimitry Andric /// the control flow of the program. 129972a253aSDimitry Andric lldb::InstructionControlFlowKind 130972a253aSDimitry Andric MapOpcodeIntoControlFlowKind(InstructionOpcodeAndModrm opcode_and_modrm) { 131972a253aSDimitry Andric uint8_t opcode = opcode_and_modrm.primary_opcode; 132972a253aSDimitry Andric uint8_t opcode_len = opcode_and_modrm.opcode_len; 133972a253aSDimitry Andric uint8_t modrm = opcode_and_modrm.modrm; 134972a253aSDimitry Andric 135972a253aSDimitry Andric if (opcode_len > 2) 136972a253aSDimitry Andric return lldb::eInstructionControlFlowKindOther; 137972a253aSDimitry Andric 138972a253aSDimitry Andric if (opcode >= 0x70 && opcode <= 0x7F) { 139972a253aSDimitry Andric if (opcode_len == 1) 140972a253aSDimitry Andric return lldb::eInstructionControlFlowKindCondJump; 141972a253aSDimitry Andric else 142972a253aSDimitry Andric return lldb::eInstructionControlFlowKindOther; 143972a253aSDimitry Andric } 144972a253aSDimitry Andric 145972a253aSDimitry Andric if (opcode >= 0x80 && opcode <= 0x8F) { 146972a253aSDimitry Andric if (opcode_len == 2) 147972a253aSDimitry Andric return lldb::eInstructionControlFlowKindCondJump; 148972a253aSDimitry Andric else 149972a253aSDimitry Andric return lldb::eInstructionControlFlowKindOther; 150972a253aSDimitry Andric } 151972a253aSDimitry Andric 152972a253aSDimitry Andric switch (opcode) { 153972a253aSDimitry Andric case 0x9A: 154972a253aSDimitry Andric if (opcode_len == 1) 155972a253aSDimitry Andric return lldb::eInstructionControlFlowKindFarCall; 156972a253aSDimitry Andric break; 157972a253aSDimitry Andric case 0xFF: 158972a253aSDimitry Andric if (opcode_len == 1) { 159972a253aSDimitry Andric uint8_t modrm_reg = (modrm >> 3) & 7; 160972a253aSDimitry Andric if (modrm_reg == 2) 161972a253aSDimitry Andric return lldb::eInstructionControlFlowKindCall; 162972a253aSDimitry Andric else if (modrm_reg == 3) 163972a253aSDimitry Andric return lldb::eInstructionControlFlowKindFarCall; 164972a253aSDimitry Andric else if (modrm_reg == 4) 165972a253aSDimitry Andric return lldb::eInstructionControlFlowKindJump; 166972a253aSDimitry Andric else if (modrm_reg == 5) 167972a253aSDimitry Andric return lldb::eInstructionControlFlowKindFarJump; 168972a253aSDimitry Andric } 169972a253aSDimitry Andric break; 170972a253aSDimitry Andric case 0xE8: 171972a253aSDimitry Andric if (opcode_len == 1) 172972a253aSDimitry Andric return lldb::eInstructionControlFlowKindCall; 173972a253aSDimitry Andric break; 174972a253aSDimitry Andric case 0xCD: 175972a253aSDimitry Andric case 0xCC: 176972a253aSDimitry Andric case 0xCE: 177972a253aSDimitry Andric case 0xF1: 178972a253aSDimitry Andric if (opcode_len == 1) 179972a253aSDimitry Andric return lldb::eInstructionControlFlowKindFarCall; 180972a253aSDimitry Andric break; 181972a253aSDimitry Andric case 0xCF: 182972a253aSDimitry Andric if (opcode_len == 1) 183972a253aSDimitry Andric return lldb::eInstructionControlFlowKindFarReturn; 184972a253aSDimitry Andric break; 185972a253aSDimitry Andric case 0xE9: 186972a253aSDimitry Andric case 0xEB: 187972a253aSDimitry Andric if (opcode_len == 1) 188972a253aSDimitry Andric return lldb::eInstructionControlFlowKindJump; 189972a253aSDimitry Andric break; 190972a253aSDimitry Andric case 0xEA: 191972a253aSDimitry Andric if (opcode_len == 1) 192972a253aSDimitry Andric return lldb::eInstructionControlFlowKindFarJump; 193972a253aSDimitry Andric break; 194972a253aSDimitry Andric case 0xE3: 195972a253aSDimitry Andric case 0xE0: 196972a253aSDimitry Andric case 0xE1: 197972a253aSDimitry Andric case 0xE2: 198972a253aSDimitry Andric if (opcode_len == 1) 199972a253aSDimitry Andric return lldb::eInstructionControlFlowKindCondJump; 200972a253aSDimitry Andric break; 201972a253aSDimitry Andric case 0xC3: 202972a253aSDimitry Andric case 0xC2: 203972a253aSDimitry Andric if (opcode_len == 1) 204972a253aSDimitry Andric return lldb::eInstructionControlFlowKindReturn; 205972a253aSDimitry Andric break; 206972a253aSDimitry Andric case 0xCB: 207972a253aSDimitry Andric case 0xCA: 208972a253aSDimitry Andric if (opcode_len == 1) 209972a253aSDimitry Andric return lldb::eInstructionControlFlowKindFarReturn; 210972a253aSDimitry Andric break; 211972a253aSDimitry Andric case 0x05: 212972a253aSDimitry Andric case 0x34: 213972a253aSDimitry Andric if (opcode_len == 2) 214972a253aSDimitry Andric return lldb::eInstructionControlFlowKindFarCall; 215972a253aSDimitry Andric break; 216972a253aSDimitry Andric case 0x35: 217972a253aSDimitry Andric case 0x07: 218972a253aSDimitry Andric if (opcode_len == 2) 219972a253aSDimitry Andric return lldb::eInstructionControlFlowKindFarReturn; 220972a253aSDimitry Andric break; 221972a253aSDimitry Andric case 0x01: 222972a253aSDimitry Andric if (opcode_len == 2) { 223972a253aSDimitry Andric switch (modrm) { 224972a253aSDimitry Andric case 0xc1: 225972a253aSDimitry Andric return lldb::eInstructionControlFlowKindFarCall; 226972a253aSDimitry Andric case 0xc2: 227972a253aSDimitry Andric case 0xc3: 228972a253aSDimitry Andric return lldb::eInstructionControlFlowKindFarReturn; 229972a253aSDimitry Andric default: 230972a253aSDimitry Andric break; 231972a253aSDimitry Andric } 232972a253aSDimitry Andric } 233972a253aSDimitry Andric break; 234972a253aSDimitry Andric default: 235972a253aSDimitry Andric break; 236972a253aSDimitry Andric } 237972a253aSDimitry Andric 238972a253aSDimitry Andric return lldb::eInstructionControlFlowKindOther; 239972a253aSDimitry Andric } 240972a253aSDimitry Andric 241972a253aSDimitry Andric /// Decode an instruction into opcode, modrm and opcode_len. 242972a253aSDimitry Andric /// Refer to http://ref.x86asm.net/coder.html for the instruction bytes layout. 243972a253aSDimitry Andric /// Opcodes in x86 are generally the first byte of instruction, though two-byte 244972a253aSDimitry Andric /// instructions and prefixes exist. ModR/M is the byte following the opcode 245972a253aSDimitry Andric /// and adds additional information for how the instruction is executed. 246972a253aSDimitry Andric /// 247972a253aSDimitry Andric /// \param[in] inst_bytes 248972a253aSDimitry Andric /// Raw bytes of the instruction 249972a253aSDimitry Andric /// 250972a253aSDimitry Andric /// 251972a253aSDimitry Andric /// \param[in] bytes_len 252972a253aSDimitry Andric /// The length of the inst_bytes array. 253972a253aSDimitry Andric /// 254972a253aSDimitry Andric /// \param[in] is_exec_mode_64b 255972a253aSDimitry Andric /// If true, the execution mode is 64 bit. 256972a253aSDimitry Andric /// 257972a253aSDimitry Andric /// \return 258972a253aSDimitry Andric /// Returns decoded instruction as struct InstructionOpcodeAndModrm, holding 259972a253aSDimitry Andric /// primary_opcode, opcode_len and modrm byte. Refer to the struct definition 260972a253aSDimitry Andric /// for more details. 261bdd1243dSDimitry Andric /// Otherwise if the given instruction is invalid, returns std::nullopt. 262bdd1243dSDimitry Andric std::optional<InstructionOpcodeAndModrm> 263972a253aSDimitry Andric InstructionLengthDecode(const uint8_t *inst_bytes, int bytes_len, 264972a253aSDimitry Andric bool is_exec_mode_64b) { 265972a253aSDimitry Andric int op_idx = 0; 266972a253aSDimitry Andric bool prefix_done = false; 267972a253aSDimitry Andric InstructionOpcodeAndModrm ret = {0, 0, 0}; 268972a253aSDimitry Andric 269972a253aSDimitry Andric // In most cases, the primary_opcode is the first byte of the instruction 270972a253aSDimitry Andric // but some instructions have a prefix to be skipped for these calculations. 271972a253aSDimitry Andric // The following mapping is inspired from libipt's instruction decoding logic 272972a253aSDimitry Andric // in `src/pt_ild.c` 273972a253aSDimitry Andric while (!prefix_done) { 274972a253aSDimitry Andric if (op_idx >= bytes_len) 275bdd1243dSDimitry Andric return std::nullopt; 276972a253aSDimitry Andric 277972a253aSDimitry Andric ret.primary_opcode = inst_bytes[op_idx]; 278972a253aSDimitry Andric switch (ret.primary_opcode) { 279972a253aSDimitry Andric // prefix_ignore 280972a253aSDimitry Andric case 0x26: 281972a253aSDimitry Andric case 0x2e: 282972a253aSDimitry Andric case 0x36: 283972a253aSDimitry Andric case 0x3e: 284972a253aSDimitry Andric case 0x64: 285972a253aSDimitry Andric case 0x65: 286972a253aSDimitry Andric // prefix_osz, prefix_asz 287972a253aSDimitry Andric case 0x66: 288972a253aSDimitry Andric case 0x67: 289972a253aSDimitry Andric // prefix_lock, prefix_f2, prefix_f3 290972a253aSDimitry Andric case 0xf0: 291972a253aSDimitry Andric case 0xf2: 292972a253aSDimitry Andric case 0xf3: 293972a253aSDimitry Andric op_idx++; 294972a253aSDimitry Andric break; 295972a253aSDimitry Andric 296972a253aSDimitry Andric // prefix_rex 297972a253aSDimitry Andric case 0x40: 298972a253aSDimitry Andric case 0x41: 299972a253aSDimitry Andric case 0x42: 300972a253aSDimitry Andric case 0x43: 301972a253aSDimitry Andric case 0x44: 302972a253aSDimitry Andric case 0x45: 303972a253aSDimitry Andric case 0x46: 304972a253aSDimitry Andric case 0x47: 305972a253aSDimitry Andric case 0x48: 306972a253aSDimitry Andric case 0x49: 307972a253aSDimitry Andric case 0x4a: 308972a253aSDimitry Andric case 0x4b: 309972a253aSDimitry Andric case 0x4c: 310972a253aSDimitry Andric case 0x4d: 311972a253aSDimitry Andric case 0x4e: 312972a253aSDimitry Andric case 0x4f: 313972a253aSDimitry Andric if (is_exec_mode_64b) 314972a253aSDimitry Andric op_idx++; 315972a253aSDimitry Andric else 316972a253aSDimitry Andric prefix_done = true; 317972a253aSDimitry Andric break; 318972a253aSDimitry Andric 319972a253aSDimitry Andric // prefix_vex_c4, c5 320972a253aSDimitry Andric case 0xc5: 321972a253aSDimitry Andric if (!is_exec_mode_64b && (inst_bytes[op_idx + 1] & 0xc0) != 0xc0) { 322972a253aSDimitry Andric prefix_done = true; 323972a253aSDimitry Andric break; 324972a253aSDimitry Andric } 325972a253aSDimitry Andric 326972a253aSDimitry Andric ret.opcode_len = 2; 327972a253aSDimitry Andric ret.primary_opcode = inst_bytes[op_idx + 2]; 328972a253aSDimitry Andric ret.modrm = inst_bytes[op_idx + 3]; 329972a253aSDimitry Andric return ret; 330972a253aSDimitry Andric 331972a253aSDimitry Andric case 0xc4: 332972a253aSDimitry Andric if (!is_exec_mode_64b && (inst_bytes[op_idx + 1] & 0xc0) != 0xc0) { 333972a253aSDimitry Andric prefix_done = true; 334972a253aSDimitry Andric break; 335972a253aSDimitry Andric } 336972a253aSDimitry Andric ret.opcode_len = inst_bytes[op_idx + 1] & 0x1f; 337972a253aSDimitry Andric ret.primary_opcode = inst_bytes[op_idx + 3]; 338972a253aSDimitry Andric ret.modrm = inst_bytes[op_idx + 4]; 339972a253aSDimitry Andric return ret; 340972a253aSDimitry Andric 341972a253aSDimitry Andric // prefix_evex 342972a253aSDimitry Andric case 0x62: 343972a253aSDimitry Andric if (!is_exec_mode_64b && (inst_bytes[op_idx + 1] & 0xc0) != 0xc0) { 344972a253aSDimitry Andric prefix_done = true; 345972a253aSDimitry Andric break; 346972a253aSDimitry Andric } 347972a253aSDimitry Andric ret.opcode_len = inst_bytes[op_idx + 1] & 0x03; 348972a253aSDimitry Andric ret.primary_opcode = inst_bytes[op_idx + 4]; 349972a253aSDimitry Andric ret.modrm = inst_bytes[op_idx + 5]; 350972a253aSDimitry Andric return ret; 351972a253aSDimitry Andric 352972a253aSDimitry Andric default: 353972a253aSDimitry Andric prefix_done = true; 354972a253aSDimitry Andric break; 355972a253aSDimitry Andric } 356972a253aSDimitry Andric } // prefix done 357972a253aSDimitry Andric 358972a253aSDimitry Andric ret.primary_opcode = inst_bytes[op_idx]; 359972a253aSDimitry Andric ret.modrm = inst_bytes[op_idx + 1]; 360972a253aSDimitry Andric ret.opcode_len = 1; 361972a253aSDimitry Andric 362972a253aSDimitry Andric // If the first opcode is 0F, it's two- or three- byte opcodes. 363972a253aSDimitry Andric if (ret.primary_opcode == 0x0F) { 364972a253aSDimitry Andric ret.primary_opcode = inst_bytes[++op_idx]; // get the next byte 365972a253aSDimitry Andric 366972a253aSDimitry Andric if (ret.primary_opcode == 0x38) { 367972a253aSDimitry Andric ret.opcode_len = 3; 368972a253aSDimitry Andric ret.primary_opcode = inst_bytes[++op_idx]; // get the next byte 369972a253aSDimitry Andric ret.modrm = inst_bytes[op_idx + 1]; 370972a253aSDimitry Andric } else if (ret.primary_opcode == 0x3A) { 371972a253aSDimitry Andric ret.opcode_len = 3; 372972a253aSDimitry Andric ret.primary_opcode = inst_bytes[++op_idx]; 373972a253aSDimitry Andric ret.modrm = inst_bytes[op_idx + 1]; 374972a253aSDimitry Andric } else if ((ret.primary_opcode & 0xf8) == 0x38) { 375972a253aSDimitry Andric ret.opcode_len = 0; 376972a253aSDimitry Andric ret.primary_opcode = inst_bytes[++op_idx]; 377972a253aSDimitry Andric ret.modrm = inst_bytes[op_idx + 1]; 378972a253aSDimitry Andric } else if (ret.primary_opcode == 0x0F) { 379972a253aSDimitry Andric ret.opcode_len = 3; 380972a253aSDimitry Andric // opcode is 0x0F, no needs to update 381972a253aSDimitry Andric ret.modrm = inst_bytes[op_idx + 1]; 382972a253aSDimitry Andric } else { 383972a253aSDimitry Andric ret.opcode_len = 2; 384972a253aSDimitry Andric ret.modrm = inst_bytes[op_idx + 1]; 385972a253aSDimitry Andric } 386972a253aSDimitry Andric } 387972a253aSDimitry Andric 388972a253aSDimitry Andric return ret; 389972a253aSDimitry Andric } 390972a253aSDimitry Andric 391972a253aSDimitry Andric lldb::InstructionControlFlowKind GetControlFlowKind(bool is_exec_mode_64b, 392972a253aSDimitry Andric Opcode m_opcode) { 393bdd1243dSDimitry Andric std::optional<InstructionOpcodeAndModrm> ret; 394972a253aSDimitry Andric 395972a253aSDimitry Andric if (m_opcode.GetOpcodeBytes() == nullptr || m_opcode.GetByteSize() <= 0) { 396972a253aSDimitry Andric // x86_64 and i386 instructions are categorized as Opcode::Type::eTypeBytes 397972a253aSDimitry Andric return lldb::eInstructionControlFlowKindUnknown; 398972a253aSDimitry Andric } 399972a253aSDimitry Andric 400972a253aSDimitry Andric // Opcode bytes will be decoded into primary_opcode, modrm and opcode length. 401972a253aSDimitry Andric // These are the three values deciding instruction control flow kind. 402972a253aSDimitry Andric ret = InstructionLengthDecode((const uint8_t *)m_opcode.GetOpcodeBytes(), 403972a253aSDimitry Andric m_opcode.GetByteSize(), is_exec_mode_64b); 404972a253aSDimitry Andric if (!ret) 405972a253aSDimitry Andric return lldb::eInstructionControlFlowKindUnknown; 406972a253aSDimitry Andric else 407bdd1243dSDimitry Andric return MapOpcodeIntoControlFlowKind(*ret); 408972a253aSDimitry Andric } 409972a253aSDimitry Andric 410972a253aSDimitry Andric } // namespace x86 411972a253aSDimitry Andric 4125ffd83dbSDimitry Andric class InstructionLLVMC : public lldb_private::Instruction { 4135ffd83dbSDimitry Andric public: 4145ffd83dbSDimitry Andric InstructionLLVMC(DisassemblerLLVMC &disasm, 4155ffd83dbSDimitry Andric const lldb_private::Address &address, 4165ffd83dbSDimitry Andric AddressClass addr_class) 4175ffd83dbSDimitry Andric : Instruction(address, addr_class), 4185ffd83dbSDimitry Andric m_disasm_wp(std::static_pointer_cast<DisassemblerLLVMC>( 41981ad6265SDimitry Andric disasm.shared_from_this())) {} 4205ffd83dbSDimitry Andric 4215ffd83dbSDimitry Andric ~InstructionLLVMC() override = default; 4225ffd83dbSDimitry Andric 4235ffd83dbSDimitry Andric bool DoesBranch() override { 4245ffd83dbSDimitry Andric VisitInstruction(); 4255ffd83dbSDimitry Andric return m_does_branch; 4265ffd83dbSDimitry Andric } 4275ffd83dbSDimitry Andric 4285ffd83dbSDimitry Andric bool HasDelaySlot() override { 4295ffd83dbSDimitry Andric VisitInstruction(); 4305ffd83dbSDimitry Andric return m_has_delay_slot; 4315ffd83dbSDimitry Andric } 4325ffd83dbSDimitry Andric 433349cc55cSDimitry Andric bool IsLoad() override { 434349cc55cSDimitry Andric VisitInstruction(); 435349cc55cSDimitry Andric return m_is_load; 436349cc55cSDimitry Andric } 437349cc55cSDimitry Andric 438349cc55cSDimitry Andric bool IsAuthenticated() override { 439349cc55cSDimitry Andric VisitInstruction(); 440349cc55cSDimitry Andric return m_is_authenticated; 441349cc55cSDimitry Andric } 442349cc55cSDimitry Andric 4435ffd83dbSDimitry Andric DisassemblerLLVMC::MCDisasmInstance *GetDisasmToUse(bool &is_alternate_isa) { 4445ffd83dbSDimitry Andric DisassemblerScope disasm(*this); 4455ffd83dbSDimitry Andric return GetDisasmToUse(is_alternate_isa, disasm); 4465ffd83dbSDimitry Andric } 4475ffd83dbSDimitry Andric 4485ffd83dbSDimitry Andric size_t Decode(const lldb_private::Disassembler &disassembler, 4495ffd83dbSDimitry Andric const lldb_private::DataExtractor &data, 4505ffd83dbSDimitry Andric lldb::offset_t data_offset) override { 4515ffd83dbSDimitry Andric // All we have to do is read the opcode which can be easy for some 4525ffd83dbSDimitry Andric // architectures 4535ffd83dbSDimitry Andric bool got_op = false; 4545ffd83dbSDimitry Andric DisassemblerScope disasm(*this); 4555ffd83dbSDimitry Andric if (disasm) { 4565ffd83dbSDimitry Andric const ArchSpec &arch = disasm->GetArchitecture(); 4575ffd83dbSDimitry Andric const lldb::ByteOrder byte_order = data.GetByteOrder(); 4585ffd83dbSDimitry Andric 4595ffd83dbSDimitry Andric const uint32_t min_op_byte_size = arch.GetMinimumOpcodeByteSize(); 4605ffd83dbSDimitry Andric const uint32_t max_op_byte_size = arch.GetMaximumOpcodeByteSize(); 4615ffd83dbSDimitry Andric if (min_op_byte_size == max_op_byte_size) { 4625ffd83dbSDimitry Andric // Fixed size instructions, just read that amount of data. 4635ffd83dbSDimitry Andric if (!data.ValidOffsetForDataOfSize(data_offset, min_op_byte_size)) 4645ffd83dbSDimitry Andric return false; 4655ffd83dbSDimitry Andric 4665ffd83dbSDimitry Andric switch (min_op_byte_size) { 4675ffd83dbSDimitry Andric case 1: 4685ffd83dbSDimitry Andric m_opcode.SetOpcode8(data.GetU8(&data_offset), byte_order); 4695ffd83dbSDimitry Andric got_op = true; 4705ffd83dbSDimitry Andric break; 4715ffd83dbSDimitry Andric 4725ffd83dbSDimitry Andric case 2: 4735ffd83dbSDimitry Andric m_opcode.SetOpcode16(data.GetU16(&data_offset), byte_order); 4745ffd83dbSDimitry Andric got_op = true; 4755ffd83dbSDimitry Andric break; 4765ffd83dbSDimitry Andric 4775ffd83dbSDimitry Andric case 4: 4785ffd83dbSDimitry Andric m_opcode.SetOpcode32(data.GetU32(&data_offset), byte_order); 4795ffd83dbSDimitry Andric got_op = true; 4805ffd83dbSDimitry Andric break; 4815ffd83dbSDimitry Andric 4825ffd83dbSDimitry Andric case 8: 4835ffd83dbSDimitry Andric m_opcode.SetOpcode64(data.GetU64(&data_offset), byte_order); 4845ffd83dbSDimitry Andric got_op = true; 4855ffd83dbSDimitry Andric break; 4865ffd83dbSDimitry Andric 4875ffd83dbSDimitry Andric default: 4885ffd83dbSDimitry Andric m_opcode.SetOpcodeBytes(data.PeekData(data_offset, min_op_byte_size), 4895ffd83dbSDimitry Andric min_op_byte_size); 4905ffd83dbSDimitry Andric got_op = true; 4915ffd83dbSDimitry Andric break; 4925ffd83dbSDimitry Andric } 4935ffd83dbSDimitry Andric } 4945ffd83dbSDimitry Andric if (!got_op) { 4955ffd83dbSDimitry Andric bool is_alternate_isa = false; 4965ffd83dbSDimitry Andric DisassemblerLLVMC::MCDisasmInstance *mc_disasm_ptr = 4975ffd83dbSDimitry Andric GetDisasmToUse(is_alternate_isa, disasm); 4985ffd83dbSDimitry Andric 4995ffd83dbSDimitry Andric const llvm::Triple::ArchType machine = arch.GetMachine(); 5005ffd83dbSDimitry Andric if (machine == llvm::Triple::arm || machine == llvm::Triple::thumb) { 5015ffd83dbSDimitry Andric if (machine == llvm::Triple::thumb || is_alternate_isa) { 5025ffd83dbSDimitry Andric uint32_t thumb_opcode = data.GetU16(&data_offset); 5035ffd83dbSDimitry Andric if ((thumb_opcode & 0xe000) != 0xe000 || 5045ffd83dbSDimitry Andric ((thumb_opcode & 0x1800u) == 0)) { 5055ffd83dbSDimitry Andric m_opcode.SetOpcode16(thumb_opcode, byte_order); 5065ffd83dbSDimitry Andric m_is_valid = true; 5075ffd83dbSDimitry Andric } else { 5085ffd83dbSDimitry Andric thumb_opcode <<= 16; 5095ffd83dbSDimitry Andric thumb_opcode |= data.GetU16(&data_offset); 5105ffd83dbSDimitry Andric m_opcode.SetOpcode16_2(thumb_opcode, byte_order); 5115ffd83dbSDimitry Andric m_is_valid = true; 5125ffd83dbSDimitry Andric } 5135ffd83dbSDimitry Andric } else { 5145ffd83dbSDimitry Andric m_opcode.SetOpcode32(data.GetU32(&data_offset), byte_order); 5155ffd83dbSDimitry Andric m_is_valid = true; 5165ffd83dbSDimitry Andric } 5175ffd83dbSDimitry Andric } else { 5185ffd83dbSDimitry Andric // The opcode isn't evenly sized, so we need to actually use the llvm 5195ffd83dbSDimitry Andric // disassembler to parse it and get the size. 5205ffd83dbSDimitry Andric uint8_t *opcode_data = 5215ffd83dbSDimitry Andric const_cast<uint8_t *>(data.PeekData(data_offset, 1)); 5225ffd83dbSDimitry Andric const size_t opcode_data_len = data.BytesLeft(data_offset); 5235ffd83dbSDimitry Andric const addr_t pc = m_address.GetFileAddress(); 5245ffd83dbSDimitry Andric llvm::MCInst inst; 5255ffd83dbSDimitry Andric 5265ffd83dbSDimitry Andric const size_t inst_size = 5275ffd83dbSDimitry Andric mc_disasm_ptr->GetMCInst(opcode_data, opcode_data_len, pc, inst); 5285ffd83dbSDimitry Andric if (inst_size == 0) 5295ffd83dbSDimitry Andric m_opcode.Clear(); 5305ffd83dbSDimitry Andric else { 5315ffd83dbSDimitry Andric m_opcode.SetOpcodeBytes(opcode_data, inst_size); 5325ffd83dbSDimitry Andric m_is_valid = true; 5335ffd83dbSDimitry Andric } 5345ffd83dbSDimitry Andric } 5355ffd83dbSDimitry Andric } 5365ffd83dbSDimitry Andric return m_opcode.GetByteSize(); 5375ffd83dbSDimitry Andric } 5385ffd83dbSDimitry Andric return 0; 5395ffd83dbSDimitry Andric } 5405ffd83dbSDimitry Andric 5415ffd83dbSDimitry Andric void AppendComment(std::string &description) { 5425ffd83dbSDimitry Andric if (m_comment.empty()) 5435ffd83dbSDimitry Andric m_comment.swap(description); 5445ffd83dbSDimitry Andric else { 5455ffd83dbSDimitry Andric m_comment.append(", "); 5465ffd83dbSDimitry Andric m_comment.append(description); 5475ffd83dbSDimitry Andric } 5485ffd83dbSDimitry Andric } 5495ffd83dbSDimitry Andric 550972a253aSDimitry Andric lldb::InstructionControlFlowKind 551972a253aSDimitry Andric GetControlFlowKind(const lldb_private::ExecutionContext *exe_ctx) override { 552972a253aSDimitry Andric DisassemblerScope disasm(*this, exe_ctx); 553972a253aSDimitry Andric if (disasm){ 554972a253aSDimitry Andric if (disasm->GetArchitecture().GetMachine() == llvm::Triple::x86) 555972a253aSDimitry Andric return x86::GetControlFlowKind(/*is_64b=*/false, m_opcode); 556972a253aSDimitry Andric else if (disasm->GetArchitecture().GetMachine() == llvm::Triple::x86_64) 557972a253aSDimitry Andric return x86::GetControlFlowKind(/*is_64b=*/true, m_opcode); 558972a253aSDimitry Andric } 559972a253aSDimitry Andric 560972a253aSDimitry Andric return eInstructionControlFlowKindUnknown; 561972a253aSDimitry Andric } 562972a253aSDimitry Andric 5635ffd83dbSDimitry Andric void CalculateMnemonicOperandsAndComment( 5645ffd83dbSDimitry Andric const lldb_private::ExecutionContext *exe_ctx) override { 5655ffd83dbSDimitry Andric DataExtractor data; 5665ffd83dbSDimitry Andric const AddressClass address_class = GetAddressClass(); 5675ffd83dbSDimitry Andric 5685ffd83dbSDimitry Andric if (m_opcode.GetData(data)) { 5695ffd83dbSDimitry Andric std::string out_string; 570*5f757f3fSDimitry Andric std::string markup_out_string; 5715ffd83dbSDimitry Andric std::string comment_string; 572*5f757f3fSDimitry Andric std::string markup_comment_string; 5735ffd83dbSDimitry Andric 5745ffd83dbSDimitry Andric DisassemblerScope disasm(*this, exe_ctx); 5755ffd83dbSDimitry Andric if (disasm) { 5765ffd83dbSDimitry Andric DisassemblerLLVMC::MCDisasmInstance *mc_disasm_ptr; 5775ffd83dbSDimitry Andric 5785ffd83dbSDimitry Andric if (address_class == AddressClass::eCodeAlternateISA) 5795ffd83dbSDimitry Andric mc_disasm_ptr = disasm->m_alternate_disasm_up.get(); 5805ffd83dbSDimitry Andric else 5815ffd83dbSDimitry Andric mc_disasm_ptr = disasm->m_disasm_up.get(); 5825ffd83dbSDimitry Andric 5835ffd83dbSDimitry Andric lldb::addr_t pc = m_address.GetFileAddress(); 5845ffd83dbSDimitry Andric m_using_file_addr = true; 5855ffd83dbSDimitry Andric 5865ffd83dbSDimitry Andric const bool data_from_file = disasm->m_data_from_file; 5875ffd83dbSDimitry Andric bool use_hex_immediates = true; 5885ffd83dbSDimitry Andric Disassembler::HexImmediateStyle hex_style = Disassembler::eHexStyleC; 5895ffd83dbSDimitry Andric 5905ffd83dbSDimitry Andric if (exe_ctx) { 5915ffd83dbSDimitry Andric Target *target = exe_ctx->GetTargetPtr(); 5925ffd83dbSDimitry Andric if (target) { 5935ffd83dbSDimitry Andric use_hex_immediates = target->GetUseHexImmediates(); 5945ffd83dbSDimitry Andric hex_style = target->GetHexImmediateStyle(); 5955ffd83dbSDimitry Andric 5965ffd83dbSDimitry Andric if (!data_from_file) { 5975ffd83dbSDimitry Andric const lldb::addr_t load_addr = m_address.GetLoadAddress(target); 5985ffd83dbSDimitry Andric if (load_addr != LLDB_INVALID_ADDRESS) { 5995ffd83dbSDimitry Andric pc = load_addr; 6005ffd83dbSDimitry Andric m_using_file_addr = false; 6015ffd83dbSDimitry Andric } 6025ffd83dbSDimitry Andric } 6035ffd83dbSDimitry Andric } 6045ffd83dbSDimitry Andric } 6055ffd83dbSDimitry Andric 6065ffd83dbSDimitry Andric const uint8_t *opcode_data = data.GetDataStart(); 6075ffd83dbSDimitry Andric const size_t opcode_data_len = data.GetByteSize(); 6085ffd83dbSDimitry Andric llvm::MCInst inst; 6095ffd83dbSDimitry Andric size_t inst_size = 6105ffd83dbSDimitry Andric mc_disasm_ptr->GetMCInst(opcode_data, opcode_data_len, pc, inst); 6115ffd83dbSDimitry Andric 6125ffd83dbSDimitry Andric if (inst_size > 0) { 6135ffd83dbSDimitry Andric mc_disasm_ptr->SetStyle(use_hex_immediates, hex_style); 614*5f757f3fSDimitry Andric 615*5f757f3fSDimitry Andric const bool saved_use_color = mc_disasm_ptr->GetUseColor(); 616*5f757f3fSDimitry Andric mc_disasm_ptr->SetUseColor(false); 617*5f757f3fSDimitry Andric mc_disasm_ptr->PrintMCInst(inst, pc, out_string, comment_string); 618*5f757f3fSDimitry Andric mc_disasm_ptr->SetUseColor(true); 619*5f757f3fSDimitry Andric mc_disasm_ptr->PrintMCInst(inst, pc, markup_out_string, 620*5f757f3fSDimitry Andric markup_comment_string); 621*5f757f3fSDimitry Andric mc_disasm_ptr->SetUseColor(saved_use_color); 6225ffd83dbSDimitry Andric 6235ffd83dbSDimitry Andric if (!comment_string.empty()) { 6245ffd83dbSDimitry Andric AppendComment(comment_string); 6255ffd83dbSDimitry Andric } 6265ffd83dbSDimitry Andric } 6275ffd83dbSDimitry Andric 6285ffd83dbSDimitry Andric if (inst_size == 0) { 6295ffd83dbSDimitry Andric m_comment.assign("unknown opcode"); 6305ffd83dbSDimitry Andric inst_size = m_opcode.GetByteSize(); 6315ffd83dbSDimitry Andric StreamString mnemonic_strm; 6325ffd83dbSDimitry Andric lldb::offset_t offset = 0; 6335ffd83dbSDimitry Andric lldb::ByteOrder byte_order = data.GetByteOrder(); 6345ffd83dbSDimitry Andric switch (inst_size) { 6355ffd83dbSDimitry Andric case 1: { 6365ffd83dbSDimitry Andric const uint8_t uval8 = data.GetU8(&offset); 6375ffd83dbSDimitry Andric m_opcode.SetOpcode8(uval8, byte_order); 6385ffd83dbSDimitry Andric m_opcode_name.assign(".byte"); 6395ffd83dbSDimitry Andric mnemonic_strm.Printf("0x%2.2x", uval8); 6405ffd83dbSDimitry Andric } break; 6415ffd83dbSDimitry Andric case 2: { 6425ffd83dbSDimitry Andric const uint16_t uval16 = data.GetU16(&offset); 6435ffd83dbSDimitry Andric m_opcode.SetOpcode16(uval16, byte_order); 6445ffd83dbSDimitry Andric m_opcode_name.assign(".short"); 6455ffd83dbSDimitry Andric mnemonic_strm.Printf("0x%4.4x", uval16); 6465ffd83dbSDimitry Andric } break; 6475ffd83dbSDimitry Andric case 4: { 6485ffd83dbSDimitry Andric const uint32_t uval32 = data.GetU32(&offset); 6495ffd83dbSDimitry Andric m_opcode.SetOpcode32(uval32, byte_order); 6505ffd83dbSDimitry Andric m_opcode_name.assign(".long"); 6515ffd83dbSDimitry Andric mnemonic_strm.Printf("0x%8.8x", uval32); 6525ffd83dbSDimitry Andric } break; 6535ffd83dbSDimitry Andric case 8: { 6545ffd83dbSDimitry Andric const uint64_t uval64 = data.GetU64(&offset); 6555ffd83dbSDimitry Andric m_opcode.SetOpcode64(uval64, byte_order); 6565ffd83dbSDimitry Andric m_opcode_name.assign(".quad"); 6575ffd83dbSDimitry Andric mnemonic_strm.Printf("0x%16.16" PRIx64, uval64); 6585ffd83dbSDimitry Andric } break; 6595ffd83dbSDimitry Andric default: 6605ffd83dbSDimitry Andric if (inst_size == 0) 6615ffd83dbSDimitry Andric return; 6625ffd83dbSDimitry Andric else { 6635ffd83dbSDimitry Andric const uint8_t *bytes = data.PeekData(offset, inst_size); 6645ffd83dbSDimitry Andric if (bytes == nullptr) 6655ffd83dbSDimitry Andric return; 6665ffd83dbSDimitry Andric m_opcode_name.assign(".byte"); 6675ffd83dbSDimitry Andric m_opcode.SetOpcodeBytes(bytes, inst_size); 6685ffd83dbSDimitry Andric mnemonic_strm.Printf("0x%2.2x", bytes[0]); 6695ffd83dbSDimitry Andric for (uint32_t i = 1; i < inst_size; ++i) 6705ffd83dbSDimitry Andric mnemonic_strm.Printf(" 0x%2.2x", bytes[i]); 6715ffd83dbSDimitry Andric } 6725ffd83dbSDimitry Andric break; 6735ffd83dbSDimitry Andric } 6745ffd83dbSDimitry Andric m_mnemonics = std::string(mnemonic_strm.GetString()); 6755ffd83dbSDimitry Andric return; 6765ffd83dbSDimitry Andric } 6775ffd83dbSDimitry Andric 6785ffd83dbSDimitry Andric static RegularExpression s_regex( 6795ffd83dbSDimitry Andric llvm::StringRef("[ \t]*([^ ^\t]+)[ \t]*([^ ^\t].*)?")); 6805ffd83dbSDimitry Andric 6815ffd83dbSDimitry Andric llvm::SmallVector<llvm::StringRef, 4> matches; 6825ffd83dbSDimitry Andric if (s_regex.Execute(out_string, &matches)) { 6835ffd83dbSDimitry Andric m_opcode_name = matches[1].str(); 6845ffd83dbSDimitry Andric m_mnemonics = matches[2].str(); 6855ffd83dbSDimitry Andric } 686*5f757f3fSDimitry Andric matches.clear(); 687*5f757f3fSDimitry Andric if (s_regex.Execute(markup_out_string, &matches)) { 688*5f757f3fSDimitry Andric m_markup_opcode_name = matches[1].str(); 689*5f757f3fSDimitry Andric m_markup_mnemonics = matches[2].str(); 690*5f757f3fSDimitry Andric } 6915ffd83dbSDimitry Andric } 6925ffd83dbSDimitry Andric } 6935ffd83dbSDimitry Andric } 6945ffd83dbSDimitry Andric 6955ffd83dbSDimitry Andric bool IsValid() const { return m_is_valid; } 6965ffd83dbSDimitry Andric 6975ffd83dbSDimitry Andric bool UsingFileAddress() const { return m_using_file_addr; } 6985ffd83dbSDimitry Andric size_t GetByteSize() const { return m_opcode.GetByteSize(); } 6995ffd83dbSDimitry Andric 7005ffd83dbSDimitry Andric /// Grants exclusive access to the disassembler and initializes it with the 7015ffd83dbSDimitry Andric /// given InstructionLLVMC and an optional ExecutionContext. 7025ffd83dbSDimitry Andric class DisassemblerScope { 7035ffd83dbSDimitry Andric std::shared_ptr<DisassemblerLLVMC> m_disasm; 7045ffd83dbSDimitry Andric 7055ffd83dbSDimitry Andric public: 7065ffd83dbSDimitry Andric explicit DisassemblerScope( 7075ffd83dbSDimitry Andric InstructionLLVMC &i, 7085ffd83dbSDimitry Andric const lldb_private::ExecutionContext *exe_ctx = nullptr) 7095ffd83dbSDimitry Andric : m_disasm(i.m_disasm_wp.lock()) { 7105ffd83dbSDimitry Andric m_disasm->m_mutex.lock(); 7115ffd83dbSDimitry Andric m_disasm->m_inst = &i; 7125ffd83dbSDimitry Andric m_disasm->m_exe_ctx = exe_ctx; 7135ffd83dbSDimitry Andric } 7145ffd83dbSDimitry Andric ~DisassemblerScope() { m_disasm->m_mutex.unlock(); } 7155ffd83dbSDimitry Andric 7165ffd83dbSDimitry Andric /// Evaluates to true if this scope contains a valid disassembler. 7175ffd83dbSDimitry Andric operator bool() const { return static_cast<bool>(m_disasm); } 7185ffd83dbSDimitry Andric 7195ffd83dbSDimitry Andric std::shared_ptr<DisassemblerLLVMC> operator->() { return m_disasm; } 7205ffd83dbSDimitry Andric }; 7215ffd83dbSDimitry Andric 7225ffd83dbSDimitry Andric static llvm::StringRef::const_iterator 7235ffd83dbSDimitry Andric ConsumeWhitespace(llvm::StringRef::const_iterator osi, 7245ffd83dbSDimitry Andric llvm::StringRef::const_iterator ose) { 7255ffd83dbSDimitry Andric while (osi != ose) { 7265ffd83dbSDimitry Andric switch (*osi) { 7275ffd83dbSDimitry Andric default: 7285ffd83dbSDimitry Andric return osi; 7295ffd83dbSDimitry Andric case ' ': 7305ffd83dbSDimitry Andric case '\t': 7315ffd83dbSDimitry Andric break; 7325ffd83dbSDimitry Andric } 7335ffd83dbSDimitry Andric ++osi; 7345ffd83dbSDimitry Andric } 7355ffd83dbSDimitry Andric 7365ffd83dbSDimitry Andric return osi; 7375ffd83dbSDimitry Andric } 7385ffd83dbSDimitry Andric 7395ffd83dbSDimitry Andric static std::pair<bool, llvm::StringRef::const_iterator> 7405ffd83dbSDimitry Andric ConsumeChar(llvm::StringRef::const_iterator osi, const char c, 7415ffd83dbSDimitry Andric llvm::StringRef::const_iterator ose) { 7425ffd83dbSDimitry Andric bool found = false; 7435ffd83dbSDimitry Andric 7445ffd83dbSDimitry Andric osi = ConsumeWhitespace(osi, ose); 7455ffd83dbSDimitry Andric if (osi != ose && *osi == c) { 7465ffd83dbSDimitry Andric found = true; 7475ffd83dbSDimitry Andric ++osi; 7485ffd83dbSDimitry Andric } 7495ffd83dbSDimitry Andric 7505ffd83dbSDimitry Andric return std::make_pair(found, osi); 7515ffd83dbSDimitry Andric } 7525ffd83dbSDimitry Andric 7535ffd83dbSDimitry Andric static std::pair<Operand, llvm::StringRef::const_iterator> 7545ffd83dbSDimitry Andric ParseRegisterName(llvm::StringRef::const_iterator osi, 7555ffd83dbSDimitry Andric llvm::StringRef::const_iterator ose) { 7565ffd83dbSDimitry Andric Operand ret; 7575ffd83dbSDimitry Andric ret.m_type = Operand::Type::Register; 7585ffd83dbSDimitry Andric std::string str; 7595ffd83dbSDimitry Andric 7605ffd83dbSDimitry Andric osi = ConsumeWhitespace(osi, ose); 7615ffd83dbSDimitry Andric 7625ffd83dbSDimitry Andric while (osi != ose) { 7635ffd83dbSDimitry Andric if (*osi >= '0' && *osi <= '9') { 7645ffd83dbSDimitry Andric if (str.empty()) { 7655ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 7665ffd83dbSDimitry Andric } else { 7675ffd83dbSDimitry Andric str.push_back(*osi); 7685ffd83dbSDimitry Andric } 7695ffd83dbSDimitry Andric } else if (*osi >= 'a' && *osi <= 'z') { 7705ffd83dbSDimitry Andric str.push_back(*osi); 7715ffd83dbSDimitry Andric } else { 7725ffd83dbSDimitry Andric switch (*osi) { 7735ffd83dbSDimitry Andric default: 7745ffd83dbSDimitry Andric if (str.empty()) { 7755ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 7765ffd83dbSDimitry Andric } else { 7775ffd83dbSDimitry Andric ret.m_register = ConstString(str); 7785ffd83dbSDimitry Andric return std::make_pair(ret, osi); 7795ffd83dbSDimitry Andric } 7805ffd83dbSDimitry Andric case '%': 7815ffd83dbSDimitry Andric if (!str.empty()) { 7825ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 7835ffd83dbSDimitry Andric } 7845ffd83dbSDimitry Andric break; 7855ffd83dbSDimitry Andric } 7865ffd83dbSDimitry Andric } 7875ffd83dbSDimitry Andric ++osi; 7885ffd83dbSDimitry Andric } 7895ffd83dbSDimitry Andric 7905ffd83dbSDimitry Andric ret.m_register = ConstString(str); 7915ffd83dbSDimitry Andric return std::make_pair(ret, osi); 7925ffd83dbSDimitry Andric } 7935ffd83dbSDimitry Andric 7945ffd83dbSDimitry Andric static std::pair<Operand, llvm::StringRef::const_iterator> 7955ffd83dbSDimitry Andric ParseImmediate(llvm::StringRef::const_iterator osi, 7965ffd83dbSDimitry Andric llvm::StringRef::const_iterator ose) { 7975ffd83dbSDimitry Andric Operand ret; 7985ffd83dbSDimitry Andric ret.m_type = Operand::Type::Immediate; 7995ffd83dbSDimitry Andric std::string str; 8005ffd83dbSDimitry Andric bool is_hex = false; 8015ffd83dbSDimitry Andric 8025ffd83dbSDimitry Andric osi = ConsumeWhitespace(osi, ose); 8035ffd83dbSDimitry Andric 8045ffd83dbSDimitry Andric while (osi != ose) { 8055ffd83dbSDimitry Andric if (*osi >= '0' && *osi <= '9') { 8065ffd83dbSDimitry Andric str.push_back(*osi); 8075ffd83dbSDimitry Andric } else if (*osi >= 'a' && *osi <= 'f') { 8085ffd83dbSDimitry Andric if (is_hex) { 8095ffd83dbSDimitry Andric str.push_back(*osi); 8105ffd83dbSDimitry Andric } else { 8115ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 8125ffd83dbSDimitry Andric } 8135ffd83dbSDimitry Andric } else { 8145ffd83dbSDimitry Andric switch (*osi) { 8155ffd83dbSDimitry Andric default: 8165ffd83dbSDimitry Andric if (str.empty()) { 8175ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 8185ffd83dbSDimitry Andric } else { 8195ffd83dbSDimitry Andric ret.m_immediate = strtoull(str.c_str(), nullptr, 0); 8205ffd83dbSDimitry Andric return std::make_pair(ret, osi); 8215ffd83dbSDimitry Andric } 8225ffd83dbSDimitry Andric case 'x': 8235ffd83dbSDimitry Andric if (!str.compare("0")) { 8245ffd83dbSDimitry Andric is_hex = true; 8255ffd83dbSDimitry Andric str.push_back(*osi); 8265ffd83dbSDimitry Andric } else { 8275ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 8285ffd83dbSDimitry Andric } 8295ffd83dbSDimitry Andric break; 8305ffd83dbSDimitry Andric case '#': 8315ffd83dbSDimitry Andric case '$': 8325ffd83dbSDimitry Andric if (!str.empty()) { 8335ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 8345ffd83dbSDimitry Andric } 8355ffd83dbSDimitry Andric break; 8365ffd83dbSDimitry Andric case '-': 8375ffd83dbSDimitry Andric if (str.empty()) { 8385ffd83dbSDimitry Andric ret.m_negative = true; 8395ffd83dbSDimitry Andric } else { 8405ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 8415ffd83dbSDimitry Andric } 8425ffd83dbSDimitry Andric } 8435ffd83dbSDimitry Andric } 8445ffd83dbSDimitry Andric ++osi; 8455ffd83dbSDimitry Andric } 8465ffd83dbSDimitry Andric 8475ffd83dbSDimitry Andric ret.m_immediate = strtoull(str.c_str(), nullptr, 0); 8485ffd83dbSDimitry Andric return std::make_pair(ret, osi); 8495ffd83dbSDimitry Andric } 8505ffd83dbSDimitry Andric 8515ffd83dbSDimitry Andric // -0x5(%rax,%rax,2) 8525ffd83dbSDimitry Andric static std::pair<Operand, llvm::StringRef::const_iterator> 8535ffd83dbSDimitry Andric ParseIntelIndexedAccess(llvm::StringRef::const_iterator osi, 8545ffd83dbSDimitry Andric llvm::StringRef::const_iterator ose) { 8555ffd83dbSDimitry Andric std::pair<Operand, llvm::StringRef::const_iterator> offset_and_iterator = 8565ffd83dbSDimitry Andric ParseImmediate(osi, ose); 8575ffd83dbSDimitry Andric if (offset_and_iterator.first.IsValid()) { 8585ffd83dbSDimitry Andric osi = offset_and_iterator.second; 8595ffd83dbSDimitry Andric } 8605ffd83dbSDimitry Andric 8615ffd83dbSDimitry Andric bool found = false; 8625ffd83dbSDimitry Andric std::tie(found, osi) = ConsumeChar(osi, '(', ose); 8635ffd83dbSDimitry Andric if (!found) { 8645ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 8655ffd83dbSDimitry Andric } 8665ffd83dbSDimitry Andric 8675ffd83dbSDimitry Andric std::pair<Operand, llvm::StringRef::const_iterator> base_and_iterator = 8685ffd83dbSDimitry Andric ParseRegisterName(osi, ose); 8695ffd83dbSDimitry Andric if (base_and_iterator.first.IsValid()) { 8705ffd83dbSDimitry Andric osi = base_and_iterator.second; 8715ffd83dbSDimitry Andric } else { 8725ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 8735ffd83dbSDimitry Andric } 8745ffd83dbSDimitry Andric 8755ffd83dbSDimitry Andric std::tie(found, osi) = ConsumeChar(osi, ',', ose); 8765ffd83dbSDimitry Andric if (!found) { 8775ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 8785ffd83dbSDimitry Andric } 8795ffd83dbSDimitry Andric 8805ffd83dbSDimitry Andric std::pair<Operand, llvm::StringRef::const_iterator> index_and_iterator = 8815ffd83dbSDimitry Andric ParseRegisterName(osi, ose); 8825ffd83dbSDimitry Andric if (index_and_iterator.first.IsValid()) { 8835ffd83dbSDimitry Andric osi = index_and_iterator.second; 8845ffd83dbSDimitry Andric } else { 8855ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 8865ffd83dbSDimitry Andric } 8875ffd83dbSDimitry Andric 8885ffd83dbSDimitry Andric std::tie(found, osi) = ConsumeChar(osi, ',', ose); 8895ffd83dbSDimitry Andric if (!found) { 8905ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 8915ffd83dbSDimitry Andric } 8925ffd83dbSDimitry Andric 8935ffd83dbSDimitry Andric std::pair<Operand, llvm::StringRef::const_iterator> 8945ffd83dbSDimitry Andric multiplier_and_iterator = ParseImmediate(osi, ose); 8955ffd83dbSDimitry Andric if (index_and_iterator.first.IsValid()) { 8965ffd83dbSDimitry Andric osi = index_and_iterator.second; 8975ffd83dbSDimitry Andric } else { 8985ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 8995ffd83dbSDimitry Andric } 9005ffd83dbSDimitry Andric 9015ffd83dbSDimitry Andric std::tie(found, osi) = ConsumeChar(osi, ')', ose); 9025ffd83dbSDimitry Andric if (!found) { 9035ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 9045ffd83dbSDimitry Andric } 9055ffd83dbSDimitry Andric 9065ffd83dbSDimitry Andric Operand product; 9075ffd83dbSDimitry Andric product.m_type = Operand::Type::Product; 9085ffd83dbSDimitry Andric product.m_children.push_back(index_and_iterator.first); 9095ffd83dbSDimitry Andric product.m_children.push_back(multiplier_and_iterator.first); 9105ffd83dbSDimitry Andric 9115ffd83dbSDimitry Andric Operand index; 9125ffd83dbSDimitry Andric index.m_type = Operand::Type::Sum; 9135ffd83dbSDimitry Andric index.m_children.push_back(base_and_iterator.first); 9145ffd83dbSDimitry Andric index.m_children.push_back(product); 9155ffd83dbSDimitry Andric 9165ffd83dbSDimitry Andric if (offset_and_iterator.first.IsValid()) { 9175ffd83dbSDimitry Andric Operand offset; 9185ffd83dbSDimitry Andric offset.m_type = Operand::Type::Sum; 9195ffd83dbSDimitry Andric offset.m_children.push_back(offset_and_iterator.first); 9205ffd83dbSDimitry Andric offset.m_children.push_back(index); 9215ffd83dbSDimitry Andric 9225ffd83dbSDimitry Andric Operand deref; 9235ffd83dbSDimitry Andric deref.m_type = Operand::Type::Dereference; 9245ffd83dbSDimitry Andric deref.m_children.push_back(offset); 9255ffd83dbSDimitry Andric return std::make_pair(deref, osi); 9265ffd83dbSDimitry Andric } else { 9275ffd83dbSDimitry Andric Operand deref; 9285ffd83dbSDimitry Andric deref.m_type = Operand::Type::Dereference; 9295ffd83dbSDimitry Andric deref.m_children.push_back(index); 9305ffd83dbSDimitry Andric return std::make_pair(deref, osi); 9315ffd83dbSDimitry Andric } 9325ffd83dbSDimitry Andric } 9335ffd83dbSDimitry Andric 9345ffd83dbSDimitry Andric // -0x10(%rbp) 9355ffd83dbSDimitry Andric static std::pair<Operand, llvm::StringRef::const_iterator> 9365ffd83dbSDimitry Andric ParseIntelDerefAccess(llvm::StringRef::const_iterator osi, 9375ffd83dbSDimitry Andric llvm::StringRef::const_iterator ose) { 9385ffd83dbSDimitry Andric std::pair<Operand, llvm::StringRef::const_iterator> offset_and_iterator = 9395ffd83dbSDimitry Andric ParseImmediate(osi, ose); 9405ffd83dbSDimitry Andric if (offset_and_iterator.first.IsValid()) { 9415ffd83dbSDimitry Andric osi = offset_and_iterator.second; 9425ffd83dbSDimitry Andric } 9435ffd83dbSDimitry Andric 9445ffd83dbSDimitry Andric bool found = false; 9455ffd83dbSDimitry Andric std::tie(found, osi) = ConsumeChar(osi, '(', ose); 9465ffd83dbSDimitry Andric if (!found) { 9475ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 9485ffd83dbSDimitry Andric } 9495ffd83dbSDimitry Andric 9505ffd83dbSDimitry Andric std::pair<Operand, llvm::StringRef::const_iterator> base_and_iterator = 9515ffd83dbSDimitry Andric ParseRegisterName(osi, ose); 9525ffd83dbSDimitry Andric if (base_and_iterator.first.IsValid()) { 9535ffd83dbSDimitry Andric osi = base_and_iterator.second; 9545ffd83dbSDimitry Andric } else { 9555ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 9565ffd83dbSDimitry Andric } 9575ffd83dbSDimitry Andric 9585ffd83dbSDimitry Andric std::tie(found, osi) = ConsumeChar(osi, ')', ose); 9595ffd83dbSDimitry Andric if (!found) { 9605ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 9615ffd83dbSDimitry Andric } 9625ffd83dbSDimitry Andric 9635ffd83dbSDimitry Andric if (offset_and_iterator.first.IsValid()) { 9645ffd83dbSDimitry Andric Operand offset; 9655ffd83dbSDimitry Andric offset.m_type = Operand::Type::Sum; 9665ffd83dbSDimitry Andric offset.m_children.push_back(offset_and_iterator.first); 9675ffd83dbSDimitry Andric offset.m_children.push_back(base_and_iterator.first); 9685ffd83dbSDimitry Andric 9695ffd83dbSDimitry Andric Operand deref; 9705ffd83dbSDimitry Andric deref.m_type = Operand::Type::Dereference; 9715ffd83dbSDimitry Andric deref.m_children.push_back(offset); 9725ffd83dbSDimitry Andric return std::make_pair(deref, osi); 9735ffd83dbSDimitry Andric } else { 9745ffd83dbSDimitry Andric Operand deref; 9755ffd83dbSDimitry Andric deref.m_type = Operand::Type::Dereference; 9765ffd83dbSDimitry Andric deref.m_children.push_back(base_and_iterator.first); 9775ffd83dbSDimitry Andric return std::make_pair(deref, osi); 9785ffd83dbSDimitry Andric } 9795ffd83dbSDimitry Andric } 9805ffd83dbSDimitry Andric 9815ffd83dbSDimitry Andric // [sp, #8]! 9825ffd83dbSDimitry Andric static std::pair<Operand, llvm::StringRef::const_iterator> 9835ffd83dbSDimitry Andric ParseARMOffsetAccess(llvm::StringRef::const_iterator osi, 9845ffd83dbSDimitry Andric llvm::StringRef::const_iterator ose) { 9855ffd83dbSDimitry Andric bool found = false; 9865ffd83dbSDimitry Andric std::tie(found, osi) = ConsumeChar(osi, '[', ose); 9875ffd83dbSDimitry Andric if (!found) { 9885ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 9895ffd83dbSDimitry Andric } 9905ffd83dbSDimitry Andric 9915ffd83dbSDimitry Andric std::pair<Operand, llvm::StringRef::const_iterator> base_and_iterator = 9925ffd83dbSDimitry Andric ParseRegisterName(osi, ose); 9935ffd83dbSDimitry Andric if (base_and_iterator.first.IsValid()) { 9945ffd83dbSDimitry Andric osi = base_and_iterator.second; 9955ffd83dbSDimitry Andric } else { 9965ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 9975ffd83dbSDimitry Andric } 9985ffd83dbSDimitry Andric 9995ffd83dbSDimitry Andric std::tie(found, osi) = ConsumeChar(osi, ',', ose); 10005ffd83dbSDimitry Andric if (!found) { 10015ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 10025ffd83dbSDimitry Andric } 10035ffd83dbSDimitry Andric 10045ffd83dbSDimitry Andric std::pair<Operand, llvm::StringRef::const_iterator> offset_and_iterator = 10055ffd83dbSDimitry Andric ParseImmediate(osi, ose); 10065ffd83dbSDimitry Andric if (offset_and_iterator.first.IsValid()) { 10075ffd83dbSDimitry Andric osi = offset_and_iterator.second; 10085ffd83dbSDimitry Andric } 10095ffd83dbSDimitry Andric 10105ffd83dbSDimitry Andric std::tie(found, osi) = ConsumeChar(osi, ']', ose); 10115ffd83dbSDimitry Andric if (!found) { 10125ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 10135ffd83dbSDimitry Andric } 10145ffd83dbSDimitry Andric 10155ffd83dbSDimitry Andric Operand offset; 10165ffd83dbSDimitry Andric offset.m_type = Operand::Type::Sum; 10175ffd83dbSDimitry Andric offset.m_children.push_back(offset_and_iterator.first); 10185ffd83dbSDimitry Andric offset.m_children.push_back(base_and_iterator.first); 10195ffd83dbSDimitry Andric 10205ffd83dbSDimitry Andric Operand deref; 10215ffd83dbSDimitry Andric deref.m_type = Operand::Type::Dereference; 10225ffd83dbSDimitry Andric deref.m_children.push_back(offset); 10235ffd83dbSDimitry Andric return std::make_pair(deref, osi); 10245ffd83dbSDimitry Andric } 10255ffd83dbSDimitry Andric 10265ffd83dbSDimitry Andric // [sp] 10275ffd83dbSDimitry Andric static std::pair<Operand, llvm::StringRef::const_iterator> 10285ffd83dbSDimitry Andric ParseARMDerefAccess(llvm::StringRef::const_iterator osi, 10295ffd83dbSDimitry Andric llvm::StringRef::const_iterator ose) { 10305ffd83dbSDimitry Andric bool found = false; 10315ffd83dbSDimitry Andric std::tie(found, osi) = ConsumeChar(osi, '[', ose); 10325ffd83dbSDimitry Andric if (!found) { 10335ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 10345ffd83dbSDimitry Andric } 10355ffd83dbSDimitry Andric 10365ffd83dbSDimitry Andric std::pair<Operand, llvm::StringRef::const_iterator> base_and_iterator = 10375ffd83dbSDimitry Andric ParseRegisterName(osi, ose); 10385ffd83dbSDimitry Andric if (base_and_iterator.first.IsValid()) { 10395ffd83dbSDimitry Andric osi = base_and_iterator.second; 10405ffd83dbSDimitry Andric } else { 10415ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 10425ffd83dbSDimitry Andric } 10435ffd83dbSDimitry Andric 10445ffd83dbSDimitry Andric std::tie(found, osi) = ConsumeChar(osi, ']', ose); 10455ffd83dbSDimitry Andric if (!found) { 10465ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 10475ffd83dbSDimitry Andric } 10485ffd83dbSDimitry Andric 10495ffd83dbSDimitry Andric Operand deref; 10505ffd83dbSDimitry Andric deref.m_type = Operand::Type::Dereference; 10515ffd83dbSDimitry Andric deref.m_children.push_back(base_and_iterator.first); 10525ffd83dbSDimitry Andric return std::make_pair(deref, osi); 10535ffd83dbSDimitry Andric } 10545ffd83dbSDimitry Andric 10555ffd83dbSDimitry Andric static void DumpOperand(const Operand &op, Stream &s) { 10565ffd83dbSDimitry Andric switch (op.m_type) { 10575ffd83dbSDimitry Andric case Operand::Type::Dereference: 10585ffd83dbSDimitry Andric s.PutCString("*"); 10595ffd83dbSDimitry Andric DumpOperand(op.m_children[0], s); 10605ffd83dbSDimitry Andric break; 10615ffd83dbSDimitry Andric case Operand::Type::Immediate: 10625ffd83dbSDimitry Andric if (op.m_negative) { 10635ffd83dbSDimitry Andric s.PutCString("-"); 10645ffd83dbSDimitry Andric } 10655ffd83dbSDimitry Andric s.PutCString(llvm::to_string(op.m_immediate)); 10665ffd83dbSDimitry Andric break; 10675ffd83dbSDimitry Andric case Operand::Type::Invalid: 10685ffd83dbSDimitry Andric s.PutCString("Invalid"); 10695ffd83dbSDimitry Andric break; 10705ffd83dbSDimitry Andric case Operand::Type::Product: 10715ffd83dbSDimitry Andric s.PutCString("("); 10725ffd83dbSDimitry Andric DumpOperand(op.m_children[0], s); 10735ffd83dbSDimitry Andric s.PutCString("*"); 10745ffd83dbSDimitry Andric DumpOperand(op.m_children[1], s); 10755ffd83dbSDimitry Andric s.PutCString(")"); 10765ffd83dbSDimitry Andric break; 10775ffd83dbSDimitry Andric case Operand::Type::Register: 10785ffd83dbSDimitry Andric s.PutCString(op.m_register.GetStringRef()); 10795ffd83dbSDimitry Andric break; 10805ffd83dbSDimitry Andric case Operand::Type::Sum: 10815ffd83dbSDimitry Andric s.PutCString("("); 10825ffd83dbSDimitry Andric DumpOperand(op.m_children[0], s); 10835ffd83dbSDimitry Andric s.PutCString("+"); 10845ffd83dbSDimitry Andric DumpOperand(op.m_children[1], s); 10855ffd83dbSDimitry Andric s.PutCString(")"); 10865ffd83dbSDimitry Andric break; 10875ffd83dbSDimitry Andric } 10885ffd83dbSDimitry Andric } 10895ffd83dbSDimitry Andric 10905ffd83dbSDimitry Andric bool ParseOperands( 10915ffd83dbSDimitry Andric llvm::SmallVectorImpl<Instruction::Operand> &operands) override { 10925ffd83dbSDimitry Andric const char *operands_string = GetOperands(nullptr); 10935ffd83dbSDimitry Andric 10945ffd83dbSDimitry Andric if (!operands_string) { 10955ffd83dbSDimitry Andric return false; 10965ffd83dbSDimitry Andric } 10975ffd83dbSDimitry Andric 10985ffd83dbSDimitry Andric llvm::StringRef operands_ref(operands_string); 10995ffd83dbSDimitry Andric 11005ffd83dbSDimitry Andric llvm::StringRef::const_iterator osi = operands_ref.begin(); 11015ffd83dbSDimitry Andric llvm::StringRef::const_iterator ose = operands_ref.end(); 11025ffd83dbSDimitry Andric 11035ffd83dbSDimitry Andric while (osi != ose) { 11045ffd83dbSDimitry Andric Operand operand; 11055ffd83dbSDimitry Andric llvm::StringRef::const_iterator iter; 11065ffd83dbSDimitry Andric 11075ffd83dbSDimitry Andric if ((std::tie(operand, iter) = ParseIntelIndexedAccess(osi, ose), 11085ffd83dbSDimitry Andric operand.IsValid()) || 11095ffd83dbSDimitry Andric (std::tie(operand, iter) = ParseIntelDerefAccess(osi, ose), 11105ffd83dbSDimitry Andric operand.IsValid()) || 11115ffd83dbSDimitry Andric (std::tie(operand, iter) = ParseARMOffsetAccess(osi, ose), 11125ffd83dbSDimitry Andric operand.IsValid()) || 11135ffd83dbSDimitry Andric (std::tie(operand, iter) = ParseARMDerefAccess(osi, ose), 11145ffd83dbSDimitry Andric operand.IsValid()) || 11155ffd83dbSDimitry Andric (std::tie(operand, iter) = ParseRegisterName(osi, ose), 11165ffd83dbSDimitry Andric operand.IsValid()) || 11175ffd83dbSDimitry Andric (std::tie(operand, iter) = ParseImmediate(osi, ose), 11185ffd83dbSDimitry Andric operand.IsValid())) { 11195ffd83dbSDimitry Andric osi = iter; 11205ffd83dbSDimitry Andric operands.push_back(operand); 11215ffd83dbSDimitry Andric } else { 11225ffd83dbSDimitry Andric return false; 11235ffd83dbSDimitry Andric } 11245ffd83dbSDimitry Andric 11255ffd83dbSDimitry Andric std::pair<bool, llvm::StringRef::const_iterator> found_and_iter = 11265ffd83dbSDimitry Andric ConsumeChar(osi, ',', ose); 11275ffd83dbSDimitry Andric if (found_and_iter.first) { 11285ffd83dbSDimitry Andric osi = found_and_iter.second; 11295ffd83dbSDimitry Andric } 11305ffd83dbSDimitry Andric 11315ffd83dbSDimitry Andric osi = ConsumeWhitespace(osi, ose); 11325ffd83dbSDimitry Andric } 11335ffd83dbSDimitry Andric 11345ffd83dbSDimitry Andric DisassemblerSP disasm_sp = m_disasm_wp.lock(); 11355ffd83dbSDimitry Andric 11365ffd83dbSDimitry Andric if (disasm_sp && operands.size() > 1) { 11375ffd83dbSDimitry Andric // TODO tie this into the MC Disassembler's notion of clobbers. 11385ffd83dbSDimitry Andric switch (disasm_sp->GetArchitecture().GetMachine()) { 11395ffd83dbSDimitry Andric default: 11405ffd83dbSDimitry Andric break; 11415ffd83dbSDimitry Andric case llvm::Triple::x86: 11425ffd83dbSDimitry Andric case llvm::Triple::x86_64: 11435ffd83dbSDimitry Andric operands[operands.size() - 1].m_clobbered = true; 11445ffd83dbSDimitry Andric break; 11455ffd83dbSDimitry Andric case llvm::Triple::arm: 11465ffd83dbSDimitry Andric operands[0].m_clobbered = true; 11475ffd83dbSDimitry Andric break; 11485ffd83dbSDimitry Andric } 11495ffd83dbSDimitry Andric } 11505ffd83dbSDimitry Andric 115181ad6265SDimitry Andric if (Log *log = GetLog(LLDBLog::Process)) { 11525ffd83dbSDimitry Andric StreamString ss; 11535ffd83dbSDimitry Andric 11545ffd83dbSDimitry Andric ss.Printf("[%s] expands to %zu operands:\n", operands_string, 11555ffd83dbSDimitry Andric operands.size()); 11565ffd83dbSDimitry Andric for (const Operand &operand : operands) { 11575ffd83dbSDimitry Andric ss.PutCString(" "); 11585ffd83dbSDimitry Andric DumpOperand(operand, ss); 11595ffd83dbSDimitry Andric ss.PutCString("\n"); 11605ffd83dbSDimitry Andric } 11615ffd83dbSDimitry Andric 11625ffd83dbSDimitry Andric log->PutString(ss.GetString()); 11635ffd83dbSDimitry Andric } 11645ffd83dbSDimitry Andric 11655ffd83dbSDimitry Andric return true; 11665ffd83dbSDimitry Andric } 11675ffd83dbSDimitry Andric 11685ffd83dbSDimitry Andric bool IsCall() override { 11695ffd83dbSDimitry Andric VisitInstruction(); 11705ffd83dbSDimitry Andric return m_is_call; 11715ffd83dbSDimitry Andric } 11725ffd83dbSDimitry Andric 11735ffd83dbSDimitry Andric protected: 11745ffd83dbSDimitry Andric std::weak_ptr<DisassemblerLLVMC> m_disasm_wp; 11755ffd83dbSDimitry Andric 11765ffd83dbSDimitry Andric bool m_is_valid = false; 117781ad6265SDimitry Andric bool m_using_file_addr = false; 11785ffd83dbSDimitry Andric bool m_has_visited_instruction = false; 11795ffd83dbSDimitry Andric 11805ffd83dbSDimitry Andric // Be conservative. If we didn't understand the instruction, say it: 11815ffd83dbSDimitry Andric // - Might branch 11825ffd83dbSDimitry Andric // - Does not have a delay slot 11835ffd83dbSDimitry Andric // - Is not a call 1184349cc55cSDimitry Andric // - Is not a load 1185349cc55cSDimitry Andric // - Is not an authenticated instruction 11865ffd83dbSDimitry Andric bool m_does_branch = true; 11875ffd83dbSDimitry Andric bool m_has_delay_slot = false; 11885ffd83dbSDimitry Andric bool m_is_call = false; 1189349cc55cSDimitry Andric bool m_is_load = false; 1190349cc55cSDimitry Andric bool m_is_authenticated = false; 11915ffd83dbSDimitry Andric 11925ffd83dbSDimitry Andric void VisitInstruction() { 11935ffd83dbSDimitry Andric if (m_has_visited_instruction) 11945ffd83dbSDimitry Andric return; 11955ffd83dbSDimitry Andric 11965ffd83dbSDimitry Andric DisassemblerScope disasm(*this); 11975ffd83dbSDimitry Andric if (!disasm) 11985ffd83dbSDimitry Andric return; 11995ffd83dbSDimitry Andric 12005ffd83dbSDimitry Andric DataExtractor data; 12015ffd83dbSDimitry Andric if (!m_opcode.GetData(data)) 12025ffd83dbSDimitry Andric return; 12035ffd83dbSDimitry Andric 12045ffd83dbSDimitry Andric bool is_alternate_isa; 12055ffd83dbSDimitry Andric lldb::addr_t pc = m_address.GetFileAddress(); 12065ffd83dbSDimitry Andric DisassemblerLLVMC::MCDisasmInstance *mc_disasm_ptr = 12075ffd83dbSDimitry Andric GetDisasmToUse(is_alternate_isa, disasm); 12085ffd83dbSDimitry Andric const uint8_t *opcode_data = data.GetDataStart(); 12095ffd83dbSDimitry Andric const size_t opcode_data_len = data.GetByteSize(); 12105ffd83dbSDimitry Andric llvm::MCInst inst; 12115ffd83dbSDimitry Andric const size_t inst_size = 12125ffd83dbSDimitry Andric mc_disasm_ptr->GetMCInst(opcode_data, opcode_data_len, pc, inst); 12135ffd83dbSDimitry Andric if (inst_size == 0) 12145ffd83dbSDimitry Andric return; 12155ffd83dbSDimitry Andric 12165ffd83dbSDimitry Andric m_has_visited_instruction = true; 12175ffd83dbSDimitry Andric m_does_branch = mc_disasm_ptr->CanBranch(inst); 12185ffd83dbSDimitry Andric m_has_delay_slot = mc_disasm_ptr->HasDelaySlot(inst); 12195ffd83dbSDimitry Andric m_is_call = mc_disasm_ptr->IsCall(inst); 1220349cc55cSDimitry Andric m_is_load = mc_disasm_ptr->IsLoad(inst); 1221349cc55cSDimitry Andric m_is_authenticated = mc_disasm_ptr->IsAuthenticated(inst); 12225ffd83dbSDimitry Andric } 12235ffd83dbSDimitry Andric 12245ffd83dbSDimitry Andric private: 12255ffd83dbSDimitry Andric DisassemblerLLVMC::MCDisasmInstance * 12265ffd83dbSDimitry Andric GetDisasmToUse(bool &is_alternate_isa, DisassemblerScope &disasm) { 12275ffd83dbSDimitry Andric is_alternate_isa = false; 12285ffd83dbSDimitry Andric if (disasm) { 12295ffd83dbSDimitry Andric if (disasm->m_alternate_disasm_up) { 12305ffd83dbSDimitry Andric const AddressClass address_class = GetAddressClass(); 12315ffd83dbSDimitry Andric 12325ffd83dbSDimitry Andric if (address_class == AddressClass::eCodeAlternateISA) { 12335ffd83dbSDimitry Andric is_alternate_isa = true; 12345ffd83dbSDimitry Andric return disasm->m_alternate_disasm_up.get(); 12355ffd83dbSDimitry Andric } 12365ffd83dbSDimitry Andric } 12375ffd83dbSDimitry Andric return disasm->m_disasm_up.get(); 12385ffd83dbSDimitry Andric } 12395ffd83dbSDimitry Andric return nullptr; 12405ffd83dbSDimitry Andric } 12415ffd83dbSDimitry Andric }; 12425ffd83dbSDimitry Andric 12435ffd83dbSDimitry Andric std::unique_ptr<DisassemblerLLVMC::MCDisasmInstance> 12445ffd83dbSDimitry Andric DisassemblerLLVMC::MCDisasmInstance::Create(const char *triple, const char *cpu, 12455ffd83dbSDimitry Andric const char *features_str, 12465ffd83dbSDimitry Andric unsigned flavor, 12475ffd83dbSDimitry Andric DisassemblerLLVMC &owner) { 12485ffd83dbSDimitry Andric using Instance = std::unique_ptr<DisassemblerLLVMC::MCDisasmInstance>; 12495ffd83dbSDimitry Andric 12505ffd83dbSDimitry Andric std::string Status; 12515ffd83dbSDimitry Andric const llvm::Target *curr_target = 12525ffd83dbSDimitry Andric llvm::TargetRegistry::lookupTarget(triple, Status); 12535ffd83dbSDimitry Andric if (!curr_target) 12545ffd83dbSDimitry Andric return Instance(); 12555ffd83dbSDimitry Andric 12565ffd83dbSDimitry Andric std::unique_ptr<llvm::MCInstrInfo> instr_info_up( 12575ffd83dbSDimitry Andric curr_target->createMCInstrInfo()); 12585ffd83dbSDimitry Andric if (!instr_info_up) 12595ffd83dbSDimitry Andric return Instance(); 12605ffd83dbSDimitry Andric 12615ffd83dbSDimitry Andric std::unique_ptr<llvm::MCRegisterInfo> reg_info_up( 12625ffd83dbSDimitry Andric curr_target->createMCRegInfo(triple)); 12635ffd83dbSDimitry Andric if (!reg_info_up) 12645ffd83dbSDimitry Andric return Instance(); 12655ffd83dbSDimitry Andric 12665ffd83dbSDimitry Andric std::unique_ptr<llvm::MCSubtargetInfo> subtarget_info_up( 12675ffd83dbSDimitry Andric curr_target->createMCSubtargetInfo(triple, cpu, features_str)); 12685ffd83dbSDimitry Andric if (!subtarget_info_up) 12695ffd83dbSDimitry Andric return Instance(); 12705ffd83dbSDimitry Andric 12715ffd83dbSDimitry Andric llvm::MCTargetOptions MCOptions; 12725ffd83dbSDimitry Andric std::unique_ptr<llvm::MCAsmInfo> asm_info_up( 12735ffd83dbSDimitry Andric curr_target->createMCAsmInfo(*reg_info_up, triple, MCOptions)); 12745ffd83dbSDimitry Andric if (!asm_info_up) 12755ffd83dbSDimitry Andric return Instance(); 12765ffd83dbSDimitry Andric 12775ffd83dbSDimitry Andric std::unique_ptr<llvm::MCContext> context_up( 1278fe6060f1SDimitry Andric new llvm::MCContext(llvm::Triple(triple), asm_info_up.get(), 1279fe6060f1SDimitry Andric reg_info_up.get(), subtarget_info_up.get())); 12805ffd83dbSDimitry Andric if (!context_up) 12815ffd83dbSDimitry Andric return Instance(); 12825ffd83dbSDimitry Andric 12835ffd83dbSDimitry Andric std::unique_ptr<llvm::MCDisassembler> disasm_up( 12845ffd83dbSDimitry Andric curr_target->createMCDisassembler(*subtarget_info_up, *context_up)); 12855ffd83dbSDimitry Andric if (!disasm_up) 12865ffd83dbSDimitry Andric return Instance(); 12875ffd83dbSDimitry Andric 12885ffd83dbSDimitry Andric std::unique_ptr<llvm::MCRelocationInfo> rel_info_up( 12895ffd83dbSDimitry Andric curr_target->createMCRelocationInfo(triple, *context_up)); 12905ffd83dbSDimitry Andric if (!rel_info_up) 12915ffd83dbSDimitry Andric return Instance(); 12925ffd83dbSDimitry Andric 12935ffd83dbSDimitry Andric std::unique_ptr<llvm::MCSymbolizer> symbolizer_up( 12945ffd83dbSDimitry Andric curr_target->createMCSymbolizer( 12955ffd83dbSDimitry Andric triple, nullptr, DisassemblerLLVMC::SymbolLookupCallback, &owner, 12965ffd83dbSDimitry Andric context_up.get(), std::move(rel_info_up))); 12975ffd83dbSDimitry Andric disasm_up->setSymbolizer(std::move(symbolizer_up)); 12985ffd83dbSDimitry Andric 12995ffd83dbSDimitry Andric unsigned asm_printer_variant = 13005ffd83dbSDimitry Andric flavor == ~0U ? asm_info_up->getAssemblerDialect() : flavor; 13015ffd83dbSDimitry Andric 13025ffd83dbSDimitry Andric std::unique_ptr<llvm::MCInstPrinter> instr_printer_up( 13035ffd83dbSDimitry Andric curr_target->createMCInstPrinter(llvm::Triple{triple}, 13045ffd83dbSDimitry Andric asm_printer_variant, *asm_info_up, 13055ffd83dbSDimitry Andric *instr_info_up, *reg_info_up)); 13065ffd83dbSDimitry Andric if (!instr_printer_up) 13075ffd83dbSDimitry Andric return Instance(); 13085ffd83dbSDimitry Andric 1309*5f757f3fSDimitry Andric instr_printer_up->setPrintBranchImmAsAddress(true); 1310*5f757f3fSDimitry Andric 1311*5f757f3fSDimitry Andric // Not all targets may have registered createMCInstrAnalysis(). 1312*5f757f3fSDimitry Andric std::unique_ptr<llvm::MCInstrAnalysis> instr_analysis_up( 1313*5f757f3fSDimitry Andric curr_target->createMCInstrAnalysis(instr_info_up.get())); 1314*5f757f3fSDimitry Andric 1315*5f757f3fSDimitry Andric return Instance(new MCDisasmInstance( 1316*5f757f3fSDimitry Andric std::move(instr_info_up), std::move(reg_info_up), 13175ffd83dbSDimitry Andric std::move(subtarget_info_up), std::move(asm_info_up), 1318*5f757f3fSDimitry Andric std::move(context_up), std::move(disasm_up), std::move(instr_printer_up), 1319*5f757f3fSDimitry Andric std::move(instr_analysis_up))); 13205ffd83dbSDimitry Andric } 13215ffd83dbSDimitry Andric 13225ffd83dbSDimitry Andric DisassemblerLLVMC::MCDisasmInstance::MCDisasmInstance( 13235ffd83dbSDimitry Andric std::unique_ptr<llvm::MCInstrInfo> &&instr_info_up, 13245ffd83dbSDimitry Andric std::unique_ptr<llvm::MCRegisterInfo> &®_info_up, 13255ffd83dbSDimitry Andric std::unique_ptr<llvm::MCSubtargetInfo> &&subtarget_info_up, 13265ffd83dbSDimitry Andric std::unique_ptr<llvm::MCAsmInfo> &&asm_info_up, 13275ffd83dbSDimitry Andric std::unique_ptr<llvm::MCContext> &&context_up, 13285ffd83dbSDimitry Andric std::unique_ptr<llvm::MCDisassembler> &&disasm_up, 1329*5f757f3fSDimitry Andric std::unique_ptr<llvm::MCInstPrinter> &&instr_printer_up, 1330*5f757f3fSDimitry Andric std::unique_ptr<llvm::MCInstrAnalysis> &&instr_analysis_up) 13315ffd83dbSDimitry Andric : m_instr_info_up(std::move(instr_info_up)), 13325ffd83dbSDimitry Andric m_reg_info_up(std::move(reg_info_up)), 13335ffd83dbSDimitry Andric m_subtarget_info_up(std::move(subtarget_info_up)), 13345ffd83dbSDimitry Andric m_asm_info_up(std::move(asm_info_up)), 13355ffd83dbSDimitry Andric m_context_up(std::move(context_up)), m_disasm_up(std::move(disasm_up)), 1336*5f757f3fSDimitry Andric m_instr_printer_up(std::move(instr_printer_up)), 1337*5f757f3fSDimitry Andric m_instr_analysis_up(std::move(instr_analysis_up)) { 13385ffd83dbSDimitry Andric assert(m_instr_info_up && m_reg_info_up && m_subtarget_info_up && 13395ffd83dbSDimitry Andric m_asm_info_up && m_context_up && m_disasm_up && m_instr_printer_up); 13405ffd83dbSDimitry Andric } 13415ffd83dbSDimitry Andric 13425ffd83dbSDimitry Andric uint64_t DisassemblerLLVMC::MCDisasmInstance::GetMCInst( 13435ffd83dbSDimitry Andric const uint8_t *opcode_data, size_t opcode_data_len, lldb::addr_t pc, 13445ffd83dbSDimitry Andric llvm::MCInst &mc_inst) const { 13455ffd83dbSDimitry Andric llvm::ArrayRef<uint8_t> data(opcode_data, opcode_data_len); 13465ffd83dbSDimitry Andric llvm::MCDisassembler::DecodeStatus status; 13475ffd83dbSDimitry Andric 13485ffd83dbSDimitry Andric uint64_t new_inst_size; 13495ffd83dbSDimitry Andric status = m_disasm_up->getInstruction(mc_inst, new_inst_size, data, pc, 13505ffd83dbSDimitry Andric llvm::nulls()); 13515ffd83dbSDimitry Andric if (status == llvm::MCDisassembler::Success) 13525ffd83dbSDimitry Andric return new_inst_size; 13535ffd83dbSDimitry Andric else 13545ffd83dbSDimitry Andric return 0; 13555ffd83dbSDimitry Andric } 13565ffd83dbSDimitry Andric 13575ffd83dbSDimitry Andric void DisassemblerLLVMC::MCDisasmInstance::PrintMCInst( 1358*5f757f3fSDimitry Andric llvm::MCInst &mc_inst, lldb::addr_t pc, std::string &inst_string, 13595ffd83dbSDimitry Andric std::string &comments_string) { 13605ffd83dbSDimitry Andric llvm::raw_string_ostream inst_stream(inst_string); 13615ffd83dbSDimitry Andric llvm::raw_string_ostream comments_stream(comments_string); 13625ffd83dbSDimitry Andric 1363*5f757f3fSDimitry Andric inst_stream.enable_colors(m_instr_printer_up->getUseColor()); 13645ffd83dbSDimitry Andric m_instr_printer_up->setCommentStream(comments_stream); 1365*5f757f3fSDimitry Andric m_instr_printer_up->printInst(&mc_inst, pc, llvm::StringRef(), 13665ffd83dbSDimitry Andric *m_subtarget_info_up, inst_stream); 13675ffd83dbSDimitry Andric m_instr_printer_up->setCommentStream(llvm::nulls()); 1368*5f757f3fSDimitry Andric 13695ffd83dbSDimitry Andric comments_stream.flush(); 13705ffd83dbSDimitry Andric 13715ffd83dbSDimitry Andric static std::string g_newlines("\r\n"); 13725ffd83dbSDimitry Andric 13735ffd83dbSDimitry Andric for (size_t newline_pos = 0; 13745ffd83dbSDimitry Andric (newline_pos = comments_string.find_first_of(g_newlines, newline_pos)) != 13755ffd83dbSDimitry Andric comments_string.npos; 13765ffd83dbSDimitry Andric /**/) { 13775ffd83dbSDimitry Andric comments_string.replace(comments_string.begin() + newline_pos, 13785ffd83dbSDimitry Andric comments_string.begin() + newline_pos + 1, 1, ' '); 13795ffd83dbSDimitry Andric } 13805ffd83dbSDimitry Andric } 13815ffd83dbSDimitry Andric 13825ffd83dbSDimitry Andric void DisassemblerLLVMC::MCDisasmInstance::SetStyle( 13835ffd83dbSDimitry Andric bool use_hex_immed, HexImmediateStyle hex_style) { 13845ffd83dbSDimitry Andric m_instr_printer_up->setPrintImmHex(use_hex_immed); 13855ffd83dbSDimitry Andric switch (hex_style) { 13865ffd83dbSDimitry Andric case eHexStyleC: 13875ffd83dbSDimitry Andric m_instr_printer_up->setPrintHexStyle(llvm::HexStyle::C); 13885ffd83dbSDimitry Andric break; 13895ffd83dbSDimitry Andric case eHexStyleAsm: 13905ffd83dbSDimitry Andric m_instr_printer_up->setPrintHexStyle(llvm::HexStyle::Asm); 13915ffd83dbSDimitry Andric break; 13925ffd83dbSDimitry Andric } 13935ffd83dbSDimitry Andric } 13945ffd83dbSDimitry Andric 1395*5f757f3fSDimitry Andric void DisassemblerLLVMC::MCDisasmInstance::SetUseColor(bool use_color) { 1396*5f757f3fSDimitry Andric m_instr_printer_up->setUseColor(use_color); 1397*5f757f3fSDimitry Andric } 1398*5f757f3fSDimitry Andric 1399*5f757f3fSDimitry Andric bool DisassemblerLLVMC::MCDisasmInstance::GetUseColor() const { 1400*5f757f3fSDimitry Andric return m_instr_printer_up->getUseColor(); 1401*5f757f3fSDimitry Andric } 1402*5f757f3fSDimitry Andric 14035ffd83dbSDimitry Andric bool DisassemblerLLVMC::MCDisasmInstance::CanBranch( 14045ffd83dbSDimitry Andric llvm::MCInst &mc_inst) const { 1405*5f757f3fSDimitry Andric if (m_instr_analysis_up) 1406*5f757f3fSDimitry Andric return m_instr_analysis_up->mayAffectControlFlow(mc_inst, *m_reg_info_up); 14075ffd83dbSDimitry Andric return m_instr_info_up->get(mc_inst.getOpcode()) 14085ffd83dbSDimitry Andric .mayAffectControlFlow(mc_inst, *m_reg_info_up); 14095ffd83dbSDimitry Andric } 14105ffd83dbSDimitry Andric 14115ffd83dbSDimitry Andric bool DisassemblerLLVMC::MCDisasmInstance::HasDelaySlot( 14125ffd83dbSDimitry Andric llvm::MCInst &mc_inst) const { 14135ffd83dbSDimitry Andric return m_instr_info_up->get(mc_inst.getOpcode()).hasDelaySlot(); 14145ffd83dbSDimitry Andric } 14155ffd83dbSDimitry Andric 14165ffd83dbSDimitry Andric bool DisassemblerLLVMC::MCDisasmInstance::IsCall(llvm::MCInst &mc_inst) const { 1417*5f757f3fSDimitry Andric if (m_instr_analysis_up) 1418*5f757f3fSDimitry Andric return m_instr_analysis_up->isCall(mc_inst); 14195ffd83dbSDimitry Andric return m_instr_info_up->get(mc_inst.getOpcode()).isCall(); 14205ffd83dbSDimitry Andric } 14215ffd83dbSDimitry Andric 1422349cc55cSDimitry Andric bool DisassemblerLLVMC::MCDisasmInstance::IsLoad(llvm::MCInst &mc_inst) const { 1423349cc55cSDimitry Andric return m_instr_info_up->get(mc_inst.getOpcode()).mayLoad(); 1424349cc55cSDimitry Andric } 1425349cc55cSDimitry Andric 1426349cc55cSDimitry Andric bool DisassemblerLLVMC::MCDisasmInstance::IsAuthenticated( 1427349cc55cSDimitry Andric llvm::MCInst &mc_inst) const { 1428bdd1243dSDimitry Andric const auto &InstrDesc = m_instr_info_up->get(mc_inst.getOpcode()); 1429349cc55cSDimitry Andric 1430349cc55cSDimitry Andric // Treat software auth traps (brk 0xc470 + aut key, where 0x70 == 'p', 0xc4 1431349cc55cSDimitry Andric // == 'a' + 'c') as authenticated instructions for reporting purposes, in 1432349cc55cSDimitry Andric // addition to the standard authenticated instructions specified in ARMv8.3. 1433349cc55cSDimitry Andric bool IsBrkC47x = false; 1434349cc55cSDimitry Andric if (InstrDesc.isTrap() && mc_inst.getNumOperands() == 1) { 1435349cc55cSDimitry Andric const llvm::MCOperand &Op0 = mc_inst.getOperand(0); 1436349cc55cSDimitry Andric if (Op0.isImm() && Op0.getImm() >= 0xc470 && Op0.getImm() <= 0xc474) 1437349cc55cSDimitry Andric IsBrkC47x = true; 1438349cc55cSDimitry Andric } 1439349cc55cSDimitry Andric 1440349cc55cSDimitry Andric return InstrDesc.isAuthenticated() || IsBrkC47x; 1441349cc55cSDimitry Andric } 1442349cc55cSDimitry Andric 14435ffd83dbSDimitry Andric DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch, 14445ffd83dbSDimitry Andric const char *flavor_string) 14455ffd83dbSDimitry Andric : Disassembler(arch, flavor_string), m_exe_ctx(nullptr), m_inst(nullptr), 1446349cc55cSDimitry Andric m_data_from_file(false), m_adrp_address(LLDB_INVALID_ADDRESS), 1447349cc55cSDimitry Andric m_adrp_insn() { 14485ffd83dbSDimitry Andric if (!FlavorValidForArchSpec(arch, m_flavor.c_str())) { 14495ffd83dbSDimitry Andric m_flavor.assign("default"); 14505ffd83dbSDimitry Andric } 14515ffd83dbSDimitry Andric 14525ffd83dbSDimitry Andric unsigned flavor = ~0U; 14535ffd83dbSDimitry Andric llvm::Triple triple = arch.GetTriple(); 14545ffd83dbSDimitry Andric 14555ffd83dbSDimitry Andric // So far the only supported flavor is "intel" on x86. The base class will 14565ffd83dbSDimitry Andric // set this correctly coming in. 14575ffd83dbSDimitry Andric if (triple.getArch() == llvm::Triple::x86 || 14585ffd83dbSDimitry Andric triple.getArch() == llvm::Triple::x86_64) { 14595ffd83dbSDimitry Andric if (m_flavor == "intel") { 14605ffd83dbSDimitry Andric flavor = 1; 14615ffd83dbSDimitry Andric } else if (m_flavor == "att") { 14625ffd83dbSDimitry Andric flavor = 0; 14635ffd83dbSDimitry Andric } 14645ffd83dbSDimitry Andric } 14655ffd83dbSDimitry Andric 14665ffd83dbSDimitry Andric ArchSpec thumb_arch(arch); 14675ffd83dbSDimitry Andric if (triple.getArch() == llvm::Triple::arm) { 14685ffd83dbSDimitry Andric std::string thumb_arch_name(thumb_arch.GetTriple().getArchName().str()); 14695ffd83dbSDimitry Andric // Replace "arm" with "thumb" so we get all thumb variants correct 14705ffd83dbSDimitry Andric if (thumb_arch_name.size() > 3) { 14715ffd83dbSDimitry Andric thumb_arch_name.erase(0, 3); 14725ffd83dbSDimitry Andric thumb_arch_name.insert(0, "thumb"); 14735ffd83dbSDimitry Andric } else { 14741fd87a68SDimitry Andric thumb_arch_name = "thumbv9.3a"; 14755ffd83dbSDimitry Andric } 14765ffd83dbSDimitry Andric thumb_arch.GetTriple().setArchName(llvm::StringRef(thumb_arch_name)); 14775ffd83dbSDimitry Andric } 14785ffd83dbSDimitry Andric 14795ffd83dbSDimitry Andric // If no sub architecture specified then use the most recent arm architecture 14801fd87a68SDimitry Andric // so the disassembler will return all instructions. Without it we will see a 14811fd87a68SDimitry Andric // lot of unknown opcodes if the code uses instructions which are not 14821fd87a68SDimitry Andric // available in the oldest arm version (which is used when no sub architecture 14831fd87a68SDimitry Andric // is specified). 14845ffd83dbSDimitry Andric if (triple.getArch() == llvm::Triple::arm && 14855ffd83dbSDimitry Andric triple.getSubArch() == llvm::Triple::NoSubArch) 14861fd87a68SDimitry Andric triple.setArchName("armv9.3a"); 14875ffd83dbSDimitry Andric 148804eeddc0SDimitry Andric std::string features_str; 14895ffd83dbSDimitry Andric const char *triple_str = triple.getTriple().c_str(); 14905ffd83dbSDimitry Andric 14915ffd83dbSDimitry Andric // ARM Cortex M0-M7 devices only execute thumb instructions 14925ffd83dbSDimitry Andric if (arch.IsAlwaysThumbInstructions()) { 14935ffd83dbSDimitry Andric triple_str = thumb_arch.GetTriple().getTriple().c_str(); 14945ffd83dbSDimitry Andric features_str += "+fp-armv8,"; 14955ffd83dbSDimitry Andric } 14965ffd83dbSDimitry Andric 14975ffd83dbSDimitry Andric const char *cpu = ""; 14985ffd83dbSDimitry Andric 14995ffd83dbSDimitry Andric switch (arch.GetCore()) { 15005ffd83dbSDimitry Andric case ArchSpec::eCore_mips32: 15015ffd83dbSDimitry Andric case ArchSpec::eCore_mips32el: 15025ffd83dbSDimitry Andric cpu = "mips32"; 15035ffd83dbSDimitry Andric break; 15045ffd83dbSDimitry Andric case ArchSpec::eCore_mips32r2: 15055ffd83dbSDimitry Andric case ArchSpec::eCore_mips32r2el: 15065ffd83dbSDimitry Andric cpu = "mips32r2"; 15075ffd83dbSDimitry Andric break; 15085ffd83dbSDimitry Andric case ArchSpec::eCore_mips32r3: 15095ffd83dbSDimitry Andric case ArchSpec::eCore_mips32r3el: 15105ffd83dbSDimitry Andric cpu = "mips32r3"; 15115ffd83dbSDimitry Andric break; 15125ffd83dbSDimitry Andric case ArchSpec::eCore_mips32r5: 15135ffd83dbSDimitry Andric case ArchSpec::eCore_mips32r5el: 15145ffd83dbSDimitry Andric cpu = "mips32r5"; 15155ffd83dbSDimitry Andric break; 15165ffd83dbSDimitry Andric case ArchSpec::eCore_mips32r6: 15175ffd83dbSDimitry Andric case ArchSpec::eCore_mips32r6el: 15185ffd83dbSDimitry Andric cpu = "mips32r6"; 15195ffd83dbSDimitry Andric break; 15205ffd83dbSDimitry Andric case ArchSpec::eCore_mips64: 15215ffd83dbSDimitry Andric case ArchSpec::eCore_mips64el: 15225ffd83dbSDimitry Andric cpu = "mips64"; 15235ffd83dbSDimitry Andric break; 15245ffd83dbSDimitry Andric case ArchSpec::eCore_mips64r2: 15255ffd83dbSDimitry Andric case ArchSpec::eCore_mips64r2el: 15265ffd83dbSDimitry Andric cpu = "mips64r2"; 15275ffd83dbSDimitry Andric break; 15285ffd83dbSDimitry Andric case ArchSpec::eCore_mips64r3: 15295ffd83dbSDimitry Andric case ArchSpec::eCore_mips64r3el: 15305ffd83dbSDimitry Andric cpu = "mips64r3"; 15315ffd83dbSDimitry Andric break; 15325ffd83dbSDimitry Andric case ArchSpec::eCore_mips64r5: 15335ffd83dbSDimitry Andric case ArchSpec::eCore_mips64r5el: 15345ffd83dbSDimitry Andric cpu = "mips64r5"; 15355ffd83dbSDimitry Andric break; 15365ffd83dbSDimitry Andric case ArchSpec::eCore_mips64r6: 15375ffd83dbSDimitry Andric case ArchSpec::eCore_mips64r6el: 15385ffd83dbSDimitry Andric cpu = "mips64r6"; 15395ffd83dbSDimitry Andric break; 15405ffd83dbSDimitry Andric default: 15415ffd83dbSDimitry Andric cpu = ""; 15425ffd83dbSDimitry Andric break; 15435ffd83dbSDimitry Andric } 15445ffd83dbSDimitry Andric 15455ffd83dbSDimitry Andric if (arch.IsMIPS()) { 15465ffd83dbSDimitry Andric uint32_t arch_flags = arch.GetFlags(); 15475ffd83dbSDimitry Andric if (arch_flags & ArchSpec::eMIPSAse_msa) 15485ffd83dbSDimitry Andric features_str += "+msa,"; 15495ffd83dbSDimitry Andric if (arch_flags & ArchSpec::eMIPSAse_dsp) 15505ffd83dbSDimitry Andric features_str += "+dsp,"; 15515ffd83dbSDimitry Andric if (arch_flags & ArchSpec::eMIPSAse_dspr2) 15525ffd83dbSDimitry Andric features_str += "+dspr2,"; 15535ffd83dbSDimitry Andric } 15545ffd83dbSDimitry Andric 155581ad6265SDimitry Andric // If any AArch64 variant, enable latest ISA with all extensions. 1556e8d8bef9SDimitry Andric if (triple.isAArch64()) { 1557753f127fSDimitry Andric features_str += "+all,"; 15585ffd83dbSDimitry Andric 1559e8d8bef9SDimitry Andric if (triple.getVendor() == llvm::Triple::Apple) 15605ffd83dbSDimitry Andric cpu = "apple-latest"; 15615ffd83dbSDimitry Andric } 15625ffd83dbSDimitry Andric 156381ad6265SDimitry Andric if (triple.isRISCV()) { 156481ad6265SDimitry Andric uint32_t arch_flags = arch.GetFlags(); 156581ad6265SDimitry Andric if (arch_flags & ArchSpec::eRISCV_rvc) 156681ad6265SDimitry Andric features_str += "+c,"; 156781ad6265SDimitry Andric if (arch_flags & ArchSpec::eRISCV_rve) 156881ad6265SDimitry Andric features_str += "+e,"; 156981ad6265SDimitry Andric if ((arch_flags & ArchSpec::eRISCV_float_abi_single) == 157081ad6265SDimitry Andric ArchSpec::eRISCV_float_abi_single) 157181ad6265SDimitry Andric features_str += "+f,"; 157281ad6265SDimitry Andric if ((arch_flags & ArchSpec::eRISCV_float_abi_double) == 157381ad6265SDimitry Andric ArchSpec::eRISCV_float_abi_double) 157481ad6265SDimitry Andric features_str += "+f,+d,"; 157581ad6265SDimitry Andric if ((arch_flags & ArchSpec::eRISCV_float_abi_quad) == 157681ad6265SDimitry Andric ArchSpec::eRISCV_float_abi_quad) 157781ad6265SDimitry Andric features_str += "+f,+d,+q,"; 157881ad6265SDimitry Andric // FIXME: how do we detect features such as `+a`, `+m`? 1579*5f757f3fSDimitry Andric // Turn them on by default now, since everyone seems to use them 1580*5f757f3fSDimitry Andric features_str += "+a,+m,"; 158181ad6265SDimitry Andric } 158281ad6265SDimitry Andric 15835ffd83dbSDimitry Andric // We use m_disasm_up.get() to tell whether we are valid or not, so if this 15845ffd83dbSDimitry Andric // isn't good for some reason, we won't be valid and FindPlugin will fail and 15855ffd83dbSDimitry Andric // we won't get used. 15865ffd83dbSDimitry Andric m_disasm_up = MCDisasmInstance::Create(triple_str, cpu, features_str.c_str(), 15875ffd83dbSDimitry Andric flavor, *this); 15885ffd83dbSDimitry Andric 15895ffd83dbSDimitry Andric llvm::Triple::ArchType llvm_arch = triple.getArch(); 15905ffd83dbSDimitry Andric 15915ffd83dbSDimitry Andric // For arm CPUs that can execute arm or thumb instructions, also create a 15925ffd83dbSDimitry Andric // thumb instruction disassembler. 15935ffd83dbSDimitry Andric if (llvm_arch == llvm::Triple::arm) { 15945ffd83dbSDimitry Andric std::string thumb_triple(thumb_arch.GetTriple().getTriple()); 15955ffd83dbSDimitry Andric m_alternate_disasm_up = 15965ffd83dbSDimitry Andric MCDisasmInstance::Create(thumb_triple.c_str(), "", features_str.c_str(), 15975ffd83dbSDimitry Andric flavor, *this); 15985ffd83dbSDimitry Andric if (!m_alternate_disasm_up) 15995ffd83dbSDimitry Andric m_disasm_up.reset(); 16005ffd83dbSDimitry Andric 16015ffd83dbSDimitry Andric } else if (arch.IsMIPS()) { 16025ffd83dbSDimitry Andric /* Create alternate disassembler for MIPS16 and microMIPS */ 16035ffd83dbSDimitry Andric uint32_t arch_flags = arch.GetFlags(); 16045ffd83dbSDimitry Andric if (arch_flags & ArchSpec::eMIPSAse_mips16) 16055ffd83dbSDimitry Andric features_str += "+mips16,"; 16065ffd83dbSDimitry Andric else if (arch_flags & ArchSpec::eMIPSAse_micromips) 16075ffd83dbSDimitry Andric features_str += "+micromips,"; 16085ffd83dbSDimitry Andric 16095ffd83dbSDimitry Andric m_alternate_disasm_up = MCDisasmInstance::Create( 16105ffd83dbSDimitry Andric triple_str, cpu, features_str.c_str(), flavor, *this); 16115ffd83dbSDimitry Andric if (!m_alternate_disasm_up) 16125ffd83dbSDimitry Andric m_disasm_up.reset(); 16135ffd83dbSDimitry Andric } 16145ffd83dbSDimitry Andric } 16155ffd83dbSDimitry Andric 16165ffd83dbSDimitry Andric DisassemblerLLVMC::~DisassemblerLLVMC() = default; 16175ffd83dbSDimitry Andric 161806c3fb27SDimitry Andric lldb::DisassemblerSP DisassemblerLLVMC::CreateInstance(const ArchSpec &arch, 16195ffd83dbSDimitry Andric const char *flavor) { 16205ffd83dbSDimitry Andric if (arch.GetTriple().getArch() != llvm::Triple::UnknownArch) { 162106c3fb27SDimitry Andric auto disasm_sp = std::make_shared<DisassemblerLLVMC>(arch, flavor); 162206c3fb27SDimitry Andric if (disasm_sp && disasm_sp->IsValid()) 162306c3fb27SDimitry Andric return disasm_sp; 16245ffd83dbSDimitry Andric } 162506c3fb27SDimitry Andric return lldb::DisassemblerSP(); 16265ffd83dbSDimitry Andric } 16275ffd83dbSDimitry Andric 16285ffd83dbSDimitry Andric size_t DisassemblerLLVMC::DecodeInstructions(const Address &base_addr, 16295ffd83dbSDimitry Andric const DataExtractor &data, 16305ffd83dbSDimitry Andric lldb::offset_t data_offset, 16315ffd83dbSDimitry Andric size_t num_instructions, 16325ffd83dbSDimitry Andric bool append, bool data_from_file) { 16335ffd83dbSDimitry Andric if (!append) 16345ffd83dbSDimitry Andric m_instruction_list.Clear(); 16355ffd83dbSDimitry Andric 16365ffd83dbSDimitry Andric if (!IsValid()) 16375ffd83dbSDimitry Andric return 0; 16385ffd83dbSDimitry Andric 16395ffd83dbSDimitry Andric m_data_from_file = data_from_file; 16405ffd83dbSDimitry Andric uint32_t data_cursor = data_offset; 16415ffd83dbSDimitry Andric const size_t data_byte_size = data.GetByteSize(); 16425ffd83dbSDimitry Andric uint32_t instructions_parsed = 0; 16435ffd83dbSDimitry Andric Address inst_addr(base_addr); 16445ffd83dbSDimitry Andric 16455ffd83dbSDimitry Andric while (data_cursor < data_byte_size && 16465ffd83dbSDimitry Andric instructions_parsed < num_instructions) { 16475ffd83dbSDimitry Andric 16485ffd83dbSDimitry Andric AddressClass address_class = AddressClass::eCode; 16495ffd83dbSDimitry Andric 16505ffd83dbSDimitry Andric if (m_alternate_disasm_up) 16515ffd83dbSDimitry Andric address_class = inst_addr.GetAddressClass(); 16525ffd83dbSDimitry Andric 16535ffd83dbSDimitry Andric InstructionSP inst_sp( 16545ffd83dbSDimitry Andric new InstructionLLVMC(*this, inst_addr, address_class)); 16555ffd83dbSDimitry Andric 16565ffd83dbSDimitry Andric if (!inst_sp) 16575ffd83dbSDimitry Andric break; 16585ffd83dbSDimitry Andric 16595ffd83dbSDimitry Andric uint32_t inst_size = inst_sp->Decode(*this, data, data_cursor); 16605ffd83dbSDimitry Andric 16615ffd83dbSDimitry Andric if (inst_size == 0) 16625ffd83dbSDimitry Andric break; 16635ffd83dbSDimitry Andric 16645ffd83dbSDimitry Andric m_instruction_list.Append(inst_sp); 16655ffd83dbSDimitry Andric data_cursor += inst_size; 16665ffd83dbSDimitry Andric inst_addr.Slide(inst_size); 16675ffd83dbSDimitry Andric instructions_parsed++; 16685ffd83dbSDimitry Andric } 16695ffd83dbSDimitry Andric 16705ffd83dbSDimitry Andric return data_cursor - data_offset; 16715ffd83dbSDimitry Andric } 16725ffd83dbSDimitry Andric 16735ffd83dbSDimitry Andric void DisassemblerLLVMC::Initialize() { 16745ffd83dbSDimitry Andric PluginManager::RegisterPlugin(GetPluginNameStatic(), 16755ffd83dbSDimitry Andric "Disassembler that uses LLVM MC to disassemble " 16765ffd83dbSDimitry Andric "i386, x86_64, ARM, and ARM64.", 16775ffd83dbSDimitry Andric CreateInstance); 16785ffd83dbSDimitry Andric 16795ffd83dbSDimitry Andric llvm::InitializeAllTargetInfos(); 16805ffd83dbSDimitry Andric llvm::InitializeAllTargetMCs(); 16815ffd83dbSDimitry Andric llvm::InitializeAllAsmParsers(); 16825ffd83dbSDimitry Andric llvm::InitializeAllDisassemblers(); 16835ffd83dbSDimitry Andric } 16845ffd83dbSDimitry Andric 16855ffd83dbSDimitry Andric void DisassemblerLLVMC::Terminate() { 16865ffd83dbSDimitry Andric PluginManager::UnregisterPlugin(CreateInstance); 16875ffd83dbSDimitry Andric } 16885ffd83dbSDimitry Andric 16895ffd83dbSDimitry Andric int DisassemblerLLVMC::OpInfoCallback(void *disassembler, uint64_t pc, 16905ffd83dbSDimitry Andric uint64_t offset, uint64_t size, 16915ffd83dbSDimitry Andric int tag_type, void *tag_bug) { 16925ffd83dbSDimitry Andric return static_cast<DisassemblerLLVMC *>(disassembler) 16935ffd83dbSDimitry Andric ->OpInfo(pc, offset, size, tag_type, tag_bug); 16945ffd83dbSDimitry Andric } 16955ffd83dbSDimitry Andric 16965ffd83dbSDimitry Andric const char *DisassemblerLLVMC::SymbolLookupCallback(void *disassembler, 16975ffd83dbSDimitry Andric uint64_t value, 16985ffd83dbSDimitry Andric uint64_t *type, uint64_t pc, 16995ffd83dbSDimitry Andric const char **name) { 17005ffd83dbSDimitry Andric return static_cast<DisassemblerLLVMC *>(disassembler) 17015ffd83dbSDimitry Andric ->SymbolLookup(value, type, pc, name); 17025ffd83dbSDimitry Andric } 17035ffd83dbSDimitry Andric 17045ffd83dbSDimitry Andric bool DisassemblerLLVMC::FlavorValidForArchSpec( 17055ffd83dbSDimitry Andric const lldb_private::ArchSpec &arch, const char *flavor) { 17065ffd83dbSDimitry Andric llvm::Triple triple = arch.GetTriple(); 17075ffd83dbSDimitry Andric if (flavor == nullptr || strcmp(flavor, "default") == 0) 17085ffd83dbSDimitry Andric return true; 17095ffd83dbSDimitry Andric 17105ffd83dbSDimitry Andric if (triple.getArch() == llvm::Triple::x86 || 17115ffd83dbSDimitry Andric triple.getArch() == llvm::Triple::x86_64) { 17125ffd83dbSDimitry Andric return strcmp(flavor, "intel") == 0 || strcmp(flavor, "att") == 0; 17135ffd83dbSDimitry Andric } else 17145ffd83dbSDimitry Andric return false; 17155ffd83dbSDimitry Andric } 17165ffd83dbSDimitry Andric 17175ffd83dbSDimitry Andric bool DisassemblerLLVMC::IsValid() const { return m_disasm_up.operator bool(); } 17185ffd83dbSDimitry Andric 17195ffd83dbSDimitry Andric int DisassemblerLLVMC::OpInfo(uint64_t PC, uint64_t Offset, uint64_t Size, 17205ffd83dbSDimitry Andric int tag_type, void *tag_bug) { 17215ffd83dbSDimitry Andric switch (tag_type) { 17225ffd83dbSDimitry Andric default: 17235ffd83dbSDimitry Andric break; 17245ffd83dbSDimitry Andric case 1: 17255ffd83dbSDimitry Andric memset(tag_bug, 0, sizeof(::LLVMOpInfo1)); 17265ffd83dbSDimitry Andric break; 17275ffd83dbSDimitry Andric } 17285ffd83dbSDimitry Andric return 0; 17295ffd83dbSDimitry Andric } 17305ffd83dbSDimitry Andric 17315ffd83dbSDimitry Andric const char *DisassemblerLLVMC::SymbolLookup(uint64_t value, uint64_t *type_ptr, 17325ffd83dbSDimitry Andric uint64_t pc, const char **name) { 17335ffd83dbSDimitry Andric if (*type_ptr) { 17345ffd83dbSDimitry Andric if (m_exe_ctx && m_inst) { 17355ffd83dbSDimitry Andric // std::string remove_this_prior_to_checkin; 17365ffd83dbSDimitry Andric Target *target = m_exe_ctx ? m_exe_ctx->GetTargetPtr() : nullptr; 17375ffd83dbSDimitry Andric Address value_so_addr; 17385ffd83dbSDimitry Andric Address pc_so_addr; 1739349cc55cSDimitry Andric if (target->GetArchitecture().GetMachine() == llvm::Triple::aarch64 || 1740349cc55cSDimitry Andric target->GetArchitecture().GetMachine() == llvm::Triple::aarch64_be || 1741349cc55cSDimitry Andric target->GetArchitecture().GetMachine() == llvm::Triple::aarch64_32) { 1742349cc55cSDimitry Andric if (*type_ptr == LLVMDisassembler_ReferenceType_In_ARM64_ADRP) { 1743349cc55cSDimitry Andric m_adrp_address = pc; 1744349cc55cSDimitry Andric m_adrp_insn = value; 1745349cc55cSDimitry Andric *name = nullptr; 1746349cc55cSDimitry Andric *type_ptr = LLVMDisassembler_ReferenceType_InOut_None; 1747349cc55cSDimitry Andric return nullptr; 1748349cc55cSDimitry Andric } 1749349cc55cSDimitry Andric // If this instruction is an ADD and 1750349cc55cSDimitry Andric // the previous instruction was an ADRP and 1751349cc55cSDimitry Andric // the ADRP's register and this ADD's register are the same, 1752349cc55cSDimitry Andric // then this is a pc-relative address calculation. 1753349cc55cSDimitry Andric if (*type_ptr == LLVMDisassembler_ReferenceType_In_ARM64_ADDXri && 175481ad6265SDimitry Andric m_adrp_insn && m_adrp_address == pc - 4 && 1755bdd1243dSDimitry Andric (*m_adrp_insn & 0x1f) == ((value >> 5) & 0x1f)) { 1756349cc55cSDimitry Andric uint32_t addxri_inst; 1757349cc55cSDimitry Andric uint64_t adrp_imm, addxri_imm; 1758349cc55cSDimitry Andric // Get immlo and immhi bits, OR them together to get the ADRP imm 1759349cc55cSDimitry Andric // value. 1760bdd1243dSDimitry Andric adrp_imm = 1761bdd1243dSDimitry Andric ((*m_adrp_insn & 0x00ffffe0) >> 3) | ((*m_adrp_insn >> 29) & 0x3); 1762349cc55cSDimitry Andric // if high bit of immhi after right-shifting set, sign extend 1763349cc55cSDimitry Andric if (adrp_imm & (1ULL << 20)) 1764349cc55cSDimitry Andric adrp_imm |= ~((1ULL << 21) - 1); 1765349cc55cSDimitry Andric 1766349cc55cSDimitry Andric addxri_inst = value; 1767349cc55cSDimitry Andric addxri_imm = (addxri_inst >> 10) & 0xfff; 1768349cc55cSDimitry Andric // check if 'sh' bit is set, shift imm value up if so 1769349cc55cSDimitry Andric // (this would make no sense, ADRP already gave us this part) 1770349cc55cSDimitry Andric if ((addxri_inst >> (12 + 5 + 5)) & 1) 1771349cc55cSDimitry Andric addxri_imm <<= 12; 1772349cc55cSDimitry Andric value = (m_adrp_address & 0xfffffffffffff000LL) + (adrp_imm << 12) + 1773349cc55cSDimitry Andric addxri_imm; 1774349cc55cSDimitry Andric } 1775349cc55cSDimitry Andric m_adrp_address = LLDB_INVALID_ADDRESS; 1776349cc55cSDimitry Andric m_adrp_insn.reset(); 1777349cc55cSDimitry Andric } 1778349cc55cSDimitry Andric 17795ffd83dbSDimitry Andric if (m_inst->UsingFileAddress()) { 17805ffd83dbSDimitry Andric ModuleSP module_sp(m_inst->GetAddress().GetModule()); 17815ffd83dbSDimitry Andric if (module_sp) { 17825ffd83dbSDimitry Andric module_sp->ResolveFileAddress(value, value_so_addr); 17835ffd83dbSDimitry Andric module_sp->ResolveFileAddress(pc, pc_so_addr); 17845ffd83dbSDimitry Andric } 17855ffd83dbSDimitry Andric } else if (target && !target->GetSectionLoadList().IsEmpty()) { 17865ffd83dbSDimitry Andric target->GetSectionLoadList().ResolveLoadAddress(value, value_so_addr); 17875ffd83dbSDimitry Andric target->GetSectionLoadList().ResolveLoadAddress(pc, pc_so_addr); 17885ffd83dbSDimitry Andric } 17895ffd83dbSDimitry Andric 17905ffd83dbSDimitry Andric SymbolContext sym_ctx; 17915ffd83dbSDimitry Andric const SymbolContextItem resolve_scope = 17925ffd83dbSDimitry Andric eSymbolContextFunction | eSymbolContextSymbol; 17935ffd83dbSDimitry Andric if (pc_so_addr.IsValid() && pc_so_addr.GetModule()) { 17945ffd83dbSDimitry Andric pc_so_addr.GetModule()->ResolveSymbolContextForAddress( 17955ffd83dbSDimitry Andric pc_so_addr, resolve_scope, sym_ctx); 17965ffd83dbSDimitry Andric } 17975ffd83dbSDimitry Andric 17985ffd83dbSDimitry Andric if (value_so_addr.IsValid() && value_so_addr.GetSection()) { 17995ffd83dbSDimitry Andric StreamString ss; 18005ffd83dbSDimitry Andric 18015ffd83dbSDimitry Andric bool format_omitting_current_func_name = false; 18025ffd83dbSDimitry Andric if (sym_ctx.symbol || sym_ctx.function) { 18035ffd83dbSDimitry Andric AddressRange range; 18045ffd83dbSDimitry Andric if (sym_ctx.GetAddressRange(resolve_scope, 0, false, range) && 18055ffd83dbSDimitry Andric range.GetBaseAddress().IsValid() && 18065ffd83dbSDimitry Andric range.ContainsLoadAddress(value_so_addr, target)) { 18075ffd83dbSDimitry Andric format_omitting_current_func_name = true; 18085ffd83dbSDimitry Andric } 18095ffd83dbSDimitry Andric } 18105ffd83dbSDimitry Andric 18115ffd83dbSDimitry Andric // If the "value" address (the target address we're symbolicating) is 18125ffd83dbSDimitry Andric // inside the same SymbolContext as the current instruction pc 18135ffd83dbSDimitry Andric // (pc_so_addr), don't print the full function name - just print it 18145ffd83dbSDimitry Andric // with DumpStyleNoFunctionName style, e.g. "<+36>". 18155ffd83dbSDimitry Andric if (format_omitting_current_func_name) { 18165ffd83dbSDimitry Andric value_so_addr.Dump(&ss, target, Address::DumpStyleNoFunctionName, 18175ffd83dbSDimitry Andric Address::DumpStyleSectionNameOffset); 18185ffd83dbSDimitry Andric } else { 18195ffd83dbSDimitry Andric value_so_addr.Dump( 18205ffd83dbSDimitry Andric &ss, target, 18215ffd83dbSDimitry Andric Address::DumpStyleResolvedDescriptionNoFunctionArguments, 18225ffd83dbSDimitry Andric Address::DumpStyleSectionNameOffset); 18235ffd83dbSDimitry Andric } 18245ffd83dbSDimitry Andric 18255ffd83dbSDimitry Andric if (!ss.GetString().empty()) { 18265ffd83dbSDimitry Andric // If Address::Dump returned a multi-line description, most commonly 18275ffd83dbSDimitry Andric // seen when we have multiple levels of inlined functions at an 18285ffd83dbSDimitry Andric // address, only show the first line. 18295ffd83dbSDimitry Andric std::string str = std::string(ss.GetString()); 18305ffd83dbSDimitry Andric size_t first_eol_char = str.find_first_of("\r\n"); 18315ffd83dbSDimitry Andric if (first_eol_char != std::string::npos) { 18325ffd83dbSDimitry Andric str.erase(first_eol_char); 18335ffd83dbSDimitry Andric } 18345ffd83dbSDimitry Andric m_inst->AppendComment(str); 18355ffd83dbSDimitry Andric } 18365ffd83dbSDimitry Andric } 18375ffd83dbSDimitry Andric } 18385ffd83dbSDimitry Andric } 18395ffd83dbSDimitry Andric 1840349cc55cSDimitry Andric // TODO: llvm-objdump sets the type_ptr to the 1841349cc55cSDimitry Andric // LLVMDisassembler_ReferenceType_Out_* values 1842349cc55cSDimitry Andric // based on where value_so_addr is pointing, with 1843349cc55cSDimitry Andric // Mach-O specific augmentations in MachODump.cpp. e.g. 1844349cc55cSDimitry Andric // see what AArch64ExternalSymbolizer::tryAddingSymbolicOperand 1845349cc55cSDimitry Andric // handles. 18465ffd83dbSDimitry Andric *type_ptr = LLVMDisassembler_ReferenceType_InOut_None; 18475ffd83dbSDimitry Andric *name = nullptr; 18485ffd83dbSDimitry Andric return nullptr; 18495ffd83dbSDimitry Andric } 1850