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" 215ffd83dbSDimitry Andric #include "llvm/MC/MCInstrInfo.h" 225ffd83dbSDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 235ffd83dbSDimitry Andric #include "llvm/MC/MCSubtargetInfo.h" 245ffd83dbSDimitry Andric #include "llvm/MC/MCTargetOptions.h" 25349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h" 265ffd83dbSDimitry Andric #include "llvm/Support/ErrorHandling.h" 275ffd83dbSDimitry Andric #include "llvm/Support/ScopedPrinter.h" 285ffd83dbSDimitry Andric #include "llvm/Support/TargetSelect.h" 29*06c3fb27SDimitry Andric #include "llvm/TargetParser/AArch64TargetParser.h" 305ffd83dbSDimitry Andric 315ffd83dbSDimitry Andric #include "lldb/Core/Address.h" 325ffd83dbSDimitry Andric #include "lldb/Core/Module.h" 335ffd83dbSDimitry Andric #include "lldb/Symbol/SymbolContext.h" 345ffd83dbSDimitry Andric #include "lldb/Target/ExecutionContext.h" 355ffd83dbSDimitry Andric #include "lldb/Target/Process.h" 365ffd83dbSDimitry Andric #include "lldb/Target/RegisterContext.h" 375ffd83dbSDimitry Andric #include "lldb/Target/SectionLoadList.h" 385ffd83dbSDimitry Andric #include "lldb/Target/StackFrame.h" 395ffd83dbSDimitry Andric #include "lldb/Target/Target.h" 405ffd83dbSDimitry Andric #include "lldb/Utility/DataExtractor.h" 4181ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h" 425ffd83dbSDimitry Andric #include "lldb/Utility/Log.h" 435ffd83dbSDimitry Andric #include "lldb/Utility/RegularExpression.h" 445ffd83dbSDimitry Andric #include "lldb/Utility/Stream.h" 45bdd1243dSDimitry Andric #include <optional> 465ffd83dbSDimitry Andric 475ffd83dbSDimitry Andric using namespace lldb; 485ffd83dbSDimitry Andric using namespace lldb_private; 495ffd83dbSDimitry Andric 505ffd83dbSDimitry Andric LLDB_PLUGIN_DEFINE(DisassemblerLLVMC) 515ffd83dbSDimitry Andric 525ffd83dbSDimitry Andric class DisassemblerLLVMC::MCDisasmInstance { 535ffd83dbSDimitry Andric public: 545ffd83dbSDimitry Andric static std::unique_ptr<MCDisasmInstance> 555ffd83dbSDimitry Andric Create(const char *triple, const char *cpu, const char *features_str, 565ffd83dbSDimitry Andric unsigned flavor, DisassemblerLLVMC &owner); 575ffd83dbSDimitry Andric 585ffd83dbSDimitry Andric ~MCDisasmInstance() = default; 595ffd83dbSDimitry Andric 605ffd83dbSDimitry Andric uint64_t GetMCInst(const uint8_t *opcode_data, size_t opcode_data_len, 615ffd83dbSDimitry Andric lldb::addr_t pc, llvm::MCInst &mc_inst) const; 625ffd83dbSDimitry Andric void PrintMCInst(llvm::MCInst &mc_inst, std::string &inst_string, 635ffd83dbSDimitry Andric std::string &comments_string); 645ffd83dbSDimitry Andric void SetStyle(bool use_hex_immed, HexImmediateStyle hex_style); 655ffd83dbSDimitry Andric bool CanBranch(llvm::MCInst &mc_inst) const; 665ffd83dbSDimitry Andric bool HasDelaySlot(llvm::MCInst &mc_inst) const; 675ffd83dbSDimitry Andric bool IsCall(llvm::MCInst &mc_inst) const; 68349cc55cSDimitry Andric bool IsLoad(llvm::MCInst &mc_inst) const; 69349cc55cSDimitry Andric bool IsAuthenticated(llvm::MCInst &mc_inst) const; 705ffd83dbSDimitry Andric 715ffd83dbSDimitry Andric private: 725ffd83dbSDimitry Andric MCDisasmInstance(std::unique_ptr<llvm::MCInstrInfo> &&instr_info_up, 735ffd83dbSDimitry Andric std::unique_ptr<llvm::MCRegisterInfo> &®_info_up, 745ffd83dbSDimitry Andric std::unique_ptr<llvm::MCSubtargetInfo> &&subtarget_info_up, 755ffd83dbSDimitry Andric std::unique_ptr<llvm::MCAsmInfo> &&asm_info_up, 765ffd83dbSDimitry Andric std::unique_ptr<llvm::MCContext> &&context_up, 775ffd83dbSDimitry Andric std::unique_ptr<llvm::MCDisassembler> &&disasm_up, 785ffd83dbSDimitry Andric std::unique_ptr<llvm::MCInstPrinter> &&instr_printer_up); 795ffd83dbSDimitry Andric 805ffd83dbSDimitry Andric std::unique_ptr<llvm::MCInstrInfo> m_instr_info_up; 815ffd83dbSDimitry Andric std::unique_ptr<llvm::MCRegisterInfo> m_reg_info_up; 825ffd83dbSDimitry Andric std::unique_ptr<llvm::MCSubtargetInfo> m_subtarget_info_up; 835ffd83dbSDimitry Andric std::unique_ptr<llvm::MCAsmInfo> m_asm_info_up; 845ffd83dbSDimitry Andric std::unique_ptr<llvm::MCContext> m_context_up; 855ffd83dbSDimitry Andric std::unique_ptr<llvm::MCDisassembler> m_disasm_up; 865ffd83dbSDimitry Andric std::unique_ptr<llvm::MCInstPrinter> m_instr_printer_up; 875ffd83dbSDimitry Andric }; 885ffd83dbSDimitry Andric 89972a253aSDimitry Andric namespace x86 { 90972a253aSDimitry Andric 91972a253aSDimitry Andric /// These are the three values deciding instruction control flow kind. 92972a253aSDimitry Andric /// InstructionLengthDecode function decodes an instruction and get this struct. 93972a253aSDimitry Andric /// 94972a253aSDimitry Andric /// primary_opcode 95972a253aSDimitry Andric /// Primary opcode of the instruction. 96972a253aSDimitry Andric /// For one-byte opcode instruction, it's the first byte after prefix. 97972a253aSDimitry Andric /// For two- and three-byte opcodes, it's the second byte. 98972a253aSDimitry Andric /// 99972a253aSDimitry Andric /// opcode_len 100972a253aSDimitry Andric /// The length of opcode in bytes. Valid opcode lengths are 1, 2, or 3. 101972a253aSDimitry Andric /// 102972a253aSDimitry Andric /// modrm 103972a253aSDimitry Andric /// ModR/M byte of the instruction. 104972a253aSDimitry Andric /// Bits[7:6] indicate MOD. Bits[5:3] specify a register and R/M bits[2:0] 105972a253aSDimitry Andric /// may contain a register or specify an addressing mode, depending on MOD. 106972a253aSDimitry Andric struct InstructionOpcodeAndModrm { 107972a253aSDimitry Andric uint8_t primary_opcode; 108972a253aSDimitry Andric uint8_t opcode_len; 109972a253aSDimitry Andric uint8_t modrm; 110972a253aSDimitry Andric }; 111972a253aSDimitry Andric 112972a253aSDimitry Andric /// Determine the InstructionControlFlowKind based on opcode and modrm bytes. 113972a253aSDimitry Andric /// Refer to http://ref.x86asm.net/coder.html for the full list of opcode and 114972a253aSDimitry Andric /// instruction set. 115972a253aSDimitry Andric /// 116972a253aSDimitry Andric /// \param[in] opcode_and_modrm 117972a253aSDimitry Andric /// Contains primary_opcode byte, its length, and ModR/M byte. 118972a253aSDimitry Andric /// Refer to the struct InstructionOpcodeAndModrm for details. 119972a253aSDimitry Andric /// 120972a253aSDimitry Andric /// \return 121972a253aSDimitry Andric /// The control flow kind of the instruction or 122972a253aSDimitry Andric /// eInstructionControlFlowKindOther if the instruction doesn't affect 123972a253aSDimitry Andric /// the control flow of the program. 124972a253aSDimitry Andric lldb::InstructionControlFlowKind 125972a253aSDimitry Andric MapOpcodeIntoControlFlowKind(InstructionOpcodeAndModrm opcode_and_modrm) { 126972a253aSDimitry Andric uint8_t opcode = opcode_and_modrm.primary_opcode; 127972a253aSDimitry Andric uint8_t opcode_len = opcode_and_modrm.opcode_len; 128972a253aSDimitry Andric uint8_t modrm = opcode_and_modrm.modrm; 129972a253aSDimitry Andric 130972a253aSDimitry Andric if (opcode_len > 2) 131972a253aSDimitry Andric return lldb::eInstructionControlFlowKindOther; 132972a253aSDimitry Andric 133972a253aSDimitry Andric if (opcode >= 0x70 && opcode <= 0x7F) { 134972a253aSDimitry Andric if (opcode_len == 1) 135972a253aSDimitry Andric return lldb::eInstructionControlFlowKindCondJump; 136972a253aSDimitry Andric else 137972a253aSDimitry Andric return lldb::eInstructionControlFlowKindOther; 138972a253aSDimitry Andric } 139972a253aSDimitry Andric 140972a253aSDimitry Andric if (opcode >= 0x80 && opcode <= 0x8F) { 141972a253aSDimitry Andric if (opcode_len == 2) 142972a253aSDimitry Andric return lldb::eInstructionControlFlowKindCondJump; 143972a253aSDimitry Andric else 144972a253aSDimitry Andric return lldb::eInstructionControlFlowKindOther; 145972a253aSDimitry Andric } 146972a253aSDimitry Andric 147972a253aSDimitry Andric switch (opcode) { 148972a253aSDimitry Andric case 0x9A: 149972a253aSDimitry Andric if (opcode_len == 1) 150972a253aSDimitry Andric return lldb::eInstructionControlFlowKindFarCall; 151972a253aSDimitry Andric break; 152972a253aSDimitry Andric case 0xFF: 153972a253aSDimitry Andric if (opcode_len == 1) { 154972a253aSDimitry Andric uint8_t modrm_reg = (modrm >> 3) & 7; 155972a253aSDimitry Andric if (modrm_reg == 2) 156972a253aSDimitry Andric return lldb::eInstructionControlFlowKindCall; 157972a253aSDimitry Andric else if (modrm_reg == 3) 158972a253aSDimitry Andric return lldb::eInstructionControlFlowKindFarCall; 159972a253aSDimitry Andric else if (modrm_reg == 4) 160972a253aSDimitry Andric return lldb::eInstructionControlFlowKindJump; 161972a253aSDimitry Andric else if (modrm_reg == 5) 162972a253aSDimitry Andric return lldb::eInstructionControlFlowKindFarJump; 163972a253aSDimitry Andric } 164972a253aSDimitry Andric break; 165972a253aSDimitry Andric case 0xE8: 166972a253aSDimitry Andric if (opcode_len == 1) 167972a253aSDimitry Andric return lldb::eInstructionControlFlowKindCall; 168972a253aSDimitry Andric break; 169972a253aSDimitry Andric case 0xCD: 170972a253aSDimitry Andric case 0xCC: 171972a253aSDimitry Andric case 0xCE: 172972a253aSDimitry Andric case 0xF1: 173972a253aSDimitry Andric if (opcode_len == 1) 174972a253aSDimitry Andric return lldb::eInstructionControlFlowKindFarCall; 175972a253aSDimitry Andric break; 176972a253aSDimitry Andric case 0xCF: 177972a253aSDimitry Andric if (opcode_len == 1) 178972a253aSDimitry Andric return lldb::eInstructionControlFlowKindFarReturn; 179972a253aSDimitry Andric break; 180972a253aSDimitry Andric case 0xE9: 181972a253aSDimitry Andric case 0xEB: 182972a253aSDimitry Andric if (opcode_len == 1) 183972a253aSDimitry Andric return lldb::eInstructionControlFlowKindJump; 184972a253aSDimitry Andric break; 185972a253aSDimitry Andric case 0xEA: 186972a253aSDimitry Andric if (opcode_len == 1) 187972a253aSDimitry Andric return lldb::eInstructionControlFlowKindFarJump; 188972a253aSDimitry Andric break; 189972a253aSDimitry Andric case 0xE3: 190972a253aSDimitry Andric case 0xE0: 191972a253aSDimitry Andric case 0xE1: 192972a253aSDimitry Andric case 0xE2: 193972a253aSDimitry Andric if (opcode_len == 1) 194972a253aSDimitry Andric return lldb::eInstructionControlFlowKindCondJump; 195972a253aSDimitry Andric break; 196972a253aSDimitry Andric case 0xC3: 197972a253aSDimitry Andric case 0xC2: 198972a253aSDimitry Andric if (opcode_len == 1) 199972a253aSDimitry Andric return lldb::eInstructionControlFlowKindReturn; 200972a253aSDimitry Andric break; 201972a253aSDimitry Andric case 0xCB: 202972a253aSDimitry Andric case 0xCA: 203972a253aSDimitry Andric if (opcode_len == 1) 204972a253aSDimitry Andric return lldb::eInstructionControlFlowKindFarReturn; 205972a253aSDimitry Andric break; 206972a253aSDimitry Andric case 0x05: 207972a253aSDimitry Andric case 0x34: 208972a253aSDimitry Andric if (opcode_len == 2) 209972a253aSDimitry Andric return lldb::eInstructionControlFlowKindFarCall; 210972a253aSDimitry Andric break; 211972a253aSDimitry Andric case 0x35: 212972a253aSDimitry Andric case 0x07: 213972a253aSDimitry Andric if (opcode_len == 2) 214972a253aSDimitry Andric return lldb::eInstructionControlFlowKindFarReturn; 215972a253aSDimitry Andric break; 216972a253aSDimitry Andric case 0x01: 217972a253aSDimitry Andric if (opcode_len == 2) { 218972a253aSDimitry Andric switch (modrm) { 219972a253aSDimitry Andric case 0xc1: 220972a253aSDimitry Andric return lldb::eInstructionControlFlowKindFarCall; 221972a253aSDimitry Andric case 0xc2: 222972a253aSDimitry Andric case 0xc3: 223972a253aSDimitry Andric return lldb::eInstructionControlFlowKindFarReturn; 224972a253aSDimitry Andric default: 225972a253aSDimitry Andric break; 226972a253aSDimitry Andric } 227972a253aSDimitry Andric } 228972a253aSDimitry Andric break; 229972a253aSDimitry Andric default: 230972a253aSDimitry Andric break; 231972a253aSDimitry Andric } 232972a253aSDimitry Andric 233972a253aSDimitry Andric return lldb::eInstructionControlFlowKindOther; 234972a253aSDimitry Andric } 235972a253aSDimitry Andric 236972a253aSDimitry Andric /// Decode an instruction into opcode, modrm and opcode_len. 237972a253aSDimitry Andric /// Refer to http://ref.x86asm.net/coder.html for the instruction bytes layout. 238972a253aSDimitry Andric /// Opcodes in x86 are generally the first byte of instruction, though two-byte 239972a253aSDimitry Andric /// instructions and prefixes exist. ModR/M is the byte following the opcode 240972a253aSDimitry Andric /// and adds additional information for how the instruction is executed. 241972a253aSDimitry Andric /// 242972a253aSDimitry Andric /// \param[in] inst_bytes 243972a253aSDimitry Andric /// Raw bytes of the instruction 244972a253aSDimitry Andric /// 245972a253aSDimitry Andric /// 246972a253aSDimitry Andric /// \param[in] bytes_len 247972a253aSDimitry Andric /// The length of the inst_bytes array. 248972a253aSDimitry Andric /// 249972a253aSDimitry Andric /// \param[in] is_exec_mode_64b 250972a253aSDimitry Andric /// If true, the execution mode is 64 bit. 251972a253aSDimitry Andric /// 252972a253aSDimitry Andric /// \return 253972a253aSDimitry Andric /// Returns decoded instruction as struct InstructionOpcodeAndModrm, holding 254972a253aSDimitry Andric /// primary_opcode, opcode_len and modrm byte. Refer to the struct definition 255972a253aSDimitry Andric /// for more details. 256bdd1243dSDimitry Andric /// Otherwise if the given instruction is invalid, returns std::nullopt. 257bdd1243dSDimitry Andric std::optional<InstructionOpcodeAndModrm> 258972a253aSDimitry Andric InstructionLengthDecode(const uint8_t *inst_bytes, int bytes_len, 259972a253aSDimitry Andric bool is_exec_mode_64b) { 260972a253aSDimitry Andric int op_idx = 0; 261972a253aSDimitry Andric bool prefix_done = false; 262972a253aSDimitry Andric InstructionOpcodeAndModrm ret = {0, 0, 0}; 263972a253aSDimitry Andric 264972a253aSDimitry Andric // In most cases, the primary_opcode is the first byte of the instruction 265972a253aSDimitry Andric // but some instructions have a prefix to be skipped for these calculations. 266972a253aSDimitry Andric // The following mapping is inspired from libipt's instruction decoding logic 267972a253aSDimitry Andric // in `src/pt_ild.c` 268972a253aSDimitry Andric while (!prefix_done) { 269972a253aSDimitry Andric if (op_idx >= bytes_len) 270bdd1243dSDimitry Andric return std::nullopt; 271972a253aSDimitry Andric 272972a253aSDimitry Andric ret.primary_opcode = inst_bytes[op_idx]; 273972a253aSDimitry Andric switch (ret.primary_opcode) { 274972a253aSDimitry Andric // prefix_ignore 275972a253aSDimitry Andric case 0x26: 276972a253aSDimitry Andric case 0x2e: 277972a253aSDimitry Andric case 0x36: 278972a253aSDimitry Andric case 0x3e: 279972a253aSDimitry Andric case 0x64: 280972a253aSDimitry Andric case 0x65: 281972a253aSDimitry Andric // prefix_osz, prefix_asz 282972a253aSDimitry Andric case 0x66: 283972a253aSDimitry Andric case 0x67: 284972a253aSDimitry Andric // prefix_lock, prefix_f2, prefix_f3 285972a253aSDimitry Andric case 0xf0: 286972a253aSDimitry Andric case 0xf2: 287972a253aSDimitry Andric case 0xf3: 288972a253aSDimitry Andric op_idx++; 289972a253aSDimitry Andric break; 290972a253aSDimitry Andric 291972a253aSDimitry Andric // prefix_rex 292972a253aSDimitry Andric case 0x40: 293972a253aSDimitry Andric case 0x41: 294972a253aSDimitry Andric case 0x42: 295972a253aSDimitry Andric case 0x43: 296972a253aSDimitry Andric case 0x44: 297972a253aSDimitry Andric case 0x45: 298972a253aSDimitry Andric case 0x46: 299972a253aSDimitry Andric case 0x47: 300972a253aSDimitry Andric case 0x48: 301972a253aSDimitry Andric case 0x49: 302972a253aSDimitry Andric case 0x4a: 303972a253aSDimitry Andric case 0x4b: 304972a253aSDimitry Andric case 0x4c: 305972a253aSDimitry Andric case 0x4d: 306972a253aSDimitry Andric case 0x4e: 307972a253aSDimitry Andric case 0x4f: 308972a253aSDimitry Andric if (is_exec_mode_64b) 309972a253aSDimitry Andric op_idx++; 310972a253aSDimitry Andric else 311972a253aSDimitry Andric prefix_done = true; 312972a253aSDimitry Andric break; 313972a253aSDimitry Andric 314972a253aSDimitry Andric // prefix_vex_c4, c5 315972a253aSDimitry Andric case 0xc5: 316972a253aSDimitry Andric if (!is_exec_mode_64b && (inst_bytes[op_idx + 1] & 0xc0) != 0xc0) { 317972a253aSDimitry Andric prefix_done = true; 318972a253aSDimitry Andric break; 319972a253aSDimitry Andric } 320972a253aSDimitry Andric 321972a253aSDimitry Andric ret.opcode_len = 2; 322972a253aSDimitry Andric ret.primary_opcode = inst_bytes[op_idx + 2]; 323972a253aSDimitry Andric ret.modrm = inst_bytes[op_idx + 3]; 324972a253aSDimitry Andric return ret; 325972a253aSDimitry Andric 326972a253aSDimitry Andric case 0xc4: 327972a253aSDimitry Andric if (!is_exec_mode_64b && (inst_bytes[op_idx + 1] & 0xc0) != 0xc0) { 328972a253aSDimitry Andric prefix_done = true; 329972a253aSDimitry Andric break; 330972a253aSDimitry Andric } 331972a253aSDimitry Andric ret.opcode_len = inst_bytes[op_idx + 1] & 0x1f; 332972a253aSDimitry Andric ret.primary_opcode = inst_bytes[op_idx + 3]; 333972a253aSDimitry Andric ret.modrm = inst_bytes[op_idx + 4]; 334972a253aSDimitry Andric return ret; 335972a253aSDimitry Andric 336972a253aSDimitry Andric // prefix_evex 337972a253aSDimitry Andric case 0x62: 338972a253aSDimitry Andric if (!is_exec_mode_64b && (inst_bytes[op_idx + 1] & 0xc0) != 0xc0) { 339972a253aSDimitry Andric prefix_done = true; 340972a253aSDimitry Andric break; 341972a253aSDimitry Andric } 342972a253aSDimitry Andric ret.opcode_len = inst_bytes[op_idx + 1] & 0x03; 343972a253aSDimitry Andric ret.primary_opcode = inst_bytes[op_idx + 4]; 344972a253aSDimitry Andric ret.modrm = inst_bytes[op_idx + 5]; 345972a253aSDimitry Andric return ret; 346972a253aSDimitry Andric 347972a253aSDimitry Andric default: 348972a253aSDimitry Andric prefix_done = true; 349972a253aSDimitry Andric break; 350972a253aSDimitry Andric } 351972a253aSDimitry Andric } // prefix done 352972a253aSDimitry Andric 353972a253aSDimitry Andric ret.primary_opcode = inst_bytes[op_idx]; 354972a253aSDimitry Andric ret.modrm = inst_bytes[op_idx + 1]; 355972a253aSDimitry Andric ret.opcode_len = 1; 356972a253aSDimitry Andric 357972a253aSDimitry Andric // If the first opcode is 0F, it's two- or three- byte opcodes. 358972a253aSDimitry Andric if (ret.primary_opcode == 0x0F) { 359972a253aSDimitry Andric ret.primary_opcode = inst_bytes[++op_idx]; // get the next byte 360972a253aSDimitry Andric 361972a253aSDimitry Andric if (ret.primary_opcode == 0x38) { 362972a253aSDimitry Andric ret.opcode_len = 3; 363972a253aSDimitry Andric ret.primary_opcode = inst_bytes[++op_idx]; // get the next byte 364972a253aSDimitry Andric ret.modrm = inst_bytes[op_idx + 1]; 365972a253aSDimitry Andric } else if (ret.primary_opcode == 0x3A) { 366972a253aSDimitry Andric ret.opcode_len = 3; 367972a253aSDimitry Andric ret.primary_opcode = inst_bytes[++op_idx]; 368972a253aSDimitry Andric ret.modrm = inst_bytes[op_idx + 1]; 369972a253aSDimitry Andric } else if ((ret.primary_opcode & 0xf8) == 0x38) { 370972a253aSDimitry Andric ret.opcode_len = 0; 371972a253aSDimitry Andric ret.primary_opcode = inst_bytes[++op_idx]; 372972a253aSDimitry Andric ret.modrm = inst_bytes[op_idx + 1]; 373972a253aSDimitry Andric } else if (ret.primary_opcode == 0x0F) { 374972a253aSDimitry Andric ret.opcode_len = 3; 375972a253aSDimitry Andric // opcode is 0x0F, no needs to update 376972a253aSDimitry Andric ret.modrm = inst_bytes[op_idx + 1]; 377972a253aSDimitry Andric } else { 378972a253aSDimitry Andric ret.opcode_len = 2; 379972a253aSDimitry Andric ret.modrm = inst_bytes[op_idx + 1]; 380972a253aSDimitry Andric } 381972a253aSDimitry Andric } 382972a253aSDimitry Andric 383972a253aSDimitry Andric return ret; 384972a253aSDimitry Andric } 385972a253aSDimitry Andric 386972a253aSDimitry Andric lldb::InstructionControlFlowKind GetControlFlowKind(bool is_exec_mode_64b, 387972a253aSDimitry Andric Opcode m_opcode) { 388bdd1243dSDimitry Andric std::optional<InstructionOpcodeAndModrm> ret; 389972a253aSDimitry Andric 390972a253aSDimitry Andric if (m_opcode.GetOpcodeBytes() == nullptr || m_opcode.GetByteSize() <= 0) { 391972a253aSDimitry Andric // x86_64 and i386 instructions are categorized as Opcode::Type::eTypeBytes 392972a253aSDimitry Andric return lldb::eInstructionControlFlowKindUnknown; 393972a253aSDimitry Andric } 394972a253aSDimitry Andric 395972a253aSDimitry Andric // Opcode bytes will be decoded into primary_opcode, modrm and opcode length. 396972a253aSDimitry Andric // These are the three values deciding instruction control flow kind. 397972a253aSDimitry Andric ret = InstructionLengthDecode((const uint8_t *)m_opcode.GetOpcodeBytes(), 398972a253aSDimitry Andric m_opcode.GetByteSize(), is_exec_mode_64b); 399972a253aSDimitry Andric if (!ret) 400972a253aSDimitry Andric return lldb::eInstructionControlFlowKindUnknown; 401972a253aSDimitry Andric else 402bdd1243dSDimitry Andric return MapOpcodeIntoControlFlowKind(*ret); 403972a253aSDimitry Andric } 404972a253aSDimitry Andric 405972a253aSDimitry Andric } // namespace x86 406972a253aSDimitry Andric 4075ffd83dbSDimitry Andric class InstructionLLVMC : public lldb_private::Instruction { 4085ffd83dbSDimitry Andric public: 4095ffd83dbSDimitry Andric InstructionLLVMC(DisassemblerLLVMC &disasm, 4105ffd83dbSDimitry Andric const lldb_private::Address &address, 4115ffd83dbSDimitry Andric AddressClass addr_class) 4125ffd83dbSDimitry Andric : Instruction(address, addr_class), 4135ffd83dbSDimitry Andric m_disasm_wp(std::static_pointer_cast<DisassemblerLLVMC>( 41481ad6265SDimitry Andric disasm.shared_from_this())) {} 4155ffd83dbSDimitry Andric 4165ffd83dbSDimitry Andric ~InstructionLLVMC() override = default; 4175ffd83dbSDimitry Andric 4185ffd83dbSDimitry Andric bool DoesBranch() override { 4195ffd83dbSDimitry Andric VisitInstruction(); 4205ffd83dbSDimitry Andric return m_does_branch; 4215ffd83dbSDimitry Andric } 4225ffd83dbSDimitry Andric 4235ffd83dbSDimitry Andric bool HasDelaySlot() override { 4245ffd83dbSDimitry Andric VisitInstruction(); 4255ffd83dbSDimitry Andric return m_has_delay_slot; 4265ffd83dbSDimitry Andric } 4275ffd83dbSDimitry Andric 428349cc55cSDimitry Andric bool IsLoad() override { 429349cc55cSDimitry Andric VisitInstruction(); 430349cc55cSDimitry Andric return m_is_load; 431349cc55cSDimitry Andric } 432349cc55cSDimitry Andric 433349cc55cSDimitry Andric bool IsAuthenticated() override { 434349cc55cSDimitry Andric VisitInstruction(); 435349cc55cSDimitry Andric return m_is_authenticated; 436349cc55cSDimitry Andric } 437349cc55cSDimitry Andric 4385ffd83dbSDimitry Andric DisassemblerLLVMC::MCDisasmInstance *GetDisasmToUse(bool &is_alternate_isa) { 4395ffd83dbSDimitry Andric DisassemblerScope disasm(*this); 4405ffd83dbSDimitry Andric return GetDisasmToUse(is_alternate_isa, disasm); 4415ffd83dbSDimitry Andric } 4425ffd83dbSDimitry Andric 4435ffd83dbSDimitry Andric size_t Decode(const lldb_private::Disassembler &disassembler, 4445ffd83dbSDimitry Andric const lldb_private::DataExtractor &data, 4455ffd83dbSDimitry Andric lldb::offset_t data_offset) override { 4465ffd83dbSDimitry Andric // All we have to do is read the opcode which can be easy for some 4475ffd83dbSDimitry Andric // architectures 4485ffd83dbSDimitry Andric bool got_op = false; 4495ffd83dbSDimitry Andric DisassemblerScope disasm(*this); 4505ffd83dbSDimitry Andric if (disasm) { 4515ffd83dbSDimitry Andric const ArchSpec &arch = disasm->GetArchitecture(); 4525ffd83dbSDimitry Andric const lldb::ByteOrder byte_order = data.GetByteOrder(); 4535ffd83dbSDimitry Andric 4545ffd83dbSDimitry Andric const uint32_t min_op_byte_size = arch.GetMinimumOpcodeByteSize(); 4555ffd83dbSDimitry Andric const uint32_t max_op_byte_size = arch.GetMaximumOpcodeByteSize(); 4565ffd83dbSDimitry Andric if (min_op_byte_size == max_op_byte_size) { 4575ffd83dbSDimitry Andric // Fixed size instructions, just read that amount of data. 4585ffd83dbSDimitry Andric if (!data.ValidOffsetForDataOfSize(data_offset, min_op_byte_size)) 4595ffd83dbSDimitry Andric return false; 4605ffd83dbSDimitry Andric 4615ffd83dbSDimitry Andric switch (min_op_byte_size) { 4625ffd83dbSDimitry Andric case 1: 4635ffd83dbSDimitry Andric m_opcode.SetOpcode8(data.GetU8(&data_offset), byte_order); 4645ffd83dbSDimitry Andric got_op = true; 4655ffd83dbSDimitry Andric break; 4665ffd83dbSDimitry Andric 4675ffd83dbSDimitry Andric case 2: 4685ffd83dbSDimitry Andric m_opcode.SetOpcode16(data.GetU16(&data_offset), byte_order); 4695ffd83dbSDimitry Andric got_op = true; 4705ffd83dbSDimitry Andric break; 4715ffd83dbSDimitry Andric 4725ffd83dbSDimitry Andric case 4: 4735ffd83dbSDimitry Andric m_opcode.SetOpcode32(data.GetU32(&data_offset), byte_order); 4745ffd83dbSDimitry Andric got_op = true; 4755ffd83dbSDimitry Andric break; 4765ffd83dbSDimitry Andric 4775ffd83dbSDimitry Andric case 8: 4785ffd83dbSDimitry Andric m_opcode.SetOpcode64(data.GetU64(&data_offset), byte_order); 4795ffd83dbSDimitry Andric got_op = true; 4805ffd83dbSDimitry Andric break; 4815ffd83dbSDimitry Andric 4825ffd83dbSDimitry Andric default: 4835ffd83dbSDimitry Andric m_opcode.SetOpcodeBytes(data.PeekData(data_offset, min_op_byte_size), 4845ffd83dbSDimitry Andric min_op_byte_size); 4855ffd83dbSDimitry Andric got_op = true; 4865ffd83dbSDimitry Andric break; 4875ffd83dbSDimitry Andric } 4885ffd83dbSDimitry Andric } 4895ffd83dbSDimitry Andric if (!got_op) { 4905ffd83dbSDimitry Andric bool is_alternate_isa = false; 4915ffd83dbSDimitry Andric DisassemblerLLVMC::MCDisasmInstance *mc_disasm_ptr = 4925ffd83dbSDimitry Andric GetDisasmToUse(is_alternate_isa, disasm); 4935ffd83dbSDimitry Andric 4945ffd83dbSDimitry Andric const llvm::Triple::ArchType machine = arch.GetMachine(); 4955ffd83dbSDimitry Andric if (machine == llvm::Triple::arm || machine == llvm::Triple::thumb) { 4965ffd83dbSDimitry Andric if (machine == llvm::Triple::thumb || is_alternate_isa) { 4975ffd83dbSDimitry Andric uint32_t thumb_opcode = data.GetU16(&data_offset); 4985ffd83dbSDimitry Andric if ((thumb_opcode & 0xe000) != 0xe000 || 4995ffd83dbSDimitry Andric ((thumb_opcode & 0x1800u) == 0)) { 5005ffd83dbSDimitry Andric m_opcode.SetOpcode16(thumb_opcode, byte_order); 5015ffd83dbSDimitry Andric m_is_valid = true; 5025ffd83dbSDimitry Andric } else { 5035ffd83dbSDimitry Andric thumb_opcode <<= 16; 5045ffd83dbSDimitry Andric thumb_opcode |= data.GetU16(&data_offset); 5055ffd83dbSDimitry Andric m_opcode.SetOpcode16_2(thumb_opcode, byte_order); 5065ffd83dbSDimitry Andric m_is_valid = true; 5075ffd83dbSDimitry Andric } 5085ffd83dbSDimitry Andric } else { 5095ffd83dbSDimitry Andric m_opcode.SetOpcode32(data.GetU32(&data_offset), byte_order); 5105ffd83dbSDimitry Andric m_is_valid = true; 5115ffd83dbSDimitry Andric } 5125ffd83dbSDimitry Andric } else { 5135ffd83dbSDimitry Andric // The opcode isn't evenly sized, so we need to actually use the llvm 5145ffd83dbSDimitry Andric // disassembler to parse it and get the size. 5155ffd83dbSDimitry Andric uint8_t *opcode_data = 5165ffd83dbSDimitry Andric const_cast<uint8_t *>(data.PeekData(data_offset, 1)); 5175ffd83dbSDimitry Andric const size_t opcode_data_len = data.BytesLeft(data_offset); 5185ffd83dbSDimitry Andric const addr_t pc = m_address.GetFileAddress(); 5195ffd83dbSDimitry Andric llvm::MCInst inst; 5205ffd83dbSDimitry Andric 5215ffd83dbSDimitry Andric const size_t inst_size = 5225ffd83dbSDimitry Andric mc_disasm_ptr->GetMCInst(opcode_data, opcode_data_len, pc, inst); 5235ffd83dbSDimitry Andric if (inst_size == 0) 5245ffd83dbSDimitry Andric m_opcode.Clear(); 5255ffd83dbSDimitry Andric else { 5265ffd83dbSDimitry Andric m_opcode.SetOpcodeBytes(opcode_data, inst_size); 5275ffd83dbSDimitry Andric m_is_valid = true; 5285ffd83dbSDimitry Andric } 5295ffd83dbSDimitry Andric } 5305ffd83dbSDimitry Andric } 5315ffd83dbSDimitry Andric return m_opcode.GetByteSize(); 5325ffd83dbSDimitry Andric } 5335ffd83dbSDimitry Andric return 0; 5345ffd83dbSDimitry Andric } 5355ffd83dbSDimitry Andric 5365ffd83dbSDimitry Andric void AppendComment(std::string &description) { 5375ffd83dbSDimitry Andric if (m_comment.empty()) 5385ffd83dbSDimitry Andric m_comment.swap(description); 5395ffd83dbSDimitry Andric else { 5405ffd83dbSDimitry Andric m_comment.append(", "); 5415ffd83dbSDimitry Andric m_comment.append(description); 5425ffd83dbSDimitry Andric } 5435ffd83dbSDimitry Andric } 5445ffd83dbSDimitry Andric 545972a253aSDimitry Andric lldb::InstructionControlFlowKind 546972a253aSDimitry Andric GetControlFlowKind(const lldb_private::ExecutionContext *exe_ctx) override { 547972a253aSDimitry Andric DisassemblerScope disasm(*this, exe_ctx); 548972a253aSDimitry Andric if (disasm){ 549972a253aSDimitry Andric if (disasm->GetArchitecture().GetMachine() == llvm::Triple::x86) 550972a253aSDimitry Andric return x86::GetControlFlowKind(/*is_64b=*/false, m_opcode); 551972a253aSDimitry Andric else if (disasm->GetArchitecture().GetMachine() == llvm::Triple::x86_64) 552972a253aSDimitry Andric return x86::GetControlFlowKind(/*is_64b=*/true, m_opcode); 553972a253aSDimitry Andric } 554972a253aSDimitry Andric 555972a253aSDimitry Andric return eInstructionControlFlowKindUnknown; 556972a253aSDimitry Andric } 557972a253aSDimitry Andric 5585ffd83dbSDimitry Andric void CalculateMnemonicOperandsAndComment( 5595ffd83dbSDimitry Andric const lldb_private::ExecutionContext *exe_ctx) override { 5605ffd83dbSDimitry Andric DataExtractor data; 5615ffd83dbSDimitry Andric const AddressClass address_class = GetAddressClass(); 5625ffd83dbSDimitry Andric 5635ffd83dbSDimitry Andric if (m_opcode.GetData(data)) { 5645ffd83dbSDimitry Andric std::string out_string; 5655ffd83dbSDimitry Andric std::string comment_string; 5665ffd83dbSDimitry Andric 5675ffd83dbSDimitry Andric DisassemblerScope disasm(*this, exe_ctx); 5685ffd83dbSDimitry Andric if (disasm) { 5695ffd83dbSDimitry Andric DisassemblerLLVMC::MCDisasmInstance *mc_disasm_ptr; 5705ffd83dbSDimitry Andric 5715ffd83dbSDimitry Andric if (address_class == AddressClass::eCodeAlternateISA) 5725ffd83dbSDimitry Andric mc_disasm_ptr = disasm->m_alternate_disasm_up.get(); 5735ffd83dbSDimitry Andric else 5745ffd83dbSDimitry Andric mc_disasm_ptr = disasm->m_disasm_up.get(); 5755ffd83dbSDimitry Andric 5765ffd83dbSDimitry Andric lldb::addr_t pc = m_address.GetFileAddress(); 5775ffd83dbSDimitry Andric m_using_file_addr = true; 5785ffd83dbSDimitry Andric 5795ffd83dbSDimitry Andric const bool data_from_file = disasm->m_data_from_file; 5805ffd83dbSDimitry Andric bool use_hex_immediates = true; 5815ffd83dbSDimitry Andric Disassembler::HexImmediateStyle hex_style = Disassembler::eHexStyleC; 5825ffd83dbSDimitry Andric 5835ffd83dbSDimitry Andric if (exe_ctx) { 5845ffd83dbSDimitry Andric Target *target = exe_ctx->GetTargetPtr(); 5855ffd83dbSDimitry Andric if (target) { 5865ffd83dbSDimitry Andric use_hex_immediates = target->GetUseHexImmediates(); 5875ffd83dbSDimitry Andric hex_style = target->GetHexImmediateStyle(); 5885ffd83dbSDimitry Andric 5895ffd83dbSDimitry Andric if (!data_from_file) { 5905ffd83dbSDimitry Andric const lldb::addr_t load_addr = m_address.GetLoadAddress(target); 5915ffd83dbSDimitry Andric if (load_addr != LLDB_INVALID_ADDRESS) { 5925ffd83dbSDimitry Andric pc = load_addr; 5935ffd83dbSDimitry Andric m_using_file_addr = false; 5945ffd83dbSDimitry Andric } 5955ffd83dbSDimitry Andric } 5965ffd83dbSDimitry Andric } 5975ffd83dbSDimitry Andric } 5985ffd83dbSDimitry Andric 5995ffd83dbSDimitry Andric const uint8_t *opcode_data = data.GetDataStart(); 6005ffd83dbSDimitry Andric const size_t opcode_data_len = data.GetByteSize(); 6015ffd83dbSDimitry Andric llvm::MCInst inst; 6025ffd83dbSDimitry Andric size_t inst_size = 6035ffd83dbSDimitry Andric mc_disasm_ptr->GetMCInst(opcode_data, opcode_data_len, pc, inst); 6045ffd83dbSDimitry Andric 6055ffd83dbSDimitry Andric if (inst_size > 0) { 6065ffd83dbSDimitry Andric mc_disasm_ptr->SetStyle(use_hex_immediates, hex_style); 6075ffd83dbSDimitry Andric mc_disasm_ptr->PrintMCInst(inst, out_string, comment_string); 6085ffd83dbSDimitry Andric 6095ffd83dbSDimitry Andric if (!comment_string.empty()) { 6105ffd83dbSDimitry Andric AppendComment(comment_string); 6115ffd83dbSDimitry Andric } 6125ffd83dbSDimitry Andric } 6135ffd83dbSDimitry Andric 6145ffd83dbSDimitry Andric if (inst_size == 0) { 6155ffd83dbSDimitry Andric m_comment.assign("unknown opcode"); 6165ffd83dbSDimitry Andric inst_size = m_opcode.GetByteSize(); 6175ffd83dbSDimitry Andric StreamString mnemonic_strm; 6185ffd83dbSDimitry Andric lldb::offset_t offset = 0; 6195ffd83dbSDimitry Andric lldb::ByteOrder byte_order = data.GetByteOrder(); 6205ffd83dbSDimitry Andric switch (inst_size) { 6215ffd83dbSDimitry Andric case 1: { 6225ffd83dbSDimitry Andric const uint8_t uval8 = data.GetU8(&offset); 6235ffd83dbSDimitry Andric m_opcode.SetOpcode8(uval8, byte_order); 6245ffd83dbSDimitry Andric m_opcode_name.assign(".byte"); 6255ffd83dbSDimitry Andric mnemonic_strm.Printf("0x%2.2x", uval8); 6265ffd83dbSDimitry Andric } break; 6275ffd83dbSDimitry Andric case 2: { 6285ffd83dbSDimitry Andric const uint16_t uval16 = data.GetU16(&offset); 6295ffd83dbSDimitry Andric m_opcode.SetOpcode16(uval16, byte_order); 6305ffd83dbSDimitry Andric m_opcode_name.assign(".short"); 6315ffd83dbSDimitry Andric mnemonic_strm.Printf("0x%4.4x", uval16); 6325ffd83dbSDimitry Andric } break; 6335ffd83dbSDimitry Andric case 4: { 6345ffd83dbSDimitry Andric const uint32_t uval32 = data.GetU32(&offset); 6355ffd83dbSDimitry Andric m_opcode.SetOpcode32(uval32, byte_order); 6365ffd83dbSDimitry Andric m_opcode_name.assign(".long"); 6375ffd83dbSDimitry Andric mnemonic_strm.Printf("0x%8.8x", uval32); 6385ffd83dbSDimitry Andric } break; 6395ffd83dbSDimitry Andric case 8: { 6405ffd83dbSDimitry Andric const uint64_t uval64 = data.GetU64(&offset); 6415ffd83dbSDimitry Andric m_opcode.SetOpcode64(uval64, byte_order); 6425ffd83dbSDimitry Andric m_opcode_name.assign(".quad"); 6435ffd83dbSDimitry Andric mnemonic_strm.Printf("0x%16.16" PRIx64, uval64); 6445ffd83dbSDimitry Andric } break; 6455ffd83dbSDimitry Andric default: 6465ffd83dbSDimitry Andric if (inst_size == 0) 6475ffd83dbSDimitry Andric return; 6485ffd83dbSDimitry Andric else { 6495ffd83dbSDimitry Andric const uint8_t *bytes = data.PeekData(offset, inst_size); 6505ffd83dbSDimitry Andric if (bytes == nullptr) 6515ffd83dbSDimitry Andric return; 6525ffd83dbSDimitry Andric m_opcode_name.assign(".byte"); 6535ffd83dbSDimitry Andric m_opcode.SetOpcodeBytes(bytes, inst_size); 6545ffd83dbSDimitry Andric mnemonic_strm.Printf("0x%2.2x", bytes[0]); 6555ffd83dbSDimitry Andric for (uint32_t i = 1; i < inst_size; ++i) 6565ffd83dbSDimitry Andric mnemonic_strm.Printf(" 0x%2.2x", bytes[i]); 6575ffd83dbSDimitry Andric } 6585ffd83dbSDimitry Andric break; 6595ffd83dbSDimitry Andric } 6605ffd83dbSDimitry Andric m_mnemonics = std::string(mnemonic_strm.GetString()); 6615ffd83dbSDimitry Andric return; 6625ffd83dbSDimitry Andric } 6635ffd83dbSDimitry Andric 6645ffd83dbSDimitry Andric static RegularExpression s_regex( 6655ffd83dbSDimitry Andric llvm::StringRef("[ \t]*([^ ^\t]+)[ \t]*([^ ^\t].*)?")); 6665ffd83dbSDimitry Andric 6675ffd83dbSDimitry Andric llvm::SmallVector<llvm::StringRef, 4> matches; 6685ffd83dbSDimitry Andric if (s_regex.Execute(out_string, &matches)) { 6695ffd83dbSDimitry Andric m_opcode_name = matches[1].str(); 6705ffd83dbSDimitry Andric m_mnemonics = matches[2].str(); 6715ffd83dbSDimitry Andric } 6725ffd83dbSDimitry Andric } 6735ffd83dbSDimitry Andric } 6745ffd83dbSDimitry Andric } 6755ffd83dbSDimitry Andric 6765ffd83dbSDimitry Andric bool IsValid() const { return m_is_valid; } 6775ffd83dbSDimitry Andric 6785ffd83dbSDimitry Andric bool UsingFileAddress() const { return m_using_file_addr; } 6795ffd83dbSDimitry Andric size_t GetByteSize() const { return m_opcode.GetByteSize(); } 6805ffd83dbSDimitry Andric 6815ffd83dbSDimitry Andric /// Grants exclusive access to the disassembler and initializes it with the 6825ffd83dbSDimitry Andric /// given InstructionLLVMC and an optional ExecutionContext. 6835ffd83dbSDimitry Andric class DisassemblerScope { 6845ffd83dbSDimitry Andric std::shared_ptr<DisassemblerLLVMC> m_disasm; 6855ffd83dbSDimitry Andric 6865ffd83dbSDimitry Andric public: 6875ffd83dbSDimitry Andric explicit DisassemblerScope( 6885ffd83dbSDimitry Andric InstructionLLVMC &i, 6895ffd83dbSDimitry Andric const lldb_private::ExecutionContext *exe_ctx = nullptr) 6905ffd83dbSDimitry Andric : m_disasm(i.m_disasm_wp.lock()) { 6915ffd83dbSDimitry Andric m_disasm->m_mutex.lock(); 6925ffd83dbSDimitry Andric m_disasm->m_inst = &i; 6935ffd83dbSDimitry Andric m_disasm->m_exe_ctx = exe_ctx; 6945ffd83dbSDimitry Andric } 6955ffd83dbSDimitry Andric ~DisassemblerScope() { m_disasm->m_mutex.unlock(); } 6965ffd83dbSDimitry Andric 6975ffd83dbSDimitry Andric /// Evaluates to true if this scope contains a valid disassembler. 6985ffd83dbSDimitry Andric operator bool() const { return static_cast<bool>(m_disasm); } 6995ffd83dbSDimitry Andric 7005ffd83dbSDimitry Andric std::shared_ptr<DisassemblerLLVMC> operator->() { return m_disasm; } 7015ffd83dbSDimitry Andric }; 7025ffd83dbSDimitry Andric 7035ffd83dbSDimitry Andric static llvm::StringRef::const_iterator 7045ffd83dbSDimitry Andric ConsumeWhitespace(llvm::StringRef::const_iterator osi, 7055ffd83dbSDimitry Andric llvm::StringRef::const_iterator ose) { 7065ffd83dbSDimitry Andric while (osi != ose) { 7075ffd83dbSDimitry Andric switch (*osi) { 7085ffd83dbSDimitry Andric default: 7095ffd83dbSDimitry Andric return osi; 7105ffd83dbSDimitry Andric case ' ': 7115ffd83dbSDimitry Andric case '\t': 7125ffd83dbSDimitry Andric break; 7135ffd83dbSDimitry Andric } 7145ffd83dbSDimitry Andric ++osi; 7155ffd83dbSDimitry Andric } 7165ffd83dbSDimitry Andric 7175ffd83dbSDimitry Andric return osi; 7185ffd83dbSDimitry Andric } 7195ffd83dbSDimitry Andric 7205ffd83dbSDimitry Andric static std::pair<bool, llvm::StringRef::const_iterator> 7215ffd83dbSDimitry Andric ConsumeChar(llvm::StringRef::const_iterator osi, const char c, 7225ffd83dbSDimitry Andric llvm::StringRef::const_iterator ose) { 7235ffd83dbSDimitry Andric bool found = false; 7245ffd83dbSDimitry Andric 7255ffd83dbSDimitry Andric osi = ConsumeWhitespace(osi, ose); 7265ffd83dbSDimitry Andric if (osi != ose && *osi == c) { 7275ffd83dbSDimitry Andric found = true; 7285ffd83dbSDimitry Andric ++osi; 7295ffd83dbSDimitry Andric } 7305ffd83dbSDimitry Andric 7315ffd83dbSDimitry Andric return std::make_pair(found, osi); 7325ffd83dbSDimitry Andric } 7335ffd83dbSDimitry Andric 7345ffd83dbSDimitry Andric static std::pair<Operand, llvm::StringRef::const_iterator> 7355ffd83dbSDimitry Andric ParseRegisterName(llvm::StringRef::const_iterator osi, 7365ffd83dbSDimitry Andric llvm::StringRef::const_iterator ose) { 7375ffd83dbSDimitry Andric Operand ret; 7385ffd83dbSDimitry Andric ret.m_type = Operand::Type::Register; 7395ffd83dbSDimitry Andric std::string str; 7405ffd83dbSDimitry Andric 7415ffd83dbSDimitry Andric osi = ConsumeWhitespace(osi, ose); 7425ffd83dbSDimitry Andric 7435ffd83dbSDimitry Andric while (osi != ose) { 7445ffd83dbSDimitry Andric if (*osi >= '0' && *osi <= '9') { 7455ffd83dbSDimitry Andric if (str.empty()) { 7465ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 7475ffd83dbSDimitry Andric } else { 7485ffd83dbSDimitry Andric str.push_back(*osi); 7495ffd83dbSDimitry Andric } 7505ffd83dbSDimitry Andric } else if (*osi >= 'a' && *osi <= 'z') { 7515ffd83dbSDimitry Andric str.push_back(*osi); 7525ffd83dbSDimitry Andric } else { 7535ffd83dbSDimitry Andric switch (*osi) { 7545ffd83dbSDimitry Andric default: 7555ffd83dbSDimitry Andric if (str.empty()) { 7565ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 7575ffd83dbSDimitry Andric } else { 7585ffd83dbSDimitry Andric ret.m_register = ConstString(str); 7595ffd83dbSDimitry Andric return std::make_pair(ret, osi); 7605ffd83dbSDimitry Andric } 7615ffd83dbSDimitry Andric case '%': 7625ffd83dbSDimitry Andric if (!str.empty()) { 7635ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 7645ffd83dbSDimitry Andric } 7655ffd83dbSDimitry Andric break; 7665ffd83dbSDimitry Andric } 7675ffd83dbSDimitry Andric } 7685ffd83dbSDimitry Andric ++osi; 7695ffd83dbSDimitry Andric } 7705ffd83dbSDimitry Andric 7715ffd83dbSDimitry Andric ret.m_register = ConstString(str); 7725ffd83dbSDimitry Andric return std::make_pair(ret, osi); 7735ffd83dbSDimitry Andric } 7745ffd83dbSDimitry Andric 7755ffd83dbSDimitry Andric static std::pair<Operand, llvm::StringRef::const_iterator> 7765ffd83dbSDimitry Andric ParseImmediate(llvm::StringRef::const_iterator osi, 7775ffd83dbSDimitry Andric llvm::StringRef::const_iterator ose) { 7785ffd83dbSDimitry Andric Operand ret; 7795ffd83dbSDimitry Andric ret.m_type = Operand::Type::Immediate; 7805ffd83dbSDimitry Andric std::string str; 7815ffd83dbSDimitry Andric bool is_hex = false; 7825ffd83dbSDimitry Andric 7835ffd83dbSDimitry Andric osi = ConsumeWhitespace(osi, ose); 7845ffd83dbSDimitry Andric 7855ffd83dbSDimitry Andric while (osi != ose) { 7865ffd83dbSDimitry Andric if (*osi >= '0' && *osi <= '9') { 7875ffd83dbSDimitry Andric str.push_back(*osi); 7885ffd83dbSDimitry Andric } else if (*osi >= 'a' && *osi <= 'f') { 7895ffd83dbSDimitry Andric if (is_hex) { 7905ffd83dbSDimitry Andric str.push_back(*osi); 7915ffd83dbSDimitry Andric } else { 7925ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 7935ffd83dbSDimitry Andric } 7945ffd83dbSDimitry Andric } else { 7955ffd83dbSDimitry Andric switch (*osi) { 7965ffd83dbSDimitry Andric default: 7975ffd83dbSDimitry Andric if (str.empty()) { 7985ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 7995ffd83dbSDimitry Andric } else { 8005ffd83dbSDimitry Andric ret.m_immediate = strtoull(str.c_str(), nullptr, 0); 8015ffd83dbSDimitry Andric return std::make_pair(ret, osi); 8025ffd83dbSDimitry Andric } 8035ffd83dbSDimitry Andric case 'x': 8045ffd83dbSDimitry Andric if (!str.compare("0")) { 8055ffd83dbSDimitry Andric is_hex = true; 8065ffd83dbSDimitry Andric str.push_back(*osi); 8075ffd83dbSDimitry Andric } else { 8085ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 8095ffd83dbSDimitry Andric } 8105ffd83dbSDimitry Andric break; 8115ffd83dbSDimitry Andric case '#': 8125ffd83dbSDimitry Andric case '$': 8135ffd83dbSDimitry Andric if (!str.empty()) { 8145ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 8155ffd83dbSDimitry Andric } 8165ffd83dbSDimitry Andric break; 8175ffd83dbSDimitry Andric case '-': 8185ffd83dbSDimitry Andric if (str.empty()) { 8195ffd83dbSDimitry Andric ret.m_negative = true; 8205ffd83dbSDimitry Andric } else { 8215ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 8225ffd83dbSDimitry Andric } 8235ffd83dbSDimitry Andric } 8245ffd83dbSDimitry Andric } 8255ffd83dbSDimitry Andric ++osi; 8265ffd83dbSDimitry Andric } 8275ffd83dbSDimitry Andric 8285ffd83dbSDimitry Andric ret.m_immediate = strtoull(str.c_str(), nullptr, 0); 8295ffd83dbSDimitry Andric return std::make_pair(ret, osi); 8305ffd83dbSDimitry Andric } 8315ffd83dbSDimitry Andric 8325ffd83dbSDimitry Andric // -0x5(%rax,%rax,2) 8335ffd83dbSDimitry Andric static std::pair<Operand, llvm::StringRef::const_iterator> 8345ffd83dbSDimitry Andric ParseIntelIndexedAccess(llvm::StringRef::const_iterator osi, 8355ffd83dbSDimitry Andric llvm::StringRef::const_iterator ose) { 8365ffd83dbSDimitry Andric std::pair<Operand, llvm::StringRef::const_iterator> offset_and_iterator = 8375ffd83dbSDimitry Andric ParseImmediate(osi, ose); 8385ffd83dbSDimitry Andric if (offset_and_iterator.first.IsValid()) { 8395ffd83dbSDimitry Andric osi = offset_and_iterator.second; 8405ffd83dbSDimitry Andric } 8415ffd83dbSDimitry Andric 8425ffd83dbSDimitry Andric bool found = false; 8435ffd83dbSDimitry Andric std::tie(found, osi) = ConsumeChar(osi, '(', ose); 8445ffd83dbSDimitry Andric if (!found) { 8455ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 8465ffd83dbSDimitry Andric } 8475ffd83dbSDimitry Andric 8485ffd83dbSDimitry Andric std::pair<Operand, llvm::StringRef::const_iterator> base_and_iterator = 8495ffd83dbSDimitry Andric ParseRegisterName(osi, ose); 8505ffd83dbSDimitry Andric if (base_and_iterator.first.IsValid()) { 8515ffd83dbSDimitry Andric osi = base_and_iterator.second; 8525ffd83dbSDimitry Andric } else { 8535ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 8545ffd83dbSDimitry Andric } 8555ffd83dbSDimitry Andric 8565ffd83dbSDimitry Andric std::tie(found, osi) = ConsumeChar(osi, ',', ose); 8575ffd83dbSDimitry Andric if (!found) { 8585ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 8595ffd83dbSDimitry Andric } 8605ffd83dbSDimitry Andric 8615ffd83dbSDimitry Andric std::pair<Operand, llvm::StringRef::const_iterator> index_and_iterator = 8625ffd83dbSDimitry Andric ParseRegisterName(osi, ose); 8635ffd83dbSDimitry Andric if (index_and_iterator.first.IsValid()) { 8645ffd83dbSDimitry Andric osi = index_and_iterator.second; 8655ffd83dbSDimitry Andric } else { 8665ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 8675ffd83dbSDimitry Andric } 8685ffd83dbSDimitry Andric 8695ffd83dbSDimitry Andric std::tie(found, osi) = ConsumeChar(osi, ',', ose); 8705ffd83dbSDimitry Andric if (!found) { 8715ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 8725ffd83dbSDimitry Andric } 8735ffd83dbSDimitry Andric 8745ffd83dbSDimitry Andric std::pair<Operand, llvm::StringRef::const_iterator> 8755ffd83dbSDimitry Andric multiplier_and_iterator = ParseImmediate(osi, ose); 8765ffd83dbSDimitry Andric if (index_and_iterator.first.IsValid()) { 8775ffd83dbSDimitry Andric osi = index_and_iterator.second; 8785ffd83dbSDimitry Andric } else { 8795ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 8805ffd83dbSDimitry Andric } 8815ffd83dbSDimitry Andric 8825ffd83dbSDimitry Andric std::tie(found, osi) = ConsumeChar(osi, ')', ose); 8835ffd83dbSDimitry Andric if (!found) { 8845ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 8855ffd83dbSDimitry Andric } 8865ffd83dbSDimitry Andric 8875ffd83dbSDimitry Andric Operand product; 8885ffd83dbSDimitry Andric product.m_type = Operand::Type::Product; 8895ffd83dbSDimitry Andric product.m_children.push_back(index_and_iterator.first); 8905ffd83dbSDimitry Andric product.m_children.push_back(multiplier_and_iterator.first); 8915ffd83dbSDimitry Andric 8925ffd83dbSDimitry Andric Operand index; 8935ffd83dbSDimitry Andric index.m_type = Operand::Type::Sum; 8945ffd83dbSDimitry Andric index.m_children.push_back(base_and_iterator.first); 8955ffd83dbSDimitry Andric index.m_children.push_back(product); 8965ffd83dbSDimitry Andric 8975ffd83dbSDimitry Andric if (offset_and_iterator.first.IsValid()) { 8985ffd83dbSDimitry Andric Operand offset; 8995ffd83dbSDimitry Andric offset.m_type = Operand::Type::Sum; 9005ffd83dbSDimitry Andric offset.m_children.push_back(offset_and_iterator.first); 9015ffd83dbSDimitry Andric offset.m_children.push_back(index); 9025ffd83dbSDimitry Andric 9035ffd83dbSDimitry Andric Operand deref; 9045ffd83dbSDimitry Andric deref.m_type = Operand::Type::Dereference; 9055ffd83dbSDimitry Andric deref.m_children.push_back(offset); 9065ffd83dbSDimitry Andric return std::make_pair(deref, osi); 9075ffd83dbSDimitry Andric } else { 9085ffd83dbSDimitry Andric Operand deref; 9095ffd83dbSDimitry Andric deref.m_type = Operand::Type::Dereference; 9105ffd83dbSDimitry Andric deref.m_children.push_back(index); 9115ffd83dbSDimitry Andric return std::make_pair(deref, osi); 9125ffd83dbSDimitry Andric } 9135ffd83dbSDimitry Andric } 9145ffd83dbSDimitry Andric 9155ffd83dbSDimitry Andric // -0x10(%rbp) 9165ffd83dbSDimitry Andric static std::pair<Operand, llvm::StringRef::const_iterator> 9175ffd83dbSDimitry Andric ParseIntelDerefAccess(llvm::StringRef::const_iterator osi, 9185ffd83dbSDimitry Andric llvm::StringRef::const_iterator ose) { 9195ffd83dbSDimitry Andric std::pair<Operand, llvm::StringRef::const_iterator> offset_and_iterator = 9205ffd83dbSDimitry Andric ParseImmediate(osi, ose); 9215ffd83dbSDimitry Andric if (offset_and_iterator.first.IsValid()) { 9225ffd83dbSDimitry Andric osi = offset_and_iterator.second; 9235ffd83dbSDimitry Andric } 9245ffd83dbSDimitry Andric 9255ffd83dbSDimitry Andric bool found = false; 9265ffd83dbSDimitry Andric std::tie(found, osi) = ConsumeChar(osi, '(', ose); 9275ffd83dbSDimitry Andric if (!found) { 9285ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 9295ffd83dbSDimitry Andric } 9305ffd83dbSDimitry Andric 9315ffd83dbSDimitry Andric std::pair<Operand, llvm::StringRef::const_iterator> base_and_iterator = 9325ffd83dbSDimitry Andric ParseRegisterName(osi, ose); 9335ffd83dbSDimitry Andric if (base_and_iterator.first.IsValid()) { 9345ffd83dbSDimitry Andric osi = base_and_iterator.second; 9355ffd83dbSDimitry Andric } else { 9365ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 9375ffd83dbSDimitry Andric } 9385ffd83dbSDimitry Andric 9395ffd83dbSDimitry Andric std::tie(found, osi) = ConsumeChar(osi, ')', ose); 9405ffd83dbSDimitry Andric if (!found) { 9415ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 9425ffd83dbSDimitry Andric } 9435ffd83dbSDimitry Andric 9445ffd83dbSDimitry Andric if (offset_and_iterator.first.IsValid()) { 9455ffd83dbSDimitry Andric Operand offset; 9465ffd83dbSDimitry Andric offset.m_type = Operand::Type::Sum; 9475ffd83dbSDimitry Andric offset.m_children.push_back(offset_and_iterator.first); 9485ffd83dbSDimitry Andric offset.m_children.push_back(base_and_iterator.first); 9495ffd83dbSDimitry Andric 9505ffd83dbSDimitry Andric Operand deref; 9515ffd83dbSDimitry Andric deref.m_type = Operand::Type::Dereference; 9525ffd83dbSDimitry Andric deref.m_children.push_back(offset); 9535ffd83dbSDimitry Andric return std::make_pair(deref, osi); 9545ffd83dbSDimitry Andric } else { 9555ffd83dbSDimitry Andric Operand deref; 9565ffd83dbSDimitry Andric deref.m_type = Operand::Type::Dereference; 9575ffd83dbSDimitry Andric deref.m_children.push_back(base_and_iterator.first); 9585ffd83dbSDimitry Andric return std::make_pair(deref, osi); 9595ffd83dbSDimitry Andric } 9605ffd83dbSDimitry Andric } 9615ffd83dbSDimitry Andric 9625ffd83dbSDimitry Andric // [sp, #8]! 9635ffd83dbSDimitry Andric static std::pair<Operand, llvm::StringRef::const_iterator> 9645ffd83dbSDimitry Andric ParseARMOffsetAccess(llvm::StringRef::const_iterator osi, 9655ffd83dbSDimitry Andric llvm::StringRef::const_iterator ose) { 9665ffd83dbSDimitry Andric bool found = false; 9675ffd83dbSDimitry Andric std::tie(found, osi) = ConsumeChar(osi, '[', ose); 9685ffd83dbSDimitry Andric if (!found) { 9695ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 9705ffd83dbSDimitry Andric } 9715ffd83dbSDimitry Andric 9725ffd83dbSDimitry Andric std::pair<Operand, llvm::StringRef::const_iterator> base_and_iterator = 9735ffd83dbSDimitry Andric ParseRegisterName(osi, ose); 9745ffd83dbSDimitry Andric if (base_and_iterator.first.IsValid()) { 9755ffd83dbSDimitry Andric osi = base_and_iterator.second; 9765ffd83dbSDimitry Andric } else { 9775ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 9785ffd83dbSDimitry Andric } 9795ffd83dbSDimitry Andric 9805ffd83dbSDimitry Andric std::tie(found, osi) = ConsumeChar(osi, ',', ose); 9815ffd83dbSDimitry Andric if (!found) { 9825ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 9835ffd83dbSDimitry Andric } 9845ffd83dbSDimitry Andric 9855ffd83dbSDimitry Andric std::pair<Operand, llvm::StringRef::const_iterator> offset_and_iterator = 9865ffd83dbSDimitry Andric ParseImmediate(osi, ose); 9875ffd83dbSDimitry Andric if (offset_and_iterator.first.IsValid()) { 9885ffd83dbSDimitry Andric osi = offset_and_iterator.second; 9895ffd83dbSDimitry Andric } 9905ffd83dbSDimitry Andric 9915ffd83dbSDimitry Andric std::tie(found, osi) = ConsumeChar(osi, ']', ose); 9925ffd83dbSDimitry Andric if (!found) { 9935ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 9945ffd83dbSDimitry Andric } 9955ffd83dbSDimitry Andric 9965ffd83dbSDimitry Andric Operand offset; 9975ffd83dbSDimitry Andric offset.m_type = Operand::Type::Sum; 9985ffd83dbSDimitry Andric offset.m_children.push_back(offset_and_iterator.first); 9995ffd83dbSDimitry Andric offset.m_children.push_back(base_and_iterator.first); 10005ffd83dbSDimitry Andric 10015ffd83dbSDimitry Andric Operand deref; 10025ffd83dbSDimitry Andric deref.m_type = Operand::Type::Dereference; 10035ffd83dbSDimitry Andric deref.m_children.push_back(offset); 10045ffd83dbSDimitry Andric return std::make_pair(deref, osi); 10055ffd83dbSDimitry Andric } 10065ffd83dbSDimitry Andric 10075ffd83dbSDimitry Andric // [sp] 10085ffd83dbSDimitry Andric static std::pair<Operand, llvm::StringRef::const_iterator> 10095ffd83dbSDimitry Andric ParseARMDerefAccess(llvm::StringRef::const_iterator osi, 10105ffd83dbSDimitry Andric llvm::StringRef::const_iterator ose) { 10115ffd83dbSDimitry Andric bool found = false; 10125ffd83dbSDimitry Andric std::tie(found, osi) = ConsumeChar(osi, '[', ose); 10135ffd83dbSDimitry Andric if (!found) { 10145ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 10155ffd83dbSDimitry Andric } 10165ffd83dbSDimitry Andric 10175ffd83dbSDimitry Andric std::pair<Operand, llvm::StringRef::const_iterator> base_and_iterator = 10185ffd83dbSDimitry Andric ParseRegisterName(osi, ose); 10195ffd83dbSDimitry Andric if (base_and_iterator.first.IsValid()) { 10205ffd83dbSDimitry Andric osi = base_and_iterator.second; 10215ffd83dbSDimitry Andric } else { 10225ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 10235ffd83dbSDimitry Andric } 10245ffd83dbSDimitry Andric 10255ffd83dbSDimitry Andric std::tie(found, osi) = ConsumeChar(osi, ']', ose); 10265ffd83dbSDimitry Andric if (!found) { 10275ffd83dbSDimitry Andric return std::make_pair(Operand(), osi); 10285ffd83dbSDimitry Andric } 10295ffd83dbSDimitry Andric 10305ffd83dbSDimitry Andric Operand deref; 10315ffd83dbSDimitry Andric deref.m_type = Operand::Type::Dereference; 10325ffd83dbSDimitry Andric deref.m_children.push_back(base_and_iterator.first); 10335ffd83dbSDimitry Andric return std::make_pair(deref, osi); 10345ffd83dbSDimitry Andric } 10355ffd83dbSDimitry Andric 10365ffd83dbSDimitry Andric static void DumpOperand(const Operand &op, Stream &s) { 10375ffd83dbSDimitry Andric switch (op.m_type) { 10385ffd83dbSDimitry Andric case Operand::Type::Dereference: 10395ffd83dbSDimitry Andric s.PutCString("*"); 10405ffd83dbSDimitry Andric DumpOperand(op.m_children[0], s); 10415ffd83dbSDimitry Andric break; 10425ffd83dbSDimitry Andric case Operand::Type::Immediate: 10435ffd83dbSDimitry Andric if (op.m_negative) { 10445ffd83dbSDimitry Andric s.PutCString("-"); 10455ffd83dbSDimitry Andric } 10465ffd83dbSDimitry Andric s.PutCString(llvm::to_string(op.m_immediate)); 10475ffd83dbSDimitry Andric break; 10485ffd83dbSDimitry Andric case Operand::Type::Invalid: 10495ffd83dbSDimitry Andric s.PutCString("Invalid"); 10505ffd83dbSDimitry Andric break; 10515ffd83dbSDimitry Andric case Operand::Type::Product: 10525ffd83dbSDimitry Andric s.PutCString("("); 10535ffd83dbSDimitry Andric DumpOperand(op.m_children[0], s); 10545ffd83dbSDimitry Andric s.PutCString("*"); 10555ffd83dbSDimitry Andric DumpOperand(op.m_children[1], s); 10565ffd83dbSDimitry Andric s.PutCString(")"); 10575ffd83dbSDimitry Andric break; 10585ffd83dbSDimitry Andric case Operand::Type::Register: 10595ffd83dbSDimitry Andric s.PutCString(op.m_register.GetStringRef()); 10605ffd83dbSDimitry Andric break; 10615ffd83dbSDimitry Andric case Operand::Type::Sum: 10625ffd83dbSDimitry Andric s.PutCString("("); 10635ffd83dbSDimitry Andric DumpOperand(op.m_children[0], s); 10645ffd83dbSDimitry Andric s.PutCString("+"); 10655ffd83dbSDimitry Andric DumpOperand(op.m_children[1], s); 10665ffd83dbSDimitry Andric s.PutCString(")"); 10675ffd83dbSDimitry Andric break; 10685ffd83dbSDimitry Andric } 10695ffd83dbSDimitry Andric } 10705ffd83dbSDimitry Andric 10715ffd83dbSDimitry Andric bool ParseOperands( 10725ffd83dbSDimitry Andric llvm::SmallVectorImpl<Instruction::Operand> &operands) override { 10735ffd83dbSDimitry Andric const char *operands_string = GetOperands(nullptr); 10745ffd83dbSDimitry Andric 10755ffd83dbSDimitry Andric if (!operands_string) { 10765ffd83dbSDimitry Andric return false; 10775ffd83dbSDimitry Andric } 10785ffd83dbSDimitry Andric 10795ffd83dbSDimitry Andric llvm::StringRef operands_ref(operands_string); 10805ffd83dbSDimitry Andric 10815ffd83dbSDimitry Andric llvm::StringRef::const_iterator osi = operands_ref.begin(); 10825ffd83dbSDimitry Andric llvm::StringRef::const_iterator ose = operands_ref.end(); 10835ffd83dbSDimitry Andric 10845ffd83dbSDimitry Andric while (osi != ose) { 10855ffd83dbSDimitry Andric Operand operand; 10865ffd83dbSDimitry Andric llvm::StringRef::const_iterator iter; 10875ffd83dbSDimitry Andric 10885ffd83dbSDimitry Andric if ((std::tie(operand, iter) = ParseIntelIndexedAccess(osi, ose), 10895ffd83dbSDimitry Andric operand.IsValid()) || 10905ffd83dbSDimitry Andric (std::tie(operand, iter) = ParseIntelDerefAccess(osi, ose), 10915ffd83dbSDimitry Andric operand.IsValid()) || 10925ffd83dbSDimitry Andric (std::tie(operand, iter) = ParseARMOffsetAccess(osi, ose), 10935ffd83dbSDimitry Andric operand.IsValid()) || 10945ffd83dbSDimitry Andric (std::tie(operand, iter) = ParseARMDerefAccess(osi, ose), 10955ffd83dbSDimitry Andric operand.IsValid()) || 10965ffd83dbSDimitry Andric (std::tie(operand, iter) = ParseRegisterName(osi, ose), 10975ffd83dbSDimitry Andric operand.IsValid()) || 10985ffd83dbSDimitry Andric (std::tie(operand, iter) = ParseImmediate(osi, ose), 10995ffd83dbSDimitry Andric operand.IsValid())) { 11005ffd83dbSDimitry Andric osi = iter; 11015ffd83dbSDimitry Andric operands.push_back(operand); 11025ffd83dbSDimitry Andric } else { 11035ffd83dbSDimitry Andric return false; 11045ffd83dbSDimitry Andric } 11055ffd83dbSDimitry Andric 11065ffd83dbSDimitry Andric std::pair<bool, llvm::StringRef::const_iterator> found_and_iter = 11075ffd83dbSDimitry Andric ConsumeChar(osi, ',', ose); 11085ffd83dbSDimitry Andric if (found_and_iter.first) { 11095ffd83dbSDimitry Andric osi = found_and_iter.second; 11105ffd83dbSDimitry Andric } 11115ffd83dbSDimitry Andric 11125ffd83dbSDimitry Andric osi = ConsumeWhitespace(osi, ose); 11135ffd83dbSDimitry Andric } 11145ffd83dbSDimitry Andric 11155ffd83dbSDimitry Andric DisassemblerSP disasm_sp = m_disasm_wp.lock(); 11165ffd83dbSDimitry Andric 11175ffd83dbSDimitry Andric if (disasm_sp && operands.size() > 1) { 11185ffd83dbSDimitry Andric // TODO tie this into the MC Disassembler's notion of clobbers. 11195ffd83dbSDimitry Andric switch (disasm_sp->GetArchitecture().GetMachine()) { 11205ffd83dbSDimitry Andric default: 11215ffd83dbSDimitry Andric break; 11225ffd83dbSDimitry Andric case llvm::Triple::x86: 11235ffd83dbSDimitry Andric case llvm::Triple::x86_64: 11245ffd83dbSDimitry Andric operands[operands.size() - 1].m_clobbered = true; 11255ffd83dbSDimitry Andric break; 11265ffd83dbSDimitry Andric case llvm::Triple::arm: 11275ffd83dbSDimitry Andric operands[0].m_clobbered = true; 11285ffd83dbSDimitry Andric break; 11295ffd83dbSDimitry Andric } 11305ffd83dbSDimitry Andric } 11315ffd83dbSDimitry Andric 113281ad6265SDimitry Andric if (Log *log = GetLog(LLDBLog::Process)) { 11335ffd83dbSDimitry Andric StreamString ss; 11345ffd83dbSDimitry Andric 11355ffd83dbSDimitry Andric ss.Printf("[%s] expands to %zu operands:\n", operands_string, 11365ffd83dbSDimitry Andric operands.size()); 11375ffd83dbSDimitry Andric for (const Operand &operand : operands) { 11385ffd83dbSDimitry Andric ss.PutCString(" "); 11395ffd83dbSDimitry Andric DumpOperand(operand, ss); 11405ffd83dbSDimitry Andric ss.PutCString("\n"); 11415ffd83dbSDimitry Andric } 11425ffd83dbSDimitry Andric 11435ffd83dbSDimitry Andric log->PutString(ss.GetString()); 11445ffd83dbSDimitry Andric } 11455ffd83dbSDimitry Andric 11465ffd83dbSDimitry Andric return true; 11475ffd83dbSDimitry Andric } 11485ffd83dbSDimitry Andric 11495ffd83dbSDimitry Andric bool IsCall() override { 11505ffd83dbSDimitry Andric VisitInstruction(); 11515ffd83dbSDimitry Andric return m_is_call; 11525ffd83dbSDimitry Andric } 11535ffd83dbSDimitry Andric 11545ffd83dbSDimitry Andric protected: 11555ffd83dbSDimitry Andric std::weak_ptr<DisassemblerLLVMC> m_disasm_wp; 11565ffd83dbSDimitry Andric 11575ffd83dbSDimitry Andric bool m_is_valid = false; 115881ad6265SDimitry Andric bool m_using_file_addr = false; 11595ffd83dbSDimitry Andric bool m_has_visited_instruction = false; 11605ffd83dbSDimitry Andric 11615ffd83dbSDimitry Andric // Be conservative. If we didn't understand the instruction, say it: 11625ffd83dbSDimitry Andric // - Might branch 11635ffd83dbSDimitry Andric // - Does not have a delay slot 11645ffd83dbSDimitry Andric // - Is not a call 1165349cc55cSDimitry Andric // - Is not a load 1166349cc55cSDimitry Andric // - Is not an authenticated instruction 11675ffd83dbSDimitry Andric bool m_does_branch = true; 11685ffd83dbSDimitry Andric bool m_has_delay_slot = false; 11695ffd83dbSDimitry Andric bool m_is_call = false; 1170349cc55cSDimitry Andric bool m_is_load = false; 1171349cc55cSDimitry Andric bool m_is_authenticated = false; 11725ffd83dbSDimitry Andric 11735ffd83dbSDimitry Andric void VisitInstruction() { 11745ffd83dbSDimitry Andric if (m_has_visited_instruction) 11755ffd83dbSDimitry Andric return; 11765ffd83dbSDimitry Andric 11775ffd83dbSDimitry Andric DisassemblerScope disasm(*this); 11785ffd83dbSDimitry Andric if (!disasm) 11795ffd83dbSDimitry Andric return; 11805ffd83dbSDimitry Andric 11815ffd83dbSDimitry Andric DataExtractor data; 11825ffd83dbSDimitry Andric if (!m_opcode.GetData(data)) 11835ffd83dbSDimitry Andric return; 11845ffd83dbSDimitry Andric 11855ffd83dbSDimitry Andric bool is_alternate_isa; 11865ffd83dbSDimitry Andric lldb::addr_t pc = m_address.GetFileAddress(); 11875ffd83dbSDimitry Andric DisassemblerLLVMC::MCDisasmInstance *mc_disasm_ptr = 11885ffd83dbSDimitry Andric GetDisasmToUse(is_alternate_isa, disasm); 11895ffd83dbSDimitry Andric const uint8_t *opcode_data = data.GetDataStart(); 11905ffd83dbSDimitry Andric const size_t opcode_data_len = data.GetByteSize(); 11915ffd83dbSDimitry Andric llvm::MCInst inst; 11925ffd83dbSDimitry Andric const size_t inst_size = 11935ffd83dbSDimitry Andric mc_disasm_ptr->GetMCInst(opcode_data, opcode_data_len, pc, inst); 11945ffd83dbSDimitry Andric if (inst_size == 0) 11955ffd83dbSDimitry Andric return; 11965ffd83dbSDimitry Andric 11975ffd83dbSDimitry Andric m_has_visited_instruction = true; 11985ffd83dbSDimitry Andric m_does_branch = mc_disasm_ptr->CanBranch(inst); 11995ffd83dbSDimitry Andric m_has_delay_slot = mc_disasm_ptr->HasDelaySlot(inst); 12005ffd83dbSDimitry Andric m_is_call = mc_disasm_ptr->IsCall(inst); 1201349cc55cSDimitry Andric m_is_load = mc_disasm_ptr->IsLoad(inst); 1202349cc55cSDimitry Andric m_is_authenticated = mc_disasm_ptr->IsAuthenticated(inst); 12035ffd83dbSDimitry Andric } 12045ffd83dbSDimitry Andric 12055ffd83dbSDimitry Andric private: 12065ffd83dbSDimitry Andric DisassemblerLLVMC::MCDisasmInstance * 12075ffd83dbSDimitry Andric GetDisasmToUse(bool &is_alternate_isa, DisassemblerScope &disasm) { 12085ffd83dbSDimitry Andric is_alternate_isa = false; 12095ffd83dbSDimitry Andric if (disasm) { 12105ffd83dbSDimitry Andric if (disasm->m_alternate_disasm_up) { 12115ffd83dbSDimitry Andric const AddressClass address_class = GetAddressClass(); 12125ffd83dbSDimitry Andric 12135ffd83dbSDimitry Andric if (address_class == AddressClass::eCodeAlternateISA) { 12145ffd83dbSDimitry Andric is_alternate_isa = true; 12155ffd83dbSDimitry Andric return disasm->m_alternate_disasm_up.get(); 12165ffd83dbSDimitry Andric } 12175ffd83dbSDimitry Andric } 12185ffd83dbSDimitry Andric return disasm->m_disasm_up.get(); 12195ffd83dbSDimitry Andric } 12205ffd83dbSDimitry Andric return nullptr; 12215ffd83dbSDimitry Andric } 12225ffd83dbSDimitry Andric }; 12235ffd83dbSDimitry Andric 12245ffd83dbSDimitry Andric std::unique_ptr<DisassemblerLLVMC::MCDisasmInstance> 12255ffd83dbSDimitry Andric DisassemblerLLVMC::MCDisasmInstance::Create(const char *triple, const char *cpu, 12265ffd83dbSDimitry Andric const char *features_str, 12275ffd83dbSDimitry Andric unsigned flavor, 12285ffd83dbSDimitry Andric DisassemblerLLVMC &owner) { 12295ffd83dbSDimitry Andric using Instance = std::unique_ptr<DisassemblerLLVMC::MCDisasmInstance>; 12305ffd83dbSDimitry Andric 12315ffd83dbSDimitry Andric std::string Status; 12325ffd83dbSDimitry Andric const llvm::Target *curr_target = 12335ffd83dbSDimitry Andric llvm::TargetRegistry::lookupTarget(triple, Status); 12345ffd83dbSDimitry Andric if (!curr_target) 12355ffd83dbSDimitry Andric return Instance(); 12365ffd83dbSDimitry Andric 12375ffd83dbSDimitry Andric std::unique_ptr<llvm::MCInstrInfo> instr_info_up( 12385ffd83dbSDimitry Andric curr_target->createMCInstrInfo()); 12395ffd83dbSDimitry Andric if (!instr_info_up) 12405ffd83dbSDimitry Andric return Instance(); 12415ffd83dbSDimitry Andric 12425ffd83dbSDimitry Andric std::unique_ptr<llvm::MCRegisterInfo> reg_info_up( 12435ffd83dbSDimitry Andric curr_target->createMCRegInfo(triple)); 12445ffd83dbSDimitry Andric if (!reg_info_up) 12455ffd83dbSDimitry Andric return Instance(); 12465ffd83dbSDimitry Andric 12475ffd83dbSDimitry Andric std::unique_ptr<llvm::MCSubtargetInfo> subtarget_info_up( 12485ffd83dbSDimitry Andric curr_target->createMCSubtargetInfo(triple, cpu, features_str)); 12495ffd83dbSDimitry Andric if (!subtarget_info_up) 12505ffd83dbSDimitry Andric return Instance(); 12515ffd83dbSDimitry Andric 12525ffd83dbSDimitry Andric llvm::MCTargetOptions MCOptions; 12535ffd83dbSDimitry Andric std::unique_ptr<llvm::MCAsmInfo> asm_info_up( 12545ffd83dbSDimitry Andric curr_target->createMCAsmInfo(*reg_info_up, triple, MCOptions)); 12555ffd83dbSDimitry Andric if (!asm_info_up) 12565ffd83dbSDimitry Andric return Instance(); 12575ffd83dbSDimitry Andric 12585ffd83dbSDimitry Andric std::unique_ptr<llvm::MCContext> context_up( 1259fe6060f1SDimitry Andric new llvm::MCContext(llvm::Triple(triple), asm_info_up.get(), 1260fe6060f1SDimitry Andric reg_info_up.get(), subtarget_info_up.get())); 12615ffd83dbSDimitry Andric if (!context_up) 12625ffd83dbSDimitry Andric return Instance(); 12635ffd83dbSDimitry Andric 12645ffd83dbSDimitry Andric std::unique_ptr<llvm::MCDisassembler> disasm_up( 12655ffd83dbSDimitry Andric curr_target->createMCDisassembler(*subtarget_info_up, *context_up)); 12665ffd83dbSDimitry Andric if (!disasm_up) 12675ffd83dbSDimitry Andric return Instance(); 12685ffd83dbSDimitry Andric 12695ffd83dbSDimitry Andric std::unique_ptr<llvm::MCRelocationInfo> rel_info_up( 12705ffd83dbSDimitry Andric curr_target->createMCRelocationInfo(triple, *context_up)); 12715ffd83dbSDimitry Andric if (!rel_info_up) 12725ffd83dbSDimitry Andric return Instance(); 12735ffd83dbSDimitry Andric 12745ffd83dbSDimitry Andric std::unique_ptr<llvm::MCSymbolizer> symbolizer_up( 12755ffd83dbSDimitry Andric curr_target->createMCSymbolizer( 12765ffd83dbSDimitry Andric triple, nullptr, DisassemblerLLVMC::SymbolLookupCallback, &owner, 12775ffd83dbSDimitry Andric context_up.get(), std::move(rel_info_up))); 12785ffd83dbSDimitry Andric disasm_up->setSymbolizer(std::move(symbolizer_up)); 12795ffd83dbSDimitry Andric 12805ffd83dbSDimitry Andric unsigned asm_printer_variant = 12815ffd83dbSDimitry Andric flavor == ~0U ? asm_info_up->getAssemblerDialect() : flavor; 12825ffd83dbSDimitry Andric 12835ffd83dbSDimitry Andric std::unique_ptr<llvm::MCInstPrinter> instr_printer_up( 12845ffd83dbSDimitry Andric curr_target->createMCInstPrinter(llvm::Triple{triple}, 12855ffd83dbSDimitry Andric asm_printer_variant, *asm_info_up, 12865ffd83dbSDimitry Andric *instr_info_up, *reg_info_up)); 12875ffd83dbSDimitry Andric if (!instr_printer_up) 12885ffd83dbSDimitry Andric return Instance(); 12895ffd83dbSDimitry Andric 12905ffd83dbSDimitry Andric return Instance( 12915ffd83dbSDimitry Andric new MCDisasmInstance(std::move(instr_info_up), std::move(reg_info_up), 12925ffd83dbSDimitry Andric std::move(subtarget_info_up), std::move(asm_info_up), 12935ffd83dbSDimitry Andric std::move(context_up), std::move(disasm_up), 12945ffd83dbSDimitry Andric std::move(instr_printer_up))); 12955ffd83dbSDimitry Andric } 12965ffd83dbSDimitry Andric 12975ffd83dbSDimitry Andric DisassemblerLLVMC::MCDisasmInstance::MCDisasmInstance( 12985ffd83dbSDimitry Andric std::unique_ptr<llvm::MCInstrInfo> &&instr_info_up, 12995ffd83dbSDimitry Andric std::unique_ptr<llvm::MCRegisterInfo> &®_info_up, 13005ffd83dbSDimitry Andric std::unique_ptr<llvm::MCSubtargetInfo> &&subtarget_info_up, 13015ffd83dbSDimitry Andric std::unique_ptr<llvm::MCAsmInfo> &&asm_info_up, 13025ffd83dbSDimitry Andric std::unique_ptr<llvm::MCContext> &&context_up, 13035ffd83dbSDimitry Andric std::unique_ptr<llvm::MCDisassembler> &&disasm_up, 13045ffd83dbSDimitry Andric std::unique_ptr<llvm::MCInstPrinter> &&instr_printer_up) 13055ffd83dbSDimitry Andric : m_instr_info_up(std::move(instr_info_up)), 13065ffd83dbSDimitry Andric m_reg_info_up(std::move(reg_info_up)), 13075ffd83dbSDimitry Andric m_subtarget_info_up(std::move(subtarget_info_up)), 13085ffd83dbSDimitry Andric m_asm_info_up(std::move(asm_info_up)), 13095ffd83dbSDimitry Andric m_context_up(std::move(context_up)), m_disasm_up(std::move(disasm_up)), 13105ffd83dbSDimitry Andric m_instr_printer_up(std::move(instr_printer_up)) { 13115ffd83dbSDimitry Andric assert(m_instr_info_up && m_reg_info_up && m_subtarget_info_up && 13125ffd83dbSDimitry Andric m_asm_info_up && m_context_up && m_disasm_up && m_instr_printer_up); 13135ffd83dbSDimitry Andric } 13145ffd83dbSDimitry Andric 13155ffd83dbSDimitry Andric uint64_t DisassemblerLLVMC::MCDisasmInstance::GetMCInst( 13165ffd83dbSDimitry Andric const uint8_t *opcode_data, size_t opcode_data_len, lldb::addr_t pc, 13175ffd83dbSDimitry Andric llvm::MCInst &mc_inst) const { 13185ffd83dbSDimitry Andric llvm::ArrayRef<uint8_t> data(opcode_data, opcode_data_len); 13195ffd83dbSDimitry Andric llvm::MCDisassembler::DecodeStatus status; 13205ffd83dbSDimitry Andric 13215ffd83dbSDimitry Andric uint64_t new_inst_size; 13225ffd83dbSDimitry Andric status = m_disasm_up->getInstruction(mc_inst, new_inst_size, data, pc, 13235ffd83dbSDimitry Andric llvm::nulls()); 13245ffd83dbSDimitry Andric if (status == llvm::MCDisassembler::Success) 13255ffd83dbSDimitry Andric return new_inst_size; 13265ffd83dbSDimitry Andric else 13275ffd83dbSDimitry Andric return 0; 13285ffd83dbSDimitry Andric } 13295ffd83dbSDimitry Andric 13305ffd83dbSDimitry Andric void DisassemblerLLVMC::MCDisasmInstance::PrintMCInst( 13315ffd83dbSDimitry Andric llvm::MCInst &mc_inst, std::string &inst_string, 13325ffd83dbSDimitry Andric std::string &comments_string) { 13335ffd83dbSDimitry Andric llvm::raw_string_ostream inst_stream(inst_string); 13345ffd83dbSDimitry Andric llvm::raw_string_ostream comments_stream(comments_string); 13355ffd83dbSDimitry Andric 13365ffd83dbSDimitry Andric m_instr_printer_up->setCommentStream(comments_stream); 13375ffd83dbSDimitry Andric m_instr_printer_up->printInst(&mc_inst, 0, llvm::StringRef(), 13385ffd83dbSDimitry Andric *m_subtarget_info_up, inst_stream); 13395ffd83dbSDimitry Andric m_instr_printer_up->setCommentStream(llvm::nulls()); 13405ffd83dbSDimitry Andric comments_stream.flush(); 13415ffd83dbSDimitry Andric 13425ffd83dbSDimitry Andric static std::string g_newlines("\r\n"); 13435ffd83dbSDimitry Andric 13445ffd83dbSDimitry Andric for (size_t newline_pos = 0; 13455ffd83dbSDimitry Andric (newline_pos = comments_string.find_first_of(g_newlines, newline_pos)) != 13465ffd83dbSDimitry Andric comments_string.npos; 13475ffd83dbSDimitry Andric /**/) { 13485ffd83dbSDimitry Andric comments_string.replace(comments_string.begin() + newline_pos, 13495ffd83dbSDimitry Andric comments_string.begin() + newline_pos + 1, 1, ' '); 13505ffd83dbSDimitry Andric } 13515ffd83dbSDimitry Andric } 13525ffd83dbSDimitry Andric 13535ffd83dbSDimitry Andric void DisassemblerLLVMC::MCDisasmInstance::SetStyle( 13545ffd83dbSDimitry Andric bool use_hex_immed, HexImmediateStyle hex_style) { 13555ffd83dbSDimitry Andric m_instr_printer_up->setPrintImmHex(use_hex_immed); 13565ffd83dbSDimitry Andric switch (hex_style) { 13575ffd83dbSDimitry Andric case eHexStyleC: 13585ffd83dbSDimitry Andric m_instr_printer_up->setPrintHexStyle(llvm::HexStyle::C); 13595ffd83dbSDimitry Andric break; 13605ffd83dbSDimitry Andric case eHexStyleAsm: 13615ffd83dbSDimitry Andric m_instr_printer_up->setPrintHexStyle(llvm::HexStyle::Asm); 13625ffd83dbSDimitry Andric break; 13635ffd83dbSDimitry Andric } 13645ffd83dbSDimitry Andric } 13655ffd83dbSDimitry Andric 13665ffd83dbSDimitry Andric bool DisassemblerLLVMC::MCDisasmInstance::CanBranch( 13675ffd83dbSDimitry Andric llvm::MCInst &mc_inst) const { 13685ffd83dbSDimitry Andric return m_instr_info_up->get(mc_inst.getOpcode()) 13695ffd83dbSDimitry Andric .mayAffectControlFlow(mc_inst, *m_reg_info_up); 13705ffd83dbSDimitry Andric } 13715ffd83dbSDimitry Andric 13725ffd83dbSDimitry Andric bool DisassemblerLLVMC::MCDisasmInstance::HasDelaySlot( 13735ffd83dbSDimitry Andric llvm::MCInst &mc_inst) const { 13745ffd83dbSDimitry Andric return m_instr_info_up->get(mc_inst.getOpcode()).hasDelaySlot(); 13755ffd83dbSDimitry Andric } 13765ffd83dbSDimitry Andric 13775ffd83dbSDimitry Andric bool DisassemblerLLVMC::MCDisasmInstance::IsCall(llvm::MCInst &mc_inst) const { 13785ffd83dbSDimitry Andric return m_instr_info_up->get(mc_inst.getOpcode()).isCall(); 13795ffd83dbSDimitry Andric } 13805ffd83dbSDimitry Andric 1381349cc55cSDimitry Andric bool DisassemblerLLVMC::MCDisasmInstance::IsLoad(llvm::MCInst &mc_inst) const { 1382349cc55cSDimitry Andric return m_instr_info_up->get(mc_inst.getOpcode()).mayLoad(); 1383349cc55cSDimitry Andric } 1384349cc55cSDimitry Andric 1385349cc55cSDimitry Andric bool DisassemblerLLVMC::MCDisasmInstance::IsAuthenticated( 1386349cc55cSDimitry Andric llvm::MCInst &mc_inst) const { 1387bdd1243dSDimitry Andric const auto &InstrDesc = m_instr_info_up->get(mc_inst.getOpcode()); 1388349cc55cSDimitry Andric 1389349cc55cSDimitry Andric // Treat software auth traps (brk 0xc470 + aut key, where 0x70 == 'p', 0xc4 1390349cc55cSDimitry Andric // == 'a' + 'c') as authenticated instructions for reporting purposes, in 1391349cc55cSDimitry Andric // addition to the standard authenticated instructions specified in ARMv8.3. 1392349cc55cSDimitry Andric bool IsBrkC47x = false; 1393349cc55cSDimitry Andric if (InstrDesc.isTrap() && mc_inst.getNumOperands() == 1) { 1394349cc55cSDimitry Andric const llvm::MCOperand &Op0 = mc_inst.getOperand(0); 1395349cc55cSDimitry Andric if (Op0.isImm() && Op0.getImm() >= 0xc470 && Op0.getImm() <= 0xc474) 1396349cc55cSDimitry Andric IsBrkC47x = true; 1397349cc55cSDimitry Andric } 1398349cc55cSDimitry Andric 1399349cc55cSDimitry Andric return InstrDesc.isAuthenticated() || IsBrkC47x; 1400349cc55cSDimitry Andric } 1401349cc55cSDimitry Andric 14025ffd83dbSDimitry Andric DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch, 14035ffd83dbSDimitry Andric const char *flavor_string) 14045ffd83dbSDimitry Andric : Disassembler(arch, flavor_string), m_exe_ctx(nullptr), m_inst(nullptr), 1405349cc55cSDimitry Andric m_data_from_file(false), m_adrp_address(LLDB_INVALID_ADDRESS), 1406349cc55cSDimitry Andric m_adrp_insn() { 14075ffd83dbSDimitry Andric if (!FlavorValidForArchSpec(arch, m_flavor.c_str())) { 14085ffd83dbSDimitry Andric m_flavor.assign("default"); 14095ffd83dbSDimitry Andric } 14105ffd83dbSDimitry Andric 14115ffd83dbSDimitry Andric unsigned flavor = ~0U; 14125ffd83dbSDimitry Andric llvm::Triple triple = arch.GetTriple(); 14135ffd83dbSDimitry Andric 14145ffd83dbSDimitry Andric // So far the only supported flavor is "intel" on x86. The base class will 14155ffd83dbSDimitry Andric // set this correctly coming in. 14165ffd83dbSDimitry Andric if (triple.getArch() == llvm::Triple::x86 || 14175ffd83dbSDimitry Andric triple.getArch() == llvm::Triple::x86_64) { 14185ffd83dbSDimitry Andric if (m_flavor == "intel") { 14195ffd83dbSDimitry Andric flavor = 1; 14205ffd83dbSDimitry Andric } else if (m_flavor == "att") { 14215ffd83dbSDimitry Andric flavor = 0; 14225ffd83dbSDimitry Andric } 14235ffd83dbSDimitry Andric } 14245ffd83dbSDimitry Andric 14255ffd83dbSDimitry Andric ArchSpec thumb_arch(arch); 14265ffd83dbSDimitry Andric if (triple.getArch() == llvm::Triple::arm) { 14275ffd83dbSDimitry Andric std::string thumb_arch_name(thumb_arch.GetTriple().getArchName().str()); 14285ffd83dbSDimitry Andric // Replace "arm" with "thumb" so we get all thumb variants correct 14295ffd83dbSDimitry Andric if (thumb_arch_name.size() > 3) { 14305ffd83dbSDimitry Andric thumb_arch_name.erase(0, 3); 14315ffd83dbSDimitry Andric thumb_arch_name.insert(0, "thumb"); 14325ffd83dbSDimitry Andric } else { 14331fd87a68SDimitry Andric thumb_arch_name = "thumbv9.3a"; 14345ffd83dbSDimitry Andric } 14355ffd83dbSDimitry Andric thumb_arch.GetTriple().setArchName(llvm::StringRef(thumb_arch_name)); 14365ffd83dbSDimitry Andric } 14375ffd83dbSDimitry Andric 14385ffd83dbSDimitry Andric // If no sub architecture specified then use the most recent arm architecture 14391fd87a68SDimitry Andric // so the disassembler will return all instructions. Without it we will see a 14401fd87a68SDimitry Andric // lot of unknown opcodes if the code uses instructions which are not 14411fd87a68SDimitry Andric // available in the oldest arm version (which is used when no sub architecture 14421fd87a68SDimitry Andric // is specified). 14435ffd83dbSDimitry Andric if (triple.getArch() == llvm::Triple::arm && 14445ffd83dbSDimitry Andric triple.getSubArch() == llvm::Triple::NoSubArch) 14451fd87a68SDimitry Andric triple.setArchName("armv9.3a"); 14465ffd83dbSDimitry Andric 144704eeddc0SDimitry Andric std::string features_str; 14485ffd83dbSDimitry Andric const char *triple_str = triple.getTriple().c_str(); 14495ffd83dbSDimitry Andric 14505ffd83dbSDimitry Andric // ARM Cortex M0-M7 devices only execute thumb instructions 14515ffd83dbSDimitry Andric if (arch.IsAlwaysThumbInstructions()) { 14525ffd83dbSDimitry Andric triple_str = thumb_arch.GetTriple().getTriple().c_str(); 14535ffd83dbSDimitry Andric features_str += "+fp-armv8,"; 14545ffd83dbSDimitry Andric } 14555ffd83dbSDimitry Andric 14565ffd83dbSDimitry Andric const char *cpu = ""; 14575ffd83dbSDimitry Andric 14585ffd83dbSDimitry Andric switch (arch.GetCore()) { 14595ffd83dbSDimitry Andric case ArchSpec::eCore_mips32: 14605ffd83dbSDimitry Andric case ArchSpec::eCore_mips32el: 14615ffd83dbSDimitry Andric cpu = "mips32"; 14625ffd83dbSDimitry Andric break; 14635ffd83dbSDimitry Andric case ArchSpec::eCore_mips32r2: 14645ffd83dbSDimitry Andric case ArchSpec::eCore_mips32r2el: 14655ffd83dbSDimitry Andric cpu = "mips32r2"; 14665ffd83dbSDimitry Andric break; 14675ffd83dbSDimitry Andric case ArchSpec::eCore_mips32r3: 14685ffd83dbSDimitry Andric case ArchSpec::eCore_mips32r3el: 14695ffd83dbSDimitry Andric cpu = "mips32r3"; 14705ffd83dbSDimitry Andric break; 14715ffd83dbSDimitry Andric case ArchSpec::eCore_mips32r5: 14725ffd83dbSDimitry Andric case ArchSpec::eCore_mips32r5el: 14735ffd83dbSDimitry Andric cpu = "mips32r5"; 14745ffd83dbSDimitry Andric break; 14755ffd83dbSDimitry Andric case ArchSpec::eCore_mips32r6: 14765ffd83dbSDimitry Andric case ArchSpec::eCore_mips32r6el: 14775ffd83dbSDimitry Andric cpu = "mips32r6"; 14785ffd83dbSDimitry Andric break; 14795ffd83dbSDimitry Andric case ArchSpec::eCore_mips64: 14805ffd83dbSDimitry Andric case ArchSpec::eCore_mips64el: 14815ffd83dbSDimitry Andric cpu = "mips64"; 14825ffd83dbSDimitry Andric break; 14835ffd83dbSDimitry Andric case ArchSpec::eCore_mips64r2: 14845ffd83dbSDimitry Andric case ArchSpec::eCore_mips64r2el: 14855ffd83dbSDimitry Andric cpu = "mips64r2"; 14865ffd83dbSDimitry Andric break; 14875ffd83dbSDimitry Andric case ArchSpec::eCore_mips64r3: 14885ffd83dbSDimitry Andric case ArchSpec::eCore_mips64r3el: 14895ffd83dbSDimitry Andric cpu = "mips64r3"; 14905ffd83dbSDimitry Andric break; 14915ffd83dbSDimitry Andric case ArchSpec::eCore_mips64r5: 14925ffd83dbSDimitry Andric case ArchSpec::eCore_mips64r5el: 14935ffd83dbSDimitry Andric cpu = "mips64r5"; 14945ffd83dbSDimitry Andric break; 14955ffd83dbSDimitry Andric case ArchSpec::eCore_mips64r6: 14965ffd83dbSDimitry Andric case ArchSpec::eCore_mips64r6el: 14975ffd83dbSDimitry Andric cpu = "mips64r6"; 14985ffd83dbSDimitry Andric break; 14995ffd83dbSDimitry Andric default: 15005ffd83dbSDimitry Andric cpu = ""; 15015ffd83dbSDimitry Andric break; 15025ffd83dbSDimitry Andric } 15035ffd83dbSDimitry Andric 15045ffd83dbSDimitry Andric if (arch.IsMIPS()) { 15055ffd83dbSDimitry Andric uint32_t arch_flags = arch.GetFlags(); 15065ffd83dbSDimitry Andric if (arch_flags & ArchSpec::eMIPSAse_msa) 15075ffd83dbSDimitry Andric features_str += "+msa,"; 15085ffd83dbSDimitry Andric if (arch_flags & ArchSpec::eMIPSAse_dsp) 15095ffd83dbSDimitry Andric features_str += "+dsp,"; 15105ffd83dbSDimitry Andric if (arch_flags & ArchSpec::eMIPSAse_dspr2) 15115ffd83dbSDimitry Andric features_str += "+dspr2,"; 15125ffd83dbSDimitry Andric } 15135ffd83dbSDimitry Andric 151481ad6265SDimitry Andric // If any AArch64 variant, enable latest ISA with all extensions. 1515e8d8bef9SDimitry Andric if (triple.isAArch64()) { 1516753f127fSDimitry Andric features_str += "+all,"; 15175ffd83dbSDimitry Andric 1518e8d8bef9SDimitry Andric if (triple.getVendor() == llvm::Triple::Apple) 15195ffd83dbSDimitry Andric cpu = "apple-latest"; 15205ffd83dbSDimitry Andric } 15215ffd83dbSDimitry Andric 152281ad6265SDimitry Andric if (triple.isRISCV()) { 152381ad6265SDimitry Andric uint32_t arch_flags = arch.GetFlags(); 152481ad6265SDimitry Andric if (arch_flags & ArchSpec::eRISCV_rvc) 152581ad6265SDimitry Andric features_str += "+c,"; 152681ad6265SDimitry Andric if (arch_flags & ArchSpec::eRISCV_rve) 152781ad6265SDimitry Andric features_str += "+e,"; 152881ad6265SDimitry Andric if ((arch_flags & ArchSpec::eRISCV_float_abi_single) == 152981ad6265SDimitry Andric ArchSpec::eRISCV_float_abi_single) 153081ad6265SDimitry Andric features_str += "+f,"; 153181ad6265SDimitry Andric if ((arch_flags & ArchSpec::eRISCV_float_abi_double) == 153281ad6265SDimitry Andric ArchSpec::eRISCV_float_abi_double) 153381ad6265SDimitry Andric features_str += "+f,+d,"; 153481ad6265SDimitry Andric if ((arch_flags & ArchSpec::eRISCV_float_abi_quad) == 153581ad6265SDimitry Andric ArchSpec::eRISCV_float_abi_quad) 153681ad6265SDimitry Andric features_str += "+f,+d,+q,"; 153781ad6265SDimitry Andric // FIXME: how do we detect features such as `+a`, `+m`? 153881ad6265SDimitry Andric } 153981ad6265SDimitry Andric 15405ffd83dbSDimitry Andric // We use m_disasm_up.get() to tell whether we are valid or not, so if this 15415ffd83dbSDimitry Andric // isn't good for some reason, we won't be valid and FindPlugin will fail and 15425ffd83dbSDimitry Andric // we won't get used. 15435ffd83dbSDimitry Andric m_disasm_up = MCDisasmInstance::Create(triple_str, cpu, features_str.c_str(), 15445ffd83dbSDimitry Andric flavor, *this); 15455ffd83dbSDimitry Andric 15465ffd83dbSDimitry Andric llvm::Triple::ArchType llvm_arch = triple.getArch(); 15475ffd83dbSDimitry Andric 15485ffd83dbSDimitry Andric // For arm CPUs that can execute arm or thumb instructions, also create a 15495ffd83dbSDimitry Andric // thumb instruction disassembler. 15505ffd83dbSDimitry Andric if (llvm_arch == llvm::Triple::arm) { 15515ffd83dbSDimitry Andric std::string thumb_triple(thumb_arch.GetTriple().getTriple()); 15525ffd83dbSDimitry Andric m_alternate_disasm_up = 15535ffd83dbSDimitry Andric MCDisasmInstance::Create(thumb_triple.c_str(), "", features_str.c_str(), 15545ffd83dbSDimitry Andric flavor, *this); 15555ffd83dbSDimitry Andric if (!m_alternate_disasm_up) 15565ffd83dbSDimitry Andric m_disasm_up.reset(); 15575ffd83dbSDimitry Andric 15585ffd83dbSDimitry Andric } else if (arch.IsMIPS()) { 15595ffd83dbSDimitry Andric /* Create alternate disassembler for MIPS16 and microMIPS */ 15605ffd83dbSDimitry Andric uint32_t arch_flags = arch.GetFlags(); 15615ffd83dbSDimitry Andric if (arch_flags & ArchSpec::eMIPSAse_mips16) 15625ffd83dbSDimitry Andric features_str += "+mips16,"; 15635ffd83dbSDimitry Andric else if (arch_flags & ArchSpec::eMIPSAse_micromips) 15645ffd83dbSDimitry Andric features_str += "+micromips,"; 15655ffd83dbSDimitry Andric 15665ffd83dbSDimitry Andric m_alternate_disasm_up = MCDisasmInstance::Create( 15675ffd83dbSDimitry Andric triple_str, cpu, features_str.c_str(), flavor, *this); 15685ffd83dbSDimitry Andric if (!m_alternate_disasm_up) 15695ffd83dbSDimitry Andric m_disasm_up.reset(); 15705ffd83dbSDimitry Andric } 15715ffd83dbSDimitry Andric } 15725ffd83dbSDimitry Andric 15735ffd83dbSDimitry Andric DisassemblerLLVMC::~DisassemblerLLVMC() = default; 15745ffd83dbSDimitry Andric 1575*06c3fb27SDimitry Andric lldb::DisassemblerSP DisassemblerLLVMC::CreateInstance(const ArchSpec &arch, 15765ffd83dbSDimitry Andric const char *flavor) { 15775ffd83dbSDimitry Andric if (arch.GetTriple().getArch() != llvm::Triple::UnknownArch) { 1578*06c3fb27SDimitry Andric auto disasm_sp = std::make_shared<DisassemblerLLVMC>(arch, flavor); 1579*06c3fb27SDimitry Andric if (disasm_sp && disasm_sp->IsValid()) 1580*06c3fb27SDimitry Andric return disasm_sp; 15815ffd83dbSDimitry Andric } 1582*06c3fb27SDimitry Andric return lldb::DisassemblerSP(); 15835ffd83dbSDimitry Andric } 15845ffd83dbSDimitry Andric 15855ffd83dbSDimitry Andric size_t DisassemblerLLVMC::DecodeInstructions(const Address &base_addr, 15865ffd83dbSDimitry Andric const DataExtractor &data, 15875ffd83dbSDimitry Andric lldb::offset_t data_offset, 15885ffd83dbSDimitry Andric size_t num_instructions, 15895ffd83dbSDimitry Andric bool append, bool data_from_file) { 15905ffd83dbSDimitry Andric if (!append) 15915ffd83dbSDimitry Andric m_instruction_list.Clear(); 15925ffd83dbSDimitry Andric 15935ffd83dbSDimitry Andric if (!IsValid()) 15945ffd83dbSDimitry Andric return 0; 15955ffd83dbSDimitry Andric 15965ffd83dbSDimitry Andric m_data_from_file = data_from_file; 15975ffd83dbSDimitry Andric uint32_t data_cursor = data_offset; 15985ffd83dbSDimitry Andric const size_t data_byte_size = data.GetByteSize(); 15995ffd83dbSDimitry Andric uint32_t instructions_parsed = 0; 16005ffd83dbSDimitry Andric Address inst_addr(base_addr); 16015ffd83dbSDimitry Andric 16025ffd83dbSDimitry Andric while (data_cursor < data_byte_size && 16035ffd83dbSDimitry Andric instructions_parsed < num_instructions) { 16045ffd83dbSDimitry Andric 16055ffd83dbSDimitry Andric AddressClass address_class = AddressClass::eCode; 16065ffd83dbSDimitry Andric 16075ffd83dbSDimitry Andric if (m_alternate_disasm_up) 16085ffd83dbSDimitry Andric address_class = inst_addr.GetAddressClass(); 16095ffd83dbSDimitry Andric 16105ffd83dbSDimitry Andric InstructionSP inst_sp( 16115ffd83dbSDimitry Andric new InstructionLLVMC(*this, inst_addr, address_class)); 16125ffd83dbSDimitry Andric 16135ffd83dbSDimitry Andric if (!inst_sp) 16145ffd83dbSDimitry Andric break; 16155ffd83dbSDimitry Andric 16165ffd83dbSDimitry Andric uint32_t inst_size = inst_sp->Decode(*this, data, data_cursor); 16175ffd83dbSDimitry Andric 16185ffd83dbSDimitry Andric if (inst_size == 0) 16195ffd83dbSDimitry Andric break; 16205ffd83dbSDimitry Andric 16215ffd83dbSDimitry Andric m_instruction_list.Append(inst_sp); 16225ffd83dbSDimitry Andric data_cursor += inst_size; 16235ffd83dbSDimitry Andric inst_addr.Slide(inst_size); 16245ffd83dbSDimitry Andric instructions_parsed++; 16255ffd83dbSDimitry Andric } 16265ffd83dbSDimitry Andric 16275ffd83dbSDimitry Andric return data_cursor - data_offset; 16285ffd83dbSDimitry Andric } 16295ffd83dbSDimitry Andric 16305ffd83dbSDimitry Andric void DisassemblerLLVMC::Initialize() { 16315ffd83dbSDimitry Andric PluginManager::RegisterPlugin(GetPluginNameStatic(), 16325ffd83dbSDimitry Andric "Disassembler that uses LLVM MC to disassemble " 16335ffd83dbSDimitry Andric "i386, x86_64, ARM, and ARM64.", 16345ffd83dbSDimitry Andric CreateInstance); 16355ffd83dbSDimitry Andric 16365ffd83dbSDimitry Andric llvm::InitializeAllTargetInfos(); 16375ffd83dbSDimitry Andric llvm::InitializeAllTargetMCs(); 16385ffd83dbSDimitry Andric llvm::InitializeAllAsmParsers(); 16395ffd83dbSDimitry Andric llvm::InitializeAllDisassemblers(); 16405ffd83dbSDimitry Andric } 16415ffd83dbSDimitry Andric 16425ffd83dbSDimitry Andric void DisassemblerLLVMC::Terminate() { 16435ffd83dbSDimitry Andric PluginManager::UnregisterPlugin(CreateInstance); 16445ffd83dbSDimitry Andric } 16455ffd83dbSDimitry Andric 16465ffd83dbSDimitry Andric int DisassemblerLLVMC::OpInfoCallback(void *disassembler, uint64_t pc, 16475ffd83dbSDimitry Andric uint64_t offset, uint64_t size, 16485ffd83dbSDimitry Andric int tag_type, void *tag_bug) { 16495ffd83dbSDimitry Andric return static_cast<DisassemblerLLVMC *>(disassembler) 16505ffd83dbSDimitry Andric ->OpInfo(pc, offset, size, tag_type, tag_bug); 16515ffd83dbSDimitry Andric } 16525ffd83dbSDimitry Andric 16535ffd83dbSDimitry Andric const char *DisassemblerLLVMC::SymbolLookupCallback(void *disassembler, 16545ffd83dbSDimitry Andric uint64_t value, 16555ffd83dbSDimitry Andric uint64_t *type, uint64_t pc, 16565ffd83dbSDimitry Andric const char **name) { 16575ffd83dbSDimitry Andric return static_cast<DisassemblerLLVMC *>(disassembler) 16585ffd83dbSDimitry Andric ->SymbolLookup(value, type, pc, name); 16595ffd83dbSDimitry Andric } 16605ffd83dbSDimitry Andric 16615ffd83dbSDimitry Andric bool DisassemblerLLVMC::FlavorValidForArchSpec( 16625ffd83dbSDimitry Andric const lldb_private::ArchSpec &arch, const char *flavor) { 16635ffd83dbSDimitry Andric llvm::Triple triple = arch.GetTriple(); 16645ffd83dbSDimitry Andric if (flavor == nullptr || strcmp(flavor, "default") == 0) 16655ffd83dbSDimitry Andric return true; 16665ffd83dbSDimitry Andric 16675ffd83dbSDimitry Andric if (triple.getArch() == llvm::Triple::x86 || 16685ffd83dbSDimitry Andric triple.getArch() == llvm::Triple::x86_64) { 16695ffd83dbSDimitry Andric return strcmp(flavor, "intel") == 0 || strcmp(flavor, "att") == 0; 16705ffd83dbSDimitry Andric } else 16715ffd83dbSDimitry Andric return false; 16725ffd83dbSDimitry Andric } 16735ffd83dbSDimitry Andric 16745ffd83dbSDimitry Andric bool DisassemblerLLVMC::IsValid() const { return m_disasm_up.operator bool(); } 16755ffd83dbSDimitry Andric 16765ffd83dbSDimitry Andric int DisassemblerLLVMC::OpInfo(uint64_t PC, uint64_t Offset, uint64_t Size, 16775ffd83dbSDimitry Andric int tag_type, void *tag_bug) { 16785ffd83dbSDimitry Andric switch (tag_type) { 16795ffd83dbSDimitry Andric default: 16805ffd83dbSDimitry Andric break; 16815ffd83dbSDimitry Andric case 1: 16825ffd83dbSDimitry Andric memset(tag_bug, 0, sizeof(::LLVMOpInfo1)); 16835ffd83dbSDimitry Andric break; 16845ffd83dbSDimitry Andric } 16855ffd83dbSDimitry Andric return 0; 16865ffd83dbSDimitry Andric } 16875ffd83dbSDimitry Andric 16885ffd83dbSDimitry Andric const char *DisassemblerLLVMC::SymbolLookup(uint64_t value, uint64_t *type_ptr, 16895ffd83dbSDimitry Andric uint64_t pc, const char **name) { 16905ffd83dbSDimitry Andric if (*type_ptr) { 16915ffd83dbSDimitry Andric if (m_exe_ctx && m_inst) { 16925ffd83dbSDimitry Andric // std::string remove_this_prior_to_checkin; 16935ffd83dbSDimitry Andric Target *target = m_exe_ctx ? m_exe_ctx->GetTargetPtr() : nullptr; 16945ffd83dbSDimitry Andric Address value_so_addr; 16955ffd83dbSDimitry Andric Address pc_so_addr; 1696349cc55cSDimitry Andric if (target->GetArchitecture().GetMachine() == llvm::Triple::aarch64 || 1697349cc55cSDimitry Andric target->GetArchitecture().GetMachine() == llvm::Triple::aarch64_be || 1698349cc55cSDimitry Andric target->GetArchitecture().GetMachine() == llvm::Triple::aarch64_32) { 1699349cc55cSDimitry Andric if (*type_ptr == LLVMDisassembler_ReferenceType_In_ARM64_ADRP) { 1700349cc55cSDimitry Andric m_adrp_address = pc; 1701349cc55cSDimitry Andric m_adrp_insn = value; 1702349cc55cSDimitry Andric *name = nullptr; 1703349cc55cSDimitry Andric *type_ptr = LLVMDisassembler_ReferenceType_InOut_None; 1704349cc55cSDimitry Andric return nullptr; 1705349cc55cSDimitry Andric } 1706349cc55cSDimitry Andric // If this instruction is an ADD and 1707349cc55cSDimitry Andric // the previous instruction was an ADRP and 1708349cc55cSDimitry Andric // the ADRP's register and this ADD's register are the same, 1709349cc55cSDimitry Andric // then this is a pc-relative address calculation. 1710349cc55cSDimitry Andric if (*type_ptr == LLVMDisassembler_ReferenceType_In_ARM64_ADDXri && 171181ad6265SDimitry Andric m_adrp_insn && m_adrp_address == pc - 4 && 1712bdd1243dSDimitry Andric (*m_adrp_insn & 0x1f) == ((value >> 5) & 0x1f)) { 1713349cc55cSDimitry Andric uint32_t addxri_inst; 1714349cc55cSDimitry Andric uint64_t adrp_imm, addxri_imm; 1715349cc55cSDimitry Andric // Get immlo and immhi bits, OR them together to get the ADRP imm 1716349cc55cSDimitry Andric // value. 1717bdd1243dSDimitry Andric adrp_imm = 1718bdd1243dSDimitry Andric ((*m_adrp_insn & 0x00ffffe0) >> 3) | ((*m_adrp_insn >> 29) & 0x3); 1719349cc55cSDimitry Andric // if high bit of immhi after right-shifting set, sign extend 1720349cc55cSDimitry Andric if (adrp_imm & (1ULL << 20)) 1721349cc55cSDimitry Andric adrp_imm |= ~((1ULL << 21) - 1); 1722349cc55cSDimitry Andric 1723349cc55cSDimitry Andric addxri_inst = value; 1724349cc55cSDimitry Andric addxri_imm = (addxri_inst >> 10) & 0xfff; 1725349cc55cSDimitry Andric // check if 'sh' bit is set, shift imm value up if so 1726349cc55cSDimitry Andric // (this would make no sense, ADRP already gave us this part) 1727349cc55cSDimitry Andric if ((addxri_inst >> (12 + 5 + 5)) & 1) 1728349cc55cSDimitry Andric addxri_imm <<= 12; 1729349cc55cSDimitry Andric value = (m_adrp_address & 0xfffffffffffff000LL) + (adrp_imm << 12) + 1730349cc55cSDimitry Andric addxri_imm; 1731349cc55cSDimitry Andric } 1732349cc55cSDimitry Andric m_adrp_address = LLDB_INVALID_ADDRESS; 1733349cc55cSDimitry Andric m_adrp_insn.reset(); 1734349cc55cSDimitry Andric } 1735349cc55cSDimitry Andric 17365ffd83dbSDimitry Andric if (m_inst->UsingFileAddress()) { 17375ffd83dbSDimitry Andric ModuleSP module_sp(m_inst->GetAddress().GetModule()); 17385ffd83dbSDimitry Andric if (module_sp) { 17395ffd83dbSDimitry Andric module_sp->ResolveFileAddress(value, value_so_addr); 17405ffd83dbSDimitry Andric module_sp->ResolveFileAddress(pc, pc_so_addr); 17415ffd83dbSDimitry Andric } 17425ffd83dbSDimitry Andric } else if (target && !target->GetSectionLoadList().IsEmpty()) { 17435ffd83dbSDimitry Andric target->GetSectionLoadList().ResolveLoadAddress(value, value_so_addr); 17445ffd83dbSDimitry Andric target->GetSectionLoadList().ResolveLoadAddress(pc, pc_so_addr); 17455ffd83dbSDimitry Andric } 17465ffd83dbSDimitry Andric 17475ffd83dbSDimitry Andric SymbolContext sym_ctx; 17485ffd83dbSDimitry Andric const SymbolContextItem resolve_scope = 17495ffd83dbSDimitry Andric eSymbolContextFunction | eSymbolContextSymbol; 17505ffd83dbSDimitry Andric if (pc_so_addr.IsValid() && pc_so_addr.GetModule()) { 17515ffd83dbSDimitry Andric pc_so_addr.GetModule()->ResolveSymbolContextForAddress( 17525ffd83dbSDimitry Andric pc_so_addr, resolve_scope, sym_ctx); 17535ffd83dbSDimitry Andric } 17545ffd83dbSDimitry Andric 17555ffd83dbSDimitry Andric if (value_so_addr.IsValid() && value_so_addr.GetSection()) { 17565ffd83dbSDimitry Andric StreamString ss; 17575ffd83dbSDimitry Andric 17585ffd83dbSDimitry Andric bool format_omitting_current_func_name = false; 17595ffd83dbSDimitry Andric if (sym_ctx.symbol || sym_ctx.function) { 17605ffd83dbSDimitry Andric AddressRange range; 17615ffd83dbSDimitry Andric if (sym_ctx.GetAddressRange(resolve_scope, 0, false, range) && 17625ffd83dbSDimitry Andric range.GetBaseAddress().IsValid() && 17635ffd83dbSDimitry Andric range.ContainsLoadAddress(value_so_addr, target)) { 17645ffd83dbSDimitry Andric format_omitting_current_func_name = true; 17655ffd83dbSDimitry Andric } 17665ffd83dbSDimitry Andric } 17675ffd83dbSDimitry Andric 17685ffd83dbSDimitry Andric // If the "value" address (the target address we're symbolicating) is 17695ffd83dbSDimitry Andric // inside the same SymbolContext as the current instruction pc 17705ffd83dbSDimitry Andric // (pc_so_addr), don't print the full function name - just print it 17715ffd83dbSDimitry Andric // with DumpStyleNoFunctionName style, e.g. "<+36>". 17725ffd83dbSDimitry Andric if (format_omitting_current_func_name) { 17735ffd83dbSDimitry Andric value_so_addr.Dump(&ss, target, Address::DumpStyleNoFunctionName, 17745ffd83dbSDimitry Andric Address::DumpStyleSectionNameOffset); 17755ffd83dbSDimitry Andric } else { 17765ffd83dbSDimitry Andric value_so_addr.Dump( 17775ffd83dbSDimitry Andric &ss, target, 17785ffd83dbSDimitry Andric Address::DumpStyleResolvedDescriptionNoFunctionArguments, 17795ffd83dbSDimitry Andric Address::DumpStyleSectionNameOffset); 17805ffd83dbSDimitry Andric } 17815ffd83dbSDimitry Andric 17825ffd83dbSDimitry Andric if (!ss.GetString().empty()) { 17835ffd83dbSDimitry Andric // If Address::Dump returned a multi-line description, most commonly 17845ffd83dbSDimitry Andric // seen when we have multiple levels of inlined functions at an 17855ffd83dbSDimitry Andric // address, only show the first line. 17865ffd83dbSDimitry Andric std::string str = std::string(ss.GetString()); 17875ffd83dbSDimitry Andric size_t first_eol_char = str.find_first_of("\r\n"); 17885ffd83dbSDimitry Andric if (first_eol_char != std::string::npos) { 17895ffd83dbSDimitry Andric str.erase(first_eol_char); 17905ffd83dbSDimitry Andric } 17915ffd83dbSDimitry Andric m_inst->AppendComment(str); 17925ffd83dbSDimitry Andric } 17935ffd83dbSDimitry Andric } 17945ffd83dbSDimitry Andric } 17955ffd83dbSDimitry Andric } 17965ffd83dbSDimitry Andric 1797349cc55cSDimitry Andric // TODO: llvm-objdump sets the type_ptr to the 1798349cc55cSDimitry Andric // LLVMDisassembler_ReferenceType_Out_* values 1799349cc55cSDimitry Andric // based on where value_so_addr is pointing, with 1800349cc55cSDimitry Andric // Mach-O specific augmentations in MachODump.cpp. e.g. 1801349cc55cSDimitry Andric // see what AArch64ExternalSymbolizer::tryAddingSymbolicOperand 1802349cc55cSDimitry Andric // handles. 18035ffd83dbSDimitry Andric *type_ptr = LLVMDisassembler_ReferenceType_InOut_None; 18045ffd83dbSDimitry Andric *name = nullptr; 18055ffd83dbSDimitry Andric return nullptr; 18065ffd83dbSDimitry Andric } 1807