diff options
Diffstat (limited to 'include/lldb/Core/Disassembler.h')
-rw-r--r-- | include/lldb/Core/Disassembler.h | 880 |
1 files changed, 453 insertions, 427 deletions
diff --git a/include/lldb/Core/Disassembler.h b/include/lldb/Core/Disassembler.h index bfa99de81ea4..c42074719b1a 100644 --- a/include/lldb/Core/Disassembler.h +++ b/include/lldb/Core/Disassembler.h @@ -12,472 +12,498 @@ // C Includes // C++ Includes -#include <vector> #include <string> +#include <vector> // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" #include "lldb/Core/Address.h" #include "lldb/Core/ArchSpec.h" #include "lldb/Core/EmulateInstruction.h" #include "lldb/Core/Opcode.h" #include "lldb/Core/PluginInterface.h" +#include "lldb/Host/FileSpec.h" #include "lldb/Interpreter/OptionValue.h" +#include "lldb/Symbol/LineEntry.h" +#include "lldb/lldb-private.h" namespace lldb_private { -class Instruction -{ +class Instruction { public: - Instruction (const Address &address, - lldb::AddressClass addr_class = lldb::eAddressClassInvalid); - - virtual - ~Instruction(); - - const Address & - GetAddress () const - { - return m_address; - } - - const char * - GetMnemonic (const ExecutionContext* exe_ctx) - { - CalculateMnemonicOperandsAndCommentIfNeeded (exe_ctx); - return m_opcode_name.c_str(); - } - - const char * - GetOperands (const ExecutionContext* exe_ctx) - { - CalculateMnemonicOperandsAndCommentIfNeeded (exe_ctx); - return m_mnemonics.c_str(); - } - - const char * - GetComment (const ExecutionContext* exe_ctx) - { - CalculateMnemonicOperandsAndCommentIfNeeded (exe_ctx); - return m_comment.c_str(); - } - - virtual void - CalculateMnemonicOperandsAndComment (const ExecutionContext* exe_ctx) = 0; - - lldb::AddressClass - GetAddressClass (); - - void - SetAddress (const Address &addr) - { - // Invalidate the address class to lazily discover - // it if we need to. - m_address_class = lldb::eAddressClassInvalid; - m_address = addr; - } - - //------------------------------------------------------------------ - /// Dump the text representation of this Instruction to a Stream - /// - /// Print the (optional) address, (optional) bytes, opcode, - /// operands, and instruction comments to a stream. - /// - /// @param[in] s - /// The Stream to add the text to. - /// - /// @param[in] show_address - /// Whether the address (using disassembly_addr_format_spec formatting) - /// should be printed. - /// - /// @param[in] show_bytes - /// Whether the bytes of the assembly instruction should be printed. - /// - /// @param[in] max_opcode_byte_size - /// The size (in bytes) of the largest instruction in the list that - /// we are printing (for text justification/alignment purposes) - /// Only needed if show_bytes is true. - /// - /// @param[in] exe_ctx - /// The current execution context, if available. May be used in - /// the assembling of the operands+comments for this instruction. - /// Pass NULL if not applicable. - /// - /// @param[in] sym_ctx - /// The SymbolContext for this instruction. - /// Pass NULL if not available/computed. - /// Only needed if show_address is true. - /// - /// @param[in] prev_sym_ctx - /// The SymbolContext for the previous instruction. Depending on - /// the disassembly address format specification, a change in - /// Symbol / Function may mean that a line is printed with the new - /// symbol/function name. - /// Pass NULL if unavailable, or if this is the first instruction of - /// the InstructionList. - /// Only needed if show_address is true. - /// - /// @param[in] disassembly_addr_format - /// The format specification for how addresses are printed. - /// Only needed if show_address is true. - /// - /// @param[in] max_address_text_size - /// The length of the longest address string at the start of the - /// disassembly line that will be printed (the Debugger::FormatDisassemblerAddress() string) - /// so this method can properly align the instruction opcodes. - /// May be 0 to indicate no indentation/alignment of the opcodes. - //------------------------------------------------------------------ - virtual void - Dump (Stream *s, - uint32_t max_opcode_byte_size, - bool show_address, - bool show_bytes, - const ExecutionContext* exe_ctx, - const SymbolContext *sym_ctx, - const SymbolContext *prev_sym_ctx, - const FormatEntity::Entry *disassembly_addr_format, - size_t max_address_text_size); - - virtual bool - DoesBranch () = 0; - - virtual bool - HasDelaySlot (); - - virtual size_t - Decode (const Disassembler &disassembler, - const DataExtractor& data, - lldb::offset_t data_offset) = 0; - - virtual void - SetDescription (const char *) {} // May be overridden in sub-classes that have descriptions. - - lldb::OptionValueSP - ReadArray (FILE *in_file, Stream *out_stream, OptionValue::Type data_type); - - lldb::OptionValueSP - ReadDictionary (FILE *in_file, Stream *out_stream); - - bool - DumpEmulation (const ArchSpec &arch); - - virtual bool - TestEmulation (Stream *stream, const char *test_file_name); - - bool - Emulate (const ArchSpec &arch, - uint32_t evaluate_options, - void *baton, - EmulateInstruction::ReadMemoryCallback read_mem_callback, - EmulateInstruction::WriteMemoryCallback write_mem_calback, - EmulateInstruction::ReadRegisterCallback read_reg_callback, - EmulateInstruction::WriteRegisterCallback write_reg_callback); - - const Opcode & - GetOpcode () const - { - return m_opcode; - } - - uint32_t - GetData (DataExtractor &data); + Instruction(const Address &address, + lldb::AddressClass addr_class = lldb::eAddressClassInvalid); + + virtual ~Instruction(); + + const Address &GetAddress() const { return m_address; } + + const char *GetMnemonic(const ExecutionContext *exe_ctx) { + CalculateMnemonicOperandsAndCommentIfNeeded(exe_ctx); + return m_opcode_name.c_str(); + } + + const char *GetOperands(const ExecutionContext *exe_ctx) { + CalculateMnemonicOperandsAndCommentIfNeeded(exe_ctx); + return m_mnemonics.c_str(); + } + + const char *GetComment(const ExecutionContext *exe_ctx) { + CalculateMnemonicOperandsAndCommentIfNeeded(exe_ctx); + return m_comment.c_str(); + } + + virtual void + CalculateMnemonicOperandsAndComment(const ExecutionContext *exe_ctx) = 0; + + lldb::AddressClass GetAddressClass(); + + void SetAddress(const Address &addr) { + // Invalidate the address class to lazily discover + // it if we need to. + m_address_class = lldb::eAddressClassInvalid; + m_address = addr; + } + + //------------------------------------------------------------------ + /// Dump the text representation of this Instruction to a Stream + /// + /// Print the (optional) address, (optional) bytes, opcode, + /// operands, and instruction comments to a stream. + /// + /// @param[in] s + /// The Stream to add the text to. + /// + /// @param[in] show_address + /// Whether the address (using disassembly_addr_format_spec formatting) + /// should be printed. + /// + /// @param[in] show_bytes + /// Whether the bytes of the assembly instruction should be printed. + /// + /// @param[in] max_opcode_byte_size + /// The size (in bytes) of the largest instruction in the list that + /// we are printing (for text justification/alignment purposes) + /// Only needed if show_bytes is true. + /// + /// @param[in] exe_ctx + /// The current execution context, if available. May be used in + /// the assembling of the operands+comments for this instruction. + /// Pass NULL if not applicable. + /// + /// @param[in] sym_ctx + /// The SymbolContext for this instruction. + /// Pass NULL if not available/computed. + /// Only needed if show_address is true. + /// + /// @param[in] prev_sym_ctx + /// The SymbolContext for the previous instruction. Depending on + /// the disassembly address format specification, a change in + /// Symbol / Function may mean that a line is printed with the new + /// symbol/function name. + /// Pass NULL if unavailable, or if this is the first instruction of + /// the InstructionList. + /// Only needed if show_address is true. + /// + /// @param[in] disassembly_addr_format + /// The format specification for how addresses are printed. + /// Only needed if show_address is true. + /// + /// @param[in] max_address_text_size + /// The length of the longest address string at the start of the + /// disassembly line that will be printed (the + /// Debugger::FormatDisassemblerAddress() string) + /// so this method can properly align the instruction opcodes. + /// May be 0 to indicate no indentation/alignment of the opcodes. + //------------------------------------------------------------------ + virtual void Dump(Stream *s, uint32_t max_opcode_byte_size, bool show_address, + bool show_bytes, const ExecutionContext *exe_ctx, + const SymbolContext *sym_ctx, + const SymbolContext *prev_sym_ctx, + const FormatEntity::Entry *disassembly_addr_format, + size_t max_address_text_size); + + virtual bool DoesBranch() = 0; + + virtual bool HasDelaySlot(); + + virtual size_t Decode(const Disassembler &disassembler, + const DataExtractor &data, + lldb::offset_t data_offset) = 0; + + virtual void SetDescription(llvm::StringRef) { + } // May be overridden in sub-classes that have descriptions. + + lldb::OptionValueSP ReadArray(FILE *in_file, Stream *out_stream, + OptionValue::Type data_type); + + lldb::OptionValueSP ReadDictionary(FILE *in_file, Stream *out_stream); + + bool DumpEmulation(const ArchSpec &arch); + + virtual bool TestEmulation(Stream *stream, const char *test_file_name); + + bool Emulate(const ArchSpec &arch, uint32_t evaluate_options, void *baton, + EmulateInstruction::ReadMemoryCallback read_mem_callback, + EmulateInstruction::WriteMemoryCallback write_mem_calback, + EmulateInstruction::ReadRegisterCallback read_reg_callback, + EmulateInstruction::WriteRegisterCallback write_reg_callback); + + const Opcode &GetOpcode() const { return m_opcode; } + + uint32_t GetData(DataExtractor &data); + + struct Operand { + enum class Type { + Invalid = 0, + Register, + Immediate, + Dereference, + Sum, + Product + } m_type = Type::Invalid; + std::vector<Operand> m_children; + lldb::addr_t m_immediate = 0; + ConstString m_register; + bool m_negative = false; + bool m_clobbered = false; + + bool IsValid() { return m_type != Type::Invalid; } + + static Operand BuildRegister(ConstString &r); + static Operand BuildImmediate(lldb::addr_t imm, bool neg); + static Operand BuildImmediate(int64_t imm); + static Operand BuildDereference(const Operand &ref); + static Operand BuildSum(const Operand &lhs, const Operand &rhs); + static Operand BuildProduct(const Operand &lhs, const Operand &rhs); + }; + + virtual bool ParseOperands(llvm::SmallVectorImpl<Operand> &operands) { + return false; + } + + virtual bool IsCall() { return false; } protected: - Address m_address; // The section offset address of this instruction - // We include an address class in the Instruction class to - // allow the instruction specify the eAddressClassCodeAlternateISA - // (currently used for thumb), and also to specify data (eAddressClassData). - // The usual value will be eAddressClassCode, but often when - // disassembling memory, you might run into data. This can - // help us to disassemble appropriately. + Address m_address; // The section offset address of this instruction + // We include an address class in the Instruction class to + // allow the instruction specify the eAddressClassCodeAlternateISA + // (currently used for thumb), and also to specify data (eAddressClassData). + // The usual value will be eAddressClassCode, but often when + // disassembling memory, you might run into data. This can + // help us to disassemble appropriately. private: - lldb::AddressClass m_address_class; // Use GetAddressClass () accessor function! + lldb::AddressClass + m_address_class; // Use GetAddressClass () accessor function! protected: - Opcode m_opcode; // The opcode for this instruction - std::string m_opcode_name; - std::string m_mnemonics; - std::string m_comment; - bool m_calculated_strings; - - void - CalculateMnemonicOperandsAndCommentIfNeeded (const ExecutionContext* exe_ctx) - { - if (!m_calculated_strings) - { - m_calculated_strings = true; - CalculateMnemonicOperandsAndComment(exe_ctx); - } + Opcode m_opcode; // The opcode for this instruction + std::string m_opcode_name; + std::string m_mnemonics; + std::string m_comment; + bool m_calculated_strings; + + void + CalculateMnemonicOperandsAndCommentIfNeeded(const ExecutionContext *exe_ctx) { + if (!m_calculated_strings) { + m_calculated_strings = true; + CalculateMnemonicOperandsAndComment(exe_ctx); } + } }; -class InstructionList -{ +namespace OperandMatchers { +std::function<bool(const Instruction::Operand &)> +MatchBinaryOp(std::function<bool(const Instruction::Operand &)> base, + std::function<bool(const Instruction::Operand &)> left, + std::function<bool(const Instruction::Operand &)> right); + +std::function<bool(const Instruction::Operand &)> +MatchUnaryOp(std::function<bool(const Instruction::Operand &)> base, + std::function<bool(const Instruction::Operand &)> child); + +std::function<bool(const Instruction::Operand &)> +MatchRegOp(const RegisterInfo &info); + +std::function<bool(const Instruction::Operand &)> FetchRegOp(ConstString ®); + +std::function<bool(const Instruction::Operand &)> MatchImmOp(int64_t imm); + +std::function<bool(const Instruction::Operand &)> FetchImmOp(int64_t &imm); + +std::function<bool(const Instruction::Operand &)> +MatchOpType(Instruction::Operand::Type type); +} + +class InstructionList { public: - InstructionList(); - ~InstructionList(); - - size_t - GetSize() const; - - uint32_t - GetMaxOpcocdeByteSize () const; - - lldb::InstructionSP - GetInstructionAtIndex (size_t idx) const; - - uint32_t - GetIndexOfNextBranchInstruction(uint32_t start, Target &target) const; - - uint32_t - GetIndexOfInstructionAtLoadAddress (lldb::addr_t load_addr, Target &target); - - uint32_t - GetIndexOfInstructionAtAddress (const Address &addr); - - void - Clear(); - - void - Append (lldb::InstructionSP &inst_sp); - - void - Dump (Stream *s, - bool show_address, - bool show_bytes, - const ExecutionContext* exe_ctx); + InstructionList(); + ~InstructionList(); + + size_t GetSize() const; + + uint32_t GetMaxOpcocdeByteSize() const; + + lldb::InstructionSP GetInstructionAtIndex(size_t idx) const; + + uint32_t GetIndexOfNextBranchInstruction(uint32_t start, + Target &target) const; + + uint32_t GetIndexOfInstructionAtLoadAddress(lldb::addr_t load_addr, + Target &target); + + uint32_t GetIndexOfInstructionAtAddress(const Address &addr); + + void Clear(); + + void Append(lldb::InstructionSP &inst_sp); + + void Dump(Stream *s, bool show_address, bool show_bytes, + const ExecutionContext *exe_ctx); private: - typedef std::vector<lldb::InstructionSP> collection; - typedef collection::iterator iterator; - typedef collection::const_iterator const_iterator; + typedef std::vector<lldb::InstructionSP> collection; + typedef collection::iterator iterator; + typedef collection::const_iterator const_iterator; - collection m_instructions; + collection m_instructions; }; -class PseudoInstruction : - public Instruction -{ +class PseudoInstruction : public Instruction { public: + PseudoInstruction(); + + ~PseudoInstruction() override; + + bool DoesBranch() override; + + bool HasDelaySlot() override; + + void CalculateMnemonicOperandsAndComment( + const ExecutionContext *exe_ctx) override { + // TODO: fill this in and put opcode name into Instruction::m_opcode_name, + // mnemonic into Instruction::m_mnemonics, and any comment into + // Instruction::m_comment + } + + size_t Decode(const Disassembler &disassembler, const DataExtractor &data, + lldb::offset_t data_offset) override; + + void SetOpcode(size_t opcode_size, void *opcode_data); + + void SetDescription(llvm::StringRef description) override; - PseudoInstruction (); - - ~PseudoInstruction() override; - - bool - DoesBranch() override; - - bool - HasDelaySlot() override; - - void - CalculateMnemonicOperandsAndComment(const ExecutionContext* exe_ctx) override - { - // TODO: fill this in and put opcode name into Instruction::m_opcode_name, - // mnemonic into Instruction::m_mnemonics, and any comment into - // Instruction::m_comment - } - - size_t - Decode(const Disassembler &disassembler, - const DataExtractor &data, - lldb::offset_t data_offset) override; - - void - SetOpcode (size_t opcode_size, void *opcode_data); - - void - SetDescription(const char *description) override; - protected: - std::string m_description; - - DISALLOW_COPY_AND_ASSIGN (PseudoInstruction); + std::string m_description; + + DISALLOW_COPY_AND_ASSIGN(PseudoInstruction); }; -class Disassembler : - public std::enable_shared_from_this<Disassembler>, - public PluginInterface -{ +class Disassembler : public std::enable_shared_from_this<Disassembler>, + public PluginInterface { public: + enum { + eOptionNone = 0u, + eOptionShowBytes = (1u << 0), + eOptionRawOuput = (1u << 1), + eOptionMarkPCSourceLine = (1u << 2), // Mark the source line that contains + // the current PC (mixed mode only) + eOptionMarkPCAddress = + (1u << 3) // Mark the disassembly line the contains the PC + }; + + enum HexImmediateStyle { + eHexStyleC, + eHexStyleAsm, + }; + + // FindPlugin should be lax about the flavor string (it is too annoying to + // have various internal uses of the + // disassembler fail because the global flavor string gets set wrong. + // Instead, if you get a flavor string you + // don't understand, use the default. Folks who care to check can use the + // FlavorValidForArchSpec method on the + // disassembler they got back. + static lldb::DisassemblerSP + FindPlugin(const ArchSpec &arch, const char *flavor, const char *plugin_name); + + // This version will use the value in the Target settings if flavor is NULL; + static lldb::DisassemblerSP + FindPluginForTarget(const lldb::TargetSP target_sp, const ArchSpec &arch, + const char *flavor, const char *plugin_name); + + static lldb::DisassemblerSP + DisassembleRange(const ArchSpec &arch, const char *plugin_name, + const char *flavor, const ExecutionContext &exe_ctx, + const AddressRange &disasm_range, bool prefer_file_cache); + + static lldb::DisassemblerSP + DisassembleBytes(const ArchSpec &arch, const char *plugin_name, + const char *flavor, const Address &start, const void *bytes, + size_t length, uint32_t max_num_instructions, + bool data_from_file); + + static bool Disassemble(Debugger &debugger, const ArchSpec &arch, + const char *plugin_name, const char *flavor, + const ExecutionContext &exe_ctx, + const AddressRange &range, uint32_t num_instructions, + bool mixed_source_and_assembly, + uint32_t num_mixed_context_lines, uint32_t options, + Stream &strm); + + static bool Disassemble(Debugger &debugger, const ArchSpec &arch, + const char *plugin_name, const char *flavor, + const ExecutionContext &exe_ctx, const Address &start, + uint32_t num_instructions, + bool mixed_source_and_assembly, + uint32_t num_mixed_context_lines, uint32_t options, + Stream &strm); + + static size_t + Disassemble(Debugger &debugger, const ArchSpec &arch, const char *plugin_name, + const char *flavor, const ExecutionContext &exe_ctx, + SymbolContextList &sc_list, uint32_t num_instructions, + bool mixed_source_and_assembly, uint32_t num_mixed_context_lines, + uint32_t options, Stream &strm); + + static bool + Disassemble(Debugger &debugger, const ArchSpec &arch, const char *plugin_name, + const char *flavor, const ExecutionContext &exe_ctx, + const ConstString &name, Module *module, + uint32_t num_instructions, bool mixed_source_and_assembly, + uint32_t num_mixed_context_lines, uint32_t options, Stream &strm); + + static bool + Disassemble(Debugger &debugger, const ArchSpec &arch, const char *plugin_name, + const char *flavor, const ExecutionContext &exe_ctx, + uint32_t num_instructions, bool mixed_source_and_assembly, + uint32_t num_mixed_context_lines, uint32_t options, Stream &strm); + + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + Disassembler(const ArchSpec &arch, const char *flavor); + ~Disassembler() override; + + typedef const char *(*SummaryCallback)(const Instruction &inst, + ExecutionContext *exe_context, + void *user_data); + + static bool PrintInstructions(Disassembler *disasm_ptr, Debugger &debugger, + const ArchSpec &arch, + const ExecutionContext &exe_ctx, + uint32_t num_instructions, + bool mixed_source_and_assembly, + uint32_t num_mixed_context_lines, + uint32_t options, Stream &strm); + + size_t ParseInstructions(const ExecutionContext *exe_ctx, + const AddressRange &range, Stream *error_strm_ptr, + bool prefer_file_cache); + + size_t ParseInstructions(const ExecutionContext *exe_ctx, + const Address &range, uint32_t num_instructions, + bool prefer_file_cache); + + virtual size_t DecodeInstructions(const Address &base_addr, + const DataExtractor &data, + lldb::offset_t data_offset, + size_t num_instructions, bool append, + bool data_from_file) = 0; + + InstructionList &GetInstructionList(); + + const InstructionList &GetInstructionList() const; + + const ArchSpec &GetArchitecture() const { return m_arch; } + + const char *GetFlavor() const { return m_flavor.c_str(); } + + virtual bool FlavorValidForArchSpec(const lldb_private::ArchSpec &arch, + const char *flavor) = 0; + +protected: + // SourceLine and SourceLinesToDisplay structures are only used in + // the mixed source and assembly display methods internal to this class. - enum - { - eOptionNone = 0u, - eOptionShowBytes = (1u << 0), - eOptionRawOuput = (1u << 1), - eOptionMarkPCSourceLine = (1u << 2), // Mark the source line that contains the current PC (mixed mode only) - eOptionMarkPCAddress = (1u << 3) // Mark the disassembly line the contains the PC - }; - - enum HexImmediateStyle - { - eHexStyleC, - eHexStyleAsm, - }; - - // FindPlugin should be lax about the flavor string (it is too annoying to have various internal uses of the - // disassembler fail because the global flavor string gets set wrong. Instead, if you get a flavor string you - // don't understand, use the default. Folks who care to check can use the FlavorValidForArchSpec method on the - // disassembler they got back. - static lldb::DisassemblerSP - FindPlugin (const ArchSpec &arch, const char *flavor, const char *plugin_name); - - // This version will use the value in the Target settings if flavor is NULL; - static lldb::DisassemblerSP - FindPluginForTarget(const lldb::TargetSP target_sp, const ArchSpec &arch, const char *flavor, const char *plugin_name); - - static lldb::DisassemblerSP - DisassembleRange (const ArchSpec &arch, - const char *plugin_name, - const char *flavor, - const ExecutionContext &exe_ctx, - const AddressRange &disasm_range, - bool prefer_file_cache); - - static lldb::DisassemblerSP - DisassembleBytes (const ArchSpec &arch, - const char *plugin_name, - const char *flavor, - const Address &start, - const void *bytes, - size_t length, - uint32_t max_num_instructions, - bool data_from_file); - - static bool - Disassemble (Debugger &debugger, - const ArchSpec &arch, - const char *plugin_name, - const char *flavor, - const ExecutionContext &exe_ctx, - const AddressRange &range, - uint32_t num_instructions, - uint32_t num_mixed_context_lines, - uint32_t options, - Stream &strm); - - static bool - Disassemble (Debugger &debugger, - const ArchSpec &arch, - const char *plugin_name, - const char *flavor, - const ExecutionContext &exe_ctx, - const Address &start, - uint32_t num_instructions, - uint32_t num_mixed_context_lines, - uint32_t options, - Stream &strm); - - static size_t - Disassemble (Debugger &debugger, - const ArchSpec &arch, - const char *plugin_name, - const char *flavor, - const ExecutionContext &exe_ctx, - SymbolContextList &sc_list, - uint32_t num_instructions, - uint32_t num_mixed_context_lines, - uint32_t options, - Stream &strm); - - static bool - Disassemble (Debugger &debugger, - const ArchSpec &arch, - const char *plugin_name, - const char *flavor, - const ExecutionContext &exe_ctx, - const ConstString &name, - Module *module, - uint32_t num_instructions, - uint32_t num_mixed_context_lines, - uint32_t options, - Stream &strm); - - static bool - Disassemble (Debugger &debugger, - const ArchSpec &arch, - const char *plugin_name, - const char *flavor, - const ExecutionContext &exe_ctx, - uint32_t num_instructions, - uint32_t num_mixed_context_lines, - uint32_t options, - Stream &strm); - - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - Disassembler(const ArchSpec &arch, const char *flavor); - ~Disassembler() override; - - typedef const char * (*SummaryCallback)(const Instruction& inst, ExecutionContext *exe_context, void *user_data); - - static bool - PrintInstructions (Disassembler *disasm_ptr, - Debugger &debugger, - const ArchSpec &arch, - const ExecutionContext &exe_ctx, - uint32_t num_instructions, - uint32_t num_mixed_context_lines, - uint32_t options, - Stream &strm); - - size_t - ParseInstructions (const ExecutionContext *exe_ctx, - const AddressRange &range, - Stream *error_strm_ptr, - bool prefer_file_cache); - - size_t - ParseInstructions (const ExecutionContext *exe_ctx, - const Address &range, - uint32_t num_instructions, - bool prefer_file_cache); - - virtual size_t - DecodeInstructions (const Address &base_addr, - const DataExtractor& data, - lldb::offset_t data_offset, - size_t num_instructions, - bool append, - bool data_from_file) = 0; - - InstructionList & - GetInstructionList (); - - const InstructionList & - GetInstructionList () const; - - const ArchSpec & - GetArchitecture () const - { - return m_arch; + struct SourceLine { + FileSpec file; + uint32_t line; + uint32_t column; + + SourceLine() : file(), line(LLDB_INVALID_LINE_NUMBER), column(0) {} + + bool operator==(const SourceLine &rhs) const { + return file == rhs.file && line == rhs.line && rhs.column == column; } - - const char * - GetFlavor () const - { - return m_flavor.c_str(); + + bool operator!=(const SourceLine &rhs) const { + return file != rhs.file || line != rhs.line || column != rhs.column; } - - virtual bool - FlavorValidForArchSpec (const lldb_private::ArchSpec &arch, const char *flavor) = 0; -protected: - //------------------------------------------------------------------ - // Classes that inherit from Disassembler can see and modify these - //------------------------------------------------------------------ - ArchSpec m_arch; - InstructionList m_instruction_list; - lldb::addr_t m_base_addr; - std::string m_flavor; + bool IsValid() const { return line != LLDB_INVALID_LINE_NUMBER; } + }; + + struct SourceLinesToDisplay { + std::vector<SourceLine> lines; + + // index of the "current" source line, if we want to highlight that + // when displaying the source lines. (as opposed to the surrounding + // source lines provided to give context) + size_t current_source_line; + + // Whether to print a blank line at the end of the source lines. + bool print_source_context_end_eol; + + SourceLinesToDisplay() + : lines(), current_source_line(-1), print_source_context_end_eol(true) { + } + }; + + // Get the function's declaration line number, hopefully a line number earlier + // than the opening curly brace at the start of the function body. + static SourceLine GetFunctionDeclLineEntry(const SymbolContext &sc); + + // Add the provided SourceLine to the map of filenames-to-source-lines-seen. + static void AddLineToSourceLineTables( + SourceLine &line, + std::map<FileSpec, std::set<uint32_t>> &source_lines_seen); + + // Given a source line, determine if we should print it when we're doing + // mixed source & assembly output. + // We're currently using the target.process.thread.step-avoid-regexp setting + // (which is used for stepping over inlined STL functions by default) to + // determine what source lines to avoid showing. + // + // Returns true if this source line should be elided (if the source line + // should + // not be displayed). + static bool + ElideMixedSourceAndDisassemblyLine(const ExecutionContext &exe_ctx, + const SymbolContext &sc, SourceLine &line); + + static bool + ElideMixedSourceAndDisassemblyLine(const ExecutionContext &exe_ctx, + const SymbolContext &sc, LineEntry &line) { + SourceLine sl; + sl.file = line.file; + sl.line = line.line; + sl.column = line.column; + return ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, sl); + }; + + //------------------------------------------------------------------ + // Classes that inherit from Disassembler can see and modify these + //------------------------------------------------------------------ + ArchSpec m_arch; + InstructionList m_instruction_list; + lldb::addr_t m_base_addr; + std::string m_flavor; private: - //------------------------------------------------------------------ - // For Disassembler only - //------------------------------------------------------------------ - DISALLOW_COPY_AND_ASSIGN (Disassembler); + //------------------------------------------------------------------ + // For Disassembler only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN(Disassembler); }; } // namespace lldb_private |