10b57cec5SDimitry Andric //===-- Disassembler.h ------------------------------------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 95ffd83dbSDimitry Andric #ifndef LLDB_CORE_DISASSEMBLER_H 105ffd83dbSDimitry Andric #define LLDB_CORE_DISASSEMBLER_H 110b57cec5SDimitry Andric 120b57cec5SDimitry Andric #include "lldb/Core/Address.h" 130b57cec5SDimitry Andric #include "lldb/Core/EmulateInstruction.h" 140b57cec5SDimitry Andric #include "lldb/Core/FormatEntity.h" 150b57cec5SDimitry Andric #include "lldb/Core/Opcode.h" 160b57cec5SDimitry Andric #include "lldb/Core/PluginInterface.h" 170b57cec5SDimitry Andric #include "lldb/Interpreter/OptionValue.h" 180b57cec5SDimitry Andric #include "lldb/Symbol/LineEntry.h" 190b57cec5SDimitry Andric #include "lldb/Target/ExecutionContext.h" 200b57cec5SDimitry Andric #include "lldb/Utility/ArchSpec.h" 210b57cec5SDimitry Andric #include "lldb/Utility/ConstString.h" 220b57cec5SDimitry Andric #include "lldb/Utility/FileSpec.h" 230b57cec5SDimitry Andric #include "lldb/lldb-defines.h" 240b57cec5SDimitry Andric #include "lldb/lldb-forward.h" 250b57cec5SDimitry Andric #include "lldb/lldb-private-enumerations.h" 260b57cec5SDimitry Andric #include "lldb/lldb-types.h" 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric #include <functional> 310b57cec5SDimitry Andric #include <map> 320b57cec5SDimitry Andric #include <memory> 330b57cec5SDimitry Andric #include <set> 340b57cec5SDimitry Andric #include <string> 350b57cec5SDimitry Andric #include <vector> 360b57cec5SDimitry Andric 37fe6060f1SDimitry Andric #include <cstddef> 38fe6060f1SDimitry Andric #include <cstdint> 39fe6060f1SDimitry Andric #include <cstdio> 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric namespace llvm { 420b57cec5SDimitry Andric template <typename T> class SmallVectorImpl; 430b57cec5SDimitry Andric } 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric namespace lldb_private { 460b57cec5SDimitry Andric class AddressRange; 470b57cec5SDimitry Andric class DataExtractor; 480b57cec5SDimitry Andric class Debugger; 490b57cec5SDimitry Andric class Disassembler; 500b57cec5SDimitry Andric class Module; 51e8d8bef9SDimitry Andric class StackFrame; 520b57cec5SDimitry Andric class Stream; 530b57cec5SDimitry Andric class SymbolContext; 540b57cec5SDimitry Andric class SymbolContextList; 550b57cec5SDimitry Andric class Target; 560b57cec5SDimitry Andric struct RegisterInfo; 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric class Instruction { 590b57cec5SDimitry Andric public: 600b57cec5SDimitry Andric Instruction(const Address &address, 610b57cec5SDimitry Andric AddressClass addr_class = AddressClass::eInvalid); 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric virtual ~Instruction(); 640b57cec5SDimitry Andric GetAddress()650b57cec5SDimitry Andric const Address &GetAddress() const { return m_address; } 660b57cec5SDimitry Andric 675f757f3fSDimitry Andric const char *GetMnemonic(const ExecutionContext *exe_ctx, 685f757f3fSDimitry Andric bool markup = false) { 690b57cec5SDimitry Andric CalculateMnemonicOperandsAndCommentIfNeeded(exe_ctx); 705f757f3fSDimitry Andric return markup ? m_markup_opcode_name.c_str() : m_opcode_name.c_str(); 710b57cec5SDimitry Andric } 720b57cec5SDimitry Andric 735f757f3fSDimitry Andric const char *GetOperands(const ExecutionContext *exe_ctx, 745f757f3fSDimitry Andric bool markup = false) { 750b57cec5SDimitry Andric CalculateMnemonicOperandsAndCommentIfNeeded(exe_ctx); 765f757f3fSDimitry Andric return markup ? m_markup_mnemonics.c_str() : m_mnemonics.c_str(); 770b57cec5SDimitry Andric } 780b57cec5SDimitry Andric GetComment(const ExecutionContext * exe_ctx)790b57cec5SDimitry Andric const char *GetComment(const ExecutionContext *exe_ctx) { 800b57cec5SDimitry Andric CalculateMnemonicOperandsAndCommentIfNeeded(exe_ctx); 810b57cec5SDimitry Andric return m_comment.c_str(); 820b57cec5SDimitry Andric } 830b57cec5SDimitry Andric 84753f127fSDimitry Andric /// \return 85753f127fSDimitry Andric /// The control flow kind of this instruction, or 86753f127fSDimitry Andric /// eInstructionControlFlowKindUnknown if the instruction 87753f127fSDimitry Andric /// can't be classified. 88972a253aSDimitry Andric virtual lldb::InstructionControlFlowKind GetControlFlowKind(const ExecutionContext * exe_ctx)89972a253aSDimitry Andric GetControlFlowKind(const ExecutionContext *exe_ctx) { 90972a253aSDimitry Andric return lldb::eInstructionControlFlowKindUnknown; 91972a253aSDimitry Andric } 92753f127fSDimitry Andric 930b57cec5SDimitry Andric virtual void 940b57cec5SDimitry Andric CalculateMnemonicOperandsAndComment(const ExecutionContext *exe_ctx) = 0; 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric AddressClass GetAddressClass(); 970b57cec5SDimitry Andric SetAddress(const Address & addr)980b57cec5SDimitry Andric void SetAddress(const Address &addr) { 990b57cec5SDimitry Andric // Invalidate the address class to lazily discover it if we need to. 1000b57cec5SDimitry Andric m_address_class = AddressClass::eInvalid; 1010b57cec5SDimitry Andric m_address = addr; 1020b57cec5SDimitry Andric } 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric /// Dump the text representation of this Instruction to a Stream 1050b57cec5SDimitry Andric /// 1060b57cec5SDimitry Andric /// Print the (optional) address, (optional) bytes, opcode, 1070b57cec5SDimitry Andric /// operands, and instruction comments to a stream. 1080b57cec5SDimitry Andric /// 1090b57cec5SDimitry Andric /// \param[in] s 1100b57cec5SDimitry Andric /// The Stream to add the text to. 1110b57cec5SDimitry Andric /// 1120b57cec5SDimitry Andric /// \param[in] show_address 1130b57cec5SDimitry Andric /// Whether the address (using disassembly_addr_format_spec formatting) 1140b57cec5SDimitry Andric /// should be printed. 1150b57cec5SDimitry Andric /// 1160b57cec5SDimitry Andric /// \param[in] show_bytes 1170b57cec5SDimitry Andric /// Whether the bytes of the assembly instruction should be printed. 1180b57cec5SDimitry Andric /// 119753f127fSDimitry Andric /// \param[in] show_control_flow_kind 120753f127fSDimitry Andric /// Whether the control flow kind of the instruction should be printed. 121753f127fSDimitry Andric /// 1220b57cec5SDimitry Andric /// \param[in] max_opcode_byte_size 1230b57cec5SDimitry Andric /// The size (in bytes) of the largest instruction in the list that 1240b57cec5SDimitry Andric /// we are printing (for text justification/alignment purposes) 1250b57cec5SDimitry Andric /// Only needed if show_bytes is true. 1260b57cec5SDimitry Andric /// 1270b57cec5SDimitry Andric /// \param[in] exe_ctx 1280b57cec5SDimitry Andric /// The current execution context, if available. May be used in 1290b57cec5SDimitry Andric /// the assembling of the operands+comments for this instruction. 1300b57cec5SDimitry Andric /// Pass NULL if not applicable. 1310b57cec5SDimitry Andric /// 1320b57cec5SDimitry Andric /// \param[in] sym_ctx 1330b57cec5SDimitry Andric /// The SymbolContext for this instruction. 1340b57cec5SDimitry Andric /// Pass NULL if not available/computed. 1350b57cec5SDimitry Andric /// Only needed if show_address is true. 1360b57cec5SDimitry Andric /// 1370b57cec5SDimitry Andric /// \param[in] prev_sym_ctx 1380b57cec5SDimitry Andric /// The SymbolContext for the previous instruction. Depending on 1390b57cec5SDimitry Andric /// the disassembly address format specification, a change in 1400b57cec5SDimitry Andric /// Symbol / Function may mean that a line is printed with the new 1410b57cec5SDimitry Andric /// symbol/function name. 1420b57cec5SDimitry Andric /// Pass NULL if unavailable, or if this is the first instruction of 1430b57cec5SDimitry Andric /// the InstructionList. 1440b57cec5SDimitry Andric /// Only needed if show_address is true. 1450b57cec5SDimitry Andric /// 1460b57cec5SDimitry Andric /// \param[in] disassembly_addr_format 1470b57cec5SDimitry Andric /// The format specification for how addresses are printed. 1480b57cec5SDimitry Andric /// Only needed if show_address is true. 1490b57cec5SDimitry Andric /// 1500b57cec5SDimitry Andric /// \param[in] max_address_text_size 1510b57cec5SDimitry Andric /// The length of the longest address string at the start of the 1520b57cec5SDimitry Andric /// disassembly line that will be printed (the 1530b57cec5SDimitry Andric /// Debugger::FormatDisassemblerAddress() string) 1540b57cec5SDimitry Andric /// so this method can properly align the instruction opcodes. 1550b57cec5SDimitry Andric /// May be 0 to indicate no indentation/alignment of the opcodes. 1560b57cec5SDimitry Andric virtual void Dump(Stream *s, uint32_t max_opcode_byte_size, bool show_address, 157753f127fSDimitry Andric bool show_bytes, bool show_control_flow_kind, 158753f127fSDimitry Andric const ExecutionContext *exe_ctx, 1590b57cec5SDimitry Andric const SymbolContext *sym_ctx, 1600b57cec5SDimitry Andric const SymbolContext *prev_sym_ctx, 1610b57cec5SDimitry Andric const FormatEntity::Entry *disassembly_addr_format, 1620b57cec5SDimitry Andric size_t max_address_text_size); 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric virtual bool DoesBranch() = 0; 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andric virtual bool HasDelaySlot(); 1670b57cec5SDimitry Andric 168349cc55cSDimitry Andric virtual bool IsLoad() = 0; 169349cc55cSDimitry Andric 170349cc55cSDimitry Andric virtual bool IsAuthenticated() = 0; 171349cc55cSDimitry Andric 1720b57cec5SDimitry Andric bool CanSetBreakpoint (); 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric virtual size_t Decode(const Disassembler &disassembler, 1750b57cec5SDimitry Andric const DataExtractor &data, 1760b57cec5SDimitry Andric lldb::offset_t data_offset) = 0; 1770b57cec5SDimitry Andric SetDescription(llvm::StringRef)1780b57cec5SDimitry Andric virtual void SetDescription(llvm::StringRef) { 1790b57cec5SDimitry Andric } // May be overridden in sub-classes that have descriptions. 1800b57cec5SDimitry Andric 18106c3fb27SDimitry Andric lldb::OptionValueSP ReadArray(FILE *in_file, Stream &out_stream, 1820b57cec5SDimitry Andric OptionValue::Type data_type); 1830b57cec5SDimitry Andric 18406c3fb27SDimitry Andric lldb::OptionValueSP ReadDictionary(FILE *in_file, Stream &out_stream); 1850b57cec5SDimitry Andric 1860b57cec5SDimitry Andric bool DumpEmulation(const ArchSpec &arch); 1870b57cec5SDimitry Andric 18806c3fb27SDimitry Andric virtual bool TestEmulation(Stream &stream, const char *test_file_name); 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric bool Emulate(const ArchSpec &arch, uint32_t evaluate_options, void *baton, 1910b57cec5SDimitry Andric EmulateInstruction::ReadMemoryCallback read_mem_callback, 1920b57cec5SDimitry Andric EmulateInstruction::WriteMemoryCallback write_mem_calback, 1930b57cec5SDimitry Andric EmulateInstruction::ReadRegisterCallback read_reg_callback, 1940b57cec5SDimitry Andric EmulateInstruction::WriteRegisterCallback write_reg_callback); 1950b57cec5SDimitry Andric GetOpcode()1960b57cec5SDimitry Andric const Opcode &GetOpcode() const { return m_opcode; } 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric uint32_t GetData(DataExtractor &data); 1990b57cec5SDimitry Andric 2000b57cec5SDimitry Andric struct Operand { 2010b57cec5SDimitry Andric enum class Type { 2020b57cec5SDimitry Andric Invalid = 0, 2030b57cec5SDimitry Andric Register, 2040b57cec5SDimitry Andric Immediate, 2050b57cec5SDimitry Andric Dereference, 2060b57cec5SDimitry Andric Sum, 2070b57cec5SDimitry Andric Product 2080b57cec5SDimitry Andric } m_type = Type::Invalid; 2090b57cec5SDimitry Andric std::vector<Operand> m_children; 2100b57cec5SDimitry Andric lldb::addr_t m_immediate = 0; 2110b57cec5SDimitry Andric ConstString m_register; 2120b57cec5SDimitry Andric bool m_negative = false; 2130b57cec5SDimitry Andric bool m_clobbered = false; 2140b57cec5SDimitry Andric IsValidOperand2150b57cec5SDimitry Andric bool IsValid() { return m_type != Type::Invalid; } 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric static Operand BuildRegister(ConstString &r); 2180b57cec5SDimitry Andric static Operand BuildImmediate(lldb::addr_t imm, bool neg); 2190b57cec5SDimitry Andric static Operand BuildImmediate(int64_t imm); 2200b57cec5SDimitry Andric static Operand BuildDereference(const Operand &ref); 2210b57cec5SDimitry Andric static Operand BuildSum(const Operand &lhs, const Operand &rhs); 2220b57cec5SDimitry Andric static Operand BuildProduct(const Operand &lhs, const Operand &rhs); 2230b57cec5SDimitry Andric }; 2240b57cec5SDimitry Andric ParseOperands(llvm::SmallVectorImpl<Operand> & operands)2250b57cec5SDimitry Andric virtual bool ParseOperands(llvm::SmallVectorImpl<Operand> &operands) { 2260b57cec5SDimitry Andric return false; 2270b57cec5SDimitry Andric } 2280b57cec5SDimitry Andric IsCall()2290b57cec5SDimitry Andric virtual bool IsCall() { return false; } 2300b57cec5SDimitry Andric 231972a253aSDimitry Andric static const char *GetNameForInstructionControlFlowKind( 232972a253aSDimitry Andric lldb::InstructionControlFlowKind instruction_control_flow_kind); 233972a253aSDimitry Andric 2340b57cec5SDimitry Andric protected: 2350b57cec5SDimitry Andric Address m_address; // The section offset address of this instruction 2360b57cec5SDimitry Andric // We include an address class in the Instruction class to 2370b57cec5SDimitry Andric // allow the instruction specify the 2380b57cec5SDimitry Andric // AddressClass::eCodeAlternateISA (currently used for 2390b57cec5SDimitry Andric // thumb), and also to specify data (AddressClass::eData). 2400b57cec5SDimitry Andric // The usual value will be AddressClass::eCode, but often 2410b57cec5SDimitry Andric // when disassembling memory, you might run into data. 2420b57cec5SDimitry Andric // This can help us to disassemble appropriately. 2430b57cec5SDimitry Andric private: 2440b57cec5SDimitry Andric AddressClass m_address_class; // Use GetAddressClass () accessor function! 2450b57cec5SDimitry Andric 2460b57cec5SDimitry Andric protected: 2470b57cec5SDimitry Andric Opcode m_opcode; // The opcode for this instruction 2480b57cec5SDimitry Andric std::string m_opcode_name; 2495f757f3fSDimitry Andric std::string m_markup_opcode_name; 2500b57cec5SDimitry Andric std::string m_mnemonics; 2515f757f3fSDimitry Andric std::string m_markup_mnemonics; 2520b57cec5SDimitry Andric std::string m_comment; 2530b57cec5SDimitry Andric bool m_calculated_strings; 2540b57cec5SDimitry Andric 2550b57cec5SDimitry Andric void CalculateMnemonicOperandsAndCommentIfNeeded(const ExecutionContext * exe_ctx)2560b57cec5SDimitry Andric CalculateMnemonicOperandsAndCommentIfNeeded(const ExecutionContext *exe_ctx) { 2570b57cec5SDimitry Andric if (!m_calculated_strings) { 2580b57cec5SDimitry Andric m_calculated_strings = true; 2590b57cec5SDimitry Andric CalculateMnemonicOperandsAndComment(exe_ctx); 2600b57cec5SDimitry Andric } 2610b57cec5SDimitry Andric } 2620b57cec5SDimitry Andric }; 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric namespace OperandMatchers { 2650b57cec5SDimitry Andric std::function<bool(const Instruction::Operand &)> 2660b57cec5SDimitry Andric MatchBinaryOp(std::function<bool(const Instruction::Operand &)> base, 2670b57cec5SDimitry Andric std::function<bool(const Instruction::Operand &)> left, 2680b57cec5SDimitry Andric std::function<bool(const Instruction::Operand &)> right); 2690b57cec5SDimitry Andric 2700b57cec5SDimitry Andric std::function<bool(const Instruction::Operand &)> 2710b57cec5SDimitry Andric MatchUnaryOp(std::function<bool(const Instruction::Operand &)> base, 2720b57cec5SDimitry Andric std::function<bool(const Instruction::Operand &)> child); 2730b57cec5SDimitry Andric 2740b57cec5SDimitry Andric std::function<bool(const Instruction::Operand &)> 2750b57cec5SDimitry Andric MatchRegOp(const RegisterInfo &info); 2760b57cec5SDimitry Andric 2770b57cec5SDimitry Andric std::function<bool(const Instruction::Operand &)> FetchRegOp(ConstString ®); 2780b57cec5SDimitry Andric 2790b57cec5SDimitry Andric std::function<bool(const Instruction::Operand &)> MatchImmOp(int64_t imm); 2800b57cec5SDimitry Andric 2810b57cec5SDimitry Andric std::function<bool(const Instruction::Operand &)> FetchImmOp(int64_t &imm); 2820b57cec5SDimitry Andric 2830b57cec5SDimitry Andric std::function<bool(const Instruction::Operand &)> 2840b57cec5SDimitry Andric MatchOpType(Instruction::Operand::Type type); 2850b57cec5SDimitry Andric } 2860b57cec5SDimitry Andric 2870b57cec5SDimitry Andric class InstructionList { 2880b57cec5SDimitry Andric public: 2890b57cec5SDimitry Andric InstructionList(); 2900b57cec5SDimitry Andric ~InstructionList(); 2910b57cec5SDimitry Andric 2920b57cec5SDimitry Andric size_t GetSize() const; 2930b57cec5SDimitry Andric 2940b57cec5SDimitry Andric uint32_t GetMaxOpcocdeByteSize() const; 2950b57cec5SDimitry Andric 2960b57cec5SDimitry Andric lldb::InstructionSP GetInstructionAtIndex(size_t idx) const; 2970b57cec5SDimitry Andric 298e8d8bef9SDimitry Andric /// Get the instruction at the given address. 299e8d8bef9SDimitry Andric /// 300e8d8bef9SDimitry Andric /// \return 301e8d8bef9SDimitry Andric /// A valid \a InstructionSP if the address could be found, or null 302e8d8bef9SDimitry Andric /// otherwise. 303e8d8bef9SDimitry Andric lldb::InstructionSP GetInstructionAtAddress(const Address &addr); 304e8d8bef9SDimitry Andric 3050b57cec5SDimitry Andric //------------------------------------------------------------------ 3060b57cec5SDimitry Andric /// Get the index of the next branch instruction. 3070b57cec5SDimitry Andric /// 3080b57cec5SDimitry Andric /// Given a list of instructions, find the next branch instruction 3090b57cec5SDimitry Andric /// in the list by returning an index. 3100b57cec5SDimitry Andric /// 3110b57cec5SDimitry Andric /// @param[in] start 3120b57cec5SDimitry Andric /// The instruction index of the first instruction to check. 3130b57cec5SDimitry Andric /// 3140b57cec5SDimitry Andric /// @param[in] ignore_calls 3150b57cec5SDimitry Andric /// It true, then fine the first branch instruction that isn't 3160b57cec5SDimitry Andric /// a function call (a branch that calls and returns to the next 3170b57cec5SDimitry Andric /// instruction). If false, find the instruction index of any 3180b57cec5SDimitry Andric /// branch in the list. 3190b57cec5SDimitry Andric /// 320480093f4SDimitry Andric /// @param[out] found_calls 321480093f4SDimitry Andric /// If non-null, this will be set to true if any calls were found in 322480093f4SDimitry Andric /// extending the range. 323480093f4SDimitry Andric /// 3240b57cec5SDimitry Andric /// @return 3250b57cec5SDimitry Andric /// The instruction index of the first branch that is at or past 3260b57cec5SDimitry Andric /// \a start. Returns UINT32_MAX if no matching branches are 3270b57cec5SDimitry Andric /// found. 3280b57cec5SDimitry Andric //------------------------------------------------------------------ 3290b57cec5SDimitry Andric uint32_t GetIndexOfNextBranchInstruction(uint32_t start, 330480093f4SDimitry Andric bool ignore_calls, 331480093f4SDimitry Andric bool *found_calls) const; 3320b57cec5SDimitry Andric 3330b57cec5SDimitry Andric uint32_t GetIndexOfInstructionAtLoadAddress(lldb::addr_t load_addr, 3340b57cec5SDimitry Andric Target &target); 3350b57cec5SDimitry Andric 3360b57cec5SDimitry Andric uint32_t GetIndexOfInstructionAtAddress(const Address &addr); 3370b57cec5SDimitry Andric 3380b57cec5SDimitry Andric void Clear(); 3390b57cec5SDimitry Andric 3400b57cec5SDimitry Andric void Append(lldb::InstructionSP &inst_sp); 3410b57cec5SDimitry Andric 3420b57cec5SDimitry Andric void Dump(Stream *s, bool show_address, bool show_bytes, 343753f127fSDimitry Andric bool show_control_flow_kind, const ExecutionContext *exe_ctx); 3440b57cec5SDimitry Andric 3450b57cec5SDimitry Andric private: 3460b57cec5SDimitry Andric typedef std::vector<lldb::InstructionSP> collection; 3470b57cec5SDimitry Andric typedef collection::iterator iterator; 3480b57cec5SDimitry Andric typedef collection::const_iterator const_iterator; 3490b57cec5SDimitry Andric 3500b57cec5SDimitry Andric collection m_instructions; 3510b57cec5SDimitry Andric }; 3520b57cec5SDimitry Andric 3530b57cec5SDimitry Andric class PseudoInstruction : public Instruction { 3540b57cec5SDimitry Andric public: 3550b57cec5SDimitry Andric PseudoInstruction(); 3560b57cec5SDimitry Andric 3570b57cec5SDimitry Andric ~PseudoInstruction() override; 3580b57cec5SDimitry Andric 3590b57cec5SDimitry Andric bool DoesBranch() override; 3600b57cec5SDimitry Andric 3610b57cec5SDimitry Andric bool HasDelaySlot() override; 3620b57cec5SDimitry Andric 363349cc55cSDimitry Andric bool IsLoad() override; 364349cc55cSDimitry Andric 365349cc55cSDimitry Andric bool IsAuthenticated() override; 366349cc55cSDimitry Andric CalculateMnemonicOperandsAndComment(const ExecutionContext * exe_ctx)3670b57cec5SDimitry Andric void CalculateMnemonicOperandsAndComment( 3680b57cec5SDimitry Andric const ExecutionContext *exe_ctx) override { 3690b57cec5SDimitry Andric // TODO: fill this in and put opcode name into Instruction::m_opcode_name, 3700b57cec5SDimitry Andric // mnemonic into Instruction::m_mnemonics, and any comment into 3710b57cec5SDimitry Andric // Instruction::m_comment 3720b57cec5SDimitry Andric } 3730b57cec5SDimitry Andric 3740b57cec5SDimitry Andric size_t Decode(const Disassembler &disassembler, const DataExtractor &data, 3750b57cec5SDimitry Andric lldb::offset_t data_offset) override; 3760b57cec5SDimitry Andric 3770b57cec5SDimitry Andric void SetOpcode(size_t opcode_size, void *opcode_data); 3780b57cec5SDimitry Andric 3790b57cec5SDimitry Andric void SetDescription(llvm::StringRef description) override; 3800b57cec5SDimitry Andric 3810b57cec5SDimitry Andric protected: 3820b57cec5SDimitry Andric std::string m_description; 3830b57cec5SDimitry Andric 3845ffd83dbSDimitry Andric PseudoInstruction(const PseudoInstruction &) = delete; 3855ffd83dbSDimitry Andric const PseudoInstruction &operator=(const PseudoInstruction &) = delete; 3860b57cec5SDimitry Andric }; 3870b57cec5SDimitry Andric 3880b57cec5SDimitry Andric class Disassembler : public std::enable_shared_from_this<Disassembler>, 3890b57cec5SDimitry Andric public PluginInterface { 3900b57cec5SDimitry Andric public: 3910b57cec5SDimitry Andric enum { 3920b57cec5SDimitry Andric eOptionNone = 0u, 3930b57cec5SDimitry Andric eOptionShowBytes = (1u << 0), 3940b57cec5SDimitry Andric eOptionRawOuput = (1u << 1), 3950b57cec5SDimitry Andric eOptionMarkPCSourceLine = (1u << 2), // Mark the source line that contains 3960b57cec5SDimitry Andric // the current PC (mixed mode only) 3970b57cec5SDimitry Andric eOptionMarkPCAddress = 398753f127fSDimitry Andric (1u << 3), // Mark the disassembly line the contains the PC 399753f127fSDimitry Andric eOptionShowControlFlowKind = (1u << 4), 4000b57cec5SDimitry Andric }; 4010b57cec5SDimitry Andric 4020b57cec5SDimitry Andric enum HexImmediateStyle { 4030b57cec5SDimitry Andric eHexStyleC, 4040b57cec5SDimitry Andric eHexStyleAsm, 4050b57cec5SDimitry Andric }; 4060b57cec5SDimitry Andric 4070b57cec5SDimitry Andric // FindPlugin should be lax about the flavor string (it is too annoying to 4080b57cec5SDimitry Andric // have various internal uses of the disassembler fail because the global 4090b57cec5SDimitry Andric // flavor string gets set wrong. Instead, if you get a flavor string you 4100b57cec5SDimitry Andric // don't understand, use the default. Folks who care to check can use the 4110b57cec5SDimitry Andric // FlavorValidForArchSpec method on the disassembler they got back. 4120b57cec5SDimitry Andric static lldb::DisassemblerSP 4130b57cec5SDimitry Andric FindPlugin(const ArchSpec &arch, const char *flavor, const char *plugin_name); 4140b57cec5SDimitry Andric 4150b57cec5SDimitry Andric // This version will use the value in the Target settings if flavor is NULL; 4165ffd83dbSDimitry Andric static lldb::DisassemblerSP FindPluginForTarget(const Target &target, 4175ffd83dbSDimitry Andric const ArchSpec &arch, 4185ffd83dbSDimitry Andric const char *flavor, 4195ffd83dbSDimitry Andric const char *plugin_name); 4205ffd83dbSDimitry Andric 4215ffd83dbSDimitry Andric struct Limit { 4225ffd83dbSDimitry Andric enum { Bytes, Instructions } kind; 4235ffd83dbSDimitry Andric lldb::addr_t value; 4245ffd83dbSDimitry Andric }; 4250b57cec5SDimitry Andric 426fe6060f1SDimitry Andric static lldb::DisassemblerSP DisassembleRange(const ArchSpec &arch, 427fe6060f1SDimitry Andric const char *plugin_name, 428fe6060f1SDimitry Andric const char *flavor, 429fe6060f1SDimitry Andric Target &target, 430fe6060f1SDimitry Andric const AddressRange &disasm_range, 431fe6060f1SDimitry Andric bool force_live_memory = false); 4320b57cec5SDimitry Andric 4330b57cec5SDimitry Andric static lldb::DisassemblerSP 4340b57cec5SDimitry Andric DisassembleBytes(const ArchSpec &arch, const char *plugin_name, 4350b57cec5SDimitry Andric const char *flavor, const Address &start, const void *bytes, 4360b57cec5SDimitry Andric size_t length, uint32_t max_num_instructions, 4370b57cec5SDimitry Andric bool data_from_file); 4380b57cec5SDimitry Andric 4390b57cec5SDimitry Andric static bool Disassemble(Debugger &debugger, const ArchSpec &arch, 4400b57cec5SDimitry Andric const char *plugin_name, const char *flavor, 4410b57cec5SDimitry Andric const ExecutionContext &exe_ctx, const Address &start, 4425ffd83dbSDimitry Andric Limit limit, bool mixed_source_and_assembly, 4430b57cec5SDimitry Andric uint32_t num_mixed_context_lines, uint32_t options, 4440b57cec5SDimitry Andric Stream &strm); 4450b57cec5SDimitry Andric 446e8d8bef9SDimitry Andric static bool Disassemble(Debugger &debugger, const ArchSpec &arch, 447e8d8bef9SDimitry Andric StackFrame &frame, Stream &strm); 4480b57cec5SDimitry Andric 4490b57cec5SDimitry Andric // Constructors and Destructors 4500b57cec5SDimitry Andric Disassembler(const ArchSpec &arch, const char *flavor); 4510b57cec5SDimitry Andric ~Disassembler() override; 4520b57cec5SDimitry Andric 4535ffd83dbSDimitry Andric void PrintInstructions(Debugger &debugger, const ArchSpec &arch, 4540b57cec5SDimitry Andric const ExecutionContext &exe_ctx, 4550b57cec5SDimitry Andric bool mixed_source_and_assembly, 4565ffd83dbSDimitry Andric uint32_t num_mixed_context_lines, uint32_t options, 4575ffd83dbSDimitry Andric Stream &strm); 4580b57cec5SDimitry Andric 4595ffd83dbSDimitry Andric size_t ParseInstructions(Target &target, Address address, Limit limit, 460fe6060f1SDimitry Andric Stream *error_strm_ptr, 461fe6060f1SDimitry Andric bool force_live_memory = false); 4620b57cec5SDimitry Andric 4630b57cec5SDimitry Andric virtual size_t DecodeInstructions(const Address &base_addr, 4640b57cec5SDimitry Andric const DataExtractor &data, 4650b57cec5SDimitry Andric lldb::offset_t data_offset, 4660b57cec5SDimitry Andric size_t num_instructions, bool append, 4670b57cec5SDimitry Andric bool data_from_file) = 0; 4680b57cec5SDimitry Andric 4690b57cec5SDimitry Andric InstructionList &GetInstructionList(); 4700b57cec5SDimitry Andric 4710b57cec5SDimitry Andric const InstructionList &GetInstructionList() const; 4720b57cec5SDimitry Andric GetArchitecture()4730b57cec5SDimitry Andric const ArchSpec &GetArchitecture() const { return m_arch; } 4740b57cec5SDimitry Andric GetFlavor()4750b57cec5SDimitry Andric const char *GetFlavor() const { return m_flavor.c_str(); } 4760b57cec5SDimitry Andric 4770b57cec5SDimitry Andric virtual bool FlavorValidForArchSpec(const lldb_private::ArchSpec &arch, 4780b57cec5SDimitry Andric const char *flavor) = 0; 4790b57cec5SDimitry Andric 4800b57cec5SDimitry Andric protected: 4810b57cec5SDimitry Andric // SourceLine and SourceLinesToDisplay structures are only used in the mixed 4820b57cec5SDimitry Andric // source and assembly display methods internal to this class. 4830b57cec5SDimitry Andric 4840b57cec5SDimitry Andric struct SourceLine { 4850b57cec5SDimitry Andric FileSpec file; 486fe6060f1SDimitry Andric uint32_t line = LLDB_INVALID_LINE_NUMBER; 487fe6060f1SDimitry Andric uint32_t column = 0; 4880b57cec5SDimitry Andric 48981ad6265SDimitry Andric SourceLine() = default; 4900b57cec5SDimitry Andric 4910b57cec5SDimitry Andric bool operator==(const SourceLine &rhs) const { 4920b57cec5SDimitry Andric return file == rhs.file && line == rhs.line && rhs.column == column; 4930b57cec5SDimitry Andric } 4940b57cec5SDimitry Andric 4950b57cec5SDimitry Andric bool operator!=(const SourceLine &rhs) const { 4960b57cec5SDimitry Andric return file != rhs.file || line != rhs.line || column != rhs.column; 4970b57cec5SDimitry Andric } 4980b57cec5SDimitry Andric IsValidSourceLine4990b57cec5SDimitry Andric bool IsValid() const { return line != LLDB_INVALID_LINE_NUMBER; } 5000b57cec5SDimitry Andric }; 5010b57cec5SDimitry Andric 5020b57cec5SDimitry Andric struct SourceLinesToDisplay { 5030b57cec5SDimitry Andric std::vector<SourceLine> lines; 5040b57cec5SDimitry Andric 5050b57cec5SDimitry Andric // index of the "current" source line, if we want to highlight that when 5060b57cec5SDimitry Andric // displaying the source lines. (as opposed to the surrounding source 5070b57cec5SDimitry Andric // lines provided to give context) 508fe6060f1SDimitry Andric size_t current_source_line = -1; 5090b57cec5SDimitry Andric 5100b57cec5SDimitry Andric // Whether to print a blank line at the end of the source lines. 511fe6060f1SDimitry Andric bool print_source_context_end_eol = true; 5120b57cec5SDimitry Andric 51381ad6265SDimitry Andric SourceLinesToDisplay() = default; 5140b57cec5SDimitry Andric }; 5150b57cec5SDimitry Andric 5160b57cec5SDimitry Andric // Get the function's declaration line number, hopefully a line number 5170b57cec5SDimitry Andric // earlier than the opening curly brace at the start of the function body. 5180b57cec5SDimitry Andric static SourceLine GetFunctionDeclLineEntry(const SymbolContext &sc); 5190b57cec5SDimitry Andric 5200b57cec5SDimitry Andric // Add the provided SourceLine to the map of filenames-to-source-lines-seen. 5210b57cec5SDimitry Andric static void AddLineToSourceLineTables( 5220b57cec5SDimitry Andric SourceLine &line, 5230b57cec5SDimitry Andric std::map<FileSpec, std::set<uint32_t>> &source_lines_seen); 5240b57cec5SDimitry Andric 5250b57cec5SDimitry Andric // Given a source line, determine if we should print it when we're doing 5260b57cec5SDimitry Andric // mixed source & assembly output. We're currently using the 5270b57cec5SDimitry Andric // target.process.thread.step-avoid-regexp setting (which is used for 5280b57cec5SDimitry Andric // stepping over inlined STL functions by default) to determine what source 5290b57cec5SDimitry Andric // lines to avoid showing. 5300b57cec5SDimitry Andric // 5310b57cec5SDimitry Andric // Returns true if this source line should be elided (if the source line 5320b57cec5SDimitry Andric // should not be displayed). 5330b57cec5SDimitry Andric static bool 5340b57cec5SDimitry Andric ElideMixedSourceAndDisassemblyLine(const ExecutionContext &exe_ctx, 5350b57cec5SDimitry Andric const SymbolContext &sc, SourceLine &line); 5360b57cec5SDimitry Andric 5370b57cec5SDimitry Andric static bool ElideMixedSourceAndDisassemblyLine(const ExecutionContext & exe_ctx,const SymbolContext & sc,LineEntry & line)5380b57cec5SDimitry Andric ElideMixedSourceAndDisassemblyLine(const ExecutionContext &exe_ctx, 5390b57cec5SDimitry Andric const SymbolContext &sc, LineEntry &line) { 5400b57cec5SDimitry Andric SourceLine sl; 5410b57cec5SDimitry Andric sl.file = line.file; 5420b57cec5SDimitry Andric sl.line = line.line; 5430b57cec5SDimitry Andric sl.column = line.column; 5440b57cec5SDimitry Andric return ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, sl); 5450b57cec5SDimitry Andric }; 5460b57cec5SDimitry Andric 5470b57cec5SDimitry Andric // Classes that inherit from Disassembler can see and modify these 5480b57cec5SDimitry Andric ArchSpec m_arch; 5490b57cec5SDimitry Andric InstructionList m_instruction_list; 5500b57cec5SDimitry Andric lldb::addr_t m_base_addr; 5510b57cec5SDimitry Andric std::string m_flavor; 5520b57cec5SDimitry Andric 5530b57cec5SDimitry Andric private: 5540b57cec5SDimitry Andric // For Disassembler only 5555ffd83dbSDimitry Andric Disassembler(const Disassembler &) = delete; 5565ffd83dbSDimitry Andric const Disassembler &operator=(const Disassembler &) = delete; 5570b57cec5SDimitry Andric }; 5580b57cec5SDimitry Andric 5590b57cec5SDimitry Andric } // namespace lldb_private 5600b57cec5SDimitry Andric 5615ffd83dbSDimitry Andric #endif // LLDB_CORE_DISASSEMBLER_H 562