Coverage Report

Created: 2022-01-25 06:29

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/include/lldb/Core/Disassembler.h
Line
Count
Source (jump to first uncovered line)
1
//===-- Disassembler.h ------------------------------------------*- C++ -*-===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#ifndef LLDB_CORE_DISASSEMBLER_H
10
#define LLDB_CORE_DISASSEMBLER_H
11
12
#include "lldb/Core/Address.h"
13
#include "lldb/Core/EmulateInstruction.h"
14
#include "lldb/Core/FormatEntity.h"
15
#include "lldb/Core/Opcode.h"
16
#include "lldb/Core/PluginInterface.h"
17
#include "lldb/Interpreter/OptionValue.h"
18
#include "lldb/Symbol/LineEntry.h"
19
#include "lldb/Target/ExecutionContext.h"
20
#include "lldb/Utility/ArchSpec.h"
21
#include "lldb/Utility/ConstString.h"
22
#include "lldb/Utility/FileSpec.h"
23
#include "lldb/lldb-defines.h"
24
#include "lldb/lldb-forward.h"
25
#include "lldb/lldb-private-enumerations.h"
26
#include "lldb/lldb-types.h"
27
28
#include "llvm/ADT/StringRef.h"
29
30
#include <functional>
31
#include <map>
32
#include <memory>
33
#include <set>
34
#include <string>
35
#include <vector>
36
37
#include <cstddef>
38
#include <cstdint>
39
#include <cstdio>
40
41
namespace llvm {
42
template <typename T> class SmallVectorImpl;
43
}
44
45
namespace lldb_private {
46
class AddressRange;
47
class DataExtractor;
48
class Debugger;
49
class Disassembler;
50
class Module;
51
class StackFrame;
52
class Stream;
53
class SymbolContext;
54
class SymbolContextList;
55
class Target;
56
struct RegisterInfo;
57
58
class Instruction {
59
public:
60
  Instruction(const Address &address,
61
              AddressClass addr_class = AddressClass::eInvalid);
62
63
  virtual ~Instruction();
64
65
2.20M
  const Address &GetAddress() const { return m_address; }
66
67
35
  const char *GetMnemonic(const ExecutionContext *exe_ctx) {
68
35
    CalculateMnemonicOperandsAndCommentIfNeeded(exe_ctx);
69
35
    return m_opcode_name.c_str();
70
35
  }
71
72
291
  const char *GetOperands(const ExecutionContext *exe_ctx) {
73
291
    CalculateMnemonicOperandsAndCommentIfNeeded(exe_ctx);
74
291
    return m_mnemonics.c_str();
75
291
  }
76
77
94
  const char *GetComment(const ExecutionContext *exe_ctx) {
78
94
    CalculateMnemonicOperandsAndCommentIfNeeded(exe_ctx);
79
94
    return m_comment.c_str();
80
94
  }
81
82
  virtual void
83
  CalculateMnemonicOperandsAndComment(const ExecutionContext *exe_ctx) = 0;
84
85
  AddressClass GetAddressClass();
86
87
0
  void SetAddress(const Address &addr) {
88
0
    // Invalidate the address class to lazily discover it if we need to.
89
0
    m_address_class = AddressClass::eInvalid;
90
0
    m_address = addr;
91
0
  }
92
93
  /// Dump the text representation of this Instruction to a Stream
94
  ///
95
  /// Print the (optional) address, (optional) bytes, opcode,
96
  /// operands, and instruction comments to a stream.
97
  ///
98
  /// \param[in] s
99
  ///     The Stream to add the text to.
100
  ///
101
  /// \param[in] show_address
102
  ///     Whether the address (using disassembly_addr_format_spec formatting)
103
  ///     should be printed.
104
  ///
105
  /// \param[in] show_bytes
106
  ///     Whether the bytes of the assembly instruction should be printed.
107
  ///
108
  /// \param[in] max_opcode_byte_size
109
  ///     The size (in bytes) of the largest instruction in the list that
110
  ///     we are printing (for text justification/alignment purposes)
111
  ///     Only needed if show_bytes is true.
112
  ///
113
  /// \param[in] exe_ctx
114
  ///     The current execution context, if available.  May be used in
115
  ///     the assembling of the operands+comments for this instruction.
116
  ///     Pass NULL if not applicable.
117
  ///
118
  /// \param[in] sym_ctx
119
  ///     The SymbolContext for this instruction.
120
  ///     Pass NULL if not available/computed.
121
  ///     Only needed if show_address is true.
122
  ///
123
  /// \param[in] prev_sym_ctx
124
  ///     The SymbolContext for the previous instruction.  Depending on
125
  ///     the disassembly address format specification, a change in
126
  ///     Symbol / Function may mean that a line is printed with the new
127
  ///     symbol/function name.
128
  ///     Pass NULL if unavailable, or if this is the first instruction of
129
  ///     the InstructionList.
130
  ///     Only needed if show_address is true.
131
  ///
132
  /// \param[in] disassembly_addr_format
133
  ///     The format specification for how addresses are printed.
134
  ///     Only needed if show_address is true.
135
  ///
136
  /// \param[in] max_address_text_size
137
  ///     The length of the longest address string at the start of the
138
  ///     disassembly line that will be printed (the
139
  ///     Debugger::FormatDisassemblerAddress() string)
140
  ///     so this method can properly align the instruction opcodes.
141
  ///     May be 0 to indicate no indentation/alignment of the opcodes.
142
  virtual void Dump(Stream *s, uint32_t max_opcode_byte_size, bool show_address,
143
                    bool show_bytes, const ExecutionContext *exe_ctx,
144
                    const SymbolContext *sym_ctx,
145
                    const SymbolContext *prev_sym_ctx,
146
                    const FormatEntity::Entry *disassembly_addr_format,
147
                    size_t max_address_text_size);
148
149
  virtual bool DoesBranch() = 0;
150
151
  virtual bool HasDelaySlot();
152
153
  virtual bool IsLoad() = 0;
154
155
  virtual bool IsAuthenticated() = 0;
156
157
  bool CanSetBreakpoint ();
158
159
  virtual size_t Decode(const Disassembler &disassembler,
160
                        const DataExtractor &data,
161
                        lldb::offset_t data_offset) = 0;
162
163
0
  virtual void SetDescription(llvm::StringRef) {
164
0
  } // May be overridden in sub-classes that have descriptions.
165
166
  lldb::OptionValueSP ReadArray(FILE *in_file, Stream *out_stream,
167
                                OptionValue::Type data_type);
168
169
  lldb::OptionValueSP ReadDictionary(FILE *in_file, Stream *out_stream);
170
171
  bool DumpEmulation(const ArchSpec &arch);
172
173
  virtual bool TestEmulation(Stream *stream, const char *test_file_name);
174
175
  bool Emulate(const ArchSpec &arch, uint32_t evaluate_options, void *baton,
176
               EmulateInstruction::ReadMemoryCallback read_mem_callback,
177
               EmulateInstruction::WriteMemoryCallback write_mem_calback,
178
               EmulateInstruction::ReadRegisterCallback read_reg_callback,
179
               EmulateInstruction::WriteRegisterCallback write_reg_callback);
180
181
978k
  const Opcode &GetOpcode() const { return m_opcode; }
182
183
  uint32_t GetData(DataExtractor &data);
184
185
  struct Operand {
186
    enum class Type {
187
      Invalid = 0,
188
      Register,
189
      Immediate,
190
      Dereference,
191
      Sum,
192
      Product
193
    } m_type = Type::Invalid;
194
    std::vector<Operand> m_children;
195
    lldb::addr_t m_immediate = 0;
196
    ConstString m_register;
197
    bool m_negative = false;
198
    bool m_clobbered = false;
199
200
3.66k
    bool IsValid() { return m_type != Type::Invalid; }
201
202
    static Operand BuildRegister(ConstString &r);
203
    static Operand BuildImmediate(lldb::addr_t imm, bool neg);
204
    static Operand BuildImmediate(int64_t imm);
205
    static Operand BuildDereference(const Operand &ref);
206
    static Operand BuildSum(const Operand &lhs, const Operand &rhs);
207
    static Operand BuildProduct(const Operand &lhs, const Operand &rhs);
208
  };
209
210
0
  virtual bool ParseOperands(llvm::SmallVectorImpl<Operand> &operands) {
211
0
    return false;
212
0
  }
213
214
0
  virtual bool IsCall() { return false; }
215
216
protected:
217
  Address m_address; // The section offset address of this instruction
218
                     // We include an address class in the Instruction class to
219
                     // allow the instruction specify the
220
                     // AddressClass::eCodeAlternateISA (currently used for
221
                     // thumb), and also to specify data (AddressClass::eData).
222
                     // The usual value will be AddressClass::eCode, but often
223
                     // when disassembling memory, you might run into data.
224
                     // This can help us to disassemble appropriately.
225
private:
226
  AddressClass m_address_class; // Use GetAddressClass () accessor function!
227
228
protected:
229
  Opcode m_opcode; // The opcode for this instruction
230
  std::string m_opcode_name;
231
  std::string m_mnemonics;
232
  std::string m_comment;
233
  bool m_calculated_strings;
234
235
  void
236
978k
  CalculateMnemonicOperandsAndCommentIfNeeded(const ExecutionContext *exe_ctx) {
237
978k
    if (!m_calculated_strings) {
238
978k
      m_calculated_strings = true;
239
978k
      CalculateMnemonicOperandsAndComment(exe_ctx);
240
978k
    }
241
978k
  }
242
};
243
244
namespace OperandMatchers {
245
std::function<bool(const Instruction::Operand &)>
246
MatchBinaryOp(std::function<bool(const Instruction::Operand &)> base,
247
              std::function<bool(const Instruction::Operand &)> left,
248
              std::function<bool(const Instruction::Operand &)> right);
249
250
std::function<bool(const Instruction::Operand &)>
251
MatchUnaryOp(std::function<bool(const Instruction::Operand &)> base,
252
             std::function<bool(const Instruction::Operand &)> child);
253
254
std::function<bool(const Instruction::Operand &)>
255
MatchRegOp(const RegisterInfo &info);
256
257
std::function<bool(const Instruction::Operand &)> FetchRegOp(ConstString &reg);
258
259
std::function<bool(const Instruction::Operand &)> MatchImmOp(int64_t imm);
260
261
std::function<bool(const Instruction::Operand &)> FetchImmOp(int64_t &imm);
262
263
std::function<bool(const Instruction::Operand &)>
264
MatchOpType(Instruction::Operand::Type type);
265
}
266
267
class InstructionList {
268
public:
269
  InstructionList();
270
  ~InstructionList();
271
272
  size_t GetSize() const;
273
274
  uint32_t GetMaxOpcocdeByteSize() const;
275
276
  lldb::InstructionSP GetInstructionAtIndex(size_t idx) const;
277
278
  /// Get the instruction at the given address.
279
  ///
280
  /// \return
281
  ///    A valid \a InstructionSP if the address could be found, or null
282
  ///    otherwise.
283
  lldb::InstructionSP GetInstructionAtAddress(const Address &addr);
284
285
  //------------------------------------------------------------------
286
  /// Get the index of the next branch instruction.
287
  ///
288
  /// Given a list of instructions, find the next branch instruction
289
  /// in the list by returning an index.
290
  ///
291
  /// @param[in] start
292
  ///     The instruction index of the first instruction to check.
293
  ///
294
  /// @param[in] ignore_calls
295
  ///     It true, then fine the first branch instruction that isn't
296
  ///     a function call (a branch that calls and returns to the next
297
  ///     instruction). If false, find the instruction index of any 
298
  ///     branch in the list.
299
  ///     
300
  /// @param[out] found_calls
301
  ///     If non-null, this will be set to true if any calls were found in 
302
  ///     extending the range.
303
  ///    
304
  /// @return
305
  ///     The instruction index of the first branch that is at or past
306
  ///     \a start. Returns UINT32_MAX if no matching branches are 
307
  ///     found.
308
  //------------------------------------------------------------------
309
  uint32_t GetIndexOfNextBranchInstruction(uint32_t start,
310
                                           bool ignore_calls,
311
                                           bool *found_calls) const;
312
313
  uint32_t GetIndexOfInstructionAtLoadAddress(lldb::addr_t load_addr,
314
                                              Target &target);
315
316
  uint32_t GetIndexOfInstructionAtAddress(const Address &addr);
317
318
  void Clear();
319
320
  void Append(lldb::InstructionSP &inst_sp);
321
322
  void Dump(Stream *s, bool show_address, bool show_bytes,
323
            const ExecutionContext *exe_ctx);
324
325
private:
326
  typedef std::vector<lldb::InstructionSP> collection;
327
  typedef collection::iterator iterator;
328
  typedef collection::const_iterator const_iterator;
329
330
  collection m_instructions;
331
};
332
333
class PseudoInstruction : public Instruction {
334
public:
335
  PseudoInstruction();
336
337
  ~PseudoInstruction() override;
338
339
  bool DoesBranch() override;
340
341
  bool HasDelaySlot() override;
342
343
  bool IsLoad() override;
344
345
  bool IsAuthenticated() override;
346
347
  void CalculateMnemonicOperandsAndComment(
348
0
      const ExecutionContext *exe_ctx) override {
349
    // TODO: fill this in and put opcode name into Instruction::m_opcode_name,
350
    // mnemonic into Instruction::m_mnemonics, and any comment into
351
    // Instruction::m_comment
352
0
  }
353
354
  size_t Decode(const Disassembler &disassembler, const DataExtractor &data,
355
                lldb::offset_t data_offset) override;
356
357
  void SetOpcode(size_t opcode_size, void *opcode_data);
358
359
  void SetDescription(llvm::StringRef description) override;
360
361
protected:
362
  std::string m_description;
363
364
  PseudoInstruction(const PseudoInstruction &) = delete;
365
  const PseudoInstruction &operator=(const PseudoInstruction &) = delete;
366
};
367
368
class Disassembler : public std::enable_shared_from_this<Disassembler>,
369
                     public PluginInterface {
370
public:
371
  enum {
372
    eOptionNone = 0u,
373
    eOptionShowBytes = (1u << 0),
374
    eOptionRawOuput = (1u << 1),
375
    eOptionMarkPCSourceLine = (1u << 2), // Mark the source line that contains
376
                                         // the current PC (mixed mode only)
377
    eOptionMarkPCAddress =
378
        (1u << 3) // Mark the disassembly line the contains the PC
379
  };
380
381
  enum HexImmediateStyle {
382
    eHexStyleC,
383
    eHexStyleAsm,
384
  };
385
386
  // FindPlugin should be lax about the flavor string (it is too annoying to
387
  // have various internal uses of the disassembler fail because the global
388
  // flavor string gets set wrong. Instead, if you get a flavor string you
389
  // don't understand, use the default.  Folks who care to check can use the
390
  // FlavorValidForArchSpec method on the disassembler they got back.
391
  static lldb::DisassemblerSP
392
  FindPlugin(const ArchSpec &arch, const char *flavor, const char *plugin_name);
393
394
  // This version will use the value in the Target settings if flavor is NULL;
395
  static lldb::DisassemblerSP FindPluginForTarget(const Target &target,
396
                                                  const ArchSpec &arch,
397
                                                  const char *flavor,
398
                                                  const char *plugin_name);
399
400
  struct Limit {
401
    enum { Bytes, Instructions } kind;
402
    lldb::addr_t value;
403
  };
404
405
  static lldb::DisassemblerSP DisassembleRange(const ArchSpec &arch,
406
                                               const char *plugin_name,
407
                                               const char *flavor,
408
                                               Target &target,
409
                                               const AddressRange &disasm_range,
410
                                               bool force_live_memory = false);
411
412
  static lldb::DisassemblerSP
413
  DisassembleBytes(const ArchSpec &arch, const char *plugin_name,
414
                   const char *flavor, const Address &start, const void *bytes,
415
                   size_t length, uint32_t max_num_instructions,
416
                   bool data_from_file);
417
418
  static bool Disassemble(Debugger &debugger, const ArchSpec &arch,
419
                          const char *plugin_name, const char *flavor,
420
                          const ExecutionContext &exe_ctx, const Address &start,
421
                          Limit limit, bool mixed_source_and_assembly,
422
                          uint32_t num_mixed_context_lines, uint32_t options,
423
                          Stream &strm);
424
425
  static bool Disassemble(Debugger &debugger, const ArchSpec &arch,
426
                          StackFrame &frame, Stream &strm);
427
428
  // Constructors and Destructors
429
  Disassembler(const ArchSpec &arch, const char *flavor);
430
  ~Disassembler() override;
431
432
  void PrintInstructions(Debugger &debugger, const ArchSpec &arch,
433
                         const ExecutionContext &exe_ctx,
434
                         bool mixed_source_and_assembly,
435
                         uint32_t num_mixed_context_lines, uint32_t options,
436
                         Stream &strm);
437
438
  size_t ParseInstructions(Target &target, Address address, Limit limit,
439
                           Stream *error_strm_ptr,
440
                           bool force_live_memory = false);
441
442
  virtual size_t DecodeInstructions(const Address &base_addr,
443
                                    const DataExtractor &data,
444
                                    lldb::offset_t data_offset,
445
                                    size_t num_instructions, bool append,
446
                                    bool data_from_file) = 0;
447
448
  InstructionList &GetInstructionList();
449
450
  const InstructionList &GetInstructionList() const;
451
452
984k
  const ArchSpec &GetArchitecture() const { return m_arch; }
453
454
0
  const char *GetFlavor() const { return m_flavor.c_str(); }
455
456
  virtual bool FlavorValidForArchSpec(const lldb_private::ArchSpec &arch,
457
                                      const char *flavor) = 0;
458
459
protected:
460
  // SourceLine and SourceLinesToDisplay structures are only used in the mixed
461
  // source and assembly display methods internal to this class.
462
463
  struct SourceLine {
464
    FileSpec file;
465
    uint32_t line = LLDB_INVALID_LINE_NUMBER;
466
    uint32_t column = 0;
467
468
28.3k
    SourceLine() {}
469
470
0
    bool operator==(const SourceLine &rhs) const {
471
0
      return file == rhs.file && line == rhs.line && rhs.column == column;
472
0
    }
473
474
0
    bool operator!=(const SourceLine &rhs) const {
475
0
      return file != rhs.file || line != rhs.line || column != rhs.column;
476
0
    }
477
478
0
    bool IsValid() const { return line != LLDB_INVALID_LINE_NUMBER; }
479
  };
480
481
  struct SourceLinesToDisplay {
482
    std::vector<SourceLine> lines;
483
484
    // index of the "current" source line, if we want to highlight that when
485
    // displaying the source lines.  (as opposed to the surrounding source
486
    // lines provided to give context)
487
    size_t current_source_line = -1;
488
489
    // Whether to print a blank line at the end of the source lines.
490
    bool print_source_context_end_eol = true;
491
492
968k
    SourceLinesToDisplay() {}
493
  };
494
495
  // Get the function's declaration line number, hopefully a line number
496
  // earlier than the opening curly brace at the start of the function body.
497
  static SourceLine GetFunctionDeclLineEntry(const SymbolContext &sc);
498
499
  // Add the provided SourceLine to the map of filenames-to-source-lines-seen.
500
  static void AddLineToSourceLineTables(
501
      SourceLine &line,
502
      std::map<FileSpec, std::set<uint32_t>> &source_lines_seen);
503
504
  // Given a source line, determine if we should print it when we're doing
505
  // mixed source & assembly output. We're currently using the
506
  // target.process.thread.step-avoid-regexp setting (which is used for
507
  // stepping over inlined STL functions by default) to determine what source
508
  // lines to avoid showing.
509
  //
510
  // Returns true if this source line should be elided (if the source line
511
  // should not be displayed).
512
  static bool
513
  ElideMixedSourceAndDisassemblyLine(const ExecutionContext &exe_ctx,
514
                                     const SymbolContext &sc, SourceLine &line);
515
516
  static bool
517
  ElideMixedSourceAndDisassemblyLine(const ExecutionContext &exe_ctx,
518
0
                                     const SymbolContext &sc, LineEntry &line) {
519
0
    SourceLine sl;
520
0
    sl.file = line.file;
521
0
    sl.line = line.line;
522
0
    sl.column = line.column;
523
0
    return ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, sl);
524
0
  };
525
526
  // Classes that inherit from Disassembler can see and modify these
527
  ArchSpec m_arch;
528
  InstructionList m_instruction_list;
529
  lldb::addr_t m_base_addr;
530
  std::string m_flavor;
531
532
private:
533
  // For Disassembler only
534
  Disassembler(const Disassembler &) = delete;
535
  const Disassembler &operator=(const Disassembler &) = delete;
536
};
537
538
} // namespace lldb_private
539
540
#endif // LLDB_CORE_DISASSEMBLER_H