1254721Semaste//===-- Disassembler.h ------------------------------------------*- C++ -*-===//
2254721Semaste//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6254721Semaste//
7254721Semaste//===----------------------------------------------------------------------===//
8254721Semaste
9254721Semaste#ifndef liblldb_Disassembler_h_
10254721Semaste#define liblldb_Disassembler_h_
11254721Semaste
12254721Semaste#include "lldb/Core/Address.h"
13254721Semaste#include "lldb/Core/EmulateInstruction.h"
14344779Sdim#include "lldb/Core/FormatEntity.h"
15254721Semaste#include "lldb/Core/Opcode.h"
16254721Semaste#include "lldb/Core/PluginInterface.h"
17254721Semaste#include "lldb/Interpreter/OptionValue.h"
18314564Sdim#include "lldb/Symbol/LineEntry.h"
19344779Sdim#include "lldb/Target/ExecutionContext.h"
20327952Sdim#include "lldb/Utility/ArchSpec.h"
21344779Sdim#include "lldb/Utility/ConstString.h"
22321369Sdim#include "lldb/Utility/FileSpec.h"
23344779Sdim#include "lldb/lldb-defines.h"
24344779Sdim#include "lldb/lldb-forward.h"
25344779Sdim#include "lldb/lldb-private-enumerations.h"
26344779Sdim#include "lldb/lldb-types.h"
27254721Semaste
28344779Sdim#include "llvm/ADT/StringRef.h"
29321369Sdim
30344779Sdim#include <functional>
31321369Sdim#include <map>
32344779Sdim#include <memory>
33321369Sdim#include <set>
34321369Sdim#include <string>
35321369Sdim#include <vector>
36321369Sdim
37344779Sdim#include <stddef.h>
38344779Sdim#include <stdint.h>
39344779Sdim#include <stdio.h>
40321369Sdim
41353358Sdimnamespace llvm {
42353358Sdimtemplate <typename T> class SmallVectorImpl;
43353358Sdim}
44353358Sdim
45254721Semastenamespace lldb_private {
46321369Sdimclass AddressRange;
47321369Sdimclass DataExtractor;
48321369Sdimclass Debugger;
49321369Sdimclass Disassembler;
50321369Sdimclass Module;
51321369Sdimclass Stream;
52321369Sdimclass SymbolContext;
53321369Sdimclass SymbolContextList;
54321369Sdimclass Target;
55321369Sdimstruct RegisterInfo;
56254721Semaste
57314564Sdimclass Instruction {
58254721Semastepublic:
59314564Sdim  Instruction(const Address &address,
60341825Sdim              AddressClass addr_class = AddressClass::eInvalid);
61254721Semaste
62314564Sdim  virtual ~Instruction();
63254721Semaste
64314564Sdim  const Address &GetAddress() const { return m_address; }
65296417Sdim
66314564Sdim  const char *GetMnemonic(const ExecutionContext *exe_ctx) {
67314564Sdim    CalculateMnemonicOperandsAndCommentIfNeeded(exe_ctx);
68314564Sdim    return m_opcode_name.c_str();
69314564Sdim  }
70254721Semaste
71314564Sdim  const char *GetOperands(const ExecutionContext *exe_ctx) {
72314564Sdim    CalculateMnemonicOperandsAndCommentIfNeeded(exe_ctx);
73314564Sdim    return m_mnemonics.c_str();
74314564Sdim  }
75254721Semaste
76314564Sdim  const char *GetComment(const ExecutionContext *exe_ctx) {
77314564Sdim    CalculateMnemonicOperandsAndCommentIfNeeded(exe_ctx);
78314564Sdim    return m_comment.c_str();
79314564Sdim  }
80254721Semaste
81314564Sdim  virtual void
82314564Sdim  CalculateMnemonicOperandsAndComment(const ExecutionContext *exe_ctx) = 0;
83254721Semaste
84341825Sdim  AddressClass GetAddressClass();
85296417Sdim
86314564Sdim  void SetAddress(const Address &addr) {
87341825Sdim    // Invalidate the address class to lazily discover it if we need to.
88341825Sdim    m_address_class = AddressClass::eInvalid;
89314564Sdim    m_address = addr;
90314564Sdim  }
91254721Semaste
92314564Sdim  /// Dump the text representation of this Instruction to a Stream
93314564Sdim  ///
94314564Sdim  /// Print the (optional) address, (optional) bytes, opcode,
95314564Sdim  /// operands, and instruction comments to a stream.
96314564Sdim  ///
97353358Sdim  /// \param[in] s
98314564Sdim  ///     The Stream to add the text to.
99314564Sdim  ///
100353358Sdim  /// \param[in] show_address
101314564Sdim  ///     Whether the address (using disassembly_addr_format_spec formatting)
102314564Sdim  ///     should be printed.
103314564Sdim  ///
104353358Sdim  /// \param[in] show_bytes
105314564Sdim  ///     Whether the bytes of the assembly instruction should be printed.
106314564Sdim  ///
107353358Sdim  /// \param[in] max_opcode_byte_size
108314564Sdim  ///     The size (in bytes) of the largest instruction in the list that
109314564Sdim  ///     we are printing (for text justification/alignment purposes)
110314564Sdim  ///     Only needed if show_bytes is true.
111314564Sdim  ///
112353358Sdim  /// \param[in] exe_ctx
113314564Sdim  ///     The current execution context, if available.  May be used in
114314564Sdim  ///     the assembling of the operands+comments for this instruction.
115314564Sdim  ///     Pass NULL if not applicable.
116314564Sdim  ///
117353358Sdim  /// \param[in] sym_ctx
118314564Sdim  ///     The SymbolContext for this instruction.
119314564Sdim  ///     Pass NULL if not available/computed.
120314564Sdim  ///     Only needed if show_address is true.
121314564Sdim  ///
122353358Sdim  /// \param[in] prev_sym_ctx
123314564Sdim  ///     The SymbolContext for the previous instruction.  Depending on
124314564Sdim  ///     the disassembly address format specification, a change in
125314564Sdim  ///     Symbol / Function may mean that a line is printed with the new
126314564Sdim  ///     symbol/function name.
127314564Sdim  ///     Pass NULL if unavailable, or if this is the first instruction of
128314564Sdim  ///     the InstructionList.
129314564Sdim  ///     Only needed if show_address is true.
130314564Sdim  ///
131353358Sdim  /// \param[in] disassembly_addr_format
132314564Sdim  ///     The format specification for how addresses are printed.
133314564Sdim  ///     Only needed if show_address is true.
134314564Sdim  ///
135353358Sdim  /// \param[in] max_address_text_size
136314564Sdim  ///     The length of the longest address string at the start of the
137314564Sdim  ///     disassembly line that will be printed (the
138314564Sdim  ///     Debugger::FormatDisassemblerAddress() string)
139314564Sdim  ///     so this method can properly align the instruction opcodes.
140314564Sdim  ///     May be 0 to indicate no indentation/alignment of the opcodes.
141314564Sdim  virtual void Dump(Stream *s, uint32_t max_opcode_byte_size, bool show_address,
142314564Sdim                    bool show_bytes, const ExecutionContext *exe_ctx,
143314564Sdim                    const SymbolContext *sym_ctx,
144314564Sdim                    const SymbolContext *prev_sym_ctx,
145314564Sdim                    const FormatEntity::Entry *disassembly_addr_format,
146314564Sdim                    size_t max_address_text_size);
147254721Semaste
148314564Sdim  virtual bool DoesBranch() = 0;
149254721Semaste
150314564Sdim  virtual bool HasDelaySlot();
151314564Sdim
152321369Sdim  bool CanSetBreakpoint ();
153321369Sdim
154314564Sdim  virtual size_t Decode(const Disassembler &disassembler,
155314564Sdim                        const DataExtractor &data,
156314564Sdim                        lldb::offset_t data_offset) = 0;
157314564Sdim
158314564Sdim  virtual void SetDescription(llvm::StringRef) {
159314564Sdim  } // May be overridden in sub-classes that have descriptions.
160314564Sdim
161314564Sdim  lldb::OptionValueSP ReadArray(FILE *in_file, Stream *out_stream,
162314564Sdim                                OptionValue::Type data_type);
163314564Sdim
164314564Sdim  lldb::OptionValueSP ReadDictionary(FILE *in_file, Stream *out_stream);
165314564Sdim
166314564Sdim  bool DumpEmulation(const ArchSpec &arch);
167314564Sdim
168314564Sdim  virtual bool TestEmulation(Stream *stream, const char *test_file_name);
169314564Sdim
170314564Sdim  bool Emulate(const ArchSpec &arch, uint32_t evaluate_options, void *baton,
171314564Sdim               EmulateInstruction::ReadMemoryCallback read_mem_callback,
172314564Sdim               EmulateInstruction::WriteMemoryCallback write_mem_calback,
173314564Sdim               EmulateInstruction::ReadRegisterCallback read_reg_callback,
174314564Sdim               EmulateInstruction::WriteRegisterCallback write_reg_callback);
175314564Sdim
176314564Sdim  const Opcode &GetOpcode() const { return m_opcode; }
177314564Sdim
178314564Sdim  uint32_t GetData(DataExtractor &data);
179314564Sdim
180314564Sdim  struct Operand {
181314564Sdim    enum class Type {
182314564Sdim      Invalid = 0,
183314564Sdim      Register,
184314564Sdim      Immediate,
185314564Sdim      Dereference,
186314564Sdim      Sum,
187314564Sdim      Product
188314564Sdim    } m_type = Type::Invalid;
189314564Sdim    std::vector<Operand> m_children;
190314564Sdim    lldb::addr_t m_immediate = 0;
191314564Sdim    ConstString m_register;
192314564Sdim    bool m_negative = false;
193314564Sdim    bool m_clobbered = false;
194314564Sdim
195314564Sdim    bool IsValid() { return m_type != Type::Invalid; }
196314564Sdim
197314564Sdim    static Operand BuildRegister(ConstString &r);
198314564Sdim    static Operand BuildImmediate(lldb::addr_t imm, bool neg);
199314564Sdim    static Operand BuildImmediate(int64_t imm);
200314564Sdim    static Operand BuildDereference(const Operand &ref);
201314564Sdim    static Operand BuildSum(const Operand &lhs, const Operand &rhs);
202314564Sdim    static Operand BuildProduct(const Operand &lhs, const Operand &rhs);
203314564Sdim  };
204314564Sdim
205314564Sdim  virtual bool ParseOperands(llvm::SmallVectorImpl<Operand> &operands) {
206314564Sdim    return false;
207314564Sdim  }
208314564Sdim
209314564Sdim  virtual bool IsCall() { return false; }
210314564Sdim
211254721Semasteprotected:
212314564Sdim  Address m_address; // The section offset address of this instruction
213314564Sdim                     // We include an address class in the Instruction class to
214341825Sdim                     // allow the instruction specify the
215341825Sdim                     // AddressClass::eCodeAlternateISA (currently used for
216341825Sdim                     // thumb), and also to specify data (AddressClass::eData).
217341825Sdim                     // The usual value will be AddressClass::eCode, but often
218341825Sdim                     // when disassembling memory, you might run into data.
219341825Sdim                     // This can help us to disassemble appropriately.
220254721Semasteprivate:
221341825Sdim  AddressClass m_address_class; // Use GetAddressClass () accessor function!
222341825Sdim
223254721Semasteprotected:
224314564Sdim  Opcode m_opcode; // The opcode for this instruction
225314564Sdim  std::string m_opcode_name;
226314564Sdim  std::string m_mnemonics;
227314564Sdim  std::string m_comment;
228314564Sdim  bool m_calculated_strings;
229254721Semaste
230314564Sdim  void
231314564Sdim  CalculateMnemonicOperandsAndCommentIfNeeded(const ExecutionContext *exe_ctx) {
232314564Sdim    if (!m_calculated_strings) {
233314564Sdim      m_calculated_strings = true;
234314564Sdim      CalculateMnemonicOperandsAndComment(exe_ctx);
235254721Semaste    }
236314564Sdim  }
237254721Semaste};
238254721Semaste
239314564Sdimnamespace OperandMatchers {
240314564Sdimstd::function<bool(const Instruction::Operand &)>
241314564SdimMatchBinaryOp(std::function<bool(const Instruction::Operand &)> base,
242314564Sdim              std::function<bool(const Instruction::Operand &)> left,
243314564Sdim              std::function<bool(const Instruction::Operand &)> right);
244314564Sdim
245314564Sdimstd::function<bool(const Instruction::Operand &)>
246314564SdimMatchUnaryOp(std::function<bool(const Instruction::Operand &)> base,
247314564Sdim             std::function<bool(const Instruction::Operand &)> child);
248314564Sdim
249314564Sdimstd::function<bool(const Instruction::Operand &)>
250314564SdimMatchRegOp(const RegisterInfo &info);
251314564Sdim
252314564Sdimstd::function<bool(const Instruction::Operand &)> FetchRegOp(ConstString &reg);
253314564Sdim
254314564Sdimstd::function<bool(const Instruction::Operand &)> MatchImmOp(int64_t imm);
255314564Sdim
256314564Sdimstd::function<bool(const Instruction::Operand &)> FetchImmOp(int64_t &imm);
257314564Sdim
258314564Sdimstd::function<bool(const Instruction::Operand &)>
259314564SdimMatchOpType(Instruction::Operand::Type type);
260314564Sdim}
261314564Sdim
262314564Sdimclass InstructionList {
263254721Semastepublic:
264314564Sdim  InstructionList();
265314564Sdim  ~InstructionList();
266254721Semaste
267314564Sdim  size_t GetSize() const;
268254721Semaste
269314564Sdim  uint32_t GetMaxOpcocdeByteSize() const;
270254721Semaste
271314564Sdim  lldb::InstructionSP GetInstructionAtIndex(size_t idx) const;
272262528Semaste
273353358Sdim  //------------------------------------------------------------------
274353358Sdim  /// Get the index of the next branch instruction.
275353358Sdim  ///
276353358Sdim  /// Given a list of instructions, find the next branch instruction
277353358Sdim  /// in the list by returning an index.
278353358Sdim  ///
279353358Sdim  /// @param[in] start
280353358Sdim  ///     The instruction index of the first instruction to check.
281353358Sdim  ///
282353358Sdim  /// @param[in] target
283353358Sdim  ///     A LLDB target object that is used to resolve addresses.
284353358Sdim  ///
285353358Sdim  /// @param[in] ignore_calls
286353358Sdim  ///     It true, then fine the first branch instruction that isn't
287353358Sdim  ///     a function call (a branch that calls and returns to the next
288353358Sdim  ///     instruction). If false, find the instruction index of any
289353358Sdim  ///     branch in the list.
290360784Sdim  ///
291360784Sdim  /// @param[out] found_calls
292360784Sdim  ///     If non-null, this will be set to true if any calls were found in
293360784Sdim  ///     extending the range.
294353358Sdim  ///
295353358Sdim  /// @return
296353358Sdim  ///     The instruction index of the first branch that is at or past
297353358Sdim  ///     \a start. Returns UINT32_MAX if no matching branches are
298353358Sdim  ///     found.
299353358Sdim  //------------------------------------------------------------------
300314564Sdim  uint32_t GetIndexOfNextBranchInstruction(uint32_t start,
301353358Sdim                                           Target &target,
302360784Sdim                                           bool ignore_calls,
303360784Sdim                                           bool *found_calls) const;
304254721Semaste
305314564Sdim  uint32_t GetIndexOfInstructionAtLoadAddress(lldb::addr_t load_addr,
306314564Sdim                                              Target &target);
307254721Semaste
308314564Sdim  uint32_t GetIndexOfInstructionAtAddress(const Address &addr);
309254721Semaste
310314564Sdim  void Clear();
311314564Sdim
312314564Sdim  void Append(lldb::InstructionSP &inst_sp);
313314564Sdim
314314564Sdim  void Dump(Stream *s, bool show_address, bool show_bytes,
315314564Sdim            const ExecutionContext *exe_ctx);
316314564Sdim
317254721Semasteprivate:
318314564Sdim  typedef std::vector<lldb::InstructionSP> collection;
319314564Sdim  typedef collection::iterator iterator;
320314564Sdim  typedef collection::const_iterator const_iterator;
321254721Semaste
322314564Sdim  collection m_instructions;
323254721Semaste};
324254721Semaste
325314564Sdimclass PseudoInstruction : public Instruction {
326254721Semastepublic:
327314564Sdim  PseudoInstruction();
328254721Semaste
329314564Sdim  ~PseudoInstruction() override;
330254721Semaste
331314564Sdim  bool DoesBranch() override;
332296417Sdim
333314564Sdim  bool HasDelaySlot() override;
334314564Sdim
335314564Sdim  void CalculateMnemonicOperandsAndComment(
336314564Sdim      const ExecutionContext *exe_ctx) override {
337314564Sdim    // TODO: fill this in and put opcode name into Instruction::m_opcode_name,
338314564Sdim    // mnemonic into Instruction::m_mnemonics, and any comment into
339314564Sdim    // Instruction::m_comment
340314564Sdim  }
341314564Sdim
342314564Sdim  size_t Decode(const Disassembler &disassembler, const DataExtractor &data,
343314564Sdim                lldb::offset_t data_offset) override;
344314564Sdim
345314564Sdim  void SetOpcode(size_t opcode_size, void *opcode_data);
346314564Sdim
347314564Sdim  void SetDescription(llvm::StringRef description) override;
348314564Sdim
349254721Semasteprotected:
350314564Sdim  std::string m_description;
351314564Sdim
352314564Sdim  DISALLOW_COPY_AND_ASSIGN(PseudoInstruction);
353254721Semaste};
354254721Semaste
355314564Sdimclass Disassembler : public std::enable_shared_from_this<Disassembler>,
356314564Sdim                     public PluginInterface {
357254721Semastepublic:
358314564Sdim  enum {
359314564Sdim    eOptionNone = 0u,
360314564Sdim    eOptionShowBytes = (1u << 0),
361314564Sdim    eOptionRawOuput = (1u << 1),
362314564Sdim    eOptionMarkPCSourceLine = (1u << 2), // Mark the source line that contains
363314564Sdim                                         // the current PC (mixed mode only)
364314564Sdim    eOptionMarkPCAddress =
365314564Sdim        (1u << 3) // Mark the disassembly line the contains the PC
366314564Sdim  };
367254721Semaste
368314564Sdim  enum HexImmediateStyle {
369314564Sdim    eHexStyleC,
370314564Sdim    eHexStyleAsm,
371314564Sdim  };
372254721Semaste
373314564Sdim  // FindPlugin should be lax about the flavor string (it is too annoying to
374341825Sdim  // have various internal uses of the disassembler fail because the global
375341825Sdim  // flavor string gets set wrong. Instead, if you get a flavor string you
376314564Sdim  // don't understand, use the default.  Folks who care to check can use the
377341825Sdim  // FlavorValidForArchSpec method on the disassembler they got back.
378314564Sdim  static lldb::DisassemblerSP
379314564Sdim  FindPlugin(const ArchSpec &arch, const char *flavor, const char *plugin_name);
380254721Semaste
381314564Sdim  // This version will use the value in the Target settings if flavor is NULL;
382314564Sdim  static lldb::DisassemblerSP
383314564Sdim  FindPluginForTarget(const lldb::TargetSP target_sp, const ArchSpec &arch,
384314564Sdim                      const char *flavor, const char *plugin_name);
385254721Semaste
386314564Sdim  static lldb::DisassemblerSP
387314564Sdim  DisassembleRange(const ArchSpec &arch, const char *plugin_name,
388314564Sdim                   const char *flavor, const ExecutionContext &exe_ctx,
389314564Sdim                   const AddressRange &disasm_range, bool prefer_file_cache);
390254721Semaste
391314564Sdim  static lldb::DisassemblerSP
392314564Sdim  DisassembleBytes(const ArchSpec &arch, const char *plugin_name,
393314564Sdim                   const char *flavor, const Address &start, const void *bytes,
394314564Sdim                   size_t length, uint32_t max_num_instructions,
395314564Sdim                   bool data_from_file);
396254721Semaste
397314564Sdim  static bool Disassemble(Debugger &debugger, const ArchSpec &arch,
398314564Sdim                          const char *plugin_name, const char *flavor,
399314564Sdim                          const ExecutionContext &exe_ctx,
400314564Sdim                          const AddressRange &range, uint32_t num_instructions,
401314564Sdim                          bool mixed_source_and_assembly,
402314564Sdim                          uint32_t num_mixed_context_lines, uint32_t options,
403314564Sdim                          Stream &strm);
404254721Semaste
405314564Sdim  static bool Disassemble(Debugger &debugger, const ArchSpec &arch,
406314564Sdim                          const char *plugin_name, const char *flavor,
407314564Sdim                          const ExecutionContext &exe_ctx, const Address &start,
408314564Sdim                          uint32_t num_instructions,
409314564Sdim                          bool mixed_source_and_assembly,
410314564Sdim                          uint32_t num_mixed_context_lines, uint32_t options,
411314564Sdim                          Stream &strm);
412254721Semaste
413314564Sdim  static size_t
414314564Sdim  Disassemble(Debugger &debugger, const ArchSpec &arch, const char *plugin_name,
415314564Sdim              const char *flavor, const ExecutionContext &exe_ctx,
416314564Sdim              SymbolContextList &sc_list, uint32_t num_instructions,
417314564Sdim              bool mixed_source_and_assembly, uint32_t num_mixed_context_lines,
418314564Sdim              uint32_t options, Stream &strm);
419254721Semaste
420314564Sdim  static bool
421314564Sdim  Disassemble(Debugger &debugger, const ArchSpec &arch, const char *plugin_name,
422314564Sdim              const char *flavor, const ExecutionContext &exe_ctx,
423353358Sdim              ConstString name, Module *module,
424314564Sdim              uint32_t num_instructions, bool mixed_source_and_assembly,
425314564Sdim              uint32_t num_mixed_context_lines, uint32_t options, Stream &strm);
426254721Semaste
427314564Sdim  static bool
428314564Sdim  Disassemble(Debugger &debugger, const ArchSpec &arch, const char *plugin_name,
429314564Sdim              const char *flavor, const ExecutionContext &exe_ctx,
430314564Sdim              uint32_t num_instructions, bool mixed_source_and_assembly,
431314564Sdim              uint32_t num_mixed_context_lines, uint32_t options, Stream &strm);
432254721Semaste
433314564Sdim  // Constructors and Destructors
434314564Sdim  Disassembler(const ArchSpec &arch, const char *flavor);
435314564Sdim  ~Disassembler() override;
436254721Semaste
437314564Sdim  typedef const char *(*SummaryCallback)(const Instruction &inst,
438314564Sdim                                         ExecutionContext *exe_context,
439314564Sdim                                         void *user_data);
440254721Semaste
441314564Sdim  static bool PrintInstructions(Disassembler *disasm_ptr, Debugger &debugger,
442314564Sdim                                const ArchSpec &arch,
443314564Sdim                                const ExecutionContext &exe_ctx,
444314564Sdim                                uint32_t num_instructions,
445314564Sdim                                bool mixed_source_and_assembly,
446314564Sdim                                uint32_t num_mixed_context_lines,
447314564Sdim                                uint32_t options, Stream &strm);
448254721Semaste
449314564Sdim  size_t ParseInstructions(const ExecutionContext *exe_ctx,
450314564Sdim                           const AddressRange &range, Stream *error_strm_ptr,
451314564Sdim                           bool prefer_file_cache);
452314564Sdim
453314564Sdim  size_t ParseInstructions(const ExecutionContext *exe_ctx,
454314564Sdim                           const Address &range, uint32_t num_instructions,
455314564Sdim                           bool prefer_file_cache);
456314564Sdim
457314564Sdim  virtual size_t DecodeInstructions(const Address &base_addr,
458314564Sdim                                    const DataExtractor &data,
459314564Sdim                                    lldb::offset_t data_offset,
460314564Sdim                                    size_t num_instructions, bool append,
461314564Sdim                                    bool data_from_file) = 0;
462314564Sdim
463314564Sdim  InstructionList &GetInstructionList();
464314564Sdim
465314564Sdim  const InstructionList &GetInstructionList() const;
466314564Sdim
467314564Sdim  const ArchSpec &GetArchitecture() const { return m_arch; }
468314564Sdim
469314564Sdim  const char *GetFlavor() const { return m_flavor.c_str(); }
470314564Sdim
471314564Sdim  virtual bool FlavorValidForArchSpec(const lldb_private::ArchSpec &arch,
472314564Sdim                                      const char *flavor) = 0;
473314564Sdim
474314564Sdimprotected:
475341825Sdim  // SourceLine and SourceLinesToDisplay structures are only used in the mixed
476341825Sdim  // source and assembly display methods internal to this class.
477314564Sdim
478314564Sdim  struct SourceLine {
479314564Sdim    FileSpec file;
480314564Sdim    uint32_t line;
481314564Sdim    uint32_t column;
482314564Sdim
483314564Sdim    SourceLine() : file(), line(LLDB_INVALID_LINE_NUMBER), column(0) {}
484314564Sdim
485314564Sdim    bool operator==(const SourceLine &rhs) const {
486314564Sdim      return file == rhs.file && line == rhs.line && rhs.column == column;
487254721Semaste    }
488314564Sdim
489314564Sdim    bool operator!=(const SourceLine &rhs) const {
490314564Sdim      return file != rhs.file || line != rhs.line || column != rhs.column;
491254721Semaste    }
492254721Semaste
493314564Sdim    bool IsValid() const { return line != LLDB_INVALID_LINE_NUMBER; }
494314564Sdim  };
495254721Semaste
496314564Sdim  struct SourceLinesToDisplay {
497314564Sdim    std::vector<SourceLine> lines;
498314564Sdim
499341825Sdim    // index of the "current" source line, if we want to highlight that when
500341825Sdim    // displaying the source lines.  (as opposed to the surrounding source
501341825Sdim    // lines provided to give context)
502314564Sdim    size_t current_source_line;
503314564Sdim
504314564Sdim    // Whether to print a blank line at the end of the source lines.
505314564Sdim    bool print_source_context_end_eol;
506314564Sdim
507314564Sdim    SourceLinesToDisplay()
508314564Sdim        : lines(), current_source_line(-1), print_source_context_end_eol(true) {
509314564Sdim    }
510314564Sdim  };
511314564Sdim
512341825Sdim  // Get the function's declaration line number, hopefully a line number
513341825Sdim  // earlier than the opening curly brace at the start of the function body.
514314564Sdim  static SourceLine GetFunctionDeclLineEntry(const SymbolContext &sc);
515314564Sdim
516314564Sdim  // Add the provided SourceLine to the map of filenames-to-source-lines-seen.
517314564Sdim  static void AddLineToSourceLineTables(
518314564Sdim      SourceLine &line,
519314564Sdim      std::map<FileSpec, std::set<uint32_t>> &source_lines_seen);
520314564Sdim
521314564Sdim  // Given a source line, determine if we should print it when we're doing
522341825Sdim  // mixed source & assembly output. We're currently using the
523341825Sdim  // target.process.thread.step-avoid-regexp setting (which is used for
524341825Sdim  // stepping over inlined STL functions by default) to determine what source
525341825Sdim  // lines to avoid showing.
526314564Sdim  //
527314564Sdim  // Returns true if this source line should be elided (if the source line
528341825Sdim  // should not be displayed).
529314564Sdim  static bool
530314564Sdim  ElideMixedSourceAndDisassemblyLine(const ExecutionContext &exe_ctx,
531314564Sdim                                     const SymbolContext &sc, SourceLine &line);
532314564Sdim
533314564Sdim  static bool
534314564Sdim  ElideMixedSourceAndDisassemblyLine(const ExecutionContext &exe_ctx,
535314564Sdim                                     const SymbolContext &sc, LineEntry &line) {
536314564Sdim    SourceLine sl;
537314564Sdim    sl.file = line.file;
538314564Sdim    sl.line = line.line;
539314564Sdim    sl.column = line.column;
540314564Sdim    return ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, sl);
541314564Sdim  };
542314564Sdim
543314564Sdim  // Classes that inherit from Disassembler can see and modify these
544314564Sdim  ArchSpec m_arch;
545314564Sdim  InstructionList m_instruction_list;
546314564Sdim  lldb::addr_t m_base_addr;
547314564Sdim  std::string m_flavor;
548314564Sdim
549254721Semasteprivate:
550314564Sdim  // For Disassembler only
551314564Sdim  DISALLOW_COPY_AND_ASSIGN(Disassembler);
552254721Semaste};
553254721Semaste
554254721Semaste} // namespace lldb_private
555254721Semaste
556296417Sdim#endif // liblldb_Disassembler_h_
557