1871 lines · cpp
1//===-- DisassemblerLLVMC.cpp ---------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "DisassemblerLLVMC.h"10 11#include "llvm-c/Disassembler.h"12#include "llvm/ADT/SmallString.h"13#include "llvm/ADT/StringExtras.h"14#include "llvm/MC/MCAsmInfo.h"15#include "llvm/MC/MCContext.h"16#include "llvm/MC/MCDisassembler/MCDisassembler.h"17#include "llvm/MC/MCDisassembler/MCExternalSymbolizer.h"18#include "llvm/MC/MCDisassembler/MCRelocationInfo.h"19#include "llvm/MC/MCInst.h"20#include "llvm/MC/MCInstPrinter.h"21#include "llvm/MC/MCInstrAnalysis.h"22#include "llvm/MC/MCInstrInfo.h"23#include "llvm/MC/MCRegisterInfo.h"24#include "llvm/MC/MCSubtargetInfo.h"25#include "llvm/MC/MCTargetOptions.h"26#include "llvm/MC/TargetRegistry.h"27#include "llvm/Support/ErrorHandling.h"28#include "llvm/Support/ScopedPrinter.h"29#include "llvm/Support/TargetSelect.h"30#include "llvm/TargetParser/AArch64TargetParser.h"31 32#include "lldb/Core/Address.h"33#include "lldb/Core/Module.h"34#include "lldb/Symbol/Function.h"35#include "lldb/Symbol/SymbolContext.h"36#include "lldb/Target/ExecutionContext.h"37#include "lldb/Target/Process.h"38#include "lldb/Target/RegisterContext.h"39#include "lldb/Target/SectionLoadList.h"40#include "lldb/Target/StackFrame.h"41#include "lldb/Target/Target.h"42#include "lldb/Utility/DataExtractor.h"43#include "lldb/Utility/LLDBLog.h"44#include "lldb/Utility/Log.h"45#include "lldb/Utility/RegularExpression.h"46#include "lldb/Utility/Stream.h"47#include <optional>48 49using namespace lldb;50using namespace lldb_private;51 52LLDB_PLUGIN_DEFINE(DisassemblerLLVMC)53 54class DisassemblerLLVMC::MCDisasmInstance {55public:56 static std::unique_ptr<MCDisasmInstance>57 Create(const char *triple, const char *cpu, const char *features_str,58 unsigned flavor, DisassemblerLLVMC &owner);59 60 ~MCDisasmInstance() = default;61 62 bool GetMCInst(const uint8_t *opcode_data, size_t opcode_data_len,63 lldb::addr_t pc, llvm::MCInst &mc_inst, uint64_t &size) const;64 void PrintMCInst(llvm::MCInst &mc_inst, lldb::addr_t pc,65 std::string &inst_string, std::string &comments_string);66 void SetStyle(bool use_hex_immed, HexImmediateStyle hex_style);67 void SetUseColor(bool use_color);68 bool GetUseColor() const;69 bool CanBranch(llvm::MCInst &mc_inst) const;70 bool HasDelaySlot(llvm::MCInst &mc_inst) const;71 bool IsCall(llvm::MCInst &mc_inst) const;72 bool IsLoad(llvm::MCInst &mc_inst) const;73 bool IsAuthenticated(llvm::MCInst &mc_inst) const;74 75private:76 MCDisasmInstance(std::unique_ptr<llvm::MCInstrInfo> &&instr_info_up,77 std::unique_ptr<llvm::MCRegisterInfo> &®_info_up,78 std::unique_ptr<llvm::MCSubtargetInfo> &&subtarget_info_up,79 std::unique_ptr<llvm::MCAsmInfo> &&asm_info_up,80 std::unique_ptr<llvm::MCContext> &&context_up,81 std::unique_ptr<llvm::MCDisassembler> &&disasm_up,82 std::unique_ptr<llvm::MCInstPrinter> &&instr_printer_up,83 std::unique_ptr<llvm::MCInstrAnalysis> &&instr_analysis_up);84 85 std::unique_ptr<llvm::MCInstrInfo> m_instr_info_up;86 std::unique_ptr<llvm::MCRegisterInfo> m_reg_info_up;87 std::unique_ptr<llvm::MCSubtargetInfo> m_subtarget_info_up;88 std::unique_ptr<llvm::MCAsmInfo> m_asm_info_up;89 std::unique_ptr<llvm::MCContext> m_context_up;90 std::unique_ptr<llvm::MCDisassembler> m_disasm_up;91 std::unique_ptr<llvm::MCInstPrinter> m_instr_printer_up;92 std::unique_ptr<llvm::MCInstrAnalysis> m_instr_analysis_up;93};94 95namespace x86 {96 97/// These are the three values deciding instruction control flow kind.98/// InstructionLengthDecode function decodes an instruction and get this struct.99///100/// primary_opcode101/// Primary opcode of the instruction.102/// For one-byte opcode instruction, it's the first byte after prefix.103/// For two- and three-byte opcodes, it's the second byte.104///105/// opcode_len106/// The length of opcode in bytes. Valid opcode lengths are 1, 2, or 3.107///108/// modrm109/// ModR/M byte of the instruction.110/// Bits[7:6] indicate MOD. Bits[5:3] specify a register and R/M bits[2:0]111/// may contain a register or specify an addressing mode, depending on MOD.112struct InstructionOpcodeAndModrm {113 uint8_t primary_opcode;114 uint8_t opcode_len;115 uint8_t modrm;116};117 118/// Determine the InstructionControlFlowKind based on opcode and modrm bytes.119/// Refer to http://ref.x86asm.net/coder.html for the full list of opcode and120/// instruction set.121///122/// \param[in] opcode_and_modrm123/// Contains primary_opcode byte, its length, and ModR/M byte.124/// Refer to the struct InstructionOpcodeAndModrm for details.125///126/// \return127/// The control flow kind of the instruction or128/// eInstructionControlFlowKindOther if the instruction doesn't affect129/// the control flow of the program.130lldb::InstructionControlFlowKind131MapOpcodeIntoControlFlowKind(InstructionOpcodeAndModrm opcode_and_modrm) {132 uint8_t opcode = opcode_and_modrm.primary_opcode;133 uint8_t opcode_len = opcode_and_modrm.opcode_len;134 uint8_t modrm = opcode_and_modrm.modrm;135 136 if (opcode_len > 2)137 return lldb::eInstructionControlFlowKindOther;138 139 if (opcode >= 0x70 && opcode <= 0x7F) {140 if (opcode_len == 1)141 return lldb::eInstructionControlFlowKindCondJump;142 else143 return lldb::eInstructionControlFlowKindOther;144 }145 146 if (opcode >= 0x80 && opcode <= 0x8F) {147 if (opcode_len == 2)148 return lldb::eInstructionControlFlowKindCondJump;149 else150 return lldb::eInstructionControlFlowKindOther;151 }152 153 switch (opcode) {154 case 0x9A:155 if (opcode_len == 1)156 return lldb::eInstructionControlFlowKindFarCall;157 break;158 case 0xFF:159 if (opcode_len == 1) {160 uint8_t modrm_reg = (modrm >> 3) & 7;161 if (modrm_reg == 2)162 return lldb::eInstructionControlFlowKindCall;163 else if (modrm_reg == 3)164 return lldb::eInstructionControlFlowKindFarCall;165 else if (modrm_reg == 4)166 return lldb::eInstructionControlFlowKindJump;167 else if (modrm_reg == 5)168 return lldb::eInstructionControlFlowKindFarJump;169 }170 break;171 case 0xE8:172 if (opcode_len == 1)173 return lldb::eInstructionControlFlowKindCall;174 break;175 case 0xCD:176 case 0xCC:177 case 0xCE:178 case 0xF1:179 if (opcode_len == 1)180 return lldb::eInstructionControlFlowKindFarCall;181 break;182 case 0xCF:183 if (opcode_len == 1)184 return lldb::eInstructionControlFlowKindFarReturn;185 break;186 case 0xE9:187 case 0xEB:188 if (opcode_len == 1)189 return lldb::eInstructionControlFlowKindJump;190 break;191 case 0xEA:192 if (opcode_len == 1)193 return lldb::eInstructionControlFlowKindFarJump;194 break;195 case 0xE3:196 case 0xE0:197 case 0xE1:198 case 0xE2:199 if (opcode_len == 1)200 return lldb::eInstructionControlFlowKindCondJump;201 break;202 case 0xC3:203 case 0xC2:204 if (opcode_len == 1)205 return lldb::eInstructionControlFlowKindReturn;206 break;207 case 0xCB:208 case 0xCA:209 if (opcode_len == 1)210 return lldb::eInstructionControlFlowKindFarReturn;211 break;212 case 0x05:213 case 0x34:214 if (opcode_len == 2)215 return lldb::eInstructionControlFlowKindFarCall;216 break;217 case 0x35:218 case 0x07:219 if (opcode_len == 2)220 return lldb::eInstructionControlFlowKindFarReturn;221 break;222 case 0x01:223 if (opcode_len == 2) {224 switch (modrm) {225 case 0xc1:226 return lldb::eInstructionControlFlowKindFarCall;227 case 0xc2:228 case 0xc3:229 return lldb::eInstructionControlFlowKindFarReturn;230 default:231 break;232 }233 }234 break;235 default:236 break;237 }238 239 return lldb::eInstructionControlFlowKindOther;240}241 242/// Decode an instruction into opcode, modrm and opcode_len.243/// Refer to http://ref.x86asm.net/coder.html for the instruction bytes layout.244/// Opcodes in x86 are generally the first byte of instruction, though two-byte245/// instructions and prefixes exist. ModR/M is the byte following the opcode246/// and adds additional information for how the instruction is executed.247///248/// \param[in] inst_bytes249/// Raw bytes of the instruction250///251///252/// \param[in] bytes_len253/// The length of the inst_bytes array.254///255/// \param[in] is_exec_mode_64b256/// If true, the execution mode is 64 bit.257///258/// \return259/// Returns decoded instruction as struct InstructionOpcodeAndModrm, holding260/// primary_opcode, opcode_len and modrm byte. Refer to the struct definition261/// for more details.262/// Otherwise if the given instruction is invalid, returns std::nullopt.263std::optional<InstructionOpcodeAndModrm>264InstructionLengthDecode(const uint8_t *inst_bytes, int bytes_len,265 bool is_exec_mode_64b) {266 int op_idx = 0;267 bool prefix_done = false;268 InstructionOpcodeAndModrm ret = {0, 0, 0};269 270 // In most cases, the primary_opcode is the first byte of the instruction271 // but some instructions have a prefix to be skipped for these calculations.272 // The following mapping is inspired from libipt's instruction decoding logic273 // in `src/pt_ild.c`274 while (!prefix_done) {275 if (op_idx >= bytes_len)276 return std::nullopt;277 278 ret.primary_opcode = inst_bytes[op_idx];279 switch (ret.primary_opcode) {280 // prefix_ignore281 case 0x26:282 case 0x2e:283 case 0x36:284 case 0x3e:285 case 0x64:286 case 0x65:287 // prefix_osz, prefix_asz288 case 0x66:289 case 0x67:290 // prefix_lock, prefix_f2, prefix_f3291 case 0xf0:292 case 0xf2:293 case 0xf3:294 op_idx++;295 break;296 297 // prefix_rex298 case 0x40:299 case 0x41:300 case 0x42:301 case 0x43:302 case 0x44:303 case 0x45:304 case 0x46:305 case 0x47:306 case 0x48:307 case 0x49:308 case 0x4a:309 case 0x4b:310 case 0x4c:311 case 0x4d:312 case 0x4e:313 case 0x4f:314 if (is_exec_mode_64b)315 op_idx++;316 else317 prefix_done = true;318 break;319 320 // prefix_vex_c4, c5321 case 0xc5:322 if (!is_exec_mode_64b && (inst_bytes[op_idx + 1] & 0xc0) != 0xc0) {323 prefix_done = true;324 break;325 }326 327 ret.opcode_len = 2;328 ret.primary_opcode = inst_bytes[op_idx + 2];329 ret.modrm = inst_bytes[op_idx + 3];330 return ret;331 332 case 0xc4:333 if (!is_exec_mode_64b && (inst_bytes[op_idx + 1] & 0xc0) != 0xc0) {334 prefix_done = true;335 break;336 }337 ret.opcode_len = inst_bytes[op_idx + 1] & 0x1f;338 ret.primary_opcode = inst_bytes[op_idx + 3];339 ret.modrm = inst_bytes[op_idx + 4];340 return ret;341 342 // prefix_evex343 case 0x62:344 if (!is_exec_mode_64b && (inst_bytes[op_idx + 1] & 0xc0) != 0xc0) {345 prefix_done = true;346 break;347 }348 ret.opcode_len = inst_bytes[op_idx + 1] & 0x03;349 ret.primary_opcode = inst_bytes[op_idx + 4];350 ret.modrm = inst_bytes[op_idx + 5];351 return ret;352 353 default:354 prefix_done = true;355 break;356 }357 } // prefix done358 359 ret.primary_opcode = inst_bytes[op_idx];360 ret.modrm = inst_bytes[op_idx + 1];361 ret.opcode_len = 1;362 363 // If the first opcode is 0F, it's two- or three- byte opcodes.364 if (ret.primary_opcode == 0x0F) {365 ret.primary_opcode = inst_bytes[++op_idx]; // get the next byte366 367 if (ret.primary_opcode == 0x38) {368 ret.opcode_len = 3;369 ret.primary_opcode = inst_bytes[++op_idx]; // get the next byte370 ret.modrm = inst_bytes[op_idx + 1];371 } else if (ret.primary_opcode == 0x3A) {372 ret.opcode_len = 3;373 ret.primary_opcode = inst_bytes[++op_idx];374 ret.modrm = inst_bytes[op_idx + 1];375 } else if ((ret.primary_opcode & 0xf8) == 0x38) {376 ret.opcode_len = 0;377 ret.primary_opcode = inst_bytes[++op_idx];378 ret.modrm = inst_bytes[op_idx + 1];379 } else if (ret.primary_opcode == 0x0F) {380 ret.opcode_len = 3;381 // opcode is 0x0F, no needs to update382 ret.modrm = inst_bytes[op_idx + 1];383 } else {384 ret.opcode_len = 2;385 ret.modrm = inst_bytes[op_idx + 1];386 }387 }388 389 return ret;390}391 392lldb::InstructionControlFlowKind GetControlFlowKind(bool is_exec_mode_64b,393 Opcode m_opcode) {394 std::optional<InstructionOpcodeAndModrm> ret;395 396 if (m_opcode.GetOpcodeBytes() == nullptr || m_opcode.GetByteSize() <= 0) {397 // x86_64 and i386 instructions are categorized as Opcode::Type::eTypeBytes398 return lldb::eInstructionControlFlowKindUnknown;399 }400 401 // Opcode bytes will be decoded into primary_opcode, modrm and opcode length.402 // These are the three values deciding instruction control flow kind.403 ret = InstructionLengthDecode((const uint8_t *)m_opcode.GetOpcodeBytes(),404 m_opcode.GetByteSize(), is_exec_mode_64b);405 if (!ret)406 return lldb::eInstructionControlFlowKindUnknown;407 else408 return MapOpcodeIntoControlFlowKind(*ret);409}410 411} // namespace x86412 413class InstructionLLVMC : public lldb_private::Instruction {414public:415 InstructionLLVMC(DisassemblerLLVMC &disasm,416 const lldb_private::Address &address,417 AddressClass addr_class)418 : Instruction(address, addr_class),419 m_disasm_wp(std::static_pointer_cast<DisassemblerLLVMC>(420 disasm.shared_from_this())) {}421 422 ~InstructionLLVMC() override = default;423 424 bool DoesBranch() override {425 VisitInstruction();426 return m_does_branch;427 }428 429 bool HasDelaySlot() override {430 VisitInstruction();431 return m_has_delay_slot;432 }433 434 bool IsLoad() override {435 VisitInstruction();436 return m_is_load;437 }438 439 bool IsAuthenticated() override {440 VisitInstruction();441 return m_is_authenticated;442 }443 444 DisassemblerLLVMC::MCDisasmInstance *GetDisasmToUse(bool &is_alternate_isa) {445 DisassemblerScope disasm(*this);446 return GetDisasmToUse(is_alternate_isa, disasm);447 }448 449 size_t Decode(const lldb_private::Disassembler &disassembler,450 const lldb_private::DataExtractor &data,451 lldb::offset_t data_offset) override {452 // All we have to do is read the opcode which can be easy for some453 // architectures454 bool got_op = false;455 DisassemblerScope disasm(*this);456 if (disasm) {457 const ArchSpec &arch = disasm->GetArchitecture();458 const lldb::ByteOrder byte_order = data.GetByteOrder();459 460 const uint32_t min_op_byte_size = arch.GetMinimumOpcodeByteSize();461 const uint32_t max_op_byte_size = arch.GetMaximumOpcodeByteSize();462 if (min_op_byte_size == max_op_byte_size) {463 // Fixed size instructions, just read that amount of data.464 if (!data.ValidOffsetForDataOfSize(data_offset, min_op_byte_size))465 return false;466 467 switch (min_op_byte_size) {468 case 1:469 m_opcode.SetOpcode8(data.GetU8(&data_offset), byte_order);470 got_op = true;471 break;472 473 case 2:474 m_opcode.SetOpcode16(data.GetU16(&data_offset), byte_order);475 got_op = true;476 break;477 478 case 4:479 m_opcode.SetOpcode32(data.GetU32(&data_offset), byte_order);480 got_op = true;481 break;482 483 case 8:484 m_opcode.SetOpcode64(data.GetU64(&data_offset), byte_order);485 got_op = true;486 break;487 488 default:489 if (arch.GetTriple().isRISCV())490 m_opcode.SetOpcode16_32TupleBytes(491 data.PeekData(data_offset, min_op_byte_size), min_op_byte_size,492 byte_order);493 else494 m_opcode.SetOpcodeBytes(495 data.PeekData(data_offset, min_op_byte_size), min_op_byte_size);496 got_op = true;497 break;498 }499 }500 if (!got_op) {501 bool is_alternate_isa = false;502 DisassemblerLLVMC::MCDisasmInstance *mc_disasm_ptr =503 GetDisasmToUse(is_alternate_isa, disasm);504 505 const llvm::Triple::ArchType machine = arch.GetMachine();506 if (machine == llvm::Triple::arm || machine == llvm::Triple::thumb) {507 if (machine == llvm::Triple::thumb || is_alternate_isa) {508 uint32_t thumb_opcode = data.GetU16(&data_offset);509 if ((thumb_opcode & 0xe000) != 0xe000 ||510 ((thumb_opcode & 0x1800u) == 0)) {511 m_opcode.SetOpcode16(thumb_opcode, byte_order);512 m_is_valid = true;513 } else {514 thumb_opcode <<= 16;515 thumb_opcode |= data.GetU16(&data_offset);516 m_opcode.SetOpcode16_2(thumb_opcode, byte_order);517 m_is_valid = true;518 }519 } else {520 m_opcode.SetOpcode32(data.GetU32(&data_offset), byte_order);521 m_is_valid = true;522 }523 } else {524 // The opcode isn't evenly sized, so we need to actually use the llvm525 // disassembler to parse it and get the size.526 uint8_t *opcode_data =527 const_cast<uint8_t *>(data.PeekData(data_offset, 1));528 const size_t opcode_data_len = data.BytesLeft(data_offset);529 const addr_t pc = m_address.GetFileAddress();530 llvm::MCInst inst;531 532 uint64_t inst_size = 0;533 m_is_valid = mc_disasm_ptr->GetMCInst(opcode_data, opcode_data_len,534 pc, inst, inst_size);535 m_opcode.Clear();536 if (inst_size != 0) {537 if (arch.GetTriple().isRISCV())538 m_opcode.SetOpcode16_32TupleBytes(opcode_data, inst_size,539 byte_order);540 else541 m_opcode.SetOpcodeBytes(opcode_data, inst_size);542 }543 }544 }545 return m_opcode.GetByteSize();546 }547 return 0;548 }549 550 void AppendComment(std::string &description) {551 if (m_comment.empty())552 m_comment.swap(description);553 else {554 m_comment.append(", ");555 m_comment.append(description);556 }557 }558 559 lldb::InstructionControlFlowKind560 GetControlFlowKind(const lldb_private::ExecutionContext *exe_ctx) override {561 DisassemblerScope disasm(*this, exe_ctx);562 if (disasm) {563 if (disasm->GetArchitecture().GetMachine() == llvm::Triple::x86)564 return x86::GetControlFlowKind(/*is_64b=*/false, m_opcode);565 else if (disasm->GetArchitecture().GetMachine() == llvm::Triple::x86_64)566 return x86::GetControlFlowKind(/*is_64b=*/true, m_opcode);567 }568 569 return eInstructionControlFlowKindUnknown;570 }571 572 void CalculateMnemonicOperandsAndComment(573 const lldb_private::ExecutionContext *exe_ctx) override {574 DataExtractor data;575 const AddressClass address_class = GetAddressClass();576 577 if (m_opcode.GetData(data)) {578 std::string out_string;579 std::string markup_out_string;580 std::string comment_string;581 std::string markup_comment_string;582 583 DisassemblerScope disasm(*this, exe_ctx);584 if (disasm) {585 DisassemblerLLVMC::MCDisasmInstance *mc_disasm_ptr;586 587 if (address_class == AddressClass::eCodeAlternateISA)588 mc_disasm_ptr = disasm->m_alternate_disasm_up.get();589 else590 mc_disasm_ptr = disasm->m_disasm_up.get();591 592 lldb::addr_t pc = m_address.GetFileAddress();593 m_using_file_addr = true;594 595 bool use_hex_immediates = true;596 Disassembler::HexImmediateStyle hex_style = Disassembler::eHexStyleC;597 598 if (exe_ctx) {599 Target *target = exe_ctx->GetTargetPtr();600 if (target) {601 use_hex_immediates = target->GetUseHexImmediates();602 hex_style = target->GetHexImmediateStyle();603 604 const lldb::addr_t load_addr = m_address.GetLoadAddress(target);605 if (load_addr != LLDB_INVALID_ADDRESS) {606 pc = load_addr;607 m_using_file_addr = false;608 }609 }610 }611 612 const uint8_t *opcode_data = data.GetDataStart();613 const size_t opcode_data_len = data.GetByteSize();614 llvm::MCInst inst;615 uint64_t inst_size = 0;616 bool valid = mc_disasm_ptr->GetMCInst(opcode_data, opcode_data_len, pc,617 inst, inst_size);618 619 if (valid && inst_size > 0) {620 mc_disasm_ptr->SetStyle(use_hex_immediates, hex_style);621 622 const bool saved_use_color = mc_disasm_ptr->GetUseColor();623 mc_disasm_ptr->SetUseColor(false);624 mc_disasm_ptr->PrintMCInst(inst, pc, out_string, comment_string);625 mc_disasm_ptr->SetUseColor(true);626 mc_disasm_ptr->PrintMCInst(inst, pc, markup_out_string,627 markup_comment_string);628 mc_disasm_ptr->SetUseColor(saved_use_color);629 630 if (!comment_string.empty()) {631 AppendComment(comment_string);632 }633 }634 635 if (inst_size == 0) {636 m_comment.assign("unknown opcode");637 inst_size = m_opcode.GetByteSize();638 StreamString mnemonic_strm;639 lldb::offset_t offset = 0;640 lldb::ByteOrder byte_order = data.GetByteOrder();641 switch (inst_size) {642 case 1: {643 const uint8_t uval8 = data.GetU8(&offset);644 m_opcode.SetOpcode8(uval8, byte_order);645 m_opcode_name.assign(".byte");646 mnemonic_strm.Printf("0x%2.2x", uval8);647 } break;648 case 2: {649 const uint16_t uval16 = data.GetU16(&offset);650 m_opcode.SetOpcode16(uval16, byte_order);651 m_opcode_name.assign(".short");652 mnemonic_strm.Printf("0x%4.4x", uval16);653 } break;654 case 4: {655 const uint32_t uval32 = data.GetU32(&offset);656 m_opcode.SetOpcode32(uval32, byte_order);657 m_opcode_name.assign(".long");658 mnemonic_strm.Printf("0x%8.8x", uval32);659 } break;660 case 8: {661 const uint64_t uval64 = data.GetU64(&offset);662 m_opcode.SetOpcode64(uval64, byte_order);663 m_opcode_name.assign(".quad");664 mnemonic_strm.Printf("0x%16.16" PRIx64, uval64);665 } break;666 default:667 if (inst_size == 0)668 return;669 else {670 const uint8_t *bytes = data.PeekData(offset, inst_size);671 if (bytes == nullptr)672 return;673 m_opcode_name.assign(".byte");674 m_opcode.SetOpcodeBytes(bytes, inst_size);675 mnemonic_strm.Printf("0x%2.2x", bytes[0]);676 for (uint32_t i = 1; i < inst_size; ++i)677 mnemonic_strm.Printf(" 0x%2.2x", bytes[i]);678 }679 break;680 }681 m_mnemonics = std::string(mnemonic_strm.GetString());682 return;683 }684 685 static RegularExpression s_regex(686 llvm::StringRef("[ \t]*([^ ^\t]+)[ \t]*([^ ^\t].*)?"));687 688 llvm::SmallVector<llvm::StringRef, 4> matches;689 if (s_regex.Execute(out_string, &matches)) {690 m_opcode_name = matches[1].str();691 m_mnemonics = matches[2].str();692 }693 matches.clear();694 if (s_regex.Execute(markup_out_string, &matches)) {695 m_markup_opcode_name = matches[1].str();696 m_markup_mnemonics = matches[2].str();697 }698 }699 }700 }701 702 bool IsValid() const { return m_is_valid; }703 704 bool UsingFileAddress() const { return m_using_file_addr; }705 size_t GetByteSize() const { return m_opcode.GetByteSize(); }706 707 /// Grants exclusive access to the disassembler and initializes it with the708 /// given InstructionLLVMC and an optional ExecutionContext.709 class DisassemblerScope {710 std::shared_ptr<DisassemblerLLVMC> m_disasm;711 712 public:713 explicit DisassemblerScope(714 InstructionLLVMC &i,715 const lldb_private::ExecutionContext *exe_ctx = nullptr)716 : m_disasm(i.m_disasm_wp.lock()) {717 m_disasm->m_mutex.lock();718 m_disasm->m_inst = &i;719 m_disasm->m_exe_ctx = exe_ctx;720 }721 ~DisassemblerScope() { m_disasm->m_mutex.unlock(); }722 723 /// Evaluates to true if this scope contains a valid disassembler.724 operator bool() const { return static_cast<bool>(m_disasm); }725 726 std::shared_ptr<DisassemblerLLVMC> operator->() { return m_disasm; }727 };728 729 static llvm::StringRef::const_iterator730 ConsumeWhitespace(llvm::StringRef::const_iterator osi,731 llvm::StringRef::const_iterator ose) {732 while (osi != ose) {733 switch (*osi) {734 default:735 return osi;736 case ' ':737 case '\t':738 break;739 }740 ++osi;741 }742 743 return osi;744 }745 746 static std::pair<bool, llvm::StringRef::const_iterator>747 ConsumeChar(llvm::StringRef::const_iterator osi, const char c,748 llvm::StringRef::const_iterator ose) {749 bool found = false;750 751 osi = ConsumeWhitespace(osi, ose);752 if (osi != ose && *osi == c) {753 found = true;754 ++osi;755 }756 757 return std::make_pair(found, osi);758 }759 760 static std::pair<Operand, llvm::StringRef::const_iterator>761 ParseRegisterName(llvm::StringRef::const_iterator osi,762 llvm::StringRef::const_iterator ose) {763 Operand ret;764 ret.m_type = Operand::Type::Register;765 std::string str;766 767 osi = ConsumeWhitespace(osi, ose);768 769 while (osi != ose) {770 if (*osi >= '0' && *osi <= '9') {771 if (str.empty()) {772 return std::make_pair(Operand(), osi);773 } else {774 str.push_back(*osi);775 }776 } else if (*osi >= 'a' && *osi <= 'z') {777 str.push_back(*osi);778 } else {779 switch (*osi) {780 default:781 if (str.empty()) {782 return std::make_pair(Operand(), osi);783 } else {784 ret.m_register = ConstString(str);785 return std::make_pair(ret, osi);786 }787 case '%':788 if (!str.empty()) {789 return std::make_pair(Operand(), osi);790 }791 break;792 }793 }794 ++osi;795 }796 797 ret.m_register = ConstString(str);798 return std::make_pair(ret, osi);799 }800 801 static std::pair<Operand, llvm::StringRef::const_iterator>802 ParseImmediate(llvm::StringRef::const_iterator osi,803 llvm::StringRef::const_iterator ose) {804 Operand ret;805 ret.m_type = Operand::Type::Immediate;806 std::string str;807 bool is_hex = false;808 809 osi = ConsumeWhitespace(osi, ose);810 811 while (osi != ose) {812 if (*osi >= '0' && *osi <= '9') {813 str.push_back(*osi);814 } else if (*osi >= 'a' && *osi <= 'f') {815 if (is_hex) {816 str.push_back(*osi);817 } else {818 return std::make_pair(Operand(), osi);819 }820 } else {821 switch (*osi) {822 default:823 if (str.empty()) {824 return std::make_pair(Operand(), osi);825 } else {826 ret.m_immediate = strtoull(str.c_str(), nullptr, 0);827 return std::make_pair(ret, osi);828 }829 case 'x':830 if (str == "0") {831 is_hex = true;832 str.push_back(*osi);833 } else {834 return std::make_pair(Operand(), osi);835 }836 break;837 case '#':838 case '$':839 if (!str.empty()) {840 return std::make_pair(Operand(), osi);841 }842 break;843 case '-':844 if (str.empty()) {845 ret.m_negative = true;846 } else {847 return std::make_pair(Operand(), osi);848 }849 }850 }851 ++osi;852 }853 854 ret.m_immediate = strtoull(str.c_str(), nullptr, 0);855 return std::make_pair(ret, osi);856 }857 858 // -0x5(%rax,%rax,2)859 static std::pair<Operand, llvm::StringRef::const_iterator>860 ParseIntelIndexedAccess(llvm::StringRef::const_iterator osi,861 llvm::StringRef::const_iterator ose) {862 std::pair<Operand, llvm::StringRef::const_iterator> offset_and_iterator =863 ParseImmediate(osi, ose);864 if (offset_and_iterator.first.IsValid()) {865 osi = offset_and_iterator.second;866 }867 868 bool found = false;869 std::tie(found, osi) = ConsumeChar(osi, '(', ose);870 if (!found) {871 return std::make_pair(Operand(), osi);872 }873 874 std::pair<Operand, llvm::StringRef::const_iterator> base_and_iterator =875 ParseRegisterName(osi, ose);876 if (base_and_iterator.first.IsValid()) {877 osi = base_and_iterator.second;878 } else {879 return std::make_pair(Operand(), osi);880 }881 882 std::tie(found, osi) = ConsumeChar(osi, ',', ose);883 if (!found) {884 return std::make_pair(Operand(), osi);885 }886 887 std::pair<Operand, llvm::StringRef::const_iterator> index_and_iterator =888 ParseRegisterName(osi, ose);889 if (index_and_iterator.first.IsValid()) {890 osi = index_and_iterator.second;891 } else {892 return std::make_pair(Operand(), osi);893 }894 895 std::tie(found, osi) = ConsumeChar(osi, ',', ose);896 if (!found) {897 return std::make_pair(Operand(), osi);898 }899 900 std::pair<Operand, llvm::StringRef::const_iterator>901 multiplier_and_iterator = ParseImmediate(osi, ose);902 if (index_and_iterator.first.IsValid()) {903 osi = index_and_iterator.second;904 } else {905 return std::make_pair(Operand(), osi);906 }907 908 std::tie(found, osi) = ConsumeChar(osi, ')', ose);909 if (!found) {910 return std::make_pair(Operand(), osi);911 }912 913 Operand product;914 product.m_type = Operand::Type::Product;915 product.m_children.push_back(index_and_iterator.first);916 product.m_children.push_back(multiplier_and_iterator.first);917 918 Operand index;919 index.m_type = Operand::Type::Sum;920 index.m_children.push_back(base_and_iterator.first);921 index.m_children.push_back(product);922 923 if (offset_and_iterator.first.IsValid()) {924 Operand offset;925 offset.m_type = Operand::Type::Sum;926 offset.m_children.push_back(offset_and_iterator.first);927 offset.m_children.push_back(index);928 929 Operand deref;930 deref.m_type = Operand::Type::Dereference;931 deref.m_children.push_back(offset);932 return std::make_pair(deref, osi);933 } else {934 Operand deref;935 deref.m_type = Operand::Type::Dereference;936 deref.m_children.push_back(index);937 return std::make_pair(deref, osi);938 }939 }940 941 // -0x10(%rbp)942 static std::pair<Operand, llvm::StringRef::const_iterator>943 ParseIntelDerefAccess(llvm::StringRef::const_iterator osi,944 llvm::StringRef::const_iterator ose) {945 std::pair<Operand, llvm::StringRef::const_iterator> offset_and_iterator =946 ParseImmediate(osi, ose);947 if (offset_and_iterator.first.IsValid()) {948 osi = offset_and_iterator.second;949 }950 951 bool found = false;952 std::tie(found, osi) = ConsumeChar(osi, '(', ose);953 if (!found) {954 return std::make_pair(Operand(), osi);955 }956 957 std::pair<Operand, llvm::StringRef::const_iterator> base_and_iterator =958 ParseRegisterName(osi, ose);959 if (base_and_iterator.first.IsValid()) {960 osi = base_and_iterator.second;961 } else {962 return std::make_pair(Operand(), osi);963 }964 965 std::tie(found, osi) = ConsumeChar(osi, ')', ose);966 if (!found) {967 return std::make_pair(Operand(), osi);968 }969 970 if (offset_and_iterator.first.IsValid()) {971 Operand offset;972 offset.m_type = Operand::Type::Sum;973 offset.m_children.push_back(offset_and_iterator.first);974 offset.m_children.push_back(base_and_iterator.first);975 976 Operand deref;977 deref.m_type = Operand::Type::Dereference;978 deref.m_children.push_back(offset);979 return std::make_pair(deref, osi);980 } else {981 Operand deref;982 deref.m_type = Operand::Type::Dereference;983 deref.m_children.push_back(base_and_iterator.first);984 return std::make_pair(deref, osi);985 }986 }987 988 // [sp, #8]!989 static std::pair<Operand, llvm::StringRef::const_iterator>990 ParseARMOffsetAccess(llvm::StringRef::const_iterator osi,991 llvm::StringRef::const_iterator ose) {992 bool found = false;993 std::tie(found, osi) = ConsumeChar(osi, '[', ose);994 if (!found) {995 return std::make_pair(Operand(), osi);996 }997 998 std::pair<Operand, llvm::StringRef::const_iterator> base_and_iterator =999 ParseRegisterName(osi, ose);1000 if (base_and_iterator.first.IsValid()) {1001 osi = base_and_iterator.second;1002 } else {1003 return std::make_pair(Operand(), osi);1004 }1005 1006 std::tie(found, osi) = ConsumeChar(osi, ',', ose);1007 if (!found) {1008 return std::make_pair(Operand(), osi);1009 }1010 1011 std::pair<Operand, llvm::StringRef::const_iterator> offset_and_iterator =1012 ParseImmediate(osi, ose);1013 if (offset_and_iterator.first.IsValid()) {1014 osi = offset_and_iterator.second;1015 }1016 1017 std::tie(found, osi) = ConsumeChar(osi, ']', ose);1018 if (!found) {1019 return std::make_pair(Operand(), osi);1020 }1021 1022 Operand offset;1023 offset.m_type = Operand::Type::Sum;1024 offset.m_children.push_back(offset_and_iterator.first);1025 offset.m_children.push_back(base_and_iterator.first);1026 1027 Operand deref;1028 deref.m_type = Operand::Type::Dereference;1029 deref.m_children.push_back(offset);1030 return std::make_pair(deref, osi);1031 }1032 1033 // [sp]1034 static std::pair<Operand, llvm::StringRef::const_iterator>1035 ParseARMDerefAccess(llvm::StringRef::const_iterator osi,1036 llvm::StringRef::const_iterator ose) {1037 bool found = false;1038 std::tie(found, osi) = ConsumeChar(osi, '[', ose);1039 if (!found) {1040 return std::make_pair(Operand(), osi);1041 }1042 1043 std::pair<Operand, llvm::StringRef::const_iterator> base_and_iterator =1044 ParseRegisterName(osi, ose);1045 if (base_and_iterator.first.IsValid()) {1046 osi = base_and_iterator.second;1047 } else {1048 return std::make_pair(Operand(), osi);1049 }1050 1051 std::tie(found, osi) = ConsumeChar(osi, ']', ose);1052 if (!found) {1053 return std::make_pair(Operand(), osi);1054 }1055 1056 Operand deref;1057 deref.m_type = Operand::Type::Dereference;1058 deref.m_children.push_back(base_and_iterator.first);1059 return std::make_pair(deref, osi);1060 }1061 1062 static void DumpOperand(const Operand &op, Stream &s) {1063 switch (op.m_type) {1064 case Operand::Type::Dereference:1065 s.PutCString("*");1066 DumpOperand(op.m_children[0], s);1067 break;1068 case Operand::Type::Immediate:1069 if (op.m_negative) {1070 s.PutCString("-");1071 }1072 s.PutCString(llvm::to_string(op.m_immediate));1073 break;1074 case Operand::Type::Invalid:1075 s.PutCString("Invalid");1076 break;1077 case Operand::Type::Product:1078 s.PutCString("(");1079 DumpOperand(op.m_children[0], s);1080 s.PutCString("*");1081 DumpOperand(op.m_children[1], s);1082 s.PutCString(")");1083 break;1084 case Operand::Type::Register:1085 s.PutCString(op.m_register.GetStringRef());1086 break;1087 case Operand::Type::Sum:1088 s.PutCString("(");1089 DumpOperand(op.m_children[0], s);1090 s.PutCString("+");1091 DumpOperand(op.m_children[1], s);1092 s.PutCString(")");1093 break;1094 }1095 }1096 1097 bool ParseOperands(1098 llvm::SmallVectorImpl<Instruction::Operand> &operands) override {1099 const char *operands_string = GetOperands(nullptr);1100 1101 if (!operands_string) {1102 return false;1103 }1104 1105 llvm::StringRef operands_ref(operands_string);1106 1107 llvm::StringRef::const_iterator osi = operands_ref.begin();1108 llvm::StringRef::const_iterator ose = operands_ref.end();1109 1110 while (osi != ose) {1111 Operand operand;1112 llvm::StringRef::const_iterator iter;1113 1114 if ((std::tie(operand, iter) = ParseIntelIndexedAccess(osi, ose),1115 operand.IsValid()) ||1116 (std::tie(operand, iter) = ParseIntelDerefAccess(osi, ose),1117 operand.IsValid()) ||1118 (std::tie(operand, iter) = ParseARMOffsetAccess(osi, ose),1119 operand.IsValid()) ||1120 (std::tie(operand, iter) = ParseARMDerefAccess(osi, ose),1121 operand.IsValid()) ||1122 (std::tie(operand, iter) = ParseRegisterName(osi, ose),1123 operand.IsValid()) ||1124 (std::tie(operand, iter) = ParseImmediate(osi, ose),1125 operand.IsValid())) {1126 osi = iter;1127 operands.push_back(operand);1128 } else {1129 return false;1130 }1131 1132 std::pair<bool, llvm::StringRef::const_iterator> found_and_iter =1133 ConsumeChar(osi, ',', ose);1134 if (found_and_iter.first) {1135 osi = found_and_iter.second;1136 }1137 1138 osi = ConsumeWhitespace(osi, ose);1139 }1140 1141 DisassemblerSP disasm_sp = m_disasm_wp.lock();1142 1143 if (disasm_sp && operands.size() > 1) {1144 // TODO tie this into the MC Disassembler's notion of clobbers.1145 switch (disasm_sp->GetArchitecture().GetMachine()) {1146 default:1147 break;1148 case llvm::Triple::x86:1149 case llvm::Triple::x86_64:1150 operands[operands.size() - 1].m_clobbered = true;1151 break;1152 case llvm::Triple::arm:1153 operands[0].m_clobbered = true;1154 break;1155 }1156 }1157 1158 if (Log *log = GetLog(LLDBLog::Process | LLDBLog::Disassembler)) {1159 StreamString ss;1160 1161 ss.Printf("[%s] expands to %zu operands:\n", operands_string,1162 operands.size());1163 for (const Operand &operand : operands) {1164 ss.PutCString(" ");1165 DumpOperand(operand, ss);1166 ss.PutCString("\n");1167 }1168 1169 log->PutString(ss.GetString());1170 }1171 1172 return true;1173 }1174 1175 bool IsCall() override {1176 VisitInstruction();1177 return m_is_call;1178 }1179 1180protected:1181 std::weak_ptr<DisassemblerLLVMC> m_disasm_wp;1182 1183 bool m_is_valid = false;1184 bool m_using_file_addr = false;1185 bool m_has_visited_instruction = false;1186 1187 // Be conservative. If we didn't understand the instruction, say it:1188 // - Might branch1189 // - Does not have a delay slot1190 // - Is not a call1191 // - Is not a load1192 // - Is not an authenticated instruction1193 bool m_does_branch = true;1194 bool m_has_delay_slot = false;1195 bool m_is_call = false;1196 bool m_is_load = false;1197 bool m_is_authenticated = false;1198 1199 void VisitInstruction() {1200 if (m_has_visited_instruction)1201 return;1202 1203 DisassemblerScope disasm(*this);1204 if (!disasm)1205 return;1206 1207 DataExtractor data;1208 if (!m_opcode.GetData(data))1209 return;1210 1211 bool is_alternate_isa;1212 lldb::addr_t pc = m_address.GetFileAddress();1213 DisassemblerLLVMC::MCDisasmInstance *mc_disasm_ptr =1214 GetDisasmToUse(is_alternate_isa, disasm);1215 const uint8_t *opcode_data = data.GetDataStart();1216 const size_t opcode_data_len = data.GetByteSize();1217 llvm::MCInst inst;1218 uint64_t inst_size = 0;1219 const bool valid = mc_disasm_ptr->GetMCInst(opcode_data, opcode_data_len,1220 pc, inst, inst_size);1221 if (!valid)1222 return;1223 1224 m_has_visited_instruction = true;1225 m_does_branch = mc_disasm_ptr->CanBranch(inst);1226 m_has_delay_slot = mc_disasm_ptr->HasDelaySlot(inst);1227 m_is_call = mc_disasm_ptr->IsCall(inst);1228 m_is_load = mc_disasm_ptr->IsLoad(inst);1229 m_is_authenticated = mc_disasm_ptr->IsAuthenticated(inst);1230 }1231 1232private:1233 DisassemblerLLVMC::MCDisasmInstance *1234 GetDisasmToUse(bool &is_alternate_isa, DisassemblerScope &disasm) {1235 is_alternate_isa = false;1236 if (disasm) {1237 if (disasm->m_alternate_disasm_up) {1238 const AddressClass address_class = GetAddressClass();1239 1240 if (address_class == AddressClass::eCodeAlternateISA) {1241 is_alternate_isa = true;1242 return disasm->m_alternate_disasm_up.get();1243 }1244 }1245 return disasm->m_disasm_up.get();1246 }1247 return nullptr;1248 }1249};1250 1251std::unique_ptr<DisassemblerLLVMC::MCDisasmInstance>1252DisassemblerLLVMC::MCDisasmInstance::Create(const char *triple_name,1253 const char *cpu,1254 const char *features_str,1255 unsigned flavor,1256 DisassemblerLLVMC &owner) {1257 using Instance = std::unique_ptr<DisassemblerLLVMC::MCDisasmInstance>;1258 1259 llvm::Triple triple(triple_name);1260 1261 std::string Status;1262 const llvm::Target *curr_target =1263 llvm::TargetRegistry::lookupTarget(triple, Status);1264 if (!curr_target)1265 return Instance();1266 1267 std::unique_ptr<llvm::MCInstrInfo> instr_info_up(1268 curr_target->createMCInstrInfo());1269 if (!instr_info_up)1270 return Instance();1271 1272 std::unique_ptr<llvm::MCRegisterInfo> reg_info_up(1273 curr_target->createMCRegInfo(triple));1274 if (!reg_info_up)1275 return Instance();1276 1277 std::unique_ptr<llvm::MCSubtargetInfo> subtarget_info_up(1278 curr_target->createMCSubtargetInfo(triple, cpu, features_str));1279 if (!subtarget_info_up)1280 return Instance();1281 1282 llvm::MCTargetOptions MCOptions;1283 std::unique_ptr<llvm::MCAsmInfo> asm_info_up(1284 curr_target->createMCAsmInfo(*reg_info_up, triple, MCOptions));1285 if (!asm_info_up)1286 return Instance();1287 1288 std::unique_ptr<llvm::MCContext> context_up(1289 new llvm::MCContext(llvm::Triple(triple), asm_info_up.get(),1290 reg_info_up.get(), subtarget_info_up.get()));1291 if (!context_up)1292 return Instance();1293 1294 std::unique_ptr<llvm::MCDisassembler> disasm_up(1295 curr_target->createMCDisassembler(*subtarget_info_up, *context_up));1296 if (!disasm_up)1297 return Instance();1298 1299 std::unique_ptr<llvm::MCRelocationInfo> rel_info_up(1300 curr_target->createMCRelocationInfo(triple, *context_up));1301 if (!rel_info_up)1302 return Instance();1303 1304 std::unique_ptr<llvm::MCSymbolizer> symbolizer_up(1305 curr_target->createMCSymbolizer(1306 triple, nullptr, DisassemblerLLVMC::SymbolLookupCallback, &owner,1307 context_up.get(), std::move(rel_info_up)));1308 disasm_up->setSymbolizer(std::move(symbolizer_up));1309 1310 unsigned asm_printer_variant =1311 flavor == ~0U ? asm_info_up->getAssemblerDialect() : flavor;1312 1313 std::unique_ptr<llvm::MCInstPrinter> instr_printer_up(1314 curr_target->createMCInstPrinter(llvm::Triple{triple},1315 asm_printer_variant, *asm_info_up,1316 *instr_info_up, *reg_info_up));1317 if (!instr_printer_up)1318 return Instance();1319 1320 instr_printer_up->setPrintBranchImmAsAddress(true);1321 1322 // Not all targets may have registered createMCInstrAnalysis().1323 std::unique_ptr<llvm::MCInstrAnalysis> instr_analysis_up(1324 curr_target->createMCInstrAnalysis(instr_info_up.get()));1325 1326 return Instance(new MCDisasmInstance(1327 std::move(instr_info_up), std::move(reg_info_up),1328 std::move(subtarget_info_up), std::move(asm_info_up),1329 std::move(context_up), std::move(disasm_up), std::move(instr_printer_up),1330 std::move(instr_analysis_up)));1331}1332 1333DisassemblerLLVMC::MCDisasmInstance::MCDisasmInstance(1334 std::unique_ptr<llvm::MCInstrInfo> &&instr_info_up,1335 std::unique_ptr<llvm::MCRegisterInfo> &®_info_up,1336 std::unique_ptr<llvm::MCSubtargetInfo> &&subtarget_info_up,1337 std::unique_ptr<llvm::MCAsmInfo> &&asm_info_up,1338 std::unique_ptr<llvm::MCContext> &&context_up,1339 std::unique_ptr<llvm::MCDisassembler> &&disasm_up,1340 std::unique_ptr<llvm::MCInstPrinter> &&instr_printer_up,1341 std::unique_ptr<llvm::MCInstrAnalysis> &&instr_analysis_up)1342 : m_instr_info_up(std::move(instr_info_up)),1343 m_reg_info_up(std::move(reg_info_up)),1344 m_subtarget_info_up(std::move(subtarget_info_up)),1345 m_asm_info_up(std::move(asm_info_up)),1346 m_context_up(std::move(context_up)), m_disasm_up(std::move(disasm_up)),1347 m_instr_printer_up(std::move(instr_printer_up)),1348 m_instr_analysis_up(std::move(instr_analysis_up)) {1349 assert(m_instr_info_up && m_reg_info_up && m_subtarget_info_up &&1350 m_asm_info_up && m_context_up && m_disasm_up && m_instr_printer_up);1351}1352 1353bool DisassemblerLLVMC::MCDisasmInstance::GetMCInst(const uint8_t *opcode_data,1354 size_t opcode_data_len,1355 lldb::addr_t pc,1356 llvm::MCInst &mc_inst,1357 uint64_t &size) const {1358 llvm::ArrayRef<uint8_t> data(opcode_data, opcode_data_len);1359 llvm::MCDisassembler::DecodeStatus status;1360 1361 status = m_disasm_up->getInstruction(mc_inst, size, data, pc, llvm::nulls());1362 if (status == llvm::MCDisassembler::Success)1363 return true;1364 else1365 return false;1366}1367 1368void DisassemblerLLVMC::MCDisasmInstance::PrintMCInst(1369 llvm::MCInst &mc_inst, lldb::addr_t pc, std::string &inst_string,1370 std::string &comments_string) {1371 llvm::raw_string_ostream inst_stream(inst_string);1372 llvm::raw_string_ostream comments_stream(comments_string);1373 1374 inst_stream.enable_colors(m_instr_printer_up->getUseColor());1375 m_instr_printer_up->setCommentStream(comments_stream);1376 m_instr_printer_up->printInst(&mc_inst, pc, llvm::StringRef(),1377 *m_subtarget_info_up, inst_stream);1378 m_instr_printer_up->setCommentStream(llvm::nulls());1379 1380 static std::string g_newlines("\r\n");1381 1382 for (size_t newline_pos = 0;1383 (newline_pos = comments_string.find_first_of(g_newlines, newline_pos)) !=1384 comments_string.npos;1385 /**/) {1386 comments_string.replace(comments_string.begin() + newline_pos,1387 comments_string.begin() + newline_pos + 1, 1, ' ');1388 }1389}1390 1391void DisassemblerLLVMC::MCDisasmInstance::SetStyle(1392 bool use_hex_immed, HexImmediateStyle hex_style) {1393 m_instr_printer_up->setPrintImmHex(use_hex_immed);1394 switch (hex_style) {1395 case eHexStyleC:1396 m_instr_printer_up->setPrintHexStyle(llvm::HexStyle::C);1397 break;1398 case eHexStyleAsm:1399 m_instr_printer_up->setPrintHexStyle(llvm::HexStyle::Asm);1400 break;1401 }1402}1403 1404void DisassemblerLLVMC::MCDisasmInstance::SetUseColor(bool use_color) {1405 m_instr_printer_up->setUseColor(use_color);1406}1407 1408bool DisassemblerLLVMC::MCDisasmInstance::GetUseColor() const {1409 return m_instr_printer_up->getUseColor();1410}1411 1412bool DisassemblerLLVMC::MCDisasmInstance::CanBranch(1413 llvm::MCInst &mc_inst) const {1414 if (m_instr_analysis_up)1415 return m_instr_analysis_up->mayAffectControlFlow(mc_inst, *m_reg_info_up);1416 return m_instr_info_up->get(mc_inst.getOpcode())1417 .mayAffectControlFlow(mc_inst, *m_reg_info_up);1418}1419 1420bool DisassemblerLLVMC::MCDisasmInstance::HasDelaySlot(1421 llvm::MCInst &mc_inst) const {1422 return m_instr_info_up->get(mc_inst.getOpcode()).hasDelaySlot();1423}1424 1425bool DisassemblerLLVMC::MCDisasmInstance::IsCall(llvm::MCInst &mc_inst) const {1426 if (m_instr_analysis_up)1427 return m_instr_analysis_up->isCall(mc_inst);1428 return m_instr_info_up->get(mc_inst.getOpcode()).isCall();1429}1430 1431bool DisassemblerLLVMC::MCDisasmInstance::IsLoad(llvm::MCInst &mc_inst) const {1432 return m_instr_info_up->get(mc_inst.getOpcode()).mayLoad();1433}1434 1435bool DisassemblerLLVMC::MCDisasmInstance::IsAuthenticated(1436 llvm::MCInst &mc_inst) const {1437 const auto &InstrDesc = m_instr_info_up->get(mc_inst.getOpcode());1438 1439 // Treat software auth traps (brk 0xc470 + aut key, where 0x70 == 'p', 0xc41440 // == 'a' + 'c') as authenticated instructions for reporting purposes, in1441 // addition to the standard authenticated instructions specified in ARMv8.3.1442 bool IsBrkC47x = false;1443 if (InstrDesc.isTrap() && mc_inst.getNumOperands() == 1) {1444 const llvm::MCOperand &Op0 = mc_inst.getOperand(0);1445 if (Op0.isImm() && Op0.getImm() >= 0xc470 && Op0.getImm() <= 0xc474)1446 IsBrkC47x = true;1447 }1448 1449 return InstrDesc.isAuthenticated() || IsBrkC47x;1450}1451 1452DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch,1453 const char *flavor_string,1454 const char *cpu_string,1455 const char *features_string)1456 : Disassembler(arch, flavor_string), m_exe_ctx(nullptr), m_inst(nullptr),1457 m_data_from_file(false), m_adrp_address(LLDB_INVALID_ADDRESS),1458 m_adrp_insn() {1459 if (!FlavorValidForArchSpec(arch, m_flavor.c_str())) {1460 m_flavor.assign("default");1461 }1462 1463 const bool cpu_or_features_overriden = cpu_string || features_string;1464 unsigned flavor = ~0U;1465 llvm::Triple triple = arch.GetTriple();1466 1467 // So far the only supported flavor is "intel" on x86. The base class will1468 // set this correctly coming in.1469 if (triple.getArch() == llvm::Triple::x86 ||1470 triple.getArch() == llvm::Triple::x86_64) {1471 if (m_flavor == "intel") {1472 flavor = 1;1473 } else if (m_flavor == "att") {1474 flavor = 0;1475 }1476 }1477 1478 ArchSpec thumb_arch(arch);1479 if (triple.getArch() == llvm::Triple::arm) {1480 std::string thumb_arch_name(thumb_arch.GetTriple().getArchName().str());1481 // Replace "arm" with "thumb" so we get all thumb variants correct1482 if (thumb_arch_name.size() > 3) {1483 thumb_arch_name.erase(0, 3);1484 thumb_arch_name.insert(0, "thumb");1485 } else {1486 thumb_arch_name = "thumbv9.3a";1487 }1488 thumb_arch.GetTriple().setArchName(llvm::StringRef(thumb_arch_name));1489 }1490 1491 // If no sub architecture specified then use the most recent arm architecture1492 // so the disassembler will return all instructions. Without it we will see a1493 // lot of unknown opcodes if the code uses instructions which are not1494 // available in the oldest arm version (which is used when no sub architecture1495 // is specified).1496 if (triple.getArch() == llvm::Triple::arm &&1497 triple.getSubArch() == llvm::Triple::NoSubArch)1498 triple.setArchName("armv9.3a");1499 1500 std::string features_str =1501 features_string ? std::string(features_string) : "";1502 const char *triple_str = triple.getTriple().c_str();1503 1504 // ARM Cortex M0-M7 devices only execute thumb instructions1505 if (arch.IsAlwaysThumbInstructions()) {1506 triple_str = thumb_arch.GetTriple().getTriple().c_str();1507 if (!features_string)1508 features_str += "+fp-armv8,";1509 }1510 1511 const char *cpu = cpu_string;1512 1513 if (!cpu_or_features_overriden) {1514 switch (arch.GetCore()) {1515 case ArchSpec::eCore_mips32:1516 case ArchSpec::eCore_mips32el:1517 cpu = "mips32";1518 break;1519 case ArchSpec::eCore_mips32r2:1520 case ArchSpec::eCore_mips32r2el:1521 cpu = "mips32r2";1522 break;1523 case ArchSpec::eCore_mips32r3:1524 case ArchSpec::eCore_mips32r3el:1525 cpu = "mips32r3";1526 break;1527 case ArchSpec::eCore_mips32r5:1528 case ArchSpec::eCore_mips32r5el:1529 cpu = "mips32r5";1530 break;1531 case ArchSpec::eCore_mips32r6:1532 case ArchSpec::eCore_mips32r6el:1533 cpu = "mips32r6";1534 break;1535 case ArchSpec::eCore_mips64:1536 case ArchSpec::eCore_mips64el:1537 cpu = "mips64";1538 break;1539 case ArchSpec::eCore_mips64r2:1540 case ArchSpec::eCore_mips64r2el:1541 cpu = "mips64r2";1542 break;1543 case ArchSpec::eCore_mips64r3:1544 case ArchSpec::eCore_mips64r3el:1545 cpu = "mips64r3";1546 break;1547 case ArchSpec::eCore_mips64r5:1548 case ArchSpec::eCore_mips64r5el:1549 cpu = "mips64r5";1550 break;1551 case ArchSpec::eCore_mips64r6:1552 case ArchSpec::eCore_mips64r6el:1553 cpu = "mips64r6";1554 break;1555 default:1556 cpu = "";1557 break;1558 }1559 }1560 1561 if (arch.IsMIPS() && !cpu_or_features_overriden) {1562 uint32_t arch_flags = arch.GetFlags();1563 if (arch_flags & ArchSpec::eMIPSAse_msa)1564 features_str += "+msa,";1565 if (arch_flags & ArchSpec::eMIPSAse_dsp)1566 features_str += "+dsp,";1567 if (arch_flags & ArchSpec::eMIPSAse_dspr2)1568 features_str += "+dspr2,";1569 }1570 1571 // If any AArch64 variant, enable latest ISA with all extensions unless the1572 // CPU or features were overridden.1573 if (triple.isAArch64() && !cpu_or_features_overriden) {1574 features_str += "+all,";1575 if (triple.getVendor() == llvm::Triple::Apple)1576 cpu = "apple-latest";1577 }1578 1579 if (triple.isRISCV() && !cpu_or_features_overriden) {1580 uint32_t arch_flags = arch.GetFlags();1581 if (arch_flags & ArchSpec::eRISCV_rvc)1582 features_str += "+c,";1583 if (arch_flags & ArchSpec::eRISCV_rve)1584 features_str += "+e,";1585 if ((arch_flags & ArchSpec::eRISCV_float_abi_single) ==1586 ArchSpec::eRISCV_float_abi_single)1587 features_str += "+f,";1588 if ((arch_flags & ArchSpec::eRISCV_float_abi_double) ==1589 ArchSpec::eRISCV_float_abi_double)1590 features_str += "+f,+d,";1591 if ((arch_flags & ArchSpec::eRISCV_float_abi_quad) ==1592 ArchSpec::eRISCV_float_abi_quad)1593 features_str += "+f,+d,+q,";1594 // FIXME: how do we detect features such as `+a`, `+m`?1595 // Turn them on by default now, since everyone seems to use them1596 features_str += "+a,+m,";1597 }1598 1599 // We use m_disasm_up.get() to tell whether we are valid or not, so if this1600 // isn't good for some reason, we won't be valid and FindPlugin will fail and1601 // we won't get used.1602 m_disasm_up = MCDisasmInstance::Create(triple_str, cpu, features_str.c_str(),1603 flavor, *this);1604 1605 llvm::Triple::ArchType llvm_arch = triple.getArch();1606 1607 // For arm CPUs that can execute arm or thumb instructions, also create a1608 // thumb instruction disassembler.1609 if (llvm_arch == llvm::Triple::arm) {1610 std::string thumb_triple(thumb_arch.GetTriple().getTriple());1611 m_alternate_disasm_up = MCDisasmInstance::Create(1612 thumb_triple.c_str(), "", features_str.c_str(), flavor, *this);1613 if (!m_alternate_disasm_up)1614 m_disasm_up.reset();1615 1616 } else if (arch.IsMIPS()) {1617 /* Create alternate disassembler for MIPS16 and microMIPS */1618 uint32_t arch_flags = arch.GetFlags();1619 if (arch_flags & ArchSpec::eMIPSAse_mips16)1620 features_str += "+mips16,";1621 else if (arch_flags & ArchSpec::eMIPSAse_micromips)1622 features_str += "+micromips,";1623 1624 m_alternate_disasm_up = MCDisasmInstance::Create(1625 triple_str, cpu, features_str.c_str(), flavor, *this);1626 if (!m_alternate_disasm_up)1627 m_disasm_up.reset();1628 }1629}1630 1631DisassemblerLLVMC::~DisassemblerLLVMC() = default;1632 1633lldb::DisassemblerSP DisassemblerLLVMC::CreateInstance(const ArchSpec &arch,1634 const char *flavor,1635 const char *cpu,1636 const char *features) {1637 if (arch.GetTriple().getArch() != llvm::Triple::UnknownArch) {1638 auto disasm_sp =1639 std::make_shared<DisassemblerLLVMC>(arch, flavor, cpu, features);1640 if (disasm_sp && disasm_sp->IsValid())1641 return disasm_sp;1642 }1643 return lldb::DisassemblerSP();1644}1645 1646size_t DisassemblerLLVMC::DecodeInstructions(const Address &base_addr,1647 const DataExtractor &data,1648 lldb::offset_t data_offset,1649 size_t num_instructions,1650 bool append, bool data_from_file) {1651 if (!append)1652 m_instruction_list.Clear();1653 1654 if (!IsValid())1655 return 0;1656 1657 m_data_from_file = data_from_file;1658 uint32_t data_cursor = data_offset;1659 const size_t data_byte_size = data.GetByteSize();1660 uint32_t instructions_parsed = 0;1661 Address inst_addr(base_addr);1662 1663 while (data_cursor < data_byte_size &&1664 instructions_parsed < num_instructions) {1665 1666 AddressClass address_class = AddressClass::eCode;1667 1668 if (m_alternate_disasm_up)1669 address_class = inst_addr.GetAddressClass();1670 1671 InstructionSP inst_sp(1672 new InstructionLLVMC(*this, inst_addr, address_class));1673 1674 if (!inst_sp)1675 break;1676 1677 uint32_t inst_size = inst_sp->Decode(*this, data, data_cursor);1678 1679 if (inst_size == 0)1680 break;1681 1682 m_instruction_list.Append(inst_sp);1683 data_cursor += inst_size;1684 inst_addr.Slide(inst_size);1685 instructions_parsed++;1686 }1687 1688 return data_cursor - data_offset;1689}1690 1691void DisassemblerLLVMC::Initialize() {1692 PluginManager::RegisterPlugin(GetPluginNameStatic(),1693 "Disassembler that uses LLVM MC to disassemble "1694 "i386, x86_64, ARM, and ARM64.",1695 CreateInstance);1696 1697 llvm::InitializeAllTargetInfos();1698 llvm::InitializeAllTargetMCs();1699 llvm::InitializeAllAsmParsers();1700 llvm::InitializeAllDisassemblers();1701}1702 1703void DisassemblerLLVMC::Terminate() {1704 PluginManager::UnregisterPlugin(CreateInstance);1705}1706 1707int DisassemblerLLVMC::OpInfoCallback(void *disassembler, uint64_t pc,1708 uint64_t offset, uint64_t size,1709 int tag_type, void *tag_bug) {1710 return static_cast<DisassemblerLLVMC *>(disassembler)1711 ->OpInfo(pc, offset, size, tag_type, tag_bug);1712}1713 1714const char *DisassemblerLLVMC::SymbolLookupCallback(void *disassembler,1715 uint64_t value,1716 uint64_t *type, uint64_t pc,1717 const char **name) {1718 return static_cast<DisassemblerLLVMC *>(disassembler)1719 ->SymbolLookup(value, type, pc, name);1720}1721 1722bool DisassemblerLLVMC::FlavorValidForArchSpec(1723 const lldb_private::ArchSpec &arch, const char *flavor) {1724 llvm::Triple triple = arch.GetTriple();1725 if (flavor == nullptr || strcmp(flavor, "default") == 0)1726 return true;1727 1728 if (triple.getArch() == llvm::Triple::x86 ||1729 triple.getArch() == llvm::Triple::x86_64) {1730 return strcmp(flavor, "intel") == 0 || strcmp(flavor, "att") == 0;1731 } else1732 return false;1733}1734 1735bool DisassemblerLLVMC::IsValid() const { return m_disasm_up.operator bool(); }1736 1737int DisassemblerLLVMC::OpInfo(uint64_t PC, uint64_t Offset, uint64_t Size,1738 int tag_type, void *tag_bug) {1739 switch (tag_type) {1740 default:1741 break;1742 case 1:1743 memset(tag_bug, 0, sizeof(::LLVMOpInfo1));1744 break;1745 }1746 return 0;1747}1748 1749const char *DisassemblerLLVMC::SymbolLookup(uint64_t value, uint64_t *type_ptr,1750 uint64_t pc, const char **name) {1751 if (*type_ptr) {1752 if (m_exe_ctx && m_inst) {1753 // std::string remove_this_prior_to_checkin;1754 Target *target = m_exe_ctx ? m_exe_ctx->GetTargetPtr() : nullptr;1755 Address value_so_addr;1756 Address pc_so_addr;1757 if (target->GetArchitecture().GetMachine() == llvm::Triple::aarch64 ||1758 target->GetArchitecture().GetMachine() == llvm::Triple::aarch64_be ||1759 target->GetArchitecture().GetMachine() == llvm::Triple::aarch64_32) {1760 if (*type_ptr == LLVMDisassembler_ReferenceType_In_ARM64_ADRP) {1761 m_adrp_address = pc;1762 m_adrp_insn = value;1763 *name = nullptr;1764 *type_ptr = LLVMDisassembler_ReferenceType_InOut_None;1765 return nullptr;1766 }1767 // If this instruction is an ADD and1768 // the previous instruction was an ADRP and1769 // the ADRP's register and this ADD's register are the same,1770 // then this is a pc-relative address calculation.1771 if (*type_ptr == LLVMDisassembler_ReferenceType_In_ARM64_ADDXri &&1772 m_adrp_insn && m_adrp_address == pc - 4 &&1773 (*m_adrp_insn & 0x1f) == ((value >> 5) & 0x1f)) {1774 uint32_t addxri_inst;1775 uint64_t adrp_imm, addxri_imm;1776 // Get immlo and immhi bits, OR them together to get the ADRP imm1777 // value.1778 adrp_imm =1779 ((*m_adrp_insn & 0x00ffffe0) >> 3) | ((*m_adrp_insn >> 29) & 0x3);1780 // if high bit of immhi after right-shifting set, sign extend1781 if (adrp_imm & (1ULL << 20))1782 adrp_imm |= ~((1ULL << 21) - 1);1783 1784 addxri_inst = value;1785 addxri_imm = (addxri_inst >> 10) & 0xfff;1786 // check if 'sh' bit is set, shift imm value up if so1787 // (this would make no sense, ADRP already gave us this part)1788 if ((addxri_inst >> (12 + 5 + 5)) & 1)1789 addxri_imm <<= 12;1790 value = (m_adrp_address & 0xfffffffffffff000LL) + (adrp_imm << 12) +1791 addxri_imm;1792 }1793 m_adrp_address = LLDB_INVALID_ADDRESS;1794 m_adrp_insn.reset();1795 }1796 1797 if (m_inst->UsingFileAddress()) {1798 ModuleSP module_sp(m_inst->GetAddress().GetModule());1799 if (module_sp) {1800 module_sp->ResolveFileAddress(value, value_so_addr);1801 module_sp->ResolveFileAddress(pc, pc_so_addr);1802 }1803 } else if (target && target->HasLoadedSections()) {1804 target->ResolveLoadAddress(value, value_so_addr);1805 target->ResolveLoadAddress(pc, pc_so_addr);1806 }1807 1808 SymbolContext sym_ctx;1809 const SymbolContextItem resolve_scope =1810 eSymbolContextFunction | eSymbolContextSymbol;1811 if (pc_so_addr.IsValid() && pc_so_addr.GetModule()) {1812 pc_so_addr.GetModule()->ResolveSymbolContextForAddress(1813 pc_so_addr, resolve_scope, sym_ctx);1814 }1815 1816 if (value_so_addr.IsValid() && value_so_addr.GetSection()) {1817 StreamString ss;1818 1819 bool format_omitting_current_func_name = false;1820 if (sym_ctx.symbol || sym_ctx.function) {1821 AddressRange range;1822 for (uint32_t idx = 0;1823 sym_ctx.GetAddressRange(resolve_scope, idx, false, range);1824 ++idx) {1825 if (range.ContainsLoadAddress(value_so_addr, target)) {1826 format_omitting_current_func_name = true;1827 break;1828 }1829 }1830 }1831 1832 // If the "value" address (the target address we're symbolicating) is1833 // inside the same SymbolContext as the current instruction pc1834 // (pc_so_addr), don't print the full function name - just print it1835 // with DumpStyleNoFunctionName style, e.g. "<+36>".1836 if (format_omitting_current_func_name) {1837 value_so_addr.Dump(&ss, target, Address::DumpStyleNoFunctionName,1838 Address::DumpStyleSectionNameOffset);1839 } else {1840 value_so_addr.Dump(1841 &ss, target,1842 Address::DumpStyleResolvedDescriptionNoFunctionArguments,1843 Address::DumpStyleSectionNameOffset);1844 }1845 1846 if (!ss.GetString().empty()) {1847 // If Address::Dump returned a multi-line description, most commonly1848 // seen when we have multiple levels of inlined functions at an1849 // address, only show the first line.1850 std::string str = std::string(ss.GetString());1851 size_t first_eol_char = str.find_first_of("\r\n");1852 if (first_eol_char != std::string::npos) {1853 str.erase(first_eol_char);1854 }1855 m_inst->AppendComment(str);1856 }1857 }1858 }1859 }1860 1861 // TODO: llvm-objdump sets the type_ptr to the1862 // LLVMDisassembler_ReferenceType_Out_* values1863 // based on where value_so_addr is pointing, with1864 // Mach-O specific augmentations in MachODump.cpp. e.g.1865 // see what AArch64ExternalSymbolizer::tryAddingSymbolicOperand1866 // handles.1867 *type_ptr = LLVMDisassembler_ReferenceType_InOut_None;1868 *name = nullptr;1869 return nullptr;1870}1871