brintos

brintos / llvm-project-archived public Read only

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