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 &reg);
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