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