Disassembler.cpp revision 360784
1166886Srrs//===-- Disassembler.cpp ----------------------------------------*- C++ -*-===//
2166886Srrs//
3166886Srrs// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4166886Srrs// See https://llvm.org/LICENSE.txt for license information.
5166886Srrs// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6166886Srrs//
7166886Srrs//===----------------------------------------------------------------------===//
8166886Srrs
9166886Srrs#include "lldb/Core/Disassembler.h"
10166886Srrs
11166886Srrs#include "lldb/Core/AddressRange.h"
12251067Semaste#include "lldb/Core/Debugger.h"
13166886Srrs#include "lldb/Core/EmulateInstruction.h"
14166886Srrs#include "lldb/Core/Mangled.h"
15166886Srrs#include "lldb/Core/Module.h"
16166886Srrs#include "lldb/Core/ModuleList.h"
17166886Srrs#include "lldb/Core/PluginManager.h"
18166886Srrs#include "lldb/Core/SourceManager.h"
19166886Srrs#include "lldb/Host/FileSystem.h"
20166886Srrs#include "lldb/Interpreter/OptionValue.h"
21166886Srrs#include "lldb/Interpreter/OptionValueArray.h"
22166886Srrs#include "lldb/Interpreter/OptionValueDictionary.h"
23166886Srrs#include "lldb/Interpreter/OptionValueRegex.h"
24166886Srrs#include "lldb/Interpreter/OptionValueString.h"
25166886Srrs#include "lldb/Interpreter/OptionValueUInt64.h"
26166886Srrs#include "lldb/Symbol/Function.h"
27166886Srrs#include "lldb/Symbol/Symbol.h"
28166886Srrs#include "lldb/Symbol/SymbolContext.h"
29166886Srrs#include "lldb/Target/ExecutionContext.h"
30166886Srrs#include "lldb/Target/SectionLoadList.h"
31166886Srrs#include "lldb/Target/StackFrame.h"
32166886Srrs#include "lldb/Target/Target.h"
33166886Srrs#include "lldb/Target/Thread.h"
34166886Srrs#include "lldb/Utility/DataBufferHeap.h"
35166886Srrs#include "lldb/Utility/DataExtractor.h"
36166886Srrs#include "lldb/Utility/RegularExpression.h"
37166886Srrs#include "lldb/Utility/Status.h"
38166886Srrs#include "lldb/Utility/Stream.h"
39166886Srrs#include "lldb/Utility/StreamString.h"
40166886Srrs#include "lldb/Utility/Timer.h"
41167017Srrs#include "lldb/lldb-private-enumerations.h"
42166886Srrs#include "lldb/lldb-private-interfaces.h"
43166886Srrs#include "lldb/lldb-private-types.h"
44166886Srrs#include "llvm/ADT/Triple.h"
45166886Srrs#include "llvm/Support/Compiler.h"
46166886Srrs
47170919Sbrueffer#include <cstdint>
48166886Srrs#include <cstring>
49233648Seadler#include <utility>
50166886Srrs
51170919Sbrueffer#include <assert.h>
52166886Srrs
53166886Srrs#define DEFAULT_DISASM_BYTE_SIZE 32
54166886Srrs
55166886Srrsusing namespace lldb;
56202176Sbruefferusing namespace lldb_private;
57166886Srrs
58166886SrrsDisassemblerSP Disassembler::FindPlugin(const ArchSpec &arch,
59166886Srrs                                        const char *flavor,
60166886Srrs                                        const char *plugin_name) {
61166886Srrs  static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
62166886Srrs  Timer scoped_timer(func_cat,
63166886Srrs                     "Disassembler::FindPlugin (arch = %s, plugin_name = %s)",
64166886Srrs                     arch.GetArchitectureName(), plugin_name);
65166886Srrs
66166886Srrs  DisassemblerCreateInstance create_callback = nullptr;
67166886Srrs
68166886Srrs  if (plugin_name) {
69166886Srrs    ConstString const_plugin_name(plugin_name);
70170919Sbrueffer    create_callback = PluginManager::GetDisassemblerCreateCallbackForPluginName(
71        const_plugin_name);
72    if (create_callback) {
73      DisassemblerSP disassembler_sp(create_callback(arch, flavor));
74
75      if (disassembler_sp)
76        return disassembler_sp;
77    }
78  } else {
79    for (uint32_t idx = 0;
80         (create_callback = PluginManager::GetDisassemblerCreateCallbackAtIndex(
81              idx)) != nullptr;
82         ++idx) {
83      DisassemblerSP disassembler_sp(create_callback(arch, flavor));
84
85      if (disassembler_sp)
86        return disassembler_sp;
87    }
88  }
89  return DisassemblerSP();
90}
91
92DisassemblerSP Disassembler::FindPluginForTarget(const TargetSP target_sp,
93                                                 const ArchSpec &arch,
94                                                 const char *flavor,
95                                                 const char *plugin_name) {
96  if (target_sp && flavor == nullptr) {
97    // FIXME - we don't have the mechanism in place to do per-architecture
98    // settings.  But since we know that for now we only support flavors on x86
99    // & x86_64,
100    if (arch.GetTriple().getArch() == llvm::Triple::x86 ||
101        arch.GetTriple().getArch() == llvm::Triple::x86_64)
102      flavor = target_sp->GetDisassemblyFlavor();
103  }
104  return FindPlugin(arch, flavor, plugin_name);
105}
106
107static void ResolveAddress(const ExecutionContext &exe_ctx, const Address &addr,
108                           Address &resolved_addr) {
109  if (!addr.IsSectionOffset()) {
110    // If we weren't passed in a section offset address range, try and resolve
111    // it to something
112    Target *target = exe_ctx.GetTargetPtr();
113    if (target) {
114      bool is_resolved =
115          target->GetSectionLoadList().IsEmpty() ?
116              target->GetImages().ResolveFileAddress(addr.GetOffset(),
117                                                     resolved_addr) :
118              target->GetSectionLoadList().ResolveLoadAddress(addr.GetOffset(),
119                                                              resolved_addr);
120
121      // We weren't able to resolve the address, just treat it as a raw address
122      if (is_resolved && resolved_addr.IsValid())
123        return;
124    }
125  }
126  resolved_addr = addr;
127}
128
129size_t Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch,
130                                 const char *plugin_name, const char *flavor,
131                                 const ExecutionContext &exe_ctx,
132                                 SymbolContextList &sc_list,
133                                 uint32_t num_instructions,
134                                 bool mixed_source_and_assembly,
135                                 uint32_t num_mixed_context_lines,
136                                 uint32_t options, Stream &strm) {
137  size_t success_count = 0;
138  const size_t count = sc_list.GetSize();
139  SymbolContext sc;
140  AddressRange range;
141  const uint32_t scope =
142      eSymbolContextBlock | eSymbolContextFunction | eSymbolContextSymbol;
143  const bool use_inline_block_range = true;
144  for (size_t i = 0; i < count; ++i) {
145    if (!sc_list.GetContextAtIndex(i, sc))
146      break;
147    for (uint32_t range_idx = 0;
148         sc.GetAddressRange(scope, range_idx, use_inline_block_range, range);
149         ++range_idx) {
150      if (Disassemble(debugger, arch, plugin_name, flavor, exe_ctx, range,
151                      num_instructions, mixed_source_and_assembly,
152                      num_mixed_context_lines, options, strm)) {
153        ++success_count;
154        strm.EOL();
155      }
156    }
157  }
158  return success_count;
159}
160
161bool Disassembler::Disassemble(
162    Debugger &debugger, const ArchSpec &arch, const char *plugin_name,
163    const char *flavor, const ExecutionContext &exe_ctx, ConstString name,
164    Module *module, uint32_t num_instructions, bool mixed_source_and_assembly,
165    uint32_t num_mixed_context_lines, uint32_t options, Stream &strm) {
166  // If no name is given there's nothing to disassemble.
167  if (!name)
168    return false;
169
170  const bool include_symbols = true;
171  const bool include_inlines = true;
172
173  // Find functions matching the given name.
174  SymbolContextList sc_list;
175  if (module) {
176    module->FindFunctions(name, nullptr, eFunctionNameTypeAuto, include_symbols,
177                          include_inlines, sc_list);
178  } else if (exe_ctx.GetTargetPtr()) {
179    exe_ctx.GetTargetPtr()->GetImages().FindFunctions(
180        name, eFunctionNameTypeAuto, include_symbols, include_inlines, sc_list);
181  }
182
183  // If no functions were found there's nothing to disassemble.
184  if (sc_list.IsEmpty())
185    return false;
186
187  return Disassemble(debugger, arch, plugin_name, flavor, exe_ctx, sc_list,
188                     num_instructions, mixed_source_and_assembly,
189                     num_mixed_context_lines, options, strm);
190}
191
192lldb::DisassemblerSP Disassembler::DisassembleRange(
193    const ArchSpec &arch, const char *plugin_name, const char *flavor,
194    const ExecutionContext &exe_ctx, const AddressRange &range,
195    bool prefer_file_cache) {
196  if (range.GetByteSize() <= 0)
197    return {};
198
199  if (!range.GetBaseAddress().IsValid())
200    return {};
201
202  lldb::DisassemblerSP disasm_sp = Disassembler::FindPluginForTarget(
203      exe_ctx.GetTargetSP(), arch, flavor, plugin_name);
204
205  if (!disasm_sp)
206    return {};
207
208  const size_t bytes_disassembled =
209      disasm_sp->ParseInstructions(&exe_ctx, range, nullptr, prefer_file_cache);
210  if (bytes_disassembled == 0)
211    return {};
212
213  return disasm_sp;
214}
215
216lldb::DisassemblerSP
217Disassembler::DisassembleBytes(const ArchSpec &arch, const char *plugin_name,
218                               const char *flavor, const Address &start,
219                               const void *src, size_t src_len,
220                               uint32_t num_instructions, bool data_from_file) {
221  if (!src)
222    return {};
223
224  lldb::DisassemblerSP disasm_sp =
225      Disassembler::FindPlugin(arch, flavor, plugin_name);
226
227  if (!disasm_sp)
228    return {};
229
230  DataExtractor data(src, src_len, arch.GetByteOrder(),
231                     arch.GetAddressByteSize());
232
233  (void)disasm_sp->DecodeInstructions(start, data, 0, num_instructions, false,
234                                      data_from_file);
235  return disasm_sp;
236}
237
238bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch,
239                               const char *plugin_name, const char *flavor,
240                               const ExecutionContext &exe_ctx,
241                               const AddressRange &disasm_range,
242                               uint32_t num_instructions,
243                               bool mixed_source_and_assembly,
244                               uint32_t num_mixed_context_lines,
245                               uint32_t options, Stream &strm) {
246  if (!disasm_range.GetByteSize())
247    return false;
248
249  lldb::DisassemblerSP disasm_sp(Disassembler::FindPluginForTarget(
250      exe_ctx.GetTargetSP(), arch, flavor, plugin_name));
251
252  if (!disasm_sp)
253    return false;
254
255  AddressRange range;
256  ResolveAddress(exe_ctx, disasm_range.GetBaseAddress(),
257                 range.GetBaseAddress());
258  range.SetByteSize(disasm_range.GetByteSize());
259  const bool prefer_file_cache = false;
260  size_t bytes_disassembled =
261      disasm_sp->ParseInstructions(&exe_ctx, range, &strm, prefer_file_cache);
262  if (bytes_disassembled == 0)
263    return false;
264
265  return PrintInstructions(disasm_sp.get(), debugger, arch, exe_ctx,
266                           num_instructions, mixed_source_and_assembly,
267                           num_mixed_context_lines, options, strm);
268}
269
270bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch,
271                               const char *plugin_name, const char *flavor,
272                               const ExecutionContext &exe_ctx,
273                               const Address &start_address,
274                               uint32_t num_instructions,
275                               bool mixed_source_and_assembly,
276                               uint32_t num_mixed_context_lines,
277                               uint32_t options, Stream &strm) {
278  if (num_instructions == 0)
279    return false;
280
281  lldb::DisassemblerSP disasm_sp(Disassembler::FindPluginForTarget(
282      exe_ctx.GetTargetSP(), arch, flavor, plugin_name));
283  if (!disasm_sp)
284    return false;
285
286  Address addr;
287  ResolveAddress(exe_ctx, start_address, addr);
288
289  const bool prefer_file_cache = false;
290  size_t bytes_disassembled = disasm_sp->ParseInstructions(
291      &exe_ctx, addr, num_instructions, prefer_file_cache);
292  if (bytes_disassembled == 0)
293    return false;
294
295  return PrintInstructions(disasm_sp.get(), debugger, arch, exe_ctx,
296                           num_instructions, mixed_source_and_assembly,
297                           num_mixed_context_lines, options, strm);
298}
299
300Disassembler::SourceLine
301Disassembler::GetFunctionDeclLineEntry(const SymbolContext &sc) {
302  if (!sc.function)
303    return {};
304
305  if (!sc.line_entry.IsValid())
306    return {};
307
308  LineEntry prologue_end_line = sc.line_entry;
309  FileSpec func_decl_file;
310  uint32_t func_decl_line;
311  sc.function->GetStartLineSourceInfo(func_decl_file, func_decl_line);
312
313  if (func_decl_file != prologue_end_line.file &&
314      func_decl_file != prologue_end_line.original_file)
315    return {};
316
317  SourceLine decl_line;
318  decl_line.file = func_decl_file;
319  decl_line.line = func_decl_line;
320  // TODO: Do we care about column on these entries?  If so, we need to plumb
321  // that through GetStartLineSourceInfo.
322  decl_line.column = 0;
323  return decl_line;
324}
325
326void Disassembler::AddLineToSourceLineTables(
327    SourceLine &line,
328    std::map<FileSpec, std::set<uint32_t>> &source_lines_seen) {
329  if (line.IsValid()) {
330    auto source_lines_seen_pos = source_lines_seen.find(line.file);
331    if (source_lines_seen_pos == source_lines_seen.end()) {
332      std::set<uint32_t> lines;
333      lines.insert(line.line);
334      source_lines_seen.emplace(line.file, lines);
335    } else {
336      source_lines_seen_pos->second.insert(line.line);
337    }
338  }
339}
340
341bool Disassembler::ElideMixedSourceAndDisassemblyLine(
342    const ExecutionContext &exe_ctx, const SymbolContext &sc,
343    SourceLine &line) {
344
345  // TODO: should we also check target.process.thread.step-avoid-libraries ?
346
347  const RegularExpression *avoid_regex = nullptr;
348
349  // Skip any line #0 entries - they are implementation details
350  if (line.line == 0)
351    return false;
352
353  ThreadSP thread_sp = exe_ctx.GetThreadSP();
354  if (thread_sp) {
355    avoid_regex = thread_sp->GetSymbolsToAvoidRegexp();
356  } else {
357    TargetSP target_sp = exe_ctx.GetTargetSP();
358    if (target_sp) {
359      Status error;
360      OptionValueSP value_sp = target_sp->GetDebugger().GetPropertyValue(
361          &exe_ctx, "target.process.thread.step-avoid-regexp", false, error);
362      if (value_sp && value_sp->GetType() == OptionValue::eTypeRegex) {
363        OptionValueRegex *re = value_sp->GetAsRegex();
364        if (re) {
365          avoid_regex = re->GetCurrentValue();
366        }
367      }
368    }
369  }
370  if (avoid_regex && sc.symbol != nullptr) {
371    const char *function_name =
372        sc.GetFunctionName(Mangled::ePreferDemangledWithoutArguments)
373            .GetCString();
374    if (function_name && avoid_regex->Execute(function_name)) {
375      // skip this source line
376      return true;
377    }
378  }
379  // don't skip this source line
380  return false;
381}
382
383bool Disassembler::PrintInstructions(Disassembler *disasm_ptr,
384                                     Debugger &debugger, const ArchSpec &arch,
385                                     const ExecutionContext &exe_ctx,
386                                     uint32_t num_instructions,
387                                     bool mixed_source_and_assembly,
388                                     uint32_t num_mixed_context_lines,
389                                     uint32_t options, Stream &strm) {
390  // We got some things disassembled...
391  size_t num_instructions_found = disasm_ptr->GetInstructionList().GetSize();
392
393  if (num_instructions > 0 && num_instructions < num_instructions_found)
394    num_instructions_found = num_instructions;
395
396  const uint32_t max_opcode_byte_size =
397      disasm_ptr->GetInstructionList().GetMaxOpcocdeByteSize();
398  SymbolContext sc;
399  SymbolContext prev_sc;
400  AddressRange current_source_line_range;
401  const Address *pc_addr_ptr = nullptr;
402  StackFrame *frame = exe_ctx.GetFramePtr();
403
404  TargetSP target_sp(exe_ctx.GetTargetSP());
405  SourceManager &source_manager =
406      target_sp ? target_sp->GetSourceManager() : debugger.GetSourceManager();
407
408  if (frame) {
409    pc_addr_ptr = &frame->GetFrameCodeAddress();
410  }
411  const uint32_t scope =
412      eSymbolContextLineEntry | eSymbolContextFunction | eSymbolContextSymbol;
413  const bool use_inline_block_range = false;
414
415  const FormatEntity::Entry *disassembly_format = nullptr;
416  FormatEntity::Entry format;
417  if (exe_ctx.HasTargetScope()) {
418    disassembly_format =
419        exe_ctx.GetTargetRef().GetDebugger().GetDisassemblyFormat();
420  } else {
421    FormatEntity::Parse("${addr}: ", format);
422    disassembly_format = &format;
423  }
424
425  // First pass: step through the list of instructions, find how long the
426  // initial addresses strings are, insert padding in the second pass so the
427  // opcodes all line up nicely.
428
429  // Also build up the source line mapping if this is mixed source & assembly
430  // mode. Calculate the source line for each assembly instruction (eliding
431  // inlined functions which the user wants to skip).
432
433  std::map<FileSpec, std::set<uint32_t>> source_lines_seen;
434  Symbol *previous_symbol = nullptr;
435
436  size_t address_text_size = 0;
437  for (size_t i = 0; i < num_instructions_found; ++i) {
438    Instruction *inst =
439        disasm_ptr->GetInstructionList().GetInstructionAtIndex(i).get();
440    if (inst) {
441      const Address &addr = inst->GetAddress();
442      ModuleSP module_sp(addr.GetModule());
443      if (module_sp) {
444        const SymbolContextItem resolve_mask = eSymbolContextFunction |
445                                               eSymbolContextSymbol |
446                                               eSymbolContextLineEntry;
447        uint32_t resolved_mask =
448            module_sp->ResolveSymbolContextForAddress(addr, resolve_mask, sc);
449        if (resolved_mask) {
450          StreamString strmstr;
451          Debugger::FormatDisassemblerAddress(disassembly_format, &sc, nullptr,
452                                              &exe_ctx, &addr, strmstr);
453          size_t cur_line = strmstr.GetSizeOfLastLine();
454          if (cur_line > address_text_size)
455            address_text_size = cur_line;
456
457          // Add entries to our "source_lines_seen" map+set which list which
458          // sources lines occur in this disassembly session.  We will print
459          // lines of context around a source line, but we don't want to print
460          // a source line that has a line table entry of its own - we'll leave
461          // that source line to be printed when it actually occurs in the
462          // disassembly.
463
464          if (mixed_source_and_assembly && sc.line_entry.IsValid()) {
465            if (sc.symbol != previous_symbol) {
466              SourceLine decl_line = GetFunctionDeclLineEntry(sc);
467              if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, decl_line))
468                AddLineToSourceLineTables(decl_line, source_lines_seen);
469            }
470            if (sc.line_entry.IsValid()) {
471              SourceLine this_line;
472              this_line.file = sc.line_entry.file;
473              this_line.line = sc.line_entry.line;
474              this_line.column = sc.line_entry.column;
475              if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, this_line))
476                AddLineToSourceLineTables(this_line, source_lines_seen);
477            }
478          }
479        }
480        sc.Clear(false);
481      }
482    }
483  }
484
485  previous_symbol = nullptr;
486  SourceLine previous_line;
487  for (size_t i = 0; i < num_instructions_found; ++i) {
488    Instruction *inst =
489        disasm_ptr->GetInstructionList().GetInstructionAtIndex(i).get();
490
491    if (inst) {
492      const Address &addr = inst->GetAddress();
493      const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr;
494      SourceLinesToDisplay source_lines_to_display;
495
496      prev_sc = sc;
497
498      ModuleSP module_sp(addr.GetModule());
499      if (module_sp) {
500        uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress(
501            addr, eSymbolContextEverything, sc);
502        if (resolved_mask) {
503          if (mixed_source_and_assembly) {
504
505            // If we've started a new function (non-inlined), print all of the
506            // source lines from the function declaration until the first line
507            // table entry - typically the opening curly brace of the function.
508            if (previous_symbol != sc.symbol) {
509              // The default disassembly format puts an extra blank line
510              // between functions - so when we're displaying the source
511              // context for a function, we don't want to add a blank line
512              // after the source context or we'll end up with two of them.
513              if (previous_symbol != nullptr)
514                source_lines_to_display.print_source_context_end_eol = false;
515
516              previous_symbol = sc.symbol;
517              if (sc.function && sc.line_entry.IsValid()) {
518                LineEntry prologue_end_line = sc.line_entry;
519                if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc,
520                                                        prologue_end_line)) {
521                  FileSpec func_decl_file;
522                  uint32_t func_decl_line;
523                  sc.function->GetStartLineSourceInfo(func_decl_file,
524                                                      func_decl_line);
525                  if (func_decl_file == prologue_end_line.file ||
526                      func_decl_file == prologue_end_line.original_file) {
527                    // Add all the lines between the function declaration and
528                    // the first non-prologue source line to the list of lines
529                    // to print.
530                    for (uint32_t lineno = func_decl_line;
531                         lineno <= prologue_end_line.line; lineno++) {
532                      SourceLine this_line;
533                      this_line.file = func_decl_file;
534                      this_line.line = lineno;
535                      source_lines_to_display.lines.push_back(this_line);
536                    }
537                    // Mark the last line as the "current" one.  Usually this
538                    // is the open curly brace.
539                    if (source_lines_to_display.lines.size() > 0)
540                      source_lines_to_display.current_source_line =
541                          source_lines_to_display.lines.size() - 1;
542                  }
543                }
544              }
545              sc.GetAddressRange(scope, 0, use_inline_block_range,
546                                 current_source_line_range);
547            }
548
549            // If we've left a previous source line's address range, print a
550            // new source line
551            if (!current_source_line_range.ContainsFileAddress(addr)) {
552              sc.GetAddressRange(scope, 0, use_inline_block_range,
553                                 current_source_line_range);
554
555              if (sc != prev_sc && sc.comp_unit && sc.line_entry.IsValid()) {
556                SourceLine this_line;
557                this_line.file = sc.line_entry.file;
558                this_line.line = sc.line_entry.line;
559
560                if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc,
561                                                        this_line)) {
562                  // Only print this source line if it is different from the
563                  // last source line we printed.  There may have been inlined
564                  // functions between these lines that we elided, resulting in
565                  // the same line being printed twice in a row for a
566                  // contiguous block of assembly instructions.
567                  if (this_line != previous_line) {
568
569                    std::vector<uint32_t> previous_lines;
570                    for (uint32_t i = 0;
571                         i < num_mixed_context_lines &&
572                         (this_line.line - num_mixed_context_lines) > 0;
573                         i++) {
574                      uint32_t line =
575                          this_line.line - num_mixed_context_lines + i;
576                      auto pos = source_lines_seen.find(this_line.file);
577                      if (pos != source_lines_seen.end()) {
578                        if (pos->second.count(line) == 1) {
579                          previous_lines.clear();
580                        } else {
581                          previous_lines.push_back(line);
582                        }
583                      }
584                    }
585                    for (size_t i = 0; i < previous_lines.size(); i++) {
586                      SourceLine previous_line;
587                      previous_line.file = this_line.file;
588                      previous_line.line = previous_lines[i];
589                      auto pos = source_lines_seen.find(previous_line.file);
590                      if (pos != source_lines_seen.end()) {
591                        pos->second.insert(previous_line.line);
592                      }
593                      source_lines_to_display.lines.push_back(previous_line);
594                    }
595
596                    source_lines_to_display.lines.push_back(this_line);
597                    source_lines_to_display.current_source_line =
598                        source_lines_to_display.lines.size() - 1;
599
600                    for (uint32_t i = 0; i < num_mixed_context_lines; i++) {
601                      SourceLine next_line;
602                      next_line.file = this_line.file;
603                      next_line.line = this_line.line + i + 1;
604                      auto pos = source_lines_seen.find(next_line.file);
605                      if (pos != source_lines_seen.end()) {
606                        if (pos->second.count(next_line.line) == 1)
607                          break;
608                        pos->second.insert(next_line.line);
609                      }
610                      source_lines_to_display.lines.push_back(next_line);
611                    }
612                  }
613                  previous_line = this_line;
614                }
615              }
616            }
617          }
618        } else {
619          sc.Clear(true);
620        }
621      }
622
623      if (source_lines_to_display.lines.size() > 0) {
624        strm.EOL();
625        for (size_t idx = 0; idx < source_lines_to_display.lines.size();
626             idx++) {
627          SourceLine ln = source_lines_to_display.lines[idx];
628          const char *line_highlight = "";
629          if (inst_is_at_pc && (options & eOptionMarkPCSourceLine)) {
630            line_highlight = "->";
631          } else if (idx == source_lines_to_display.current_source_line) {
632            line_highlight = "**";
633          }
634          source_manager.DisplaySourceLinesWithLineNumbers(
635              ln.file, ln.line, ln.column, 0, 0, line_highlight, &strm);
636        }
637        if (source_lines_to_display.print_source_context_end_eol)
638          strm.EOL();
639      }
640
641      const bool show_bytes = (options & eOptionShowBytes) != 0;
642      inst->Dump(&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx, &sc,
643                 &prev_sc, nullptr, address_text_size);
644      strm.EOL();
645    } else {
646      break;
647    }
648  }
649
650  return true;
651}
652
653bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch,
654                               const char *plugin_name, const char *flavor,
655                               const ExecutionContext &exe_ctx,
656                               uint32_t num_instructions,
657                               bool mixed_source_and_assembly,
658                               uint32_t num_mixed_context_lines,
659                               uint32_t options, Stream &strm) {
660  AddressRange range;
661  StackFrame *frame = exe_ctx.GetFramePtr();
662  if (frame) {
663    SymbolContext sc(
664        frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
665    if (sc.function) {
666      range = sc.function->GetAddressRange();
667    } else if (sc.symbol && sc.symbol->ValueIsAddress()) {
668      range.GetBaseAddress() = sc.symbol->GetAddressRef();
669      range.SetByteSize(sc.symbol->GetByteSize());
670    } else {
671      range.GetBaseAddress() = frame->GetFrameCodeAddress();
672    }
673
674    if (range.GetBaseAddress().IsValid() && range.GetByteSize() == 0)
675      range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE);
676  }
677
678  return Disassemble(debugger, arch, plugin_name, flavor, exe_ctx, range,
679                     num_instructions, mixed_source_and_assembly,
680                     num_mixed_context_lines, options, strm);
681}
682
683Instruction::Instruction(const Address &address, AddressClass addr_class)
684    : m_address(address), m_address_class(addr_class), m_opcode(),
685      m_calculated_strings(false) {}
686
687Instruction::~Instruction() = default;
688
689AddressClass Instruction::GetAddressClass() {
690  if (m_address_class == AddressClass::eInvalid)
691    m_address_class = m_address.GetAddressClass();
692  return m_address_class;
693}
694
695void Instruction::Dump(lldb_private::Stream *s, uint32_t max_opcode_byte_size,
696                       bool show_address, bool show_bytes,
697                       const ExecutionContext *exe_ctx,
698                       const SymbolContext *sym_ctx,
699                       const SymbolContext *prev_sym_ctx,
700                       const FormatEntity::Entry *disassembly_addr_format,
701                       size_t max_address_text_size) {
702  size_t opcode_column_width = 7;
703  const size_t operand_column_width = 25;
704
705  CalculateMnemonicOperandsAndCommentIfNeeded(exe_ctx);
706
707  StreamString ss;
708
709  if (show_address) {
710    Debugger::FormatDisassemblerAddress(disassembly_addr_format, sym_ctx,
711                                        prev_sym_ctx, exe_ctx, &m_address, ss);
712    ss.FillLastLineToColumn(max_address_text_size, ' ');
713  }
714
715  if (show_bytes) {
716    if (m_opcode.GetType() == Opcode::eTypeBytes) {
717      // x86_64 and i386 are the only ones that use bytes right now so pad out
718      // the byte dump to be able to always show 15 bytes (3 chars each) plus a
719      // space
720      if (max_opcode_byte_size > 0)
721        m_opcode.Dump(&ss, max_opcode_byte_size * 3 + 1);
722      else
723        m_opcode.Dump(&ss, 15 * 3 + 1);
724    } else {
725      // Else, we have ARM or MIPS which can show up to a uint32_t 0x00000000
726      // (10 spaces) plus two for padding...
727      if (max_opcode_byte_size > 0)
728        m_opcode.Dump(&ss, max_opcode_byte_size * 3 + 1);
729      else
730        m_opcode.Dump(&ss, 12);
731    }
732  }
733
734  const size_t opcode_pos = ss.GetSizeOfLastLine();
735
736  // The default opcode size of 7 characters is plenty for most architectures
737  // but some like arm can pull out the occasional vqrshrun.s16.  We won't get
738  // consistent column spacing in these cases, unfortunately.
739  if (m_opcode_name.length() >= opcode_column_width) {
740    opcode_column_width = m_opcode_name.length() + 1;
741  }
742
743  ss.PutCString(m_opcode_name);
744  ss.FillLastLineToColumn(opcode_pos + opcode_column_width, ' ');
745  ss.PutCString(m_mnemonics);
746
747  if (!m_comment.empty()) {
748    ss.FillLastLineToColumn(
749        opcode_pos + opcode_column_width + operand_column_width, ' ');
750    ss.PutCString(" ; ");
751    ss.PutCString(m_comment);
752  }
753  s->PutCString(ss.GetString());
754}
755
756bool Instruction::DumpEmulation(const ArchSpec &arch) {
757  std::unique_ptr<EmulateInstruction> insn_emulator_up(
758      EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr));
759  if (insn_emulator_up) {
760    insn_emulator_up->SetInstruction(GetOpcode(), GetAddress(), nullptr);
761    return insn_emulator_up->EvaluateInstruction(0);
762  }
763
764  return false;
765}
766
767bool Instruction::CanSetBreakpoint () {
768  return !HasDelaySlot();
769}
770
771bool Instruction::HasDelaySlot() {
772  // Default is false.
773  return false;
774}
775
776OptionValueSP Instruction::ReadArray(FILE *in_file, Stream *out_stream,
777                                     OptionValue::Type data_type) {
778  bool done = false;
779  char buffer[1024];
780
781  auto option_value_sp = std::make_shared<OptionValueArray>(1u << data_type);
782
783  int idx = 0;
784  while (!done) {
785    if (!fgets(buffer, 1023, in_file)) {
786      out_stream->Printf(
787          "Instruction::ReadArray:  Error reading file (fgets).\n");
788      option_value_sp.reset();
789      return option_value_sp;
790    }
791
792    std::string line(buffer);
793
794    size_t len = line.size();
795    if (line[len - 1] == '\n') {
796      line[len - 1] = '\0';
797      line.resize(len - 1);
798    }
799
800    if ((line.size() == 1) && line[0] == ']') {
801      done = true;
802      line.clear();
803    }
804
805    if (!line.empty()) {
806      std::string value;
807      static RegularExpression g_reg_exp(
808          llvm::StringRef("^[ \t]*([^ \t]+)[ \t]*$"));
809      llvm::SmallVector<llvm::StringRef, 2> matches;
810      if (g_reg_exp.Execute(line, &matches))
811        value = matches[1].str();
812      else
813        value = line;
814
815      OptionValueSP data_value_sp;
816      switch (data_type) {
817      case OptionValue::eTypeUInt64:
818        data_value_sp = std::make_shared<OptionValueUInt64>(0, 0);
819        data_value_sp->SetValueFromString(value);
820        break;
821      // Other types can be added later as needed.
822      default:
823        data_value_sp = std::make_shared<OptionValueString>(value.c_str(), "");
824        break;
825      }
826
827      option_value_sp->GetAsArray()->InsertValue(idx, data_value_sp);
828      ++idx;
829    }
830  }
831
832  return option_value_sp;
833}
834
835OptionValueSP Instruction::ReadDictionary(FILE *in_file, Stream *out_stream) {
836  bool done = false;
837  char buffer[1024];
838
839  auto option_value_sp = std::make_shared<OptionValueDictionary>();
840  static ConstString encoding_key("data_encoding");
841  OptionValue::Type data_type = OptionValue::eTypeInvalid;
842
843  while (!done) {
844    // Read the next line in the file
845    if (!fgets(buffer, 1023, in_file)) {
846      out_stream->Printf(
847          "Instruction::ReadDictionary: Error reading file (fgets).\n");
848      option_value_sp.reset();
849      return option_value_sp;
850    }
851
852    // Check to see if the line contains the end-of-dictionary marker ("}")
853    std::string line(buffer);
854
855    size_t len = line.size();
856    if (line[len - 1] == '\n') {
857      line[len - 1] = '\0';
858      line.resize(len - 1);
859    }
860
861    if ((line.size() == 1) && (line[0] == '}')) {
862      done = true;
863      line.clear();
864    }
865
866    // Try to find a key-value pair in the current line and add it to the
867    // dictionary.
868    if (!line.empty()) {
869      static RegularExpression g_reg_exp(llvm::StringRef(
870          "^[ \t]*([a-zA-Z_][a-zA-Z0-9_]*)[ \t]*=[ \t]*(.*)[ \t]*$"));
871
872      llvm::SmallVector<llvm::StringRef, 3> matches;
873
874      bool reg_exp_success = g_reg_exp.Execute(line, &matches);
875      std::string key;
876      std::string value;
877      if (reg_exp_success) {
878        key = matches[1].str();
879        value = matches[2].str();
880      } else {
881        out_stream->Printf("Instruction::ReadDictionary: Failure executing "
882                           "regular expression.\n");
883        option_value_sp.reset();
884        return option_value_sp;
885      }
886
887      ConstString const_key(key.c_str());
888      // Check value to see if it's the start of an array or dictionary.
889
890      lldb::OptionValueSP value_sp;
891      assert(value.empty() == false);
892      assert(key.empty() == false);
893
894      if (value[0] == '{') {
895        assert(value.size() == 1);
896        // value is a dictionary
897        value_sp = ReadDictionary(in_file, out_stream);
898        if (!value_sp) {
899          option_value_sp.reset();
900          return option_value_sp;
901        }
902      } else if (value[0] == '[') {
903        assert(value.size() == 1);
904        // value is an array
905        value_sp = ReadArray(in_file, out_stream, data_type);
906        if (!value_sp) {
907          option_value_sp.reset();
908          return option_value_sp;
909        }
910        // We've used the data_type to read an array; re-set the type to
911        // Invalid
912        data_type = OptionValue::eTypeInvalid;
913      } else if ((value[0] == '0') && (value[1] == 'x')) {
914        value_sp = std::make_shared<OptionValueUInt64>(0, 0);
915        value_sp->SetValueFromString(value);
916      } else {
917        size_t len = value.size();
918        if ((value[0] == '"') && (value[len - 1] == '"'))
919          value = value.substr(1, len - 2);
920        value_sp = std::make_shared<OptionValueString>(value.c_str(), "");
921      }
922
923      if (const_key == encoding_key) {
924        // A 'data_encoding=..." is NOT a normal key-value pair; it is meta-data
925        // indicating the
926        // data type of an upcoming array (usually the next bit of data to be
927        // read in).
928        if (strcmp(value.c_str(), "uint32_t") == 0)
929          data_type = OptionValue::eTypeUInt64;
930      } else
931        option_value_sp->GetAsDictionary()->SetValueForKey(const_key, value_sp,
932                                                           false);
933    }
934  }
935
936  return option_value_sp;
937}
938
939bool Instruction::TestEmulation(Stream *out_stream, const char *file_name) {
940  if (!out_stream)
941    return false;
942
943  if (!file_name) {
944    out_stream->Printf("Instruction::TestEmulation:  Missing file_name.");
945    return false;
946  }
947  FILE *test_file = FileSystem::Instance().Fopen(file_name, "r");
948  if (!test_file) {
949    out_stream->Printf(
950        "Instruction::TestEmulation: Attempt to open test file failed.");
951    return false;
952  }
953
954  char buffer[256];
955  if (!fgets(buffer, 255, test_file)) {
956    out_stream->Printf(
957        "Instruction::TestEmulation: Error reading first line of test file.\n");
958    fclose(test_file);
959    return false;
960  }
961
962  if (strncmp(buffer, "InstructionEmulationState={", 27) != 0) {
963    out_stream->Printf("Instructin::TestEmulation: Test file does not contain "
964                       "emulation state dictionary\n");
965    fclose(test_file);
966    return false;
967  }
968
969  // Read all the test information from the test file into an
970  // OptionValueDictionary.
971
972  OptionValueSP data_dictionary_sp(ReadDictionary(test_file, out_stream));
973  if (!data_dictionary_sp) {
974    out_stream->Printf(
975        "Instruction::TestEmulation:  Error reading Dictionary Object.\n");
976    fclose(test_file);
977    return false;
978  }
979
980  fclose(test_file);
981
982  OptionValueDictionary *data_dictionary =
983      data_dictionary_sp->GetAsDictionary();
984  static ConstString description_key("assembly_string");
985  static ConstString triple_key("triple");
986
987  OptionValueSP value_sp = data_dictionary->GetValueForKey(description_key);
988
989  if (!value_sp) {
990    out_stream->Printf("Instruction::TestEmulation:  Test file does not "
991                       "contain description string.\n");
992    return false;
993  }
994
995  SetDescription(value_sp->GetStringValue());
996
997  value_sp = data_dictionary->GetValueForKey(triple_key);
998  if (!value_sp) {
999    out_stream->Printf(
1000        "Instruction::TestEmulation: Test file does not contain triple.\n");
1001    return false;
1002  }
1003
1004  ArchSpec arch;
1005  arch.SetTriple(llvm::Triple(value_sp->GetStringValue()));
1006
1007  bool success = false;
1008  std::unique_ptr<EmulateInstruction> insn_emulator_up(
1009      EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr));
1010  if (insn_emulator_up)
1011    success =
1012        insn_emulator_up->TestEmulation(out_stream, arch, data_dictionary);
1013
1014  if (success)
1015    out_stream->Printf("Emulation test succeeded.");
1016  else
1017    out_stream->Printf("Emulation test failed.");
1018
1019  return success;
1020}
1021
1022bool Instruction::Emulate(
1023    const ArchSpec &arch, uint32_t evaluate_options, void *baton,
1024    EmulateInstruction::ReadMemoryCallback read_mem_callback,
1025    EmulateInstruction::WriteMemoryCallback write_mem_callback,
1026    EmulateInstruction::ReadRegisterCallback read_reg_callback,
1027    EmulateInstruction::WriteRegisterCallback write_reg_callback) {
1028  std::unique_ptr<EmulateInstruction> insn_emulator_up(
1029      EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr));
1030  if (insn_emulator_up) {
1031    insn_emulator_up->SetBaton(baton);
1032    insn_emulator_up->SetCallbacks(read_mem_callback, write_mem_callback,
1033                                   read_reg_callback, write_reg_callback);
1034    insn_emulator_up->SetInstruction(GetOpcode(), GetAddress(), nullptr);
1035    return insn_emulator_up->EvaluateInstruction(evaluate_options);
1036  }
1037
1038  return false;
1039}
1040
1041uint32_t Instruction::GetData(DataExtractor &data) {
1042  return m_opcode.GetData(data);
1043}
1044
1045InstructionList::InstructionList() : m_instructions() {}
1046
1047InstructionList::~InstructionList() = default;
1048
1049size_t InstructionList::GetSize() const { return m_instructions.size(); }
1050
1051uint32_t InstructionList::GetMaxOpcocdeByteSize() const {
1052  uint32_t max_inst_size = 0;
1053  collection::const_iterator pos, end;
1054  for (pos = m_instructions.begin(), end = m_instructions.end(); pos != end;
1055       ++pos) {
1056    uint32_t inst_size = (*pos)->GetOpcode().GetByteSize();
1057    if (max_inst_size < inst_size)
1058      max_inst_size = inst_size;
1059  }
1060  return max_inst_size;
1061}
1062
1063InstructionSP InstructionList::GetInstructionAtIndex(size_t idx) const {
1064  InstructionSP inst_sp;
1065  if (idx < m_instructions.size())
1066    inst_sp = m_instructions[idx];
1067  return inst_sp;
1068}
1069
1070void InstructionList::Dump(Stream *s, bool show_address, bool show_bytes,
1071                           const ExecutionContext *exe_ctx) {
1072  const uint32_t max_opcode_byte_size = GetMaxOpcocdeByteSize();
1073  collection::const_iterator pos, begin, end;
1074
1075  const FormatEntity::Entry *disassembly_format = nullptr;
1076  FormatEntity::Entry format;
1077  if (exe_ctx && exe_ctx->HasTargetScope()) {
1078    disassembly_format =
1079        exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat();
1080  } else {
1081    FormatEntity::Parse("${addr}: ", format);
1082    disassembly_format = &format;
1083  }
1084
1085  for (begin = m_instructions.begin(), end = m_instructions.end(), pos = begin;
1086       pos != end; ++pos) {
1087    if (pos != begin)
1088      s->EOL();
1089    (*pos)->Dump(s, max_opcode_byte_size, show_address, show_bytes, exe_ctx,
1090                 nullptr, nullptr, disassembly_format, 0);
1091  }
1092}
1093
1094void InstructionList::Clear() { m_instructions.clear(); }
1095
1096void InstructionList::Append(lldb::InstructionSP &inst_sp) {
1097  if (inst_sp)
1098    m_instructions.push_back(inst_sp);
1099}
1100
1101uint32_t
1102InstructionList::GetIndexOfNextBranchInstruction(uint32_t start,
1103                                                 Target &target,
1104                                                 bool ignore_calls,
1105                                                 bool *found_calls) const {
1106  size_t num_instructions = m_instructions.size();
1107
1108  uint32_t next_branch = UINT32_MAX;
1109  size_t i;
1110
1111  if (found_calls)
1112    *found_calls = false;
1113  for (i = start; i < num_instructions; i++) {
1114    if (m_instructions[i]->DoesBranch()) {
1115      if (ignore_calls && m_instructions[i]->IsCall()) {
1116        if (found_calls)
1117          *found_calls = true;
1118        continue;
1119      }
1120      next_branch = i;
1121      break;
1122    }
1123  }
1124
1125  // Hexagon needs the first instruction of the packet with the branch. Go
1126  // backwards until we find an instruction marked end-of-packet, or until we
1127  // hit start.
1128  if (target.GetArchitecture().GetTriple().getArch() == llvm::Triple::hexagon) {
1129    // If we didn't find a branch, find the last packet start.
1130    if (next_branch == UINT32_MAX) {
1131      i = num_instructions - 1;
1132    }
1133
1134    while (i > start) {
1135      --i;
1136
1137      Status error;
1138      uint32_t inst_bytes;
1139      bool prefer_file_cache = false; // Read from process if process is running
1140      lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
1141      target.ReadMemory(m_instructions[i]->GetAddress(), prefer_file_cache,
1142                        &inst_bytes, sizeof(inst_bytes), error, &load_addr);
1143      // If we have an error reading memory, return start
1144      if (!error.Success())
1145        return start;
1146      // check if this is the last instruction in a packet bits 15:14 will be
1147      // 11b or 00b for a duplex
1148      if (((inst_bytes & 0xC000) == 0xC000) ||
1149          ((inst_bytes & 0xC000) == 0x0000)) {
1150        // instruction after this should be the start of next packet
1151        next_branch = i + 1;
1152        break;
1153      }
1154    }
1155
1156    if (next_branch == UINT32_MAX) {
1157      // We couldn't find the previous packet, so return start
1158      next_branch = start;
1159    }
1160  }
1161  return next_branch;
1162}
1163
1164uint32_t
1165InstructionList::GetIndexOfInstructionAtAddress(const Address &address) {
1166  size_t num_instructions = m_instructions.size();
1167  uint32_t index = UINT32_MAX;
1168  for (size_t i = 0; i < num_instructions; i++) {
1169    if (m_instructions[i]->GetAddress() == address) {
1170      index = i;
1171      break;
1172    }
1173  }
1174  return index;
1175}
1176
1177uint32_t
1178InstructionList::GetIndexOfInstructionAtLoadAddress(lldb::addr_t load_addr,
1179                                                    Target &target) {
1180  Address address;
1181  address.SetLoadAddress(load_addr, &target);
1182  return GetIndexOfInstructionAtAddress(address);
1183}
1184
1185size_t Disassembler::ParseInstructions(const ExecutionContext *exe_ctx,
1186                                       const AddressRange &range,
1187                                       Stream *error_strm_ptr,
1188                                       bool prefer_file_cache) {
1189  if (exe_ctx) {
1190    Target *target = exe_ctx->GetTargetPtr();
1191    const addr_t byte_size = range.GetByteSize();
1192    if (target == nullptr || byte_size == 0 ||
1193        !range.GetBaseAddress().IsValid())
1194      return 0;
1195
1196    auto data_sp = std::make_shared<DataBufferHeap>(byte_size, '\0');
1197
1198    Status error;
1199    lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
1200    const size_t bytes_read = target->ReadMemory(
1201        range.GetBaseAddress(), prefer_file_cache, data_sp->GetBytes(),
1202        data_sp->GetByteSize(), error, &load_addr);
1203
1204    if (bytes_read > 0) {
1205      if (bytes_read != data_sp->GetByteSize())
1206        data_sp->SetByteSize(bytes_read);
1207      DataExtractor data(data_sp, m_arch.GetByteOrder(),
1208                         m_arch.GetAddressByteSize());
1209      const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS;
1210      return DecodeInstructions(range.GetBaseAddress(), data, 0, UINT32_MAX,
1211                                false, data_from_file);
1212    } else if (error_strm_ptr) {
1213      const char *error_cstr = error.AsCString();
1214      if (error_cstr) {
1215        error_strm_ptr->Printf("error: %s\n", error_cstr);
1216      }
1217    }
1218  } else if (error_strm_ptr) {
1219    error_strm_ptr->PutCString("error: invalid execution context\n");
1220  }
1221  return 0;
1222}
1223
1224size_t Disassembler::ParseInstructions(const ExecutionContext *exe_ctx,
1225                                       const Address &start,
1226                                       uint32_t num_instructions,
1227                                       bool prefer_file_cache) {
1228  m_instruction_list.Clear();
1229
1230  if (exe_ctx == nullptr || num_instructions == 0 || !start.IsValid())
1231    return 0;
1232
1233  Target *target = exe_ctx->GetTargetPtr();
1234  // Calculate the max buffer size we will need in order to disassemble
1235  const addr_t byte_size = num_instructions * m_arch.GetMaximumOpcodeByteSize();
1236
1237  if (target == nullptr || byte_size == 0)
1238    return 0;
1239
1240  DataBufferHeap *heap_buffer = new DataBufferHeap(byte_size, '\0');
1241  DataBufferSP data_sp(heap_buffer);
1242
1243  Status error;
1244  lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
1245  const size_t bytes_read =
1246      target->ReadMemory(start, prefer_file_cache, heap_buffer->GetBytes(),
1247                         byte_size, error, &load_addr);
1248
1249  const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS;
1250
1251  if (bytes_read == 0)
1252    return 0;
1253  DataExtractor data(data_sp, m_arch.GetByteOrder(),
1254                     m_arch.GetAddressByteSize());
1255
1256  const bool append_instructions = true;
1257  DecodeInstructions(start, data, 0, num_instructions, append_instructions,
1258                     data_from_file);
1259
1260  return m_instruction_list.GetSize();
1261}
1262
1263// Disassembler copy constructor
1264Disassembler::Disassembler(const ArchSpec &arch, const char *flavor)
1265    : m_arch(arch), m_instruction_list(), m_base_addr(LLDB_INVALID_ADDRESS),
1266      m_flavor() {
1267  if (flavor == nullptr)
1268    m_flavor.assign("default");
1269  else
1270    m_flavor.assign(flavor);
1271
1272  // If this is an arm variant that can only include thumb (T16, T32)
1273  // instructions, force the arch triple to be "thumbv.." instead of "armv..."
1274  if (arch.IsAlwaysThumbInstructions()) {
1275    std::string thumb_arch_name(arch.GetTriple().getArchName().str());
1276    // Replace "arm" with "thumb" so we get all thumb variants correct
1277    if (thumb_arch_name.size() > 3) {
1278      thumb_arch_name.erase(0, 3);
1279      thumb_arch_name.insert(0, "thumb");
1280    }
1281    m_arch.SetTriple(thumb_arch_name.c_str());
1282  }
1283}
1284
1285Disassembler::~Disassembler() = default;
1286
1287InstructionList &Disassembler::GetInstructionList() {
1288  return m_instruction_list;
1289}
1290
1291const InstructionList &Disassembler::GetInstructionList() const {
1292  return m_instruction_list;
1293}
1294
1295// Class PseudoInstruction
1296
1297PseudoInstruction::PseudoInstruction()
1298    : Instruction(Address(), AddressClass::eUnknown), m_description() {}
1299
1300PseudoInstruction::~PseudoInstruction() = default;
1301
1302bool PseudoInstruction::DoesBranch() {
1303  // This is NOT a valid question for a pseudo instruction.
1304  return false;
1305}
1306
1307bool PseudoInstruction::HasDelaySlot() {
1308  // This is NOT a valid question for a pseudo instruction.
1309  return false;
1310}
1311
1312size_t PseudoInstruction::Decode(const lldb_private::Disassembler &disassembler,
1313                                 const lldb_private::DataExtractor &data,
1314                                 lldb::offset_t data_offset) {
1315  return m_opcode.GetByteSize();
1316}
1317
1318void PseudoInstruction::SetOpcode(size_t opcode_size, void *opcode_data) {
1319  if (!opcode_data)
1320    return;
1321
1322  switch (opcode_size) {
1323  case 8: {
1324    uint8_t value8 = *((uint8_t *)opcode_data);
1325    m_opcode.SetOpcode8(value8, eByteOrderInvalid);
1326    break;
1327  }
1328  case 16: {
1329    uint16_t value16 = *((uint16_t *)opcode_data);
1330    m_opcode.SetOpcode16(value16, eByteOrderInvalid);
1331    break;
1332  }
1333  case 32: {
1334    uint32_t value32 = *((uint32_t *)opcode_data);
1335    m_opcode.SetOpcode32(value32, eByteOrderInvalid);
1336    break;
1337  }
1338  case 64: {
1339    uint64_t value64 = *((uint64_t *)opcode_data);
1340    m_opcode.SetOpcode64(value64, eByteOrderInvalid);
1341    break;
1342  }
1343  default:
1344    break;
1345  }
1346}
1347
1348void PseudoInstruction::SetDescription(llvm::StringRef description) {
1349  m_description = description;
1350}
1351
1352Instruction::Operand Instruction::Operand::BuildRegister(ConstString &r) {
1353  Operand ret;
1354  ret.m_type = Type::Register;
1355  ret.m_register = r;
1356  return ret;
1357}
1358
1359Instruction::Operand Instruction::Operand::BuildImmediate(lldb::addr_t imm,
1360                                                          bool neg) {
1361  Operand ret;
1362  ret.m_type = Type::Immediate;
1363  ret.m_immediate = imm;
1364  ret.m_negative = neg;
1365  return ret;
1366}
1367
1368Instruction::Operand Instruction::Operand::BuildImmediate(int64_t imm) {
1369  Operand ret;
1370  ret.m_type = Type::Immediate;
1371  if (imm < 0) {
1372    ret.m_immediate = -imm;
1373    ret.m_negative = true;
1374  } else {
1375    ret.m_immediate = imm;
1376    ret.m_negative = false;
1377  }
1378  return ret;
1379}
1380
1381Instruction::Operand
1382Instruction::Operand::BuildDereference(const Operand &ref) {
1383  Operand ret;
1384  ret.m_type = Type::Dereference;
1385  ret.m_children = {ref};
1386  return ret;
1387}
1388
1389Instruction::Operand Instruction::Operand::BuildSum(const Operand &lhs,
1390                                                    const Operand &rhs) {
1391  Operand ret;
1392  ret.m_type = Type::Sum;
1393  ret.m_children = {lhs, rhs};
1394  return ret;
1395}
1396
1397Instruction::Operand Instruction::Operand::BuildProduct(const Operand &lhs,
1398                                                        const Operand &rhs) {
1399  Operand ret;
1400  ret.m_type = Type::Product;
1401  ret.m_children = {lhs, rhs};
1402  return ret;
1403}
1404
1405std::function<bool(const Instruction::Operand &)>
1406lldb_private::OperandMatchers::MatchBinaryOp(
1407    std::function<bool(const Instruction::Operand &)> base,
1408    std::function<bool(const Instruction::Operand &)> left,
1409    std::function<bool(const Instruction::Operand &)> right) {
1410  return [base, left, right](const Instruction::Operand &op) -> bool {
1411    return (base(op) && op.m_children.size() == 2 &&
1412            ((left(op.m_children[0]) && right(op.m_children[1])) ||
1413             (left(op.m_children[1]) && right(op.m_children[0]))));
1414  };
1415}
1416
1417std::function<bool(const Instruction::Operand &)>
1418lldb_private::OperandMatchers::MatchUnaryOp(
1419    std::function<bool(const Instruction::Operand &)> base,
1420    std::function<bool(const Instruction::Operand &)> child) {
1421  return [base, child](const Instruction::Operand &op) -> bool {
1422    return (base(op) && op.m_children.size() == 1 && child(op.m_children[0]));
1423  };
1424}
1425
1426std::function<bool(const Instruction::Operand &)>
1427lldb_private::OperandMatchers::MatchRegOp(const RegisterInfo &info) {
1428  return [&info](const Instruction::Operand &op) {
1429    return (op.m_type == Instruction::Operand::Type::Register &&
1430            (op.m_register == ConstString(info.name) ||
1431             op.m_register == ConstString(info.alt_name)));
1432  };
1433}
1434
1435std::function<bool(const Instruction::Operand &)>
1436lldb_private::OperandMatchers::FetchRegOp(ConstString &reg) {
1437  return [&reg](const Instruction::Operand &op) {
1438    if (op.m_type != Instruction::Operand::Type::Register) {
1439      return false;
1440    }
1441    reg = op.m_register;
1442    return true;
1443  };
1444}
1445
1446std::function<bool(const Instruction::Operand &)>
1447lldb_private::OperandMatchers::MatchImmOp(int64_t imm) {
1448  return [imm](const Instruction::Operand &op) {
1449    return (op.m_type == Instruction::Operand::Type::Immediate &&
1450            ((op.m_negative && op.m_immediate == (uint64_t)-imm) ||
1451             (!op.m_negative && op.m_immediate == (uint64_t)imm)));
1452  };
1453}
1454
1455std::function<bool(const Instruction::Operand &)>
1456lldb_private::OperandMatchers::FetchImmOp(int64_t &imm) {
1457  return [&imm](const Instruction::Operand &op) {
1458    if (op.m_type != Instruction::Operand::Type::Immediate) {
1459      return false;
1460    }
1461    if (op.m_negative) {
1462      imm = -((int64_t)op.m_immediate);
1463    } else {
1464      imm = ((int64_t)op.m_immediate);
1465    }
1466    return true;
1467  };
1468}
1469
1470std::function<bool(const Instruction::Operand &)>
1471lldb_private::OperandMatchers::MatchOpType(Instruction::Operand::Type type) {
1472  return [type](const Instruction::Operand &op) { return op.m_type == type; };
1473}
1474