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