15ffd83dbSDimitry Andric //===-- Disassembler.cpp --------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "lldb/Core/Disassembler.h"
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #include "lldb/Core/AddressRange.h"
120b57cec5SDimitry Andric #include "lldb/Core/Debugger.h"
130b57cec5SDimitry Andric #include "lldb/Core/EmulateInstruction.h"
140b57cec5SDimitry Andric #include "lldb/Core/Mangled.h"
150b57cec5SDimitry Andric #include "lldb/Core/Module.h"
160b57cec5SDimitry Andric #include "lldb/Core/ModuleList.h"
170b57cec5SDimitry Andric #include "lldb/Core/PluginManager.h"
180b57cec5SDimitry Andric #include "lldb/Core/SourceManager.h"
190b57cec5SDimitry Andric #include "lldb/Host/FileSystem.h"
200b57cec5SDimitry Andric #include "lldb/Interpreter/OptionValue.h"
210b57cec5SDimitry Andric #include "lldb/Interpreter/OptionValueArray.h"
220b57cec5SDimitry Andric #include "lldb/Interpreter/OptionValueDictionary.h"
230b57cec5SDimitry Andric #include "lldb/Interpreter/OptionValueRegex.h"
240b57cec5SDimitry Andric #include "lldb/Interpreter/OptionValueString.h"
250b57cec5SDimitry Andric #include "lldb/Interpreter/OptionValueUInt64.h"
260b57cec5SDimitry Andric #include "lldb/Symbol/Function.h"
270b57cec5SDimitry Andric #include "lldb/Symbol/Symbol.h"
280b57cec5SDimitry Andric #include "lldb/Symbol/SymbolContext.h"
290b57cec5SDimitry Andric #include "lldb/Target/ExecutionContext.h"
300b57cec5SDimitry Andric #include "lldb/Target/SectionLoadList.h"
310b57cec5SDimitry Andric #include "lldb/Target/StackFrame.h"
320b57cec5SDimitry Andric #include "lldb/Target/Target.h"
330b57cec5SDimitry Andric #include "lldb/Target/Thread.h"
340b57cec5SDimitry Andric #include "lldb/Utility/DataBufferHeap.h"
350b57cec5SDimitry Andric #include "lldb/Utility/DataExtractor.h"
360b57cec5SDimitry Andric #include "lldb/Utility/RegularExpression.h"
370b57cec5SDimitry Andric #include "lldb/Utility/Status.h"
380b57cec5SDimitry Andric #include "lldb/Utility/Stream.h"
390b57cec5SDimitry Andric #include "lldb/Utility/StreamString.h"
400b57cec5SDimitry Andric #include "lldb/Utility/Timer.h"
410b57cec5SDimitry Andric #include "lldb/lldb-private-enumerations.h"
420b57cec5SDimitry Andric #include "lldb/lldb-private-interfaces.h"
430b57cec5SDimitry Andric #include "lldb/lldb-private-types.h"
440b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
4506c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h"
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric #include <cstdint>
480b57cec5SDimitry Andric #include <cstring>
490b57cec5SDimitry Andric #include <utility>
500b57cec5SDimitry Andric 
51fe6060f1SDimitry Andric #include <cassert>
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric #define DEFAULT_DISASM_BYTE_SIZE 32
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric using namespace lldb;
560b57cec5SDimitry Andric using namespace lldb_private;
570b57cec5SDimitry Andric 
FindPlugin(const ArchSpec & arch,const char * flavor,const char * plugin_name)580b57cec5SDimitry Andric DisassemblerSP Disassembler::FindPlugin(const ArchSpec &arch,
590b57cec5SDimitry Andric                                         const char *flavor,
600b57cec5SDimitry Andric                                         const char *plugin_name) {
61e8d8bef9SDimitry Andric   LLDB_SCOPED_TIMERF("Disassembler::FindPlugin (arch = %s, plugin_name = %s)",
620b57cec5SDimitry Andric                      arch.GetArchitectureName(), plugin_name);
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric   DisassemblerCreateInstance create_callback = nullptr;
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric   if (plugin_name) {
67349cc55cSDimitry Andric     create_callback =
68349cc55cSDimitry Andric         PluginManager::GetDisassemblerCreateCallbackForPluginName(plugin_name);
690b57cec5SDimitry Andric     if (create_callback) {
7006c3fb27SDimitry Andric       if (auto disasm_sp = create_callback(arch, flavor))
7106c3fb27SDimitry Andric         return disasm_sp;
720b57cec5SDimitry Andric     }
730b57cec5SDimitry Andric   } else {
740b57cec5SDimitry Andric     for (uint32_t idx = 0;
750b57cec5SDimitry Andric          (create_callback = PluginManager::GetDisassemblerCreateCallbackAtIndex(
760b57cec5SDimitry Andric               idx)) != nullptr;
770b57cec5SDimitry Andric          ++idx) {
7806c3fb27SDimitry Andric       if (auto disasm_sp = create_callback(arch, flavor))
7906c3fb27SDimitry Andric         return disasm_sp;
800b57cec5SDimitry Andric     }
810b57cec5SDimitry Andric   }
820b57cec5SDimitry Andric   return DisassemblerSP();
830b57cec5SDimitry Andric }
840b57cec5SDimitry Andric 
FindPluginForTarget(const Target & target,const ArchSpec & arch,const char * flavor,const char * plugin_name)855ffd83dbSDimitry Andric DisassemblerSP Disassembler::FindPluginForTarget(const Target &target,
860b57cec5SDimitry Andric                                                  const ArchSpec &arch,
870b57cec5SDimitry Andric                                                  const char *flavor,
880b57cec5SDimitry Andric                                                  const char *plugin_name) {
895ffd83dbSDimitry Andric   if (flavor == nullptr) {
900b57cec5SDimitry Andric     // FIXME - we don't have the mechanism in place to do per-architecture
910b57cec5SDimitry Andric     // settings.  But since we know that for now we only support flavors on x86
920b57cec5SDimitry Andric     // & x86_64,
930b57cec5SDimitry Andric     if (arch.GetTriple().getArch() == llvm::Triple::x86 ||
940b57cec5SDimitry Andric         arch.GetTriple().getArch() == llvm::Triple::x86_64)
955ffd83dbSDimitry Andric       flavor = target.GetDisassemblyFlavor();
960b57cec5SDimitry Andric   }
970b57cec5SDimitry Andric   return FindPlugin(arch, flavor, plugin_name);
980b57cec5SDimitry Andric }
990b57cec5SDimitry Andric 
ResolveAddress(Target & target,const Address & addr)1005ffd83dbSDimitry Andric static Address ResolveAddress(Target &target, const Address &addr) {
1010b57cec5SDimitry Andric   if (!addr.IsSectionOffset()) {
1025ffd83dbSDimitry Andric     Address resolved_addr;
1030b57cec5SDimitry Andric     // If we weren't passed in a section offset address range, try and resolve
1040b57cec5SDimitry Andric     // it to something
1055ffd83dbSDimitry Andric     bool is_resolved = target.GetSectionLoadList().IsEmpty()
1065ffd83dbSDimitry Andric                            ? target.GetImages().ResolveFileAddress(
1075ffd83dbSDimitry Andric                                  addr.GetOffset(), resolved_addr)
1085ffd83dbSDimitry Andric                            : target.GetSectionLoadList().ResolveLoadAddress(
1095ffd83dbSDimitry Andric                                  addr.GetOffset(), resolved_addr);
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric     // We weren't able to resolve the address, just treat it as a raw address
1120b57cec5SDimitry Andric     if (is_resolved && resolved_addr.IsValid())
1135ffd83dbSDimitry Andric       return resolved_addr;
1140b57cec5SDimitry Andric   }
1155ffd83dbSDimitry Andric   return addr;
1160b57cec5SDimitry Andric }
1170b57cec5SDimitry Andric 
DisassembleRange(const ArchSpec & arch,const char * plugin_name,const char * flavor,Target & target,const AddressRange & range,bool force_live_memory)1180b57cec5SDimitry Andric lldb::DisassemblerSP Disassembler::DisassembleRange(
1190b57cec5SDimitry Andric     const ArchSpec &arch, const char *plugin_name, const char *flavor,
120fe6060f1SDimitry Andric     Target &target, const AddressRange &range, bool force_live_memory) {
1219dba64beSDimitry Andric   if (range.GetByteSize() <= 0)
1229dba64beSDimitry Andric     return {};
1230b57cec5SDimitry Andric 
1249dba64beSDimitry Andric   if (!range.GetBaseAddress().IsValid())
1259dba64beSDimitry Andric     return {};
1269dba64beSDimitry Andric 
1275ffd83dbSDimitry Andric   lldb::DisassemblerSP disasm_sp =
1285ffd83dbSDimitry Andric       Disassembler::FindPluginForTarget(target, arch, flavor, plugin_name);
1299dba64beSDimitry Andric 
1309dba64beSDimitry Andric   if (!disasm_sp)
1319dba64beSDimitry Andric     return {};
1329dba64beSDimitry Andric 
1335ffd83dbSDimitry Andric   const size_t bytes_disassembled = disasm_sp->ParseInstructions(
1345ffd83dbSDimitry Andric       target, range.GetBaseAddress(), {Limit::Bytes, range.GetByteSize()},
135fe6060f1SDimitry Andric       nullptr, force_live_memory);
1360b57cec5SDimitry Andric   if (bytes_disassembled == 0)
1379dba64beSDimitry Andric     return {};
1389dba64beSDimitry Andric 
1390b57cec5SDimitry Andric   return disasm_sp;
1400b57cec5SDimitry Andric }
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric lldb::DisassemblerSP
DisassembleBytes(const ArchSpec & arch,const char * plugin_name,const char * flavor,const Address & start,const void * src,size_t src_len,uint32_t num_instructions,bool data_from_file)1430b57cec5SDimitry Andric Disassembler::DisassembleBytes(const ArchSpec &arch, const char *plugin_name,
1440b57cec5SDimitry Andric                                const char *flavor, const Address &start,
1450b57cec5SDimitry Andric                                const void *src, size_t src_len,
1460b57cec5SDimitry Andric                                uint32_t num_instructions, bool data_from_file) {
1479dba64beSDimitry Andric   if (!src)
1489dba64beSDimitry Andric     return {};
1490b57cec5SDimitry Andric 
1509dba64beSDimitry Andric   lldb::DisassemblerSP disasm_sp =
1519dba64beSDimitry Andric       Disassembler::FindPlugin(arch, flavor, plugin_name);
1520b57cec5SDimitry Andric 
1539dba64beSDimitry Andric   if (!disasm_sp)
1549dba64beSDimitry Andric     return {};
1559dba64beSDimitry Andric 
1560b57cec5SDimitry Andric   DataExtractor data(src, src_len, arch.GetByteOrder(),
1570b57cec5SDimitry Andric                      arch.GetAddressByteSize());
1580b57cec5SDimitry Andric 
1599dba64beSDimitry Andric   (void)disasm_sp->DecodeInstructions(start, data, 0, num_instructions, false,
1609dba64beSDimitry Andric                                       data_from_file);
1610b57cec5SDimitry Andric   return disasm_sp;
1620b57cec5SDimitry Andric }
1630b57cec5SDimitry Andric 
Disassemble(Debugger & debugger,const ArchSpec & arch,const char * plugin_name,const char * flavor,const ExecutionContext & exe_ctx,const Address & address,Limit limit,bool mixed_source_and_assembly,uint32_t num_mixed_context_lines,uint32_t options,Stream & strm)1640b57cec5SDimitry Andric bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch,
1650b57cec5SDimitry Andric                                const char *plugin_name, const char *flavor,
1660b57cec5SDimitry Andric                                const ExecutionContext &exe_ctx,
1675ffd83dbSDimitry Andric                                const Address &address, Limit limit,
1680b57cec5SDimitry Andric                                bool mixed_source_and_assembly,
1690b57cec5SDimitry Andric                                uint32_t num_mixed_context_lines,
1700b57cec5SDimitry Andric                                uint32_t options, Stream &strm) {
1715ffd83dbSDimitry Andric   if (!exe_ctx.GetTargetPtr())
1729dba64beSDimitry Andric     return false;
1739dba64beSDimitry Andric 
1740b57cec5SDimitry Andric   lldb::DisassemblerSP disasm_sp(Disassembler::FindPluginForTarget(
1755ffd83dbSDimitry Andric       exe_ctx.GetTargetRef(), arch, flavor, plugin_name));
1769dba64beSDimitry Andric   if (!disasm_sp)
1779dba64beSDimitry Andric     return false;
1789dba64beSDimitry Andric 
179fe6060f1SDimitry Andric   const bool force_live_memory = true;
1800b57cec5SDimitry Andric   size_t bytes_disassembled = disasm_sp->ParseInstructions(
181fe6060f1SDimitry Andric       exe_ctx.GetTargetRef(), address, limit, &strm, force_live_memory);
1820b57cec5SDimitry Andric   if (bytes_disassembled == 0)
1830b57cec5SDimitry Andric     return false;
1849dba64beSDimitry Andric 
1855ffd83dbSDimitry Andric   disasm_sp->PrintInstructions(debugger, arch, exe_ctx,
1865ffd83dbSDimitry Andric                                mixed_source_and_assembly,
1870b57cec5SDimitry Andric                                num_mixed_context_lines, options, strm);
1885ffd83dbSDimitry Andric   return true;
1890b57cec5SDimitry Andric }
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric Disassembler::SourceLine
GetFunctionDeclLineEntry(const SymbolContext & sc)1920b57cec5SDimitry Andric Disassembler::GetFunctionDeclLineEntry(const SymbolContext &sc) {
1939dba64beSDimitry Andric   if (!sc.function)
1949dba64beSDimitry Andric     return {};
1959dba64beSDimitry Andric 
1969dba64beSDimitry Andric   if (!sc.line_entry.IsValid())
1979dba64beSDimitry Andric     return {};
1989dba64beSDimitry Andric 
1990b57cec5SDimitry Andric   LineEntry prologue_end_line = sc.line_entry;
2000b57cec5SDimitry Andric   FileSpec func_decl_file;
2010b57cec5SDimitry Andric   uint32_t func_decl_line;
2020b57cec5SDimitry Andric   sc.function->GetStartLineSourceInfo(func_decl_file, func_decl_line);
2039dba64beSDimitry Andric 
2049dba64beSDimitry Andric   if (func_decl_file != prologue_end_line.file &&
2057a6dacacSDimitry Andric       func_decl_file != prologue_end_line.original_file_sp->GetSpecOnly())
2069dba64beSDimitry Andric     return {};
2079dba64beSDimitry Andric 
2089dba64beSDimitry Andric   SourceLine decl_line;
2090b57cec5SDimitry Andric   decl_line.file = func_decl_file;
2100b57cec5SDimitry Andric   decl_line.line = func_decl_line;
2119dba64beSDimitry Andric   // TODO: Do we care about column on these entries?  If so, we need to plumb
2129dba64beSDimitry Andric   // that through GetStartLineSourceInfo.
2130b57cec5SDimitry Andric   decl_line.column = 0;
2140b57cec5SDimitry Andric   return decl_line;
2150b57cec5SDimitry Andric }
2160b57cec5SDimitry Andric 
AddLineToSourceLineTables(SourceLine & line,std::map<FileSpec,std::set<uint32_t>> & source_lines_seen)2170b57cec5SDimitry Andric void Disassembler::AddLineToSourceLineTables(
2180b57cec5SDimitry Andric     SourceLine &line,
2190b57cec5SDimitry Andric     std::map<FileSpec, std::set<uint32_t>> &source_lines_seen) {
2200b57cec5SDimitry Andric   if (line.IsValid()) {
2210b57cec5SDimitry Andric     auto source_lines_seen_pos = source_lines_seen.find(line.file);
2220b57cec5SDimitry Andric     if (source_lines_seen_pos == source_lines_seen.end()) {
2230b57cec5SDimitry Andric       std::set<uint32_t> lines;
2240b57cec5SDimitry Andric       lines.insert(line.line);
2250b57cec5SDimitry Andric       source_lines_seen.emplace(line.file, lines);
2260b57cec5SDimitry Andric     } else {
2270b57cec5SDimitry Andric       source_lines_seen_pos->second.insert(line.line);
2280b57cec5SDimitry Andric     }
2290b57cec5SDimitry Andric   }
2300b57cec5SDimitry Andric }
2310b57cec5SDimitry Andric 
ElideMixedSourceAndDisassemblyLine(const ExecutionContext & exe_ctx,const SymbolContext & sc,SourceLine & line)2320b57cec5SDimitry Andric bool Disassembler::ElideMixedSourceAndDisassemblyLine(
2330b57cec5SDimitry Andric     const ExecutionContext &exe_ctx, const SymbolContext &sc,
2340b57cec5SDimitry Andric     SourceLine &line) {
2350b57cec5SDimitry Andric 
2360b57cec5SDimitry Andric   // TODO: should we also check target.process.thread.step-avoid-libraries ?
2370b57cec5SDimitry Andric 
2380b57cec5SDimitry Andric   const RegularExpression *avoid_regex = nullptr;
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric   // Skip any line #0 entries - they are implementation details
2410b57cec5SDimitry Andric   if (line.line == 0)
24206c3fb27SDimitry Andric     return true;
2430b57cec5SDimitry Andric 
2440b57cec5SDimitry Andric   ThreadSP thread_sp = exe_ctx.GetThreadSP();
2450b57cec5SDimitry Andric   if (thread_sp) {
2460b57cec5SDimitry Andric     avoid_regex = thread_sp->GetSymbolsToAvoidRegexp();
2470b57cec5SDimitry Andric   } else {
2480b57cec5SDimitry Andric     TargetSP target_sp = exe_ctx.GetTargetSP();
2490b57cec5SDimitry Andric     if (target_sp) {
2500b57cec5SDimitry Andric       Status error;
2510b57cec5SDimitry Andric       OptionValueSP value_sp = target_sp->GetDebugger().GetPropertyValue(
25206c3fb27SDimitry Andric           &exe_ctx, "target.process.thread.step-avoid-regexp", error);
2530b57cec5SDimitry Andric       if (value_sp && value_sp->GetType() == OptionValue::eTypeRegex) {
2540b57cec5SDimitry Andric         OptionValueRegex *re = value_sp->GetAsRegex();
2550b57cec5SDimitry Andric         if (re) {
2560b57cec5SDimitry Andric           avoid_regex = re->GetCurrentValue();
2570b57cec5SDimitry Andric         }
2580b57cec5SDimitry Andric       }
2590b57cec5SDimitry Andric     }
2600b57cec5SDimitry Andric   }
2610b57cec5SDimitry Andric   if (avoid_regex && sc.symbol != nullptr) {
2620b57cec5SDimitry Andric     const char *function_name =
2630b57cec5SDimitry Andric         sc.GetFunctionName(Mangled::ePreferDemangledWithoutArguments)
2640b57cec5SDimitry Andric             .GetCString();
2659dba64beSDimitry Andric     if (function_name && avoid_regex->Execute(function_name)) {
2660b57cec5SDimitry Andric       // skip this source line
2670b57cec5SDimitry Andric       return true;
2680b57cec5SDimitry Andric     }
2690b57cec5SDimitry Andric   }
2700b57cec5SDimitry Andric   // don't skip this source line
2710b57cec5SDimitry Andric   return false;
2720b57cec5SDimitry Andric }
2730b57cec5SDimitry Andric 
PrintInstructions(Debugger & debugger,const ArchSpec & arch,const ExecutionContext & exe_ctx,bool mixed_source_and_assembly,uint32_t num_mixed_context_lines,uint32_t options,Stream & strm)2745ffd83dbSDimitry Andric void Disassembler::PrintInstructions(Debugger &debugger, const ArchSpec &arch,
2750b57cec5SDimitry Andric                                      const ExecutionContext &exe_ctx,
2760b57cec5SDimitry Andric                                      bool mixed_source_and_assembly,
2770b57cec5SDimitry Andric                                      uint32_t num_mixed_context_lines,
2780b57cec5SDimitry Andric                                      uint32_t options, Stream &strm) {
2790b57cec5SDimitry Andric   // We got some things disassembled...
2805ffd83dbSDimitry Andric   size_t num_instructions_found = GetInstructionList().GetSize();
2810b57cec5SDimitry Andric 
2820b57cec5SDimitry Andric   const uint32_t max_opcode_byte_size =
2835ffd83dbSDimitry Andric       GetInstructionList().GetMaxOpcocdeByteSize();
2840b57cec5SDimitry Andric   SymbolContext sc;
2850b57cec5SDimitry Andric   SymbolContext prev_sc;
2860b57cec5SDimitry Andric   AddressRange current_source_line_range;
2870b57cec5SDimitry Andric   const Address *pc_addr_ptr = nullptr;
2880b57cec5SDimitry Andric   StackFrame *frame = exe_ctx.GetFramePtr();
2890b57cec5SDimitry Andric 
2900b57cec5SDimitry Andric   TargetSP target_sp(exe_ctx.GetTargetSP());
2910b57cec5SDimitry Andric   SourceManager &source_manager =
2920b57cec5SDimitry Andric       target_sp ? target_sp->GetSourceManager() : debugger.GetSourceManager();
2930b57cec5SDimitry Andric 
2940b57cec5SDimitry Andric   if (frame) {
2950b57cec5SDimitry Andric     pc_addr_ptr = &frame->GetFrameCodeAddress();
2960b57cec5SDimitry Andric   }
2970b57cec5SDimitry Andric   const uint32_t scope =
2980b57cec5SDimitry Andric       eSymbolContextLineEntry | eSymbolContextFunction | eSymbolContextSymbol;
2990b57cec5SDimitry Andric   const bool use_inline_block_range = false;
3000b57cec5SDimitry Andric 
3010b57cec5SDimitry Andric   const FormatEntity::Entry *disassembly_format = nullptr;
3020b57cec5SDimitry Andric   FormatEntity::Entry format;
3030b57cec5SDimitry Andric   if (exe_ctx.HasTargetScope()) {
3040b57cec5SDimitry Andric     disassembly_format =
3050b57cec5SDimitry Andric         exe_ctx.GetTargetRef().GetDebugger().GetDisassemblyFormat();
3060b57cec5SDimitry Andric   } else {
3070b57cec5SDimitry Andric     FormatEntity::Parse("${addr}: ", format);
3080b57cec5SDimitry Andric     disassembly_format = &format;
3090b57cec5SDimitry Andric   }
3100b57cec5SDimitry Andric 
3110b57cec5SDimitry Andric   // First pass: step through the list of instructions, find how long the
3120b57cec5SDimitry Andric   // initial addresses strings are, insert padding in the second pass so the
3130b57cec5SDimitry Andric   // opcodes all line up nicely.
3140b57cec5SDimitry Andric 
3150b57cec5SDimitry Andric   // Also build up the source line mapping if this is mixed source & assembly
3160b57cec5SDimitry Andric   // mode. Calculate the source line for each assembly instruction (eliding
3170b57cec5SDimitry Andric   // inlined functions which the user wants to skip).
3180b57cec5SDimitry Andric 
3190b57cec5SDimitry Andric   std::map<FileSpec, std::set<uint32_t>> source_lines_seen;
3200b57cec5SDimitry Andric   Symbol *previous_symbol = nullptr;
3210b57cec5SDimitry Andric 
3220b57cec5SDimitry Andric   size_t address_text_size = 0;
3230b57cec5SDimitry Andric   for (size_t i = 0; i < num_instructions_found; ++i) {
3245ffd83dbSDimitry Andric     Instruction *inst = GetInstructionList().GetInstructionAtIndex(i).get();
3250b57cec5SDimitry Andric     if (inst) {
3260b57cec5SDimitry Andric       const Address &addr = inst->GetAddress();
3270b57cec5SDimitry Andric       ModuleSP module_sp(addr.GetModule());
3280b57cec5SDimitry Andric       if (module_sp) {
3290b57cec5SDimitry Andric         const SymbolContextItem resolve_mask = eSymbolContextFunction |
3300b57cec5SDimitry Andric                                                eSymbolContextSymbol |
3310b57cec5SDimitry Andric                                                eSymbolContextLineEntry;
3320b57cec5SDimitry Andric         uint32_t resolved_mask =
3330b57cec5SDimitry Andric             module_sp->ResolveSymbolContextForAddress(addr, resolve_mask, sc);
3340b57cec5SDimitry Andric         if (resolved_mask) {
3350b57cec5SDimitry Andric           StreamString strmstr;
3360b57cec5SDimitry Andric           Debugger::FormatDisassemblerAddress(disassembly_format, &sc, nullptr,
3370b57cec5SDimitry Andric                                               &exe_ctx, &addr, strmstr);
3380b57cec5SDimitry Andric           size_t cur_line = strmstr.GetSizeOfLastLine();
3390b57cec5SDimitry Andric           if (cur_line > address_text_size)
3400b57cec5SDimitry Andric             address_text_size = cur_line;
3410b57cec5SDimitry Andric 
3420b57cec5SDimitry Andric           // Add entries to our "source_lines_seen" map+set which list which
3430b57cec5SDimitry Andric           // sources lines occur in this disassembly session.  We will print
3440b57cec5SDimitry Andric           // lines of context around a source line, but we don't want to print
3450b57cec5SDimitry Andric           // a source line that has a line table entry of its own - we'll leave
3460b57cec5SDimitry Andric           // that source line to be printed when it actually occurs in the
3470b57cec5SDimitry Andric           // disassembly.
3480b57cec5SDimitry Andric 
3490b57cec5SDimitry Andric           if (mixed_source_and_assembly && sc.line_entry.IsValid()) {
3500b57cec5SDimitry Andric             if (sc.symbol != previous_symbol) {
3510b57cec5SDimitry Andric               SourceLine decl_line = GetFunctionDeclLineEntry(sc);
3520b57cec5SDimitry Andric               if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, decl_line))
3530b57cec5SDimitry Andric                 AddLineToSourceLineTables(decl_line, source_lines_seen);
3540b57cec5SDimitry Andric             }
3550b57cec5SDimitry Andric             if (sc.line_entry.IsValid()) {
3560b57cec5SDimitry Andric               SourceLine this_line;
3570b57cec5SDimitry Andric               this_line.file = sc.line_entry.file;
3580b57cec5SDimitry Andric               this_line.line = sc.line_entry.line;
3590b57cec5SDimitry Andric               this_line.column = sc.line_entry.column;
3600b57cec5SDimitry Andric               if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, this_line))
3610b57cec5SDimitry Andric                 AddLineToSourceLineTables(this_line, source_lines_seen);
3620b57cec5SDimitry Andric             }
3630b57cec5SDimitry Andric           }
3640b57cec5SDimitry Andric         }
3650b57cec5SDimitry Andric         sc.Clear(false);
3660b57cec5SDimitry Andric       }
3670b57cec5SDimitry Andric     }
3680b57cec5SDimitry Andric   }
3690b57cec5SDimitry Andric 
3700b57cec5SDimitry Andric   previous_symbol = nullptr;
3710b57cec5SDimitry Andric   SourceLine previous_line;
3720b57cec5SDimitry Andric   for (size_t i = 0; i < num_instructions_found; ++i) {
3735ffd83dbSDimitry Andric     Instruction *inst = GetInstructionList().GetInstructionAtIndex(i).get();
3740b57cec5SDimitry Andric 
3750b57cec5SDimitry Andric     if (inst) {
3760b57cec5SDimitry Andric       const Address &addr = inst->GetAddress();
3770b57cec5SDimitry Andric       const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr;
3780b57cec5SDimitry Andric       SourceLinesToDisplay source_lines_to_display;
3790b57cec5SDimitry Andric 
3800b57cec5SDimitry Andric       prev_sc = sc;
3810b57cec5SDimitry Andric 
3820b57cec5SDimitry Andric       ModuleSP module_sp(addr.GetModule());
3830b57cec5SDimitry Andric       if (module_sp) {
3840b57cec5SDimitry Andric         uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress(
3850b57cec5SDimitry Andric             addr, eSymbolContextEverything, sc);
3860b57cec5SDimitry Andric         if (resolved_mask) {
3870b57cec5SDimitry Andric           if (mixed_source_and_assembly) {
3880b57cec5SDimitry Andric 
3890b57cec5SDimitry Andric             // If we've started a new function (non-inlined), print all of the
3900b57cec5SDimitry Andric             // source lines from the function declaration until the first line
3910b57cec5SDimitry Andric             // table entry - typically the opening curly brace of the function.
3920b57cec5SDimitry Andric             if (previous_symbol != sc.symbol) {
3930b57cec5SDimitry Andric               // The default disassembly format puts an extra blank line
3940b57cec5SDimitry Andric               // between functions - so when we're displaying the source
3950b57cec5SDimitry Andric               // context for a function, we don't want to add a blank line
3960b57cec5SDimitry Andric               // after the source context or we'll end up with two of them.
3970b57cec5SDimitry Andric               if (previous_symbol != nullptr)
3980b57cec5SDimitry Andric                 source_lines_to_display.print_source_context_end_eol = false;
3990b57cec5SDimitry Andric 
4000b57cec5SDimitry Andric               previous_symbol = sc.symbol;
4010b57cec5SDimitry Andric               if (sc.function && sc.line_entry.IsValid()) {
4020b57cec5SDimitry Andric                 LineEntry prologue_end_line = sc.line_entry;
4030b57cec5SDimitry Andric                 if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc,
4040b57cec5SDimitry Andric                                                         prologue_end_line)) {
4050b57cec5SDimitry Andric                   FileSpec func_decl_file;
4060b57cec5SDimitry Andric                   uint32_t func_decl_line;
4070b57cec5SDimitry Andric                   sc.function->GetStartLineSourceInfo(func_decl_file,
4080b57cec5SDimitry Andric                                                       func_decl_line);
4090b57cec5SDimitry Andric                   if (func_decl_file == prologue_end_line.file ||
4107a6dacacSDimitry Andric                       func_decl_file ==
4117a6dacacSDimitry Andric                           prologue_end_line.original_file_sp->GetSpecOnly()) {
4120b57cec5SDimitry Andric                     // Add all the lines between the function declaration and
4130b57cec5SDimitry Andric                     // the first non-prologue source line to the list of lines
4140b57cec5SDimitry Andric                     // to print.
4150b57cec5SDimitry Andric                     for (uint32_t lineno = func_decl_line;
4160b57cec5SDimitry Andric                          lineno <= prologue_end_line.line; lineno++) {
4170b57cec5SDimitry Andric                       SourceLine this_line;
4180b57cec5SDimitry Andric                       this_line.file = func_decl_file;
4190b57cec5SDimitry Andric                       this_line.line = lineno;
4200b57cec5SDimitry Andric                       source_lines_to_display.lines.push_back(this_line);
4210b57cec5SDimitry Andric                     }
4220b57cec5SDimitry Andric                     // Mark the last line as the "current" one.  Usually this
4230b57cec5SDimitry Andric                     // is the open curly brace.
4240b57cec5SDimitry Andric                     if (source_lines_to_display.lines.size() > 0)
4250b57cec5SDimitry Andric                       source_lines_to_display.current_source_line =
4260b57cec5SDimitry Andric                           source_lines_to_display.lines.size() - 1;
4270b57cec5SDimitry Andric                   }
4280b57cec5SDimitry Andric                 }
4290b57cec5SDimitry Andric               }
4300b57cec5SDimitry Andric               sc.GetAddressRange(scope, 0, use_inline_block_range,
4310b57cec5SDimitry Andric                                  current_source_line_range);
4320b57cec5SDimitry Andric             }
4330b57cec5SDimitry Andric 
4340b57cec5SDimitry Andric             // If we've left a previous source line's address range, print a
4350b57cec5SDimitry Andric             // new source line
4360b57cec5SDimitry Andric             if (!current_source_line_range.ContainsFileAddress(addr)) {
4370b57cec5SDimitry Andric               sc.GetAddressRange(scope, 0, use_inline_block_range,
4380b57cec5SDimitry Andric                                  current_source_line_range);
4390b57cec5SDimitry Andric 
4400b57cec5SDimitry Andric               if (sc != prev_sc && sc.comp_unit && sc.line_entry.IsValid()) {
4410b57cec5SDimitry Andric                 SourceLine this_line;
4420b57cec5SDimitry Andric                 this_line.file = sc.line_entry.file;
4430b57cec5SDimitry Andric                 this_line.line = sc.line_entry.line;
4440b57cec5SDimitry Andric 
4450b57cec5SDimitry Andric                 if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc,
4460b57cec5SDimitry Andric                                                         this_line)) {
4470b57cec5SDimitry Andric                   // Only print this source line if it is different from the
4480b57cec5SDimitry Andric                   // last source line we printed.  There may have been inlined
4490b57cec5SDimitry Andric                   // functions between these lines that we elided, resulting in
4500b57cec5SDimitry Andric                   // the same line being printed twice in a row for a
4510b57cec5SDimitry Andric                   // contiguous block of assembly instructions.
4520b57cec5SDimitry Andric                   if (this_line != previous_line) {
4530b57cec5SDimitry Andric 
4540b57cec5SDimitry Andric                     std::vector<uint32_t> previous_lines;
4550b57cec5SDimitry Andric                     for (uint32_t i = 0;
4560b57cec5SDimitry Andric                          i < num_mixed_context_lines &&
4570b57cec5SDimitry Andric                          (this_line.line - num_mixed_context_lines) > 0;
4580b57cec5SDimitry Andric                          i++) {
4590b57cec5SDimitry Andric                       uint32_t line =
4600b57cec5SDimitry Andric                           this_line.line - num_mixed_context_lines + i;
4610b57cec5SDimitry Andric                       auto pos = source_lines_seen.find(this_line.file);
4620b57cec5SDimitry Andric                       if (pos != source_lines_seen.end()) {
4630b57cec5SDimitry Andric                         if (pos->second.count(line) == 1) {
4640b57cec5SDimitry Andric                           previous_lines.clear();
4650b57cec5SDimitry Andric                         } else {
4660b57cec5SDimitry Andric                           previous_lines.push_back(line);
4670b57cec5SDimitry Andric                         }
4680b57cec5SDimitry Andric                       }
4690b57cec5SDimitry Andric                     }
4700b57cec5SDimitry Andric                     for (size_t i = 0; i < previous_lines.size(); i++) {
4710b57cec5SDimitry Andric                       SourceLine previous_line;
4720b57cec5SDimitry Andric                       previous_line.file = this_line.file;
4730b57cec5SDimitry Andric                       previous_line.line = previous_lines[i];
4740b57cec5SDimitry Andric                       auto pos = source_lines_seen.find(previous_line.file);
4750b57cec5SDimitry Andric                       if (pos != source_lines_seen.end()) {
4760b57cec5SDimitry Andric                         pos->second.insert(previous_line.line);
4770b57cec5SDimitry Andric                       }
4780b57cec5SDimitry Andric                       source_lines_to_display.lines.push_back(previous_line);
4790b57cec5SDimitry Andric                     }
4800b57cec5SDimitry Andric 
4810b57cec5SDimitry Andric                     source_lines_to_display.lines.push_back(this_line);
4820b57cec5SDimitry Andric                     source_lines_to_display.current_source_line =
4830b57cec5SDimitry Andric                         source_lines_to_display.lines.size() - 1;
4840b57cec5SDimitry Andric 
4850b57cec5SDimitry Andric                     for (uint32_t i = 0; i < num_mixed_context_lines; i++) {
4860b57cec5SDimitry Andric                       SourceLine next_line;
4870b57cec5SDimitry Andric                       next_line.file = this_line.file;
4880b57cec5SDimitry Andric                       next_line.line = this_line.line + i + 1;
4890b57cec5SDimitry Andric                       auto pos = source_lines_seen.find(next_line.file);
4900b57cec5SDimitry Andric                       if (pos != source_lines_seen.end()) {
4910b57cec5SDimitry Andric                         if (pos->second.count(next_line.line) == 1)
4920b57cec5SDimitry Andric                           break;
4930b57cec5SDimitry Andric                         pos->second.insert(next_line.line);
4940b57cec5SDimitry Andric                       }
4950b57cec5SDimitry Andric                       source_lines_to_display.lines.push_back(next_line);
4960b57cec5SDimitry Andric                     }
4970b57cec5SDimitry Andric                   }
4980b57cec5SDimitry Andric                   previous_line = this_line;
4990b57cec5SDimitry Andric                 }
5000b57cec5SDimitry Andric               }
5010b57cec5SDimitry Andric             }
5020b57cec5SDimitry Andric           }
5030b57cec5SDimitry Andric         } else {
5040b57cec5SDimitry Andric           sc.Clear(true);
5050b57cec5SDimitry Andric         }
5060b57cec5SDimitry Andric       }
5070b57cec5SDimitry Andric 
5080b57cec5SDimitry Andric       if (source_lines_to_display.lines.size() > 0) {
5090b57cec5SDimitry Andric         strm.EOL();
5100b57cec5SDimitry Andric         for (size_t idx = 0; idx < source_lines_to_display.lines.size();
5110b57cec5SDimitry Andric              idx++) {
5120b57cec5SDimitry Andric           SourceLine ln = source_lines_to_display.lines[idx];
5130b57cec5SDimitry Andric           const char *line_highlight = "";
5140b57cec5SDimitry Andric           if (inst_is_at_pc && (options & eOptionMarkPCSourceLine)) {
5150b57cec5SDimitry Andric             line_highlight = "->";
5160b57cec5SDimitry Andric           } else if (idx == source_lines_to_display.current_source_line) {
5170b57cec5SDimitry Andric             line_highlight = "**";
5180b57cec5SDimitry Andric           }
5190b57cec5SDimitry Andric           source_manager.DisplaySourceLinesWithLineNumbers(
5200b57cec5SDimitry Andric               ln.file, ln.line, ln.column, 0, 0, line_highlight, &strm);
5210b57cec5SDimitry Andric         }
5220b57cec5SDimitry Andric         if (source_lines_to_display.print_source_context_end_eol)
5230b57cec5SDimitry Andric           strm.EOL();
5240b57cec5SDimitry Andric       }
5250b57cec5SDimitry Andric 
5260b57cec5SDimitry Andric       const bool show_bytes = (options & eOptionShowBytes) != 0;
527753f127fSDimitry Andric       const bool show_control_flow_kind =
528753f127fSDimitry Andric           (options & eOptionShowControlFlowKind) != 0;
529753f127fSDimitry Andric       inst->Dump(&strm, max_opcode_byte_size, true, show_bytes,
530753f127fSDimitry Andric                  show_control_flow_kind, &exe_ctx, &sc, &prev_sc, nullptr,
531753f127fSDimitry Andric                  address_text_size);
5320b57cec5SDimitry Andric       strm.EOL();
5330b57cec5SDimitry Andric     } else {
5340b57cec5SDimitry Andric       break;
5350b57cec5SDimitry Andric     }
5360b57cec5SDimitry Andric   }
5370b57cec5SDimitry Andric }
5380b57cec5SDimitry Andric 
Disassemble(Debugger & debugger,const ArchSpec & arch,StackFrame & frame,Stream & strm)5390b57cec5SDimitry Andric bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch,
540e8d8bef9SDimitry Andric                                StackFrame &frame, Stream &strm) {
5410b57cec5SDimitry Andric   AddressRange range;
5420b57cec5SDimitry Andric   SymbolContext sc(
543e8d8bef9SDimitry Andric       frame.GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
5440b57cec5SDimitry Andric   if (sc.function) {
5450b57cec5SDimitry Andric     range = sc.function->GetAddressRange();
5460b57cec5SDimitry Andric   } else if (sc.symbol && sc.symbol->ValueIsAddress()) {
5470b57cec5SDimitry Andric     range.GetBaseAddress() = sc.symbol->GetAddressRef();
5480b57cec5SDimitry Andric     range.SetByteSize(sc.symbol->GetByteSize());
5490b57cec5SDimitry Andric   } else {
550e8d8bef9SDimitry Andric     range.GetBaseAddress() = frame.GetFrameCodeAddress();
5510b57cec5SDimitry Andric   }
5520b57cec5SDimitry Andric 
5530b57cec5SDimitry Andric     if (range.GetBaseAddress().IsValid() && range.GetByteSize() == 0)
5540b57cec5SDimitry Andric       range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE);
5550b57cec5SDimitry Andric 
556e8d8bef9SDimitry Andric     Disassembler::Limit limit = {Disassembler::Limit::Bytes,
557e8d8bef9SDimitry Andric                                  range.GetByteSize()};
558e8d8bef9SDimitry Andric     if (limit.value == 0)
559e8d8bef9SDimitry Andric       limit.value = DEFAULT_DISASM_BYTE_SIZE;
560e8d8bef9SDimitry Andric 
561e8d8bef9SDimitry Andric     return Disassemble(debugger, arch, nullptr, nullptr, frame,
562e8d8bef9SDimitry Andric                        range.GetBaseAddress(), limit, false, 0, 0, strm);
5630b57cec5SDimitry Andric }
5640b57cec5SDimitry Andric 
Instruction(const Address & address,AddressClass addr_class)5650b57cec5SDimitry Andric Instruction::Instruction(const Address &address, AddressClass addr_class)
5660b57cec5SDimitry Andric     : m_address(address), m_address_class(addr_class), m_opcode(),
5670b57cec5SDimitry Andric       m_calculated_strings(false) {}
5680b57cec5SDimitry Andric 
5690b57cec5SDimitry Andric Instruction::~Instruction() = default;
5700b57cec5SDimitry Andric 
GetAddressClass()5710b57cec5SDimitry Andric AddressClass Instruction::GetAddressClass() {
5720b57cec5SDimitry Andric   if (m_address_class == AddressClass::eInvalid)
5730b57cec5SDimitry Andric     m_address_class = m_address.GetAddressClass();
5740b57cec5SDimitry Andric   return m_address_class;
5750b57cec5SDimitry Andric }
5760b57cec5SDimitry Andric 
GetNameForInstructionControlFlowKind(lldb::InstructionControlFlowKind instruction_control_flow_kind)577972a253aSDimitry Andric const char *Instruction::GetNameForInstructionControlFlowKind(
578972a253aSDimitry Andric     lldb::InstructionControlFlowKind instruction_control_flow_kind) {
579972a253aSDimitry Andric   switch (instruction_control_flow_kind) {
580972a253aSDimitry Andric   case eInstructionControlFlowKindUnknown:
581972a253aSDimitry Andric     return "unknown";
582972a253aSDimitry Andric   case eInstructionControlFlowKindOther:
583972a253aSDimitry Andric     return "other";
584972a253aSDimitry Andric   case eInstructionControlFlowKindCall:
585972a253aSDimitry Andric     return "call";
586972a253aSDimitry Andric   case eInstructionControlFlowKindReturn:
587972a253aSDimitry Andric     return "return";
588972a253aSDimitry Andric   case eInstructionControlFlowKindJump:
589972a253aSDimitry Andric     return "jump";
590972a253aSDimitry Andric   case eInstructionControlFlowKindCondJump:
591972a253aSDimitry Andric     return "cond jump";
592972a253aSDimitry Andric   case eInstructionControlFlowKindFarCall:
593972a253aSDimitry Andric     return "far call";
594972a253aSDimitry Andric   case eInstructionControlFlowKindFarReturn:
595972a253aSDimitry Andric     return "far return";
596972a253aSDimitry Andric   case eInstructionControlFlowKindFarJump:
597972a253aSDimitry Andric     return "far jump";
598972a253aSDimitry Andric   }
59961cfbce3SDimitry Andric   llvm_unreachable("Fully covered switch above!");
600972a253aSDimitry Andric }
601972a253aSDimitry Andric 
Dump(lldb_private::Stream * s,uint32_t max_opcode_byte_size,bool show_address,bool show_bytes,bool show_control_flow_kind,const ExecutionContext * exe_ctx,const SymbolContext * sym_ctx,const SymbolContext * prev_sym_ctx,const FormatEntity::Entry * disassembly_addr_format,size_t max_address_text_size)6020b57cec5SDimitry Andric void Instruction::Dump(lldb_private::Stream *s, uint32_t max_opcode_byte_size,
6030b57cec5SDimitry Andric                        bool show_address, bool show_bytes,
604753f127fSDimitry Andric                        bool show_control_flow_kind,
6050b57cec5SDimitry Andric                        const ExecutionContext *exe_ctx,
6060b57cec5SDimitry Andric                        const SymbolContext *sym_ctx,
6070b57cec5SDimitry Andric                        const SymbolContext *prev_sym_ctx,
6080b57cec5SDimitry Andric                        const FormatEntity::Entry *disassembly_addr_format,
6090b57cec5SDimitry Andric                        size_t max_address_text_size) {
6100b57cec5SDimitry Andric   size_t opcode_column_width = 7;
6110b57cec5SDimitry Andric   const size_t operand_column_width = 25;
6120b57cec5SDimitry Andric 
6130b57cec5SDimitry Andric   CalculateMnemonicOperandsAndCommentIfNeeded(exe_ctx);
6140b57cec5SDimitry Andric 
6150b57cec5SDimitry Andric   StreamString ss;
6160b57cec5SDimitry Andric 
6170b57cec5SDimitry Andric   if (show_address) {
6180b57cec5SDimitry Andric     Debugger::FormatDisassemblerAddress(disassembly_addr_format, sym_ctx,
6190b57cec5SDimitry Andric                                         prev_sym_ctx, exe_ctx, &m_address, ss);
6200b57cec5SDimitry Andric     ss.FillLastLineToColumn(max_address_text_size, ' ');
6210b57cec5SDimitry Andric   }
6220b57cec5SDimitry Andric 
6230b57cec5SDimitry Andric   if (show_bytes) {
6240b57cec5SDimitry Andric     if (m_opcode.GetType() == Opcode::eTypeBytes) {
6250b57cec5SDimitry Andric       // x86_64 and i386 are the only ones that use bytes right now so pad out
6260b57cec5SDimitry Andric       // the byte dump to be able to always show 15 bytes (3 chars each) plus a
6270b57cec5SDimitry Andric       // space
6280b57cec5SDimitry Andric       if (max_opcode_byte_size > 0)
6290b57cec5SDimitry Andric         m_opcode.Dump(&ss, max_opcode_byte_size * 3 + 1);
6300b57cec5SDimitry Andric       else
6310b57cec5SDimitry Andric         m_opcode.Dump(&ss, 15 * 3 + 1);
6320b57cec5SDimitry Andric     } else {
6330b57cec5SDimitry Andric       // Else, we have ARM or MIPS which can show up to a uint32_t 0x00000000
6340b57cec5SDimitry Andric       // (10 spaces) plus two for padding...
6350b57cec5SDimitry Andric       if (max_opcode_byte_size > 0)
6360b57cec5SDimitry Andric         m_opcode.Dump(&ss, max_opcode_byte_size * 3 + 1);
6370b57cec5SDimitry Andric       else
6380b57cec5SDimitry Andric         m_opcode.Dump(&ss, 12);
6390b57cec5SDimitry Andric     }
6400b57cec5SDimitry Andric   }
6410b57cec5SDimitry Andric 
642753f127fSDimitry Andric   if (show_control_flow_kind) {
643972a253aSDimitry Andric     lldb::InstructionControlFlowKind instruction_control_flow_kind =
644972a253aSDimitry Andric         GetControlFlowKind(exe_ctx);
645972a253aSDimitry Andric     ss.Printf("%-12s", GetNameForInstructionControlFlowKind(
646972a253aSDimitry Andric                            instruction_control_flow_kind));
647753f127fSDimitry Andric   }
648753f127fSDimitry Andric 
6495f757f3fSDimitry Andric   bool show_color = false;
6505f757f3fSDimitry Andric   if (exe_ctx) {
6515f757f3fSDimitry Andric     if (TargetSP target_sp = exe_ctx->GetTargetSP()) {
6525f757f3fSDimitry Andric       show_color = target_sp->GetDebugger().GetUseColor();
6535f757f3fSDimitry Andric     }
6545f757f3fSDimitry Andric   }
6550b57cec5SDimitry Andric   const size_t opcode_pos = ss.GetSizeOfLastLine();
6565f757f3fSDimitry Andric   const std::string &opcode_name =
6575f757f3fSDimitry Andric       show_color ? m_markup_opcode_name : m_opcode_name;
6585f757f3fSDimitry Andric   const std::string &mnemonics = show_color ? m_markup_mnemonics : m_mnemonics;
6590b57cec5SDimitry Andric 
6600b57cec5SDimitry Andric   // The default opcode size of 7 characters is plenty for most architectures
6610b57cec5SDimitry Andric   // but some like arm can pull out the occasional vqrshrun.s16.  We won't get
6625f757f3fSDimitry Andric   // consistent column spacing in these cases, unfortunately. Also note that we
6635f757f3fSDimitry Andric   // need to directly use m_opcode_name here (instead of opcode_name) so we
6645f757f3fSDimitry Andric   // don't include color codes as characters.
6650b57cec5SDimitry Andric   if (m_opcode_name.length() >= opcode_column_width) {
6660b57cec5SDimitry Andric     opcode_column_width = m_opcode_name.length() + 1;
6670b57cec5SDimitry Andric   }
6680b57cec5SDimitry Andric 
6695f757f3fSDimitry Andric   ss.PutCString(opcode_name);
6700b57cec5SDimitry Andric   ss.FillLastLineToColumn(opcode_pos + opcode_column_width, ' ');
6715f757f3fSDimitry Andric   ss.PutCString(mnemonics);
6720b57cec5SDimitry Andric 
6730b57cec5SDimitry Andric   if (!m_comment.empty()) {
6740b57cec5SDimitry Andric     ss.FillLastLineToColumn(
6750b57cec5SDimitry Andric         opcode_pos + opcode_column_width + operand_column_width, ' ');
6760b57cec5SDimitry Andric     ss.PutCString(" ; ");
6770b57cec5SDimitry Andric     ss.PutCString(m_comment);
6780b57cec5SDimitry Andric   }
6790b57cec5SDimitry Andric   s->PutCString(ss.GetString());
6800b57cec5SDimitry Andric }
6810b57cec5SDimitry Andric 
DumpEmulation(const ArchSpec & arch)6820b57cec5SDimitry Andric bool Instruction::DumpEmulation(const ArchSpec &arch) {
6830b57cec5SDimitry Andric   std::unique_ptr<EmulateInstruction> insn_emulator_up(
6840b57cec5SDimitry Andric       EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr));
6850b57cec5SDimitry Andric   if (insn_emulator_up) {
6860b57cec5SDimitry Andric     insn_emulator_up->SetInstruction(GetOpcode(), GetAddress(), nullptr);
6870b57cec5SDimitry Andric     return insn_emulator_up->EvaluateInstruction(0);
6880b57cec5SDimitry Andric   }
6890b57cec5SDimitry Andric 
6900b57cec5SDimitry Andric   return false;
6910b57cec5SDimitry Andric }
6920b57cec5SDimitry Andric 
CanSetBreakpoint()6930b57cec5SDimitry Andric bool Instruction::CanSetBreakpoint () {
6940b57cec5SDimitry Andric   return !HasDelaySlot();
6950b57cec5SDimitry Andric }
6960b57cec5SDimitry Andric 
HasDelaySlot()6970b57cec5SDimitry Andric bool Instruction::HasDelaySlot() {
6980b57cec5SDimitry Andric   // Default is false.
6990b57cec5SDimitry Andric   return false;
7000b57cec5SDimitry Andric }
7010b57cec5SDimitry Andric 
ReadArray(FILE * in_file,Stream & out_stream,OptionValue::Type data_type)70206c3fb27SDimitry Andric OptionValueSP Instruction::ReadArray(FILE *in_file, Stream &out_stream,
7030b57cec5SDimitry Andric                                      OptionValue::Type data_type) {
7040b57cec5SDimitry Andric   bool done = false;
7050b57cec5SDimitry Andric   char buffer[1024];
7060b57cec5SDimitry Andric 
7070b57cec5SDimitry Andric   auto option_value_sp = std::make_shared<OptionValueArray>(1u << data_type);
7080b57cec5SDimitry Andric 
7090b57cec5SDimitry Andric   int idx = 0;
7100b57cec5SDimitry Andric   while (!done) {
7110b57cec5SDimitry Andric     if (!fgets(buffer, 1023, in_file)) {
71206c3fb27SDimitry Andric       out_stream.Printf(
7130b57cec5SDimitry Andric           "Instruction::ReadArray:  Error reading file (fgets).\n");
7140b57cec5SDimitry Andric       option_value_sp.reset();
7150b57cec5SDimitry Andric       return option_value_sp;
7160b57cec5SDimitry Andric     }
7170b57cec5SDimitry Andric 
7180b57cec5SDimitry Andric     std::string line(buffer);
7190b57cec5SDimitry Andric 
7200b57cec5SDimitry Andric     size_t len = line.size();
7210b57cec5SDimitry Andric     if (line[len - 1] == '\n') {
7220b57cec5SDimitry Andric       line[len - 1] = '\0';
7230b57cec5SDimitry Andric       line.resize(len - 1);
7240b57cec5SDimitry Andric     }
7250b57cec5SDimitry Andric 
7260b57cec5SDimitry Andric     if ((line.size() == 1) && line[0] == ']') {
7270b57cec5SDimitry Andric       done = true;
7280b57cec5SDimitry Andric       line.clear();
7290b57cec5SDimitry Andric     }
7300b57cec5SDimitry Andric 
7310b57cec5SDimitry Andric     if (!line.empty()) {
7320b57cec5SDimitry Andric       std::string value;
7330b57cec5SDimitry Andric       static RegularExpression g_reg_exp(
7340b57cec5SDimitry Andric           llvm::StringRef("^[ \t]*([^ \t]+)[ \t]*$"));
7359dba64beSDimitry Andric       llvm::SmallVector<llvm::StringRef, 2> matches;
7369dba64beSDimitry Andric       if (g_reg_exp.Execute(line, &matches))
7379dba64beSDimitry Andric         value = matches[1].str();
7380b57cec5SDimitry Andric       else
7390b57cec5SDimitry Andric         value = line;
7400b57cec5SDimitry Andric 
7410b57cec5SDimitry Andric       OptionValueSP data_value_sp;
7420b57cec5SDimitry Andric       switch (data_type) {
7430b57cec5SDimitry Andric       case OptionValue::eTypeUInt64:
7440b57cec5SDimitry Andric         data_value_sp = std::make_shared<OptionValueUInt64>(0, 0);
7450b57cec5SDimitry Andric         data_value_sp->SetValueFromString(value);
7460b57cec5SDimitry Andric         break;
7470b57cec5SDimitry Andric       // Other types can be added later as needed.
7480b57cec5SDimitry Andric       default:
7490b57cec5SDimitry Andric         data_value_sp = std::make_shared<OptionValueString>(value.c_str(), "");
7500b57cec5SDimitry Andric         break;
7510b57cec5SDimitry Andric       }
7520b57cec5SDimitry Andric 
7530b57cec5SDimitry Andric       option_value_sp->GetAsArray()->InsertValue(idx, data_value_sp);
7540b57cec5SDimitry Andric       ++idx;
7550b57cec5SDimitry Andric     }
7560b57cec5SDimitry Andric   }
7570b57cec5SDimitry Andric 
7580b57cec5SDimitry Andric   return option_value_sp;
7590b57cec5SDimitry Andric }
7600b57cec5SDimitry Andric 
ReadDictionary(FILE * in_file,Stream & out_stream)76106c3fb27SDimitry Andric OptionValueSP Instruction::ReadDictionary(FILE *in_file, Stream &out_stream) {
7620b57cec5SDimitry Andric   bool done = false;
7630b57cec5SDimitry Andric   char buffer[1024];
7640b57cec5SDimitry Andric 
7650b57cec5SDimitry Andric   auto option_value_sp = std::make_shared<OptionValueDictionary>();
76606c3fb27SDimitry Andric   static constexpr llvm::StringLiteral encoding_key("data_encoding");
7670b57cec5SDimitry Andric   OptionValue::Type data_type = OptionValue::eTypeInvalid;
7680b57cec5SDimitry Andric 
7690b57cec5SDimitry Andric   while (!done) {
7700b57cec5SDimitry Andric     // Read the next line in the file
7710b57cec5SDimitry Andric     if (!fgets(buffer, 1023, in_file)) {
77206c3fb27SDimitry Andric       out_stream.Printf(
7730b57cec5SDimitry Andric           "Instruction::ReadDictionary: Error reading file (fgets).\n");
7740b57cec5SDimitry Andric       option_value_sp.reset();
7750b57cec5SDimitry Andric       return option_value_sp;
7760b57cec5SDimitry Andric     }
7770b57cec5SDimitry Andric 
7780b57cec5SDimitry Andric     // Check to see if the line contains the end-of-dictionary marker ("}")
7790b57cec5SDimitry Andric     std::string line(buffer);
7800b57cec5SDimitry Andric 
7810b57cec5SDimitry Andric     size_t len = line.size();
7820b57cec5SDimitry Andric     if (line[len - 1] == '\n') {
7830b57cec5SDimitry Andric       line[len - 1] = '\0';
7840b57cec5SDimitry Andric       line.resize(len - 1);
7850b57cec5SDimitry Andric     }
7860b57cec5SDimitry Andric 
7870b57cec5SDimitry Andric     if ((line.size() == 1) && (line[0] == '}')) {
7880b57cec5SDimitry Andric       done = true;
7890b57cec5SDimitry Andric       line.clear();
7900b57cec5SDimitry Andric     }
7910b57cec5SDimitry Andric 
7920b57cec5SDimitry Andric     // Try to find a key-value pair in the current line and add it to the
7930b57cec5SDimitry Andric     // dictionary.
7940b57cec5SDimitry Andric     if (!line.empty()) {
7950b57cec5SDimitry Andric       static RegularExpression g_reg_exp(llvm::StringRef(
7960b57cec5SDimitry Andric           "^[ \t]*([a-zA-Z_][a-zA-Z0-9_]*)[ \t]*=[ \t]*(.*)[ \t]*$"));
7970b57cec5SDimitry Andric 
7989dba64beSDimitry Andric       llvm::SmallVector<llvm::StringRef, 3> matches;
7999dba64beSDimitry Andric 
8009dba64beSDimitry Andric       bool reg_exp_success = g_reg_exp.Execute(line, &matches);
8010b57cec5SDimitry Andric       std::string key;
8020b57cec5SDimitry Andric       std::string value;
8030b57cec5SDimitry Andric       if (reg_exp_success) {
8049dba64beSDimitry Andric         key = matches[1].str();
8059dba64beSDimitry Andric         value = matches[2].str();
8060b57cec5SDimitry Andric       } else {
80706c3fb27SDimitry Andric         out_stream.Printf("Instruction::ReadDictionary: Failure executing "
8080b57cec5SDimitry Andric                           "regular expression.\n");
8090b57cec5SDimitry Andric         option_value_sp.reset();
8100b57cec5SDimitry Andric         return option_value_sp;
8110b57cec5SDimitry Andric       }
8120b57cec5SDimitry Andric 
8130b57cec5SDimitry Andric       // Check value to see if it's the start of an array or dictionary.
8140b57cec5SDimitry Andric 
8150b57cec5SDimitry Andric       lldb::OptionValueSP value_sp;
8160b57cec5SDimitry Andric       assert(value.empty() == false);
8170b57cec5SDimitry Andric       assert(key.empty() == false);
8180b57cec5SDimitry Andric 
8190b57cec5SDimitry Andric       if (value[0] == '{') {
8200b57cec5SDimitry Andric         assert(value.size() == 1);
8210b57cec5SDimitry Andric         // value is a dictionary
8220b57cec5SDimitry Andric         value_sp = ReadDictionary(in_file, out_stream);
8230b57cec5SDimitry Andric         if (!value_sp) {
8240b57cec5SDimitry Andric           option_value_sp.reset();
8250b57cec5SDimitry Andric           return option_value_sp;
8260b57cec5SDimitry Andric         }
8270b57cec5SDimitry Andric       } else if (value[0] == '[') {
8280b57cec5SDimitry Andric         assert(value.size() == 1);
8290b57cec5SDimitry Andric         // value is an array
8300b57cec5SDimitry Andric         value_sp = ReadArray(in_file, out_stream, data_type);
8310b57cec5SDimitry Andric         if (!value_sp) {
8320b57cec5SDimitry Andric           option_value_sp.reset();
8330b57cec5SDimitry Andric           return option_value_sp;
8340b57cec5SDimitry Andric         }
8350b57cec5SDimitry Andric         // We've used the data_type to read an array; re-set the type to
8360b57cec5SDimitry Andric         // Invalid
8370b57cec5SDimitry Andric         data_type = OptionValue::eTypeInvalid;
8380b57cec5SDimitry Andric       } else if ((value[0] == '0') && (value[1] == 'x')) {
8390b57cec5SDimitry Andric         value_sp = std::make_shared<OptionValueUInt64>(0, 0);
8400b57cec5SDimitry Andric         value_sp->SetValueFromString(value);
8410b57cec5SDimitry Andric       } else {
8420b57cec5SDimitry Andric         size_t len = value.size();
8430b57cec5SDimitry Andric         if ((value[0] == '"') && (value[len - 1] == '"'))
8440b57cec5SDimitry Andric           value = value.substr(1, len - 2);
8450b57cec5SDimitry Andric         value_sp = std::make_shared<OptionValueString>(value.c_str(), "");
8460b57cec5SDimitry Andric       }
8470b57cec5SDimitry Andric 
84806c3fb27SDimitry Andric       if (key == encoding_key) {
8490b57cec5SDimitry Andric         // A 'data_encoding=..." is NOT a normal key-value pair; it is meta-data
85006c3fb27SDimitry Andric         // indicating the data type of an upcoming array (usually the next bit
85106c3fb27SDimitry Andric         // of data to be read in).
85206c3fb27SDimitry Andric         if (llvm::StringRef(value) == "uint32_t")
8530b57cec5SDimitry Andric           data_type = OptionValue::eTypeUInt64;
8540b57cec5SDimitry Andric       } else
85506c3fb27SDimitry Andric         option_value_sp->GetAsDictionary()->SetValueForKey(key, value_sp,
8560b57cec5SDimitry Andric                                                            false);
8570b57cec5SDimitry Andric     }
8580b57cec5SDimitry Andric   }
8590b57cec5SDimitry Andric 
8600b57cec5SDimitry Andric   return option_value_sp;
8610b57cec5SDimitry Andric }
8620b57cec5SDimitry Andric 
TestEmulation(Stream & out_stream,const char * file_name)86306c3fb27SDimitry Andric bool Instruction::TestEmulation(Stream &out_stream, const char *file_name) {
8640b57cec5SDimitry Andric   if (!file_name) {
86506c3fb27SDimitry Andric     out_stream.Printf("Instruction::TestEmulation:  Missing file_name.");
8660b57cec5SDimitry Andric     return false;
8670b57cec5SDimitry Andric   }
8680b57cec5SDimitry Andric   FILE *test_file = FileSystem::Instance().Fopen(file_name, "r");
8690b57cec5SDimitry Andric   if (!test_file) {
87006c3fb27SDimitry Andric     out_stream.Printf(
8710b57cec5SDimitry Andric         "Instruction::TestEmulation: Attempt to open test file failed.");
8720b57cec5SDimitry Andric     return false;
8730b57cec5SDimitry Andric   }
8740b57cec5SDimitry Andric 
8750b57cec5SDimitry Andric   char buffer[256];
8760b57cec5SDimitry Andric   if (!fgets(buffer, 255, test_file)) {
87706c3fb27SDimitry Andric     out_stream.Printf(
8780b57cec5SDimitry Andric         "Instruction::TestEmulation: Error reading first line of test file.\n");
8790b57cec5SDimitry Andric     fclose(test_file);
8800b57cec5SDimitry Andric     return false;
8810b57cec5SDimitry Andric   }
8820b57cec5SDimitry Andric 
8830b57cec5SDimitry Andric   if (strncmp(buffer, "InstructionEmulationState={", 27) != 0) {
88406c3fb27SDimitry Andric     out_stream.Printf("Instructin::TestEmulation: Test file does not contain "
8850b57cec5SDimitry Andric                       "emulation state dictionary\n");
8860b57cec5SDimitry Andric     fclose(test_file);
8870b57cec5SDimitry Andric     return false;
8880b57cec5SDimitry Andric   }
8890b57cec5SDimitry Andric 
8900b57cec5SDimitry Andric   // Read all the test information from the test file into an
8910b57cec5SDimitry Andric   // OptionValueDictionary.
8920b57cec5SDimitry Andric 
8930b57cec5SDimitry Andric   OptionValueSP data_dictionary_sp(ReadDictionary(test_file, out_stream));
8940b57cec5SDimitry Andric   if (!data_dictionary_sp) {
89506c3fb27SDimitry Andric     out_stream.Printf(
8960b57cec5SDimitry Andric         "Instruction::TestEmulation:  Error reading Dictionary Object.\n");
8970b57cec5SDimitry Andric     fclose(test_file);
8980b57cec5SDimitry Andric     return false;
8990b57cec5SDimitry Andric   }
9000b57cec5SDimitry Andric 
9010b57cec5SDimitry Andric   fclose(test_file);
9020b57cec5SDimitry Andric 
9030b57cec5SDimitry Andric   OptionValueDictionary *data_dictionary =
9040b57cec5SDimitry Andric       data_dictionary_sp->GetAsDictionary();
90506c3fb27SDimitry Andric   static constexpr llvm::StringLiteral description_key("assembly_string");
90606c3fb27SDimitry Andric   static constexpr llvm::StringLiteral triple_key("triple");
9070b57cec5SDimitry Andric 
9080b57cec5SDimitry Andric   OptionValueSP value_sp = data_dictionary->GetValueForKey(description_key);
9090b57cec5SDimitry Andric 
9100b57cec5SDimitry Andric   if (!value_sp) {
91106c3fb27SDimitry Andric     out_stream.Printf("Instruction::TestEmulation:  Test file does not "
9120b57cec5SDimitry Andric                       "contain description string.\n");
9130b57cec5SDimitry Andric     return false;
9140b57cec5SDimitry Andric   }
9150b57cec5SDimitry Andric 
91606c3fb27SDimitry Andric   SetDescription(value_sp->GetValueAs<llvm::StringRef>().value_or(""));
9170b57cec5SDimitry Andric 
9180b57cec5SDimitry Andric   value_sp = data_dictionary->GetValueForKey(triple_key);
9190b57cec5SDimitry Andric   if (!value_sp) {
92006c3fb27SDimitry Andric     out_stream.Printf(
9210b57cec5SDimitry Andric         "Instruction::TestEmulation: Test file does not contain triple.\n");
9220b57cec5SDimitry Andric     return false;
9230b57cec5SDimitry Andric   }
9240b57cec5SDimitry Andric 
9250b57cec5SDimitry Andric   ArchSpec arch;
92606c3fb27SDimitry Andric   arch.SetTriple(
92706c3fb27SDimitry Andric       llvm::Triple(value_sp->GetValueAs<llvm::StringRef>().value_or("")));
9280b57cec5SDimitry Andric 
9290b57cec5SDimitry Andric   bool success = false;
9300b57cec5SDimitry Andric   std::unique_ptr<EmulateInstruction> insn_emulator_up(
9310b57cec5SDimitry Andric       EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr));
9320b57cec5SDimitry Andric   if (insn_emulator_up)
9330b57cec5SDimitry Andric     success =
9340b57cec5SDimitry Andric         insn_emulator_up->TestEmulation(out_stream, arch, data_dictionary);
9350b57cec5SDimitry Andric 
9360b57cec5SDimitry Andric   if (success)
93706c3fb27SDimitry Andric     out_stream.Printf("Emulation test succeeded.");
9380b57cec5SDimitry Andric   else
93906c3fb27SDimitry Andric     out_stream.Printf("Emulation test failed.");
9400b57cec5SDimitry Andric 
9410b57cec5SDimitry Andric   return success;
9420b57cec5SDimitry Andric }
9430b57cec5SDimitry Andric 
Emulate(const ArchSpec & arch,uint32_t evaluate_options,void * baton,EmulateInstruction::ReadMemoryCallback read_mem_callback,EmulateInstruction::WriteMemoryCallback write_mem_callback,EmulateInstruction::ReadRegisterCallback read_reg_callback,EmulateInstruction::WriteRegisterCallback write_reg_callback)9440b57cec5SDimitry Andric bool Instruction::Emulate(
9450b57cec5SDimitry Andric     const ArchSpec &arch, uint32_t evaluate_options, void *baton,
9460b57cec5SDimitry Andric     EmulateInstruction::ReadMemoryCallback read_mem_callback,
9470b57cec5SDimitry Andric     EmulateInstruction::WriteMemoryCallback write_mem_callback,
9480b57cec5SDimitry Andric     EmulateInstruction::ReadRegisterCallback read_reg_callback,
9490b57cec5SDimitry Andric     EmulateInstruction::WriteRegisterCallback write_reg_callback) {
9500b57cec5SDimitry Andric   std::unique_ptr<EmulateInstruction> insn_emulator_up(
9510b57cec5SDimitry Andric       EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr));
9520b57cec5SDimitry Andric   if (insn_emulator_up) {
9530b57cec5SDimitry Andric     insn_emulator_up->SetBaton(baton);
9540b57cec5SDimitry Andric     insn_emulator_up->SetCallbacks(read_mem_callback, write_mem_callback,
9550b57cec5SDimitry Andric                                    read_reg_callback, write_reg_callback);
9560b57cec5SDimitry Andric     insn_emulator_up->SetInstruction(GetOpcode(), GetAddress(), nullptr);
9570b57cec5SDimitry Andric     return insn_emulator_up->EvaluateInstruction(evaluate_options);
9580b57cec5SDimitry Andric   }
9590b57cec5SDimitry Andric 
9600b57cec5SDimitry Andric   return false;
9610b57cec5SDimitry Andric }
9620b57cec5SDimitry Andric 
GetData(DataExtractor & data)9630b57cec5SDimitry Andric uint32_t Instruction::GetData(DataExtractor &data) {
9640b57cec5SDimitry Andric   return m_opcode.GetData(data);
9650b57cec5SDimitry Andric }
9660b57cec5SDimitry Andric 
InstructionList()9670b57cec5SDimitry Andric InstructionList::InstructionList() : m_instructions() {}
9680b57cec5SDimitry Andric 
9690b57cec5SDimitry Andric InstructionList::~InstructionList() = default;
9700b57cec5SDimitry Andric 
GetSize() const9710b57cec5SDimitry Andric size_t InstructionList::GetSize() const { return m_instructions.size(); }
9720b57cec5SDimitry Andric 
GetMaxOpcocdeByteSize() const9730b57cec5SDimitry Andric uint32_t InstructionList::GetMaxOpcocdeByteSize() const {
9740b57cec5SDimitry Andric   uint32_t max_inst_size = 0;
9750b57cec5SDimitry Andric   collection::const_iterator pos, end;
9760b57cec5SDimitry Andric   for (pos = m_instructions.begin(), end = m_instructions.end(); pos != end;
9770b57cec5SDimitry Andric        ++pos) {
9780b57cec5SDimitry Andric     uint32_t inst_size = (*pos)->GetOpcode().GetByteSize();
9790b57cec5SDimitry Andric     if (max_inst_size < inst_size)
9800b57cec5SDimitry Andric       max_inst_size = inst_size;
9810b57cec5SDimitry Andric   }
9820b57cec5SDimitry Andric   return max_inst_size;
9830b57cec5SDimitry Andric }
9840b57cec5SDimitry Andric 
GetInstructionAtIndex(size_t idx) const9850b57cec5SDimitry Andric InstructionSP InstructionList::GetInstructionAtIndex(size_t idx) const {
9860b57cec5SDimitry Andric   InstructionSP inst_sp;
9870b57cec5SDimitry Andric   if (idx < m_instructions.size())
9880b57cec5SDimitry Andric     inst_sp = m_instructions[idx];
9890b57cec5SDimitry Andric   return inst_sp;
9900b57cec5SDimitry Andric }
9910b57cec5SDimitry Andric 
GetInstructionAtAddress(const Address & address)992e8d8bef9SDimitry Andric InstructionSP InstructionList::GetInstructionAtAddress(const Address &address) {
993e8d8bef9SDimitry Andric   uint32_t index = GetIndexOfInstructionAtAddress(address);
994e8d8bef9SDimitry Andric   if (index != UINT32_MAX)
995e8d8bef9SDimitry Andric     return GetInstructionAtIndex(index);
996e8d8bef9SDimitry Andric   return nullptr;
997e8d8bef9SDimitry Andric }
998e8d8bef9SDimitry Andric 
Dump(Stream * s,bool show_address,bool show_bytes,bool show_control_flow_kind,const ExecutionContext * exe_ctx)9990b57cec5SDimitry Andric void InstructionList::Dump(Stream *s, bool show_address, bool show_bytes,
1000753f127fSDimitry Andric                            bool show_control_flow_kind,
10010b57cec5SDimitry Andric                            const ExecutionContext *exe_ctx) {
10020b57cec5SDimitry Andric   const uint32_t max_opcode_byte_size = GetMaxOpcocdeByteSize();
10030b57cec5SDimitry Andric   collection::const_iterator pos, begin, end;
10040b57cec5SDimitry Andric 
10050b57cec5SDimitry Andric   const FormatEntity::Entry *disassembly_format = nullptr;
10060b57cec5SDimitry Andric   FormatEntity::Entry format;
10070b57cec5SDimitry Andric   if (exe_ctx && exe_ctx->HasTargetScope()) {
10080b57cec5SDimitry Andric     disassembly_format =
10090b57cec5SDimitry Andric         exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat();
10100b57cec5SDimitry Andric   } else {
10110b57cec5SDimitry Andric     FormatEntity::Parse("${addr}: ", format);
10120b57cec5SDimitry Andric     disassembly_format = &format;
10130b57cec5SDimitry Andric   }
10140b57cec5SDimitry Andric 
10150b57cec5SDimitry Andric   for (begin = m_instructions.begin(), end = m_instructions.end(), pos = begin;
10160b57cec5SDimitry Andric        pos != end; ++pos) {
10170b57cec5SDimitry Andric     if (pos != begin)
10180b57cec5SDimitry Andric       s->EOL();
1019753f127fSDimitry Andric     (*pos)->Dump(s, max_opcode_byte_size, show_address, show_bytes,
1020753f127fSDimitry Andric                  show_control_flow_kind, exe_ctx, nullptr, nullptr,
1021753f127fSDimitry Andric                  disassembly_format, 0);
10220b57cec5SDimitry Andric   }
10230b57cec5SDimitry Andric }
10240b57cec5SDimitry Andric 
Clear()10250b57cec5SDimitry Andric void InstructionList::Clear() { m_instructions.clear(); }
10260b57cec5SDimitry Andric 
Append(lldb::InstructionSP & inst_sp)10270b57cec5SDimitry Andric void InstructionList::Append(lldb::InstructionSP &inst_sp) {
10280b57cec5SDimitry Andric   if (inst_sp)
10290b57cec5SDimitry Andric     m_instructions.push_back(inst_sp);
10300b57cec5SDimitry Andric }
10310b57cec5SDimitry Andric 
10320b57cec5SDimitry Andric uint32_t
GetIndexOfNextBranchInstruction(uint32_t start,bool ignore_calls,bool * found_calls) const10330b57cec5SDimitry Andric InstructionList::GetIndexOfNextBranchInstruction(uint32_t start,
1034480093f4SDimitry Andric                                                  bool ignore_calls,
1035480093f4SDimitry Andric                                                  bool *found_calls) const {
10360b57cec5SDimitry Andric   size_t num_instructions = m_instructions.size();
10370b57cec5SDimitry Andric 
10380b57cec5SDimitry Andric   uint32_t next_branch = UINT32_MAX;
1039480093f4SDimitry Andric 
1040480093f4SDimitry Andric   if (found_calls)
1041480093f4SDimitry Andric     *found_calls = false;
1042e8d8bef9SDimitry Andric   for (size_t i = start; i < num_instructions; i++) {
10430b57cec5SDimitry Andric     if (m_instructions[i]->DoesBranch()) {
1044480093f4SDimitry Andric       if (ignore_calls && m_instructions[i]->IsCall()) {
1045480093f4SDimitry Andric         if (found_calls)
1046480093f4SDimitry Andric           *found_calls = true;
10470b57cec5SDimitry Andric         continue;
1048480093f4SDimitry Andric       }
10490b57cec5SDimitry Andric       next_branch = i;
10500b57cec5SDimitry Andric       break;
10510b57cec5SDimitry Andric     }
10520b57cec5SDimitry Andric   }
10530b57cec5SDimitry Andric 
10540b57cec5SDimitry Andric   return next_branch;
10550b57cec5SDimitry Andric }
10560b57cec5SDimitry Andric 
10570b57cec5SDimitry Andric uint32_t
GetIndexOfInstructionAtAddress(const Address & address)10580b57cec5SDimitry Andric InstructionList::GetIndexOfInstructionAtAddress(const Address &address) {
10590b57cec5SDimitry Andric   size_t num_instructions = m_instructions.size();
10600b57cec5SDimitry Andric   uint32_t index = UINT32_MAX;
10610b57cec5SDimitry Andric   for (size_t i = 0; i < num_instructions; i++) {
10620b57cec5SDimitry Andric     if (m_instructions[i]->GetAddress() == address) {
10630b57cec5SDimitry Andric       index = i;
10640b57cec5SDimitry Andric       break;
10650b57cec5SDimitry Andric     }
10660b57cec5SDimitry Andric   }
10670b57cec5SDimitry Andric   return index;
10680b57cec5SDimitry Andric }
10690b57cec5SDimitry Andric 
10700b57cec5SDimitry Andric uint32_t
GetIndexOfInstructionAtLoadAddress(lldb::addr_t load_addr,Target & target)10710b57cec5SDimitry Andric InstructionList::GetIndexOfInstructionAtLoadAddress(lldb::addr_t load_addr,
10720b57cec5SDimitry Andric                                                     Target &target) {
10730b57cec5SDimitry Andric   Address address;
10740b57cec5SDimitry Andric   address.SetLoadAddress(load_addr, &target);
10750b57cec5SDimitry Andric   return GetIndexOfInstructionAtAddress(address);
10760b57cec5SDimitry Andric }
10770b57cec5SDimitry Andric 
ParseInstructions(Target & target,Address start,Limit limit,Stream * error_strm_ptr,bool force_live_memory)10785ffd83dbSDimitry Andric size_t Disassembler::ParseInstructions(Target &target, Address start,
10795ffd83dbSDimitry Andric                                        Limit limit, Stream *error_strm_ptr,
1080fe6060f1SDimitry Andric                                        bool force_live_memory) {
10815ffd83dbSDimitry Andric   m_instruction_list.Clear();
10825ffd83dbSDimitry Andric 
10835ffd83dbSDimitry Andric   if (!start.IsValid())
10840b57cec5SDimitry Andric     return 0;
10850b57cec5SDimitry Andric 
10865ffd83dbSDimitry Andric   start = ResolveAddress(target, start);
10875ffd83dbSDimitry Andric 
10885ffd83dbSDimitry Andric   addr_t byte_size = limit.value;
10895ffd83dbSDimitry Andric   if (limit.kind == Limit::Instructions)
10905ffd83dbSDimitry Andric     byte_size *= m_arch.GetMaximumOpcodeByteSize();
10910b57cec5SDimitry Andric   auto data_sp = std::make_shared<DataBufferHeap>(byte_size, '\0');
10920b57cec5SDimitry Andric 
10930b57cec5SDimitry Andric   Status error;
10940b57cec5SDimitry Andric   lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
10955ffd83dbSDimitry Andric   const size_t bytes_read =
1096fe6060f1SDimitry Andric       target.ReadMemory(start, data_sp->GetBytes(), data_sp->GetByteSize(),
1097fe6060f1SDimitry Andric                         error, force_live_memory, &load_addr);
10985ffd83dbSDimitry Andric   const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS;
10990b57cec5SDimitry Andric 
11005ffd83dbSDimitry Andric   if (bytes_read == 0) {
11015ffd83dbSDimitry Andric     if (error_strm_ptr) {
11025ffd83dbSDimitry Andric       if (const char *error_cstr = error.AsCString())
11035ffd83dbSDimitry Andric         error_strm_ptr->Printf("error: %s\n", error_cstr);
11045ffd83dbSDimitry Andric     }
11055ffd83dbSDimitry Andric     return 0;
11065ffd83dbSDimitry Andric   }
11075ffd83dbSDimitry Andric 
11080b57cec5SDimitry Andric   if (bytes_read != data_sp->GetByteSize())
11090b57cec5SDimitry Andric     data_sp->SetByteSize(bytes_read);
11100b57cec5SDimitry Andric   DataExtractor data(data_sp, m_arch.GetByteOrder(),
11110b57cec5SDimitry Andric                      m_arch.GetAddressByteSize());
11125ffd83dbSDimitry Andric   return DecodeInstructions(start, data, 0,
11135ffd83dbSDimitry Andric                             limit.kind == Limit::Instructions ? limit.value
11145ffd83dbSDimitry Andric                                                               : UINT32_MAX,
11150b57cec5SDimitry Andric                             false, data_from_file);
11160b57cec5SDimitry Andric }
11170b57cec5SDimitry Andric 
11180b57cec5SDimitry Andric // Disassembler copy constructor
Disassembler(const ArchSpec & arch,const char * flavor)11190b57cec5SDimitry Andric Disassembler::Disassembler(const ArchSpec &arch, const char *flavor)
11200b57cec5SDimitry Andric     : m_arch(arch), m_instruction_list(), m_base_addr(LLDB_INVALID_ADDRESS),
11210b57cec5SDimitry Andric       m_flavor() {
11220b57cec5SDimitry Andric   if (flavor == nullptr)
11230b57cec5SDimitry Andric     m_flavor.assign("default");
11240b57cec5SDimitry Andric   else
11250b57cec5SDimitry Andric     m_flavor.assign(flavor);
11260b57cec5SDimitry Andric 
11270b57cec5SDimitry Andric   // If this is an arm variant that can only include thumb (T16, T32)
11280b57cec5SDimitry Andric   // instructions, force the arch triple to be "thumbv.." instead of "armv..."
11290b57cec5SDimitry Andric   if (arch.IsAlwaysThumbInstructions()) {
11300b57cec5SDimitry Andric     std::string thumb_arch_name(arch.GetTriple().getArchName().str());
11310b57cec5SDimitry Andric     // Replace "arm" with "thumb" so we get all thumb variants correct
11320b57cec5SDimitry Andric     if (thumb_arch_name.size() > 3) {
11330b57cec5SDimitry Andric       thumb_arch_name.erase(0, 3);
11340b57cec5SDimitry Andric       thumb_arch_name.insert(0, "thumb");
11350b57cec5SDimitry Andric     }
11360b57cec5SDimitry Andric     m_arch.SetTriple(thumb_arch_name.c_str());
11370b57cec5SDimitry Andric   }
11380b57cec5SDimitry Andric }
11390b57cec5SDimitry Andric 
11400b57cec5SDimitry Andric Disassembler::~Disassembler() = default;
11410b57cec5SDimitry Andric 
GetInstructionList()11420b57cec5SDimitry Andric InstructionList &Disassembler::GetInstructionList() {
11430b57cec5SDimitry Andric   return m_instruction_list;
11440b57cec5SDimitry Andric }
11450b57cec5SDimitry Andric 
GetInstructionList() const11460b57cec5SDimitry Andric const InstructionList &Disassembler::GetInstructionList() const {
11470b57cec5SDimitry Andric   return m_instruction_list;
11480b57cec5SDimitry Andric }
11490b57cec5SDimitry Andric 
11500b57cec5SDimitry Andric // Class PseudoInstruction
11510b57cec5SDimitry Andric 
PseudoInstruction()11520b57cec5SDimitry Andric PseudoInstruction::PseudoInstruction()
11530b57cec5SDimitry Andric     : Instruction(Address(), AddressClass::eUnknown), m_description() {}
11540b57cec5SDimitry Andric 
11550b57cec5SDimitry Andric PseudoInstruction::~PseudoInstruction() = default;
11560b57cec5SDimitry Andric 
DoesBranch()11570b57cec5SDimitry Andric bool PseudoInstruction::DoesBranch() {
11580b57cec5SDimitry Andric   // This is NOT a valid question for a pseudo instruction.
11590b57cec5SDimitry Andric   return false;
11600b57cec5SDimitry Andric }
11610b57cec5SDimitry Andric 
HasDelaySlot()11620b57cec5SDimitry Andric bool PseudoInstruction::HasDelaySlot() {
11630b57cec5SDimitry Andric   // This is NOT a valid question for a pseudo instruction.
11640b57cec5SDimitry Andric   return false;
11650b57cec5SDimitry Andric }
11660b57cec5SDimitry Andric 
IsLoad()1167349cc55cSDimitry Andric bool PseudoInstruction::IsLoad() { return false; }
1168349cc55cSDimitry Andric 
IsAuthenticated()1169349cc55cSDimitry Andric bool PseudoInstruction::IsAuthenticated() { return false; }
1170349cc55cSDimitry Andric 
Decode(const lldb_private::Disassembler & disassembler,const lldb_private::DataExtractor & data,lldb::offset_t data_offset)11710b57cec5SDimitry Andric size_t PseudoInstruction::Decode(const lldb_private::Disassembler &disassembler,
11720b57cec5SDimitry Andric                                  const lldb_private::DataExtractor &data,
11730b57cec5SDimitry Andric                                  lldb::offset_t data_offset) {
11740b57cec5SDimitry Andric   return m_opcode.GetByteSize();
11750b57cec5SDimitry Andric }
11760b57cec5SDimitry Andric 
SetOpcode(size_t opcode_size,void * opcode_data)11770b57cec5SDimitry Andric void PseudoInstruction::SetOpcode(size_t opcode_size, void *opcode_data) {
11780b57cec5SDimitry Andric   if (!opcode_data)
11790b57cec5SDimitry Andric     return;
11800b57cec5SDimitry Andric 
11810b57cec5SDimitry Andric   switch (opcode_size) {
11820b57cec5SDimitry Andric   case 8: {
11830b57cec5SDimitry Andric     uint8_t value8 = *((uint8_t *)opcode_data);
11840b57cec5SDimitry Andric     m_opcode.SetOpcode8(value8, eByteOrderInvalid);
11850b57cec5SDimitry Andric     break;
11860b57cec5SDimitry Andric   }
11870b57cec5SDimitry Andric   case 16: {
11880b57cec5SDimitry Andric     uint16_t value16 = *((uint16_t *)opcode_data);
11890b57cec5SDimitry Andric     m_opcode.SetOpcode16(value16, eByteOrderInvalid);
11900b57cec5SDimitry Andric     break;
11910b57cec5SDimitry Andric   }
11920b57cec5SDimitry Andric   case 32: {
11930b57cec5SDimitry Andric     uint32_t value32 = *((uint32_t *)opcode_data);
11940b57cec5SDimitry Andric     m_opcode.SetOpcode32(value32, eByteOrderInvalid);
11950b57cec5SDimitry Andric     break;
11960b57cec5SDimitry Andric   }
11970b57cec5SDimitry Andric   case 64: {
11980b57cec5SDimitry Andric     uint64_t value64 = *((uint64_t *)opcode_data);
11990b57cec5SDimitry Andric     m_opcode.SetOpcode64(value64, eByteOrderInvalid);
12000b57cec5SDimitry Andric     break;
12010b57cec5SDimitry Andric   }
12020b57cec5SDimitry Andric   default:
12030b57cec5SDimitry Andric     break;
12040b57cec5SDimitry Andric   }
12050b57cec5SDimitry Andric }
12060b57cec5SDimitry Andric 
SetDescription(llvm::StringRef description)12070b57cec5SDimitry Andric void PseudoInstruction::SetDescription(llvm::StringRef description) {
12085ffd83dbSDimitry Andric   m_description = std::string(description);
12090b57cec5SDimitry Andric }
12100b57cec5SDimitry Andric 
BuildRegister(ConstString & r)12110b57cec5SDimitry Andric Instruction::Operand Instruction::Operand::BuildRegister(ConstString &r) {
12120b57cec5SDimitry Andric   Operand ret;
12130b57cec5SDimitry Andric   ret.m_type = Type::Register;
12140b57cec5SDimitry Andric   ret.m_register = r;
12150b57cec5SDimitry Andric   return ret;
12160b57cec5SDimitry Andric }
12170b57cec5SDimitry Andric 
BuildImmediate(lldb::addr_t imm,bool neg)12180b57cec5SDimitry Andric Instruction::Operand Instruction::Operand::BuildImmediate(lldb::addr_t imm,
12190b57cec5SDimitry Andric                                                           bool neg) {
12200b57cec5SDimitry Andric   Operand ret;
12210b57cec5SDimitry Andric   ret.m_type = Type::Immediate;
12220b57cec5SDimitry Andric   ret.m_immediate = imm;
12230b57cec5SDimitry Andric   ret.m_negative = neg;
12240b57cec5SDimitry Andric   return ret;
12250b57cec5SDimitry Andric }
12260b57cec5SDimitry Andric 
BuildImmediate(int64_t imm)12270b57cec5SDimitry Andric Instruction::Operand Instruction::Operand::BuildImmediate(int64_t imm) {
12280b57cec5SDimitry Andric   Operand ret;
12290b57cec5SDimitry Andric   ret.m_type = Type::Immediate;
12300b57cec5SDimitry Andric   if (imm < 0) {
12310b57cec5SDimitry Andric     ret.m_immediate = -imm;
12320b57cec5SDimitry Andric     ret.m_negative = true;
12330b57cec5SDimitry Andric   } else {
12340b57cec5SDimitry Andric     ret.m_immediate = imm;
12350b57cec5SDimitry Andric     ret.m_negative = false;
12360b57cec5SDimitry Andric   }
12370b57cec5SDimitry Andric   return ret;
12380b57cec5SDimitry Andric }
12390b57cec5SDimitry Andric 
12400b57cec5SDimitry Andric Instruction::Operand
BuildDereference(const Operand & ref)12410b57cec5SDimitry Andric Instruction::Operand::BuildDereference(const Operand &ref) {
12420b57cec5SDimitry Andric   Operand ret;
12430b57cec5SDimitry Andric   ret.m_type = Type::Dereference;
12440b57cec5SDimitry Andric   ret.m_children = {ref};
12450b57cec5SDimitry Andric   return ret;
12460b57cec5SDimitry Andric }
12470b57cec5SDimitry Andric 
BuildSum(const Operand & lhs,const Operand & rhs)12480b57cec5SDimitry Andric Instruction::Operand Instruction::Operand::BuildSum(const Operand &lhs,
12490b57cec5SDimitry Andric                                                     const Operand &rhs) {
12500b57cec5SDimitry Andric   Operand ret;
12510b57cec5SDimitry Andric   ret.m_type = Type::Sum;
12520b57cec5SDimitry Andric   ret.m_children = {lhs, rhs};
12530b57cec5SDimitry Andric   return ret;
12540b57cec5SDimitry Andric }
12550b57cec5SDimitry Andric 
BuildProduct(const Operand & lhs,const Operand & rhs)12560b57cec5SDimitry Andric Instruction::Operand Instruction::Operand::BuildProduct(const Operand &lhs,
12570b57cec5SDimitry Andric                                                         const Operand &rhs) {
12580b57cec5SDimitry Andric   Operand ret;
12590b57cec5SDimitry Andric   ret.m_type = Type::Product;
12600b57cec5SDimitry Andric   ret.m_children = {lhs, rhs};
12610b57cec5SDimitry Andric   return ret;
12620b57cec5SDimitry Andric }
12630b57cec5SDimitry Andric 
12640b57cec5SDimitry Andric std::function<bool(const Instruction::Operand &)>
MatchBinaryOp(std::function<bool (const Instruction::Operand &)> base,std::function<bool (const Instruction::Operand &)> left,std::function<bool (const Instruction::Operand &)> right)12650b57cec5SDimitry Andric lldb_private::OperandMatchers::MatchBinaryOp(
12660b57cec5SDimitry Andric     std::function<bool(const Instruction::Operand &)> base,
12670b57cec5SDimitry Andric     std::function<bool(const Instruction::Operand &)> left,
12680b57cec5SDimitry Andric     std::function<bool(const Instruction::Operand &)> right) {
12690b57cec5SDimitry Andric   return [base, left, right](const Instruction::Operand &op) -> bool {
12700b57cec5SDimitry Andric     return (base(op) && op.m_children.size() == 2 &&
12710b57cec5SDimitry Andric             ((left(op.m_children[0]) && right(op.m_children[1])) ||
12720b57cec5SDimitry Andric              (left(op.m_children[1]) && right(op.m_children[0]))));
12730b57cec5SDimitry Andric   };
12740b57cec5SDimitry Andric }
12750b57cec5SDimitry Andric 
12760b57cec5SDimitry Andric std::function<bool(const Instruction::Operand &)>
MatchUnaryOp(std::function<bool (const Instruction::Operand &)> base,std::function<bool (const Instruction::Operand &)> child)12770b57cec5SDimitry Andric lldb_private::OperandMatchers::MatchUnaryOp(
12780b57cec5SDimitry Andric     std::function<bool(const Instruction::Operand &)> base,
12790b57cec5SDimitry Andric     std::function<bool(const Instruction::Operand &)> child) {
12800b57cec5SDimitry Andric   return [base, child](const Instruction::Operand &op) -> bool {
12810b57cec5SDimitry Andric     return (base(op) && op.m_children.size() == 1 && child(op.m_children[0]));
12820b57cec5SDimitry Andric   };
12830b57cec5SDimitry Andric }
12840b57cec5SDimitry Andric 
12850b57cec5SDimitry Andric std::function<bool(const Instruction::Operand &)>
MatchRegOp(const RegisterInfo & info)12860b57cec5SDimitry Andric lldb_private::OperandMatchers::MatchRegOp(const RegisterInfo &info) {
12870b57cec5SDimitry Andric   return [&info](const Instruction::Operand &op) {
12880b57cec5SDimitry Andric     return (op.m_type == Instruction::Operand::Type::Register &&
12890b57cec5SDimitry Andric             (op.m_register == ConstString(info.name) ||
12900b57cec5SDimitry Andric              op.m_register == ConstString(info.alt_name)));
12910b57cec5SDimitry Andric   };
12920b57cec5SDimitry Andric }
12930b57cec5SDimitry Andric 
12940b57cec5SDimitry Andric std::function<bool(const Instruction::Operand &)>
FetchRegOp(ConstString & reg)12950b57cec5SDimitry Andric lldb_private::OperandMatchers::FetchRegOp(ConstString &reg) {
12960b57cec5SDimitry Andric   return [&reg](const Instruction::Operand &op) {
12970b57cec5SDimitry Andric     if (op.m_type != Instruction::Operand::Type::Register) {
12980b57cec5SDimitry Andric       return false;
12990b57cec5SDimitry Andric     }
13000b57cec5SDimitry Andric     reg = op.m_register;
13010b57cec5SDimitry Andric     return true;
13020b57cec5SDimitry Andric   };
13030b57cec5SDimitry Andric }
13040b57cec5SDimitry Andric 
13050b57cec5SDimitry Andric std::function<bool(const Instruction::Operand &)>
MatchImmOp(int64_t imm)13060b57cec5SDimitry Andric lldb_private::OperandMatchers::MatchImmOp(int64_t imm) {
13070b57cec5SDimitry Andric   return [imm](const Instruction::Operand &op) {
13080b57cec5SDimitry Andric     return (op.m_type == Instruction::Operand::Type::Immediate &&
13090b57cec5SDimitry Andric             ((op.m_negative && op.m_immediate == (uint64_t)-imm) ||
13100b57cec5SDimitry Andric              (!op.m_negative && op.m_immediate == (uint64_t)imm)));
13110b57cec5SDimitry Andric   };
13120b57cec5SDimitry Andric }
13130b57cec5SDimitry Andric 
13140b57cec5SDimitry Andric std::function<bool(const Instruction::Operand &)>
FetchImmOp(int64_t & imm)13150b57cec5SDimitry Andric lldb_private::OperandMatchers::FetchImmOp(int64_t &imm) {
13160b57cec5SDimitry Andric   return [&imm](const Instruction::Operand &op) {
13170b57cec5SDimitry Andric     if (op.m_type != Instruction::Operand::Type::Immediate) {
13180b57cec5SDimitry Andric       return false;
13190b57cec5SDimitry Andric     }
13200b57cec5SDimitry Andric     if (op.m_negative) {
13210b57cec5SDimitry Andric       imm = -((int64_t)op.m_immediate);
13220b57cec5SDimitry Andric     } else {
13230b57cec5SDimitry Andric       imm = ((int64_t)op.m_immediate);
13240b57cec5SDimitry Andric     }
13250b57cec5SDimitry Andric     return true;
13260b57cec5SDimitry Andric   };
13270b57cec5SDimitry Andric }
13280b57cec5SDimitry Andric 
13290b57cec5SDimitry Andric std::function<bool(const Instruction::Operand &)>
MatchOpType(Instruction::Operand::Type type)13300b57cec5SDimitry Andric lldb_private::OperandMatchers::MatchOpType(Instruction::Operand::Type type) {
13310b57cec5SDimitry Andric   return [type](const Instruction::Operand &op) { return op.m_type == type; };
13320b57cec5SDimitry Andric }
1333