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/ADT/Triple.h"
450b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric #include <cstdint>
480b57cec5SDimitry Andric #include <cstring>
490b57cec5SDimitry Andric #include <utility>
500b57cec5SDimitry Andric 
51*5f7ddb14SDimitry 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) {
61af732203SDimitry 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) {
670b57cec5SDimitry Andric     ConstString const_plugin_name(plugin_name);
680b57cec5SDimitry Andric     create_callback = PluginManager::GetDisassemblerCreateCallbackForPluginName(
690b57cec5SDimitry Andric         const_plugin_name);
700b57cec5SDimitry Andric     if (create_callback) {
710b57cec5SDimitry Andric       DisassemblerSP disassembler_sp(create_callback(arch, flavor));
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric       if (disassembler_sp)
740b57cec5SDimitry Andric         return disassembler_sp;
750b57cec5SDimitry Andric     }
760b57cec5SDimitry Andric   } else {
770b57cec5SDimitry Andric     for (uint32_t idx = 0;
780b57cec5SDimitry Andric          (create_callback = PluginManager::GetDisassemblerCreateCallbackAtIndex(
790b57cec5SDimitry Andric               idx)) != nullptr;
800b57cec5SDimitry Andric          ++idx) {
810b57cec5SDimitry Andric       DisassemblerSP disassembler_sp(create_callback(arch, flavor));
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric       if (disassembler_sp)
840b57cec5SDimitry Andric         return disassembler_sp;
850b57cec5SDimitry Andric     }
860b57cec5SDimitry Andric   }
870b57cec5SDimitry Andric   return DisassemblerSP();
880b57cec5SDimitry Andric }
890b57cec5SDimitry Andric 
FindPluginForTarget(const Target & target,const ArchSpec & arch,const char * flavor,const char * plugin_name)905ffd83dbSDimitry Andric DisassemblerSP Disassembler::FindPluginForTarget(const Target &target,
910b57cec5SDimitry Andric                                                  const ArchSpec &arch,
920b57cec5SDimitry Andric                                                  const char *flavor,
930b57cec5SDimitry Andric                                                  const char *plugin_name) {
945ffd83dbSDimitry Andric   if (flavor == nullptr) {
950b57cec5SDimitry Andric     // FIXME - we don't have the mechanism in place to do per-architecture
960b57cec5SDimitry Andric     // settings.  But since we know that for now we only support flavors on x86
970b57cec5SDimitry Andric     // & x86_64,
980b57cec5SDimitry Andric     if (arch.GetTriple().getArch() == llvm::Triple::x86 ||
990b57cec5SDimitry Andric         arch.GetTriple().getArch() == llvm::Triple::x86_64)
1005ffd83dbSDimitry Andric       flavor = target.GetDisassemblyFlavor();
1010b57cec5SDimitry Andric   }
1020b57cec5SDimitry Andric   return FindPlugin(arch, flavor, plugin_name);
1030b57cec5SDimitry Andric }
1040b57cec5SDimitry Andric 
ResolveAddress(Target & target,const Address & addr)1055ffd83dbSDimitry Andric static Address ResolveAddress(Target &target, const Address &addr) {
1060b57cec5SDimitry Andric   if (!addr.IsSectionOffset()) {
1075ffd83dbSDimitry Andric     Address resolved_addr;
1080b57cec5SDimitry Andric     // If we weren't passed in a section offset address range, try and resolve
1090b57cec5SDimitry Andric     // it to something
1105ffd83dbSDimitry Andric     bool is_resolved = target.GetSectionLoadList().IsEmpty()
1115ffd83dbSDimitry Andric                            ? target.GetImages().ResolveFileAddress(
1125ffd83dbSDimitry Andric                                  addr.GetOffset(), resolved_addr)
1135ffd83dbSDimitry Andric                            : target.GetSectionLoadList().ResolveLoadAddress(
1145ffd83dbSDimitry Andric                                  addr.GetOffset(), resolved_addr);
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric     // We weren't able to resolve the address, just treat it as a raw address
1170b57cec5SDimitry Andric     if (is_resolved && resolved_addr.IsValid())
1185ffd83dbSDimitry Andric       return resolved_addr;
1190b57cec5SDimitry Andric   }
1205ffd83dbSDimitry Andric   return addr;
1210b57cec5SDimitry Andric }
1220b57cec5SDimitry Andric 
DisassembleRange(const ArchSpec & arch,const char * plugin_name,const char * flavor,Target & target,const AddressRange & range,bool force_live_memory)1230b57cec5SDimitry Andric lldb::DisassemblerSP Disassembler::DisassembleRange(
1240b57cec5SDimitry Andric     const ArchSpec &arch, const char *plugin_name, const char *flavor,
125*5f7ddb14SDimitry Andric     Target &target, const AddressRange &range, bool force_live_memory) {
1269dba64beSDimitry Andric   if (range.GetByteSize() <= 0)
1279dba64beSDimitry Andric     return {};
1280b57cec5SDimitry Andric 
1299dba64beSDimitry Andric   if (!range.GetBaseAddress().IsValid())
1309dba64beSDimitry Andric     return {};
1319dba64beSDimitry Andric 
1325ffd83dbSDimitry Andric   lldb::DisassemblerSP disasm_sp =
1335ffd83dbSDimitry Andric       Disassembler::FindPluginForTarget(target, arch, flavor, plugin_name);
1349dba64beSDimitry Andric 
1359dba64beSDimitry Andric   if (!disasm_sp)
1369dba64beSDimitry Andric     return {};
1379dba64beSDimitry Andric 
1385ffd83dbSDimitry Andric   const size_t bytes_disassembled = disasm_sp->ParseInstructions(
1395ffd83dbSDimitry Andric       target, range.GetBaseAddress(), {Limit::Bytes, range.GetByteSize()},
140*5f7ddb14SDimitry Andric       nullptr, force_live_memory);
1410b57cec5SDimitry Andric   if (bytes_disassembled == 0)
1429dba64beSDimitry Andric     return {};
1439dba64beSDimitry Andric 
1440b57cec5SDimitry Andric   return disasm_sp;
1450b57cec5SDimitry Andric }
1460b57cec5SDimitry Andric 
1470b57cec5SDimitry 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)1480b57cec5SDimitry Andric Disassembler::DisassembleBytes(const ArchSpec &arch, const char *plugin_name,
1490b57cec5SDimitry Andric                                const char *flavor, const Address &start,
1500b57cec5SDimitry Andric                                const void *src, size_t src_len,
1510b57cec5SDimitry Andric                                uint32_t num_instructions, bool data_from_file) {
1529dba64beSDimitry Andric   if (!src)
1539dba64beSDimitry Andric     return {};
1540b57cec5SDimitry Andric 
1559dba64beSDimitry Andric   lldb::DisassemblerSP disasm_sp =
1569dba64beSDimitry Andric       Disassembler::FindPlugin(arch, flavor, plugin_name);
1570b57cec5SDimitry Andric 
1589dba64beSDimitry Andric   if (!disasm_sp)
1599dba64beSDimitry Andric     return {};
1609dba64beSDimitry Andric 
1610b57cec5SDimitry Andric   DataExtractor data(src, src_len, arch.GetByteOrder(),
1620b57cec5SDimitry Andric                      arch.GetAddressByteSize());
1630b57cec5SDimitry Andric 
1649dba64beSDimitry Andric   (void)disasm_sp->DecodeInstructions(start, data, 0, num_instructions, false,
1659dba64beSDimitry Andric                                       data_from_file);
1660b57cec5SDimitry Andric   return disasm_sp;
1670b57cec5SDimitry Andric }
1680b57cec5SDimitry 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)1690b57cec5SDimitry Andric bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch,
1700b57cec5SDimitry Andric                                const char *plugin_name, const char *flavor,
1710b57cec5SDimitry Andric                                const ExecutionContext &exe_ctx,
1725ffd83dbSDimitry Andric                                const Address &address, Limit limit,
1730b57cec5SDimitry Andric                                bool mixed_source_and_assembly,
1740b57cec5SDimitry Andric                                uint32_t num_mixed_context_lines,
1750b57cec5SDimitry Andric                                uint32_t options, Stream &strm) {
1765ffd83dbSDimitry Andric   if (!exe_ctx.GetTargetPtr())
1779dba64beSDimitry Andric     return false;
1789dba64beSDimitry Andric 
1790b57cec5SDimitry Andric   lldb::DisassemblerSP disasm_sp(Disassembler::FindPluginForTarget(
1805ffd83dbSDimitry Andric       exe_ctx.GetTargetRef(), arch, flavor, plugin_name));
1819dba64beSDimitry Andric   if (!disasm_sp)
1829dba64beSDimitry Andric     return false;
1839dba64beSDimitry Andric 
184*5f7ddb14SDimitry Andric   const bool force_live_memory = true;
1850b57cec5SDimitry Andric   size_t bytes_disassembled = disasm_sp->ParseInstructions(
186*5f7ddb14SDimitry Andric       exe_ctx.GetTargetRef(), address, limit, &strm, force_live_memory);
1870b57cec5SDimitry Andric   if (bytes_disassembled == 0)
1880b57cec5SDimitry Andric     return false;
1899dba64beSDimitry Andric 
1905ffd83dbSDimitry Andric   disasm_sp->PrintInstructions(debugger, arch, exe_ctx,
1915ffd83dbSDimitry Andric                                mixed_source_and_assembly,
1920b57cec5SDimitry Andric                                num_mixed_context_lines, options, strm);
1935ffd83dbSDimitry Andric   return true;
1940b57cec5SDimitry Andric }
1950b57cec5SDimitry Andric 
1960b57cec5SDimitry Andric Disassembler::SourceLine
GetFunctionDeclLineEntry(const SymbolContext & sc)1970b57cec5SDimitry Andric Disassembler::GetFunctionDeclLineEntry(const SymbolContext &sc) {
1989dba64beSDimitry Andric   if (!sc.function)
1999dba64beSDimitry Andric     return {};
2009dba64beSDimitry Andric 
2019dba64beSDimitry Andric   if (!sc.line_entry.IsValid())
2029dba64beSDimitry Andric     return {};
2039dba64beSDimitry Andric 
2040b57cec5SDimitry Andric   LineEntry prologue_end_line = sc.line_entry;
2050b57cec5SDimitry Andric   FileSpec func_decl_file;
2060b57cec5SDimitry Andric   uint32_t func_decl_line;
2070b57cec5SDimitry Andric   sc.function->GetStartLineSourceInfo(func_decl_file, func_decl_line);
2089dba64beSDimitry Andric 
2099dba64beSDimitry Andric   if (func_decl_file != prologue_end_line.file &&
2109dba64beSDimitry Andric       func_decl_file != prologue_end_line.original_file)
2119dba64beSDimitry Andric     return {};
2129dba64beSDimitry Andric 
2139dba64beSDimitry Andric   SourceLine decl_line;
2140b57cec5SDimitry Andric   decl_line.file = func_decl_file;
2150b57cec5SDimitry Andric   decl_line.line = func_decl_line;
2169dba64beSDimitry Andric   // TODO: Do we care about column on these entries?  If so, we need to plumb
2179dba64beSDimitry Andric   // that through GetStartLineSourceInfo.
2180b57cec5SDimitry Andric   decl_line.column = 0;
2190b57cec5SDimitry Andric   return decl_line;
2200b57cec5SDimitry Andric }
2210b57cec5SDimitry Andric 
AddLineToSourceLineTables(SourceLine & line,std::map<FileSpec,std::set<uint32_t>> & source_lines_seen)2220b57cec5SDimitry Andric void Disassembler::AddLineToSourceLineTables(
2230b57cec5SDimitry Andric     SourceLine &line,
2240b57cec5SDimitry Andric     std::map<FileSpec, std::set<uint32_t>> &source_lines_seen) {
2250b57cec5SDimitry Andric   if (line.IsValid()) {
2260b57cec5SDimitry Andric     auto source_lines_seen_pos = source_lines_seen.find(line.file);
2270b57cec5SDimitry Andric     if (source_lines_seen_pos == source_lines_seen.end()) {
2280b57cec5SDimitry Andric       std::set<uint32_t> lines;
2290b57cec5SDimitry Andric       lines.insert(line.line);
2300b57cec5SDimitry Andric       source_lines_seen.emplace(line.file, lines);
2310b57cec5SDimitry Andric     } else {
2320b57cec5SDimitry Andric       source_lines_seen_pos->second.insert(line.line);
2330b57cec5SDimitry Andric     }
2340b57cec5SDimitry Andric   }
2350b57cec5SDimitry Andric }
2360b57cec5SDimitry Andric 
ElideMixedSourceAndDisassemblyLine(const ExecutionContext & exe_ctx,const SymbolContext & sc,SourceLine & line)2370b57cec5SDimitry Andric bool Disassembler::ElideMixedSourceAndDisassemblyLine(
2380b57cec5SDimitry Andric     const ExecutionContext &exe_ctx, const SymbolContext &sc,
2390b57cec5SDimitry Andric     SourceLine &line) {
2400b57cec5SDimitry Andric 
2410b57cec5SDimitry Andric   // TODO: should we also check target.process.thread.step-avoid-libraries ?
2420b57cec5SDimitry Andric 
2430b57cec5SDimitry Andric   const RegularExpression *avoid_regex = nullptr;
2440b57cec5SDimitry Andric 
2450b57cec5SDimitry Andric   // Skip any line #0 entries - they are implementation details
2460b57cec5SDimitry Andric   if (line.line == 0)
2470b57cec5SDimitry Andric     return false;
2480b57cec5SDimitry Andric 
2490b57cec5SDimitry Andric   ThreadSP thread_sp = exe_ctx.GetThreadSP();
2500b57cec5SDimitry Andric   if (thread_sp) {
2510b57cec5SDimitry Andric     avoid_regex = thread_sp->GetSymbolsToAvoidRegexp();
2520b57cec5SDimitry Andric   } else {
2530b57cec5SDimitry Andric     TargetSP target_sp = exe_ctx.GetTargetSP();
2540b57cec5SDimitry Andric     if (target_sp) {
2550b57cec5SDimitry Andric       Status error;
2560b57cec5SDimitry Andric       OptionValueSP value_sp = target_sp->GetDebugger().GetPropertyValue(
2570b57cec5SDimitry Andric           &exe_ctx, "target.process.thread.step-avoid-regexp", false, error);
2580b57cec5SDimitry Andric       if (value_sp && value_sp->GetType() == OptionValue::eTypeRegex) {
2590b57cec5SDimitry Andric         OptionValueRegex *re = value_sp->GetAsRegex();
2600b57cec5SDimitry Andric         if (re) {
2610b57cec5SDimitry Andric           avoid_regex = re->GetCurrentValue();
2620b57cec5SDimitry Andric         }
2630b57cec5SDimitry Andric       }
2640b57cec5SDimitry Andric     }
2650b57cec5SDimitry Andric   }
2660b57cec5SDimitry Andric   if (avoid_regex && sc.symbol != nullptr) {
2670b57cec5SDimitry Andric     const char *function_name =
2680b57cec5SDimitry Andric         sc.GetFunctionName(Mangled::ePreferDemangledWithoutArguments)
2690b57cec5SDimitry Andric             .GetCString();
2709dba64beSDimitry Andric     if (function_name && avoid_regex->Execute(function_name)) {
2710b57cec5SDimitry Andric       // skip this source line
2720b57cec5SDimitry Andric       return true;
2730b57cec5SDimitry Andric     }
2740b57cec5SDimitry Andric   }
2750b57cec5SDimitry Andric   // don't skip this source line
2760b57cec5SDimitry Andric   return false;
2770b57cec5SDimitry Andric }
2780b57cec5SDimitry 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)2795ffd83dbSDimitry Andric void Disassembler::PrintInstructions(Debugger &debugger, const ArchSpec &arch,
2800b57cec5SDimitry Andric                                      const ExecutionContext &exe_ctx,
2810b57cec5SDimitry Andric                                      bool mixed_source_and_assembly,
2820b57cec5SDimitry Andric                                      uint32_t num_mixed_context_lines,
2830b57cec5SDimitry Andric                                      uint32_t options, Stream &strm) {
2840b57cec5SDimitry Andric   // We got some things disassembled...
2855ffd83dbSDimitry Andric   size_t num_instructions_found = GetInstructionList().GetSize();
2860b57cec5SDimitry Andric 
2870b57cec5SDimitry Andric   const uint32_t max_opcode_byte_size =
2885ffd83dbSDimitry Andric       GetInstructionList().GetMaxOpcocdeByteSize();
2890b57cec5SDimitry Andric   SymbolContext sc;
2900b57cec5SDimitry Andric   SymbolContext prev_sc;
2910b57cec5SDimitry Andric   AddressRange current_source_line_range;
2920b57cec5SDimitry Andric   const Address *pc_addr_ptr = nullptr;
2930b57cec5SDimitry Andric   StackFrame *frame = exe_ctx.GetFramePtr();
2940b57cec5SDimitry Andric 
2950b57cec5SDimitry Andric   TargetSP target_sp(exe_ctx.GetTargetSP());
2960b57cec5SDimitry Andric   SourceManager &source_manager =
2970b57cec5SDimitry Andric       target_sp ? target_sp->GetSourceManager() : debugger.GetSourceManager();
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric   if (frame) {
3000b57cec5SDimitry Andric     pc_addr_ptr = &frame->GetFrameCodeAddress();
3010b57cec5SDimitry Andric   }
3020b57cec5SDimitry Andric   const uint32_t scope =
3030b57cec5SDimitry Andric       eSymbolContextLineEntry | eSymbolContextFunction | eSymbolContextSymbol;
3040b57cec5SDimitry Andric   const bool use_inline_block_range = false;
3050b57cec5SDimitry Andric 
3060b57cec5SDimitry Andric   const FormatEntity::Entry *disassembly_format = nullptr;
3070b57cec5SDimitry Andric   FormatEntity::Entry format;
3080b57cec5SDimitry Andric   if (exe_ctx.HasTargetScope()) {
3090b57cec5SDimitry Andric     disassembly_format =
3100b57cec5SDimitry Andric         exe_ctx.GetTargetRef().GetDebugger().GetDisassemblyFormat();
3110b57cec5SDimitry Andric   } else {
3120b57cec5SDimitry Andric     FormatEntity::Parse("${addr}: ", format);
3130b57cec5SDimitry Andric     disassembly_format = &format;
3140b57cec5SDimitry Andric   }
3150b57cec5SDimitry Andric 
3160b57cec5SDimitry Andric   // First pass: step through the list of instructions, find how long the
3170b57cec5SDimitry Andric   // initial addresses strings are, insert padding in the second pass so the
3180b57cec5SDimitry Andric   // opcodes all line up nicely.
3190b57cec5SDimitry Andric 
3200b57cec5SDimitry Andric   // Also build up the source line mapping if this is mixed source & assembly
3210b57cec5SDimitry Andric   // mode. Calculate the source line for each assembly instruction (eliding
3220b57cec5SDimitry Andric   // inlined functions which the user wants to skip).
3230b57cec5SDimitry Andric 
3240b57cec5SDimitry Andric   std::map<FileSpec, std::set<uint32_t>> source_lines_seen;
3250b57cec5SDimitry Andric   Symbol *previous_symbol = nullptr;
3260b57cec5SDimitry Andric 
3270b57cec5SDimitry Andric   size_t address_text_size = 0;
3280b57cec5SDimitry Andric   for (size_t i = 0; i < num_instructions_found; ++i) {
3295ffd83dbSDimitry Andric     Instruction *inst = GetInstructionList().GetInstructionAtIndex(i).get();
3300b57cec5SDimitry Andric     if (inst) {
3310b57cec5SDimitry Andric       const Address &addr = inst->GetAddress();
3320b57cec5SDimitry Andric       ModuleSP module_sp(addr.GetModule());
3330b57cec5SDimitry Andric       if (module_sp) {
3340b57cec5SDimitry Andric         const SymbolContextItem resolve_mask = eSymbolContextFunction |
3350b57cec5SDimitry Andric                                                eSymbolContextSymbol |
3360b57cec5SDimitry Andric                                                eSymbolContextLineEntry;
3370b57cec5SDimitry Andric         uint32_t resolved_mask =
3380b57cec5SDimitry Andric             module_sp->ResolveSymbolContextForAddress(addr, resolve_mask, sc);
3390b57cec5SDimitry Andric         if (resolved_mask) {
3400b57cec5SDimitry Andric           StreamString strmstr;
3410b57cec5SDimitry Andric           Debugger::FormatDisassemblerAddress(disassembly_format, &sc, nullptr,
3420b57cec5SDimitry Andric                                               &exe_ctx, &addr, strmstr);
3430b57cec5SDimitry Andric           size_t cur_line = strmstr.GetSizeOfLastLine();
3440b57cec5SDimitry Andric           if (cur_line > address_text_size)
3450b57cec5SDimitry Andric             address_text_size = cur_line;
3460b57cec5SDimitry Andric 
3470b57cec5SDimitry Andric           // Add entries to our "source_lines_seen" map+set which list which
3480b57cec5SDimitry Andric           // sources lines occur in this disassembly session.  We will print
3490b57cec5SDimitry Andric           // lines of context around a source line, but we don't want to print
3500b57cec5SDimitry Andric           // a source line that has a line table entry of its own - we'll leave
3510b57cec5SDimitry Andric           // that source line to be printed when it actually occurs in the
3520b57cec5SDimitry Andric           // disassembly.
3530b57cec5SDimitry Andric 
3540b57cec5SDimitry Andric           if (mixed_source_and_assembly && sc.line_entry.IsValid()) {
3550b57cec5SDimitry Andric             if (sc.symbol != previous_symbol) {
3560b57cec5SDimitry Andric               SourceLine decl_line = GetFunctionDeclLineEntry(sc);
3570b57cec5SDimitry Andric               if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, decl_line))
3580b57cec5SDimitry Andric                 AddLineToSourceLineTables(decl_line, source_lines_seen);
3590b57cec5SDimitry Andric             }
3600b57cec5SDimitry Andric             if (sc.line_entry.IsValid()) {
3610b57cec5SDimitry Andric               SourceLine this_line;
3620b57cec5SDimitry Andric               this_line.file = sc.line_entry.file;
3630b57cec5SDimitry Andric               this_line.line = sc.line_entry.line;
3640b57cec5SDimitry Andric               this_line.column = sc.line_entry.column;
3650b57cec5SDimitry Andric               if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, this_line))
3660b57cec5SDimitry Andric                 AddLineToSourceLineTables(this_line, source_lines_seen);
3670b57cec5SDimitry Andric             }
3680b57cec5SDimitry Andric           }
3690b57cec5SDimitry Andric         }
3700b57cec5SDimitry Andric         sc.Clear(false);
3710b57cec5SDimitry Andric       }
3720b57cec5SDimitry Andric     }
3730b57cec5SDimitry Andric   }
3740b57cec5SDimitry Andric 
3750b57cec5SDimitry Andric   previous_symbol = nullptr;
3760b57cec5SDimitry Andric   SourceLine previous_line;
3770b57cec5SDimitry Andric   for (size_t i = 0; i < num_instructions_found; ++i) {
3785ffd83dbSDimitry Andric     Instruction *inst = GetInstructionList().GetInstructionAtIndex(i).get();
3790b57cec5SDimitry Andric 
3800b57cec5SDimitry Andric     if (inst) {
3810b57cec5SDimitry Andric       const Address &addr = inst->GetAddress();
3820b57cec5SDimitry Andric       const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr;
3830b57cec5SDimitry Andric       SourceLinesToDisplay source_lines_to_display;
3840b57cec5SDimitry Andric 
3850b57cec5SDimitry Andric       prev_sc = sc;
3860b57cec5SDimitry Andric 
3870b57cec5SDimitry Andric       ModuleSP module_sp(addr.GetModule());
3880b57cec5SDimitry Andric       if (module_sp) {
3890b57cec5SDimitry Andric         uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress(
3900b57cec5SDimitry Andric             addr, eSymbolContextEverything, sc);
3910b57cec5SDimitry Andric         if (resolved_mask) {
3920b57cec5SDimitry Andric           if (mixed_source_and_assembly) {
3930b57cec5SDimitry Andric 
3940b57cec5SDimitry Andric             // If we've started a new function (non-inlined), print all of the
3950b57cec5SDimitry Andric             // source lines from the function declaration until the first line
3960b57cec5SDimitry Andric             // table entry - typically the opening curly brace of the function.
3970b57cec5SDimitry Andric             if (previous_symbol != sc.symbol) {
3980b57cec5SDimitry Andric               // The default disassembly format puts an extra blank line
3990b57cec5SDimitry Andric               // between functions - so when we're displaying the source
4000b57cec5SDimitry Andric               // context for a function, we don't want to add a blank line
4010b57cec5SDimitry Andric               // after the source context or we'll end up with two of them.
4020b57cec5SDimitry Andric               if (previous_symbol != nullptr)
4030b57cec5SDimitry Andric                 source_lines_to_display.print_source_context_end_eol = false;
4040b57cec5SDimitry Andric 
4050b57cec5SDimitry Andric               previous_symbol = sc.symbol;
4060b57cec5SDimitry Andric               if (sc.function && sc.line_entry.IsValid()) {
4070b57cec5SDimitry Andric                 LineEntry prologue_end_line = sc.line_entry;
4080b57cec5SDimitry Andric                 if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc,
4090b57cec5SDimitry Andric                                                         prologue_end_line)) {
4100b57cec5SDimitry Andric                   FileSpec func_decl_file;
4110b57cec5SDimitry Andric                   uint32_t func_decl_line;
4120b57cec5SDimitry Andric                   sc.function->GetStartLineSourceInfo(func_decl_file,
4130b57cec5SDimitry Andric                                                       func_decl_line);
4140b57cec5SDimitry Andric                   if (func_decl_file == prologue_end_line.file ||
4150b57cec5SDimitry Andric                       func_decl_file == prologue_end_line.original_file) {
4160b57cec5SDimitry Andric                     // Add all the lines between the function declaration and
4170b57cec5SDimitry Andric                     // the first non-prologue source line to the list of lines
4180b57cec5SDimitry Andric                     // to print.
4190b57cec5SDimitry Andric                     for (uint32_t lineno = func_decl_line;
4200b57cec5SDimitry Andric                          lineno <= prologue_end_line.line; lineno++) {
4210b57cec5SDimitry Andric                       SourceLine this_line;
4220b57cec5SDimitry Andric                       this_line.file = func_decl_file;
4230b57cec5SDimitry Andric                       this_line.line = lineno;
4240b57cec5SDimitry Andric                       source_lines_to_display.lines.push_back(this_line);
4250b57cec5SDimitry Andric                     }
4260b57cec5SDimitry Andric                     // Mark the last line as the "current" one.  Usually this
4270b57cec5SDimitry Andric                     // is the open curly brace.
4280b57cec5SDimitry Andric                     if (source_lines_to_display.lines.size() > 0)
4290b57cec5SDimitry Andric                       source_lines_to_display.current_source_line =
4300b57cec5SDimitry Andric                           source_lines_to_display.lines.size() - 1;
4310b57cec5SDimitry Andric                   }
4320b57cec5SDimitry Andric                 }
4330b57cec5SDimitry Andric               }
4340b57cec5SDimitry Andric               sc.GetAddressRange(scope, 0, use_inline_block_range,
4350b57cec5SDimitry Andric                                  current_source_line_range);
4360b57cec5SDimitry Andric             }
4370b57cec5SDimitry Andric 
4380b57cec5SDimitry Andric             // If we've left a previous source line's address range, print a
4390b57cec5SDimitry Andric             // new source line
4400b57cec5SDimitry Andric             if (!current_source_line_range.ContainsFileAddress(addr)) {
4410b57cec5SDimitry Andric               sc.GetAddressRange(scope, 0, use_inline_block_range,
4420b57cec5SDimitry Andric                                  current_source_line_range);
4430b57cec5SDimitry Andric 
4440b57cec5SDimitry Andric               if (sc != prev_sc && sc.comp_unit && sc.line_entry.IsValid()) {
4450b57cec5SDimitry Andric                 SourceLine this_line;
4460b57cec5SDimitry Andric                 this_line.file = sc.line_entry.file;
4470b57cec5SDimitry Andric                 this_line.line = sc.line_entry.line;
4480b57cec5SDimitry Andric 
4490b57cec5SDimitry Andric                 if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc,
4500b57cec5SDimitry Andric                                                         this_line)) {
4510b57cec5SDimitry Andric                   // Only print this source line if it is different from the
4520b57cec5SDimitry Andric                   // last source line we printed.  There may have been inlined
4530b57cec5SDimitry Andric                   // functions between these lines that we elided, resulting in
4540b57cec5SDimitry Andric                   // the same line being printed twice in a row for a
4550b57cec5SDimitry Andric                   // contiguous block of assembly instructions.
4560b57cec5SDimitry Andric                   if (this_line != previous_line) {
4570b57cec5SDimitry Andric 
4580b57cec5SDimitry Andric                     std::vector<uint32_t> previous_lines;
4590b57cec5SDimitry Andric                     for (uint32_t i = 0;
4600b57cec5SDimitry Andric                          i < num_mixed_context_lines &&
4610b57cec5SDimitry Andric                          (this_line.line - num_mixed_context_lines) > 0;
4620b57cec5SDimitry Andric                          i++) {
4630b57cec5SDimitry Andric                       uint32_t line =
4640b57cec5SDimitry Andric                           this_line.line - num_mixed_context_lines + i;
4650b57cec5SDimitry Andric                       auto pos = source_lines_seen.find(this_line.file);
4660b57cec5SDimitry Andric                       if (pos != source_lines_seen.end()) {
4670b57cec5SDimitry Andric                         if (pos->second.count(line) == 1) {
4680b57cec5SDimitry Andric                           previous_lines.clear();
4690b57cec5SDimitry Andric                         } else {
4700b57cec5SDimitry Andric                           previous_lines.push_back(line);
4710b57cec5SDimitry Andric                         }
4720b57cec5SDimitry Andric                       }
4730b57cec5SDimitry Andric                     }
4740b57cec5SDimitry Andric                     for (size_t i = 0; i < previous_lines.size(); i++) {
4750b57cec5SDimitry Andric                       SourceLine previous_line;
4760b57cec5SDimitry Andric                       previous_line.file = this_line.file;
4770b57cec5SDimitry Andric                       previous_line.line = previous_lines[i];
4780b57cec5SDimitry Andric                       auto pos = source_lines_seen.find(previous_line.file);
4790b57cec5SDimitry Andric                       if (pos != source_lines_seen.end()) {
4800b57cec5SDimitry Andric                         pos->second.insert(previous_line.line);
4810b57cec5SDimitry Andric                       }
4820b57cec5SDimitry Andric                       source_lines_to_display.lines.push_back(previous_line);
4830b57cec5SDimitry Andric                     }
4840b57cec5SDimitry Andric 
4850b57cec5SDimitry Andric                     source_lines_to_display.lines.push_back(this_line);
4860b57cec5SDimitry Andric                     source_lines_to_display.current_source_line =
4870b57cec5SDimitry Andric                         source_lines_to_display.lines.size() - 1;
4880b57cec5SDimitry Andric 
4890b57cec5SDimitry Andric                     for (uint32_t i = 0; i < num_mixed_context_lines; i++) {
4900b57cec5SDimitry Andric                       SourceLine next_line;
4910b57cec5SDimitry Andric                       next_line.file = this_line.file;
4920b57cec5SDimitry Andric                       next_line.line = this_line.line + i + 1;
4930b57cec5SDimitry Andric                       auto pos = source_lines_seen.find(next_line.file);
4940b57cec5SDimitry Andric                       if (pos != source_lines_seen.end()) {
4950b57cec5SDimitry Andric                         if (pos->second.count(next_line.line) == 1)
4960b57cec5SDimitry Andric                           break;
4970b57cec5SDimitry Andric                         pos->second.insert(next_line.line);
4980b57cec5SDimitry Andric                       }
4990b57cec5SDimitry Andric                       source_lines_to_display.lines.push_back(next_line);
5000b57cec5SDimitry Andric                     }
5010b57cec5SDimitry Andric                   }
5020b57cec5SDimitry Andric                   previous_line = this_line;
5030b57cec5SDimitry Andric                 }
5040b57cec5SDimitry Andric               }
5050b57cec5SDimitry Andric             }
5060b57cec5SDimitry Andric           }
5070b57cec5SDimitry Andric         } else {
5080b57cec5SDimitry Andric           sc.Clear(true);
5090b57cec5SDimitry Andric         }
5100b57cec5SDimitry Andric       }
5110b57cec5SDimitry Andric 
5120b57cec5SDimitry Andric       if (source_lines_to_display.lines.size() > 0) {
5130b57cec5SDimitry Andric         strm.EOL();
5140b57cec5SDimitry Andric         for (size_t idx = 0; idx < source_lines_to_display.lines.size();
5150b57cec5SDimitry Andric              idx++) {
5160b57cec5SDimitry Andric           SourceLine ln = source_lines_to_display.lines[idx];
5170b57cec5SDimitry Andric           const char *line_highlight = "";
5180b57cec5SDimitry Andric           if (inst_is_at_pc && (options & eOptionMarkPCSourceLine)) {
5190b57cec5SDimitry Andric             line_highlight = "->";
5200b57cec5SDimitry Andric           } else if (idx == source_lines_to_display.current_source_line) {
5210b57cec5SDimitry Andric             line_highlight = "**";
5220b57cec5SDimitry Andric           }
5230b57cec5SDimitry Andric           source_manager.DisplaySourceLinesWithLineNumbers(
5240b57cec5SDimitry Andric               ln.file, ln.line, ln.column, 0, 0, line_highlight, &strm);
5250b57cec5SDimitry Andric         }
5260b57cec5SDimitry Andric         if (source_lines_to_display.print_source_context_end_eol)
5270b57cec5SDimitry Andric           strm.EOL();
5280b57cec5SDimitry Andric       }
5290b57cec5SDimitry Andric 
5300b57cec5SDimitry Andric       const bool show_bytes = (options & eOptionShowBytes) != 0;
5310b57cec5SDimitry Andric       inst->Dump(&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx, &sc,
5320b57cec5SDimitry Andric                  &prev_sc, nullptr, address_text_size);
5330b57cec5SDimitry Andric       strm.EOL();
5340b57cec5SDimitry Andric     } else {
5350b57cec5SDimitry Andric       break;
5360b57cec5SDimitry Andric     }
5370b57cec5SDimitry Andric   }
5380b57cec5SDimitry Andric }
5390b57cec5SDimitry Andric 
Disassemble(Debugger & debugger,const ArchSpec & arch,StackFrame & frame,Stream & strm)5400b57cec5SDimitry Andric bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch,
541af732203SDimitry Andric                                StackFrame &frame, Stream &strm) {
5420b57cec5SDimitry Andric   AddressRange range;
5430b57cec5SDimitry Andric   SymbolContext sc(
544af732203SDimitry Andric       frame.GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
5450b57cec5SDimitry Andric   if (sc.function) {
5460b57cec5SDimitry Andric     range = sc.function->GetAddressRange();
5470b57cec5SDimitry Andric   } else if (sc.symbol && sc.symbol->ValueIsAddress()) {
5480b57cec5SDimitry Andric     range.GetBaseAddress() = sc.symbol->GetAddressRef();
5490b57cec5SDimitry Andric     range.SetByteSize(sc.symbol->GetByteSize());
5500b57cec5SDimitry Andric   } else {
551af732203SDimitry Andric     range.GetBaseAddress() = frame.GetFrameCodeAddress();
5520b57cec5SDimitry Andric   }
5530b57cec5SDimitry Andric 
5540b57cec5SDimitry Andric     if (range.GetBaseAddress().IsValid() && range.GetByteSize() == 0)
5550b57cec5SDimitry Andric       range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE);
5560b57cec5SDimitry Andric 
557af732203SDimitry Andric     Disassembler::Limit limit = {Disassembler::Limit::Bytes,
558af732203SDimitry Andric                                  range.GetByteSize()};
559af732203SDimitry Andric     if (limit.value == 0)
560af732203SDimitry Andric       limit.value = DEFAULT_DISASM_BYTE_SIZE;
561af732203SDimitry Andric 
562af732203SDimitry Andric     return Disassemble(debugger, arch, nullptr, nullptr, frame,
563af732203SDimitry Andric                        range.GetBaseAddress(), limit, false, 0, 0, strm);
5640b57cec5SDimitry Andric }
5650b57cec5SDimitry Andric 
Instruction(const Address & address,AddressClass addr_class)5660b57cec5SDimitry Andric Instruction::Instruction(const Address &address, AddressClass addr_class)
5670b57cec5SDimitry Andric     : m_address(address), m_address_class(addr_class), m_opcode(),
5680b57cec5SDimitry Andric       m_calculated_strings(false) {}
5690b57cec5SDimitry Andric 
5700b57cec5SDimitry Andric Instruction::~Instruction() = default;
5710b57cec5SDimitry Andric 
GetAddressClass()5720b57cec5SDimitry Andric AddressClass Instruction::GetAddressClass() {
5730b57cec5SDimitry Andric   if (m_address_class == AddressClass::eInvalid)
5740b57cec5SDimitry Andric     m_address_class = m_address.GetAddressClass();
5750b57cec5SDimitry Andric   return m_address_class;
5760b57cec5SDimitry Andric }
5770b57cec5SDimitry Andric 
Dump(lldb_private::Stream * s,uint32_t max_opcode_byte_size,bool show_address,bool show_bytes,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)5780b57cec5SDimitry Andric void Instruction::Dump(lldb_private::Stream *s, uint32_t max_opcode_byte_size,
5790b57cec5SDimitry Andric                        bool show_address, bool show_bytes,
5800b57cec5SDimitry Andric                        const ExecutionContext *exe_ctx,
5810b57cec5SDimitry Andric                        const SymbolContext *sym_ctx,
5820b57cec5SDimitry Andric                        const SymbolContext *prev_sym_ctx,
5830b57cec5SDimitry Andric                        const FormatEntity::Entry *disassembly_addr_format,
5840b57cec5SDimitry Andric                        size_t max_address_text_size) {
5850b57cec5SDimitry Andric   size_t opcode_column_width = 7;
5860b57cec5SDimitry Andric   const size_t operand_column_width = 25;
5870b57cec5SDimitry Andric 
5880b57cec5SDimitry Andric   CalculateMnemonicOperandsAndCommentIfNeeded(exe_ctx);
5890b57cec5SDimitry Andric 
5900b57cec5SDimitry Andric   StreamString ss;
5910b57cec5SDimitry Andric 
5920b57cec5SDimitry Andric   if (show_address) {
5930b57cec5SDimitry Andric     Debugger::FormatDisassemblerAddress(disassembly_addr_format, sym_ctx,
5940b57cec5SDimitry Andric                                         prev_sym_ctx, exe_ctx, &m_address, ss);
5950b57cec5SDimitry Andric     ss.FillLastLineToColumn(max_address_text_size, ' ');
5960b57cec5SDimitry Andric   }
5970b57cec5SDimitry Andric 
5980b57cec5SDimitry Andric   if (show_bytes) {
5990b57cec5SDimitry Andric     if (m_opcode.GetType() == Opcode::eTypeBytes) {
6000b57cec5SDimitry Andric       // x86_64 and i386 are the only ones that use bytes right now so pad out
6010b57cec5SDimitry Andric       // the byte dump to be able to always show 15 bytes (3 chars each) plus a
6020b57cec5SDimitry Andric       // space
6030b57cec5SDimitry Andric       if (max_opcode_byte_size > 0)
6040b57cec5SDimitry Andric         m_opcode.Dump(&ss, max_opcode_byte_size * 3 + 1);
6050b57cec5SDimitry Andric       else
6060b57cec5SDimitry Andric         m_opcode.Dump(&ss, 15 * 3 + 1);
6070b57cec5SDimitry Andric     } else {
6080b57cec5SDimitry Andric       // Else, we have ARM or MIPS which can show up to a uint32_t 0x00000000
6090b57cec5SDimitry Andric       // (10 spaces) plus two for padding...
6100b57cec5SDimitry Andric       if (max_opcode_byte_size > 0)
6110b57cec5SDimitry Andric         m_opcode.Dump(&ss, max_opcode_byte_size * 3 + 1);
6120b57cec5SDimitry Andric       else
6130b57cec5SDimitry Andric         m_opcode.Dump(&ss, 12);
6140b57cec5SDimitry Andric     }
6150b57cec5SDimitry Andric   }
6160b57cec5SDimitry Andric 
6170b57cec5SDimitry Andric   const size_t opcode_pos = ss.GetSizeOfLastLine();
6180b57cec5SDimitry Andric 
6190b57cec5SDimitry Andric   // The default opcode size of 7 characters is plenty for most architectures
6200b57cec5SDimitry Andric   // but some like arm can pull out the occasional vqrshrun.s16.  We won't get
6210b57cec5SDimitry Andric   // consistent column spacing in these cases, unfortunately.
6220b57cec5SDimitry Andric   if (m_opcode_name.length() >= opcode_column_width) {
6230b57cec5SDimitry Andric     opcode_column_width = m_opcode_name.length() + 1;
6240b57cec5SDimitry Andric   }
6250b57cec5SDimitry Andric 
6260b57cec5SDimitry Andric   ss.PutCString(m_opcode_name);
6270b57cec5SDimitry Andric   ss.FillLastLineToColumn(opcode_pos + opcode_column_width, ' ');
6280b57cec5SDimitry Andric   ss.PutCString(m_mnemonics);
6290b57cec5SDimitry Andric 
6300b57cec5SDimitry Andric   if (!m_comment.empty()) {
6310b57cec5SDimitry Andric     ss.FillLastLineToColumn(
6320b57cec5SDimitry Andric         opcode_pos + opcode_column_width + operand_column_width, ' ');
6330b57cec5SDimitry Andric     ss.PutCString(" ; ");
6340b57cec5SDimitry Andric     ss.PutCString(m_comment);
6350b57cec5SDimitry Andric   }
6360b57cec5SDimitry Andric   s->PutCString(ss.GetString());
6370b57cec5SDimitry Andric }
6380b57cec5SDimitry Andric 
DumpEmulation(const ArchSpec & arch)6390b57cec5SDimitry Andric bool Instruction::DumpEmulation(const ArchSpec &arch) {
6400b57cec5SDimitry Andric   std::unique_ptr<EmulateInstruction> insn_emulator_up(
6410b57cec5SDimitry Andric       EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr));
6420b57cec5SDimitry Andric   if (insn_emulator_up) {
6430b57cec5SDimitry Andric     insn_emulator_up->SetInstruction(GetOpcode(), GetAddress(), nullptr);
6440b57cec5SDimitry Andric     return insn_emulator_up->EvaluateInstruction(0);
6450b57cec5SDimitry Andric   }
6460b57cec5SDimitry Andric 
6470b57cec5SDimitry Andric   return false;
6480b57cec5SDimitry Andric }
6490b57cec5SDimitry Andric 
CanSetBreakpoint()6500b57cec5SDimitry Andric bool Instruction::CanSetBreakpoint () {
6510b57cec5SDimitry Andric   return !HasDelaySlot();
6520b57cec5SDimitry Andric }
6530b57cec5SDimitry Andric 
HasDelaySlot()6540b57cec5SDimitry Andric bool Instruction::HasDelaySlot() {
6550b57cec5SDimitry Andric   // Default is false.
6560b57cec5SDimitry Andric   return false;
6570b57cec5SDimitry Andric }
6580b57cec5SDimitry Andric 
ReadArray(FILE * in_file,Stream * out_stream,OptionValue::Type data_type)6590b57cec5SDimitry Andric OptionValueSP Instruction::ReadArray(FILE *in_file, Stream *out_stream,
6600b57cec5SDimitry Andric                                      OptionValue::Type data_type) {
6610b57cec5SDimitry Andric   bool done = false;
6620b57cec5SDimitry Andric   char buffer[1024];
6630b57cec5SDimitry Andric 
6640b57cec5SDimitry Andric   auto option_value_sp = std::make_shared<OptionValueArray>(1u << data_type);
6650b57cec5SDimitry Andric 
6660b57cec5SDimitry Andric   int idx = 0;
6670b57cec5SDimitry Andric   while (!done) {
6680b57cec5SDimitry Andric     if (!fgets(buffer, 1023, in_file)) {
6690b57cec5SDimitry Andric       out_stream->Printf(
6700b57cec5SDimitry Andric           "Instruction::ReadArray:  Error reading file (fgets).\n");
6710b57cec5SDimitry Andric       option_value_sp.reset();
6720b57cec5SDimitry Andric       return option_value_sp;
6730b57cec5SDimitry Andric     }
6740b57cec5SDimitry Andric 
6750b57cec5SDimitry Andric     std::string line(buffer);
6760b57cec5SDimitry Andric 
6770b57cec5SDimitry Andric     size_t len = line.size();
6780b57cec5SDimitry Andric     if (line[len - 1] == '\n') {
6790b57cec5SDimitry Andric       line[len - 1] = '\0';
6800b57cec5SDimitry Andric       line.resize(len - 1);
6810b57cec5SDimitry Andric     }
6820b57cec5SDimitry Andric 
6830b57cec5SDimitry Andric     if ((line.size() == 1) && line[0] == ']') {
6840b57cec5SDimitry Andric       done = true;
6850b57cec5SDimitry Andric       line.clear();
6860b57cec5SDimitry Andric     }
6870b57cec5SDimitry Andric 
6880b57cec5SDimitry Andric     if (!line.empty()) {
6890b57cec5SDimitry Andric       std::string value;
6900b57cec5SDimitry Andric       static RegularExpression g_reg_exp(
6910b57cec5SDimitry Andric           llvm::StringRef("^[ \t]*([^ \t]+)[ \t]*$"));
6929dba64beSDimitry Andric       llvm::SmallVector<llvm::StringRef, 2> matches;
6939dba64beSDimitry Andric       if (g_reg_exp.Execute(line, &matches))
6949dba64beSDimitry Andric         value = matches[1].str();
6950b57cec5SDimitry Andric       else
6960b57cec5SDimitry Andric         value = line;
6970b57cec5SDimitry Andric 
6980b57cec5SDimitry Andric       OptionValueSP data_value_sp;
6990b57cec5SDimitry Andric       switch (data_type) {
7000b57cec5SDimitry Andric       case OptionValue::eTypeUInt64:
7010b57cec5SDimitry Andric         data_value_sp = std::make_shared<OptionValueUInt64>(0, 0);
7020b57cec5SDimitry Andric         data_value_sp->SetValueFromString(value);
7030b57cec5SDimitry Andric         break;
7040b57cec5SDimitry Andric       // Other types can be added later as needed.
7050b57cec5SDimitry Andric       default:
7060b57cec5SDimitry Andric         data_value_sp = std::make_shared<OptionValueString>(value.c_str(), "");
7070b57cec5SDimitry Andric         break;
7080b57cec5SDimitry Andric       }
7090b57cec5SDimitry Andric 
7100b57cec5SDimitry Andric       option_value_sp->GetAsArray()->InsertValue(idx, data_value_sp);
7110b57cec5SDimitry Andric       ++idx;
7120b57cec5SDimitry Andric     }
7130b57cec5SDimitry Andric   }
7140b57cec5SDimitry Andric 
7150b57cec5SDimitry Andric   return option_value_sp;
7160b57cec5SDimitry Andric }
7170b57cec5SDimitry Andric 
ReadDictionary(FILE * in_file,Stream * out_stream)7180b57cec5SDimitry Andric OptionValueSP Instruction::ReadDictionary(FILE *in_file, Stream *out_stream) {
7190b57cec5SDimitry Andric   bool done = false;
7200b57cec5SDimitry Andric   char buffer[1024];
7210b57cec5SDimitry Andric 
7220b57cec5SDimitry Andric   auto option_value_sp = std::make_shared<OptionValueDictionary>();
7230b57cec5SDimitry Andric   static ConstString encoding_key("data_encoding");
7240b57cec5SDimitry Andric   OptionValue::Type data_type = OptionValue::eTypeInvalid;
7250b57cec5SDimitry Andric 
7260b57cec5SDimitry Andric   while (!done) {
7270b57cec5SDimitry Andric     // Read the next line in the file
7280b57cec5SDimitry Andric     if (!fgets(buffer, 1023, in_file)) {
7290b57cec5SDimitry Andric       out_stream->Printf(
7300b57cec5SDimitry Andric           "Instruction::ReadDictionary: Error reading file (fgets).\n");
7310b57cec5SDimitry Andric       option_value_sp.reset();
7320b57cec5SDimitry Andric       return option_value_sp;
7330b57cec5SDimitry Andric     }
7340b57cec5SDimitry Andric 
7350b57cec5SDimitry Andric     // Check to see if the line contains the end-of-dictionary marker ("}")
7360b57cec5SDimitry Andric     std::string line(buffer);
7370b57cec5SDimitry Andric 
7380b57cec5SDimitry Andric     size_t len = line.size();
7390b57cec5SDimitry Andric     if (line[len - 1] == '\n') {
7400b57cec5SDimitry Andric       line[len - 1] = '\0';
7410b57cec5SDimitry Andric       line.resize(len - 1);
7420b57cec5SDimitry Andric     }
7430b57cec5SDimitry Andric 
7440b57cec5SDimitry Andric     if ((line.size() == 1) && (line[0] == '}')) {
7450b57cec5SDimitry Andric       done = true;
7460b57cec5SDimitry Andric       line.clear();
7470b57cec5SDimitry Andric     }
7480b57cec5SDimitry Andric 
7490b57cec5SDimitry Andric     // Try to find a key-value pair in the current line and add it to the
7500b57cec5SDimitry Andric     // dictionary.
7510b57cec5SDimitry Andric     if (!line.empty()) {
7520b57cec5SDimitry Andric       static RegularExpression g_reg_exp(llvm::StringRef(
7530b57cec5SDimitry Andric           "^[ \t]*([a-zA-Z_][a-zA-Z0-9_]*)[ \t]*=[ \t]*(.*)[ \t]*$"));
7540b57cec5SDimitry Andric 
7559dba64beSDimitry Andric       llvm::SmallVector<llvm::StringRef, 3> matches;
7569dba64beSDimitry Andric 
7579dba64beSDimitry Andric       bool reg_exp_success = g_reg_exp.Execute(line, &matches);
7580b57cec5SDimitry Andric       std::string key;
7590b57cec5SDimitry Andric       std::string value;
7600b57cec5SDimitry Andric       if (reg_exp_success) {
7619dba64beSDimitry Andric         key = matches[1].str();
7629dba64beSDimitry Andric         value = matches[2].str();
7630b57cec5SDimitry Andric       } else {
7640b57cec5SDimitry Andric         out_stream->Printf("Instruction::ReadDictionary: Failure executing "
7650b57cec5SDimitry Andric                            "regular expression.\n");
7660b57cec5SDimitry Andric         option_value_sp.reset();
7670b57cec5SDimitry Andric         return option_value_sp;
7680b57cec5SDimitry Andric       }
7690b57cec5SDimitry Andric 
7700b57cec5SDimitry Andric       ConstString const_key(key.c_str());
7710b57cec5SDimitry Andric       // Check value to see if it's the start of an array or dictionary.
7720b57cec5SDimitry Andric 
7730b57cec5SDimitry Andric       lldb::OptionValueSP value_sp;
7740b57cec5SDimitry Andric       assert(value.empty() == false);
7750b57cec5SDimitry Andric       assert(key.empty() == false);
7760b57cec5SDimitry Andric 
7770b57cec5SDimitry Andric       if (value[0] == '{') {
7780b57cec5SDimitry Andric         assert(value.size() == 1);
7790b57cec5SDimitry Andric         // value is a dictionary
7800b57cec5SDimitry Andric         value_sp = ReadDictionary(in_file, out_stream);
7810b57cec5SDimitry Andric         if (!value_sp) {
7820b57cec5SDimitry Andric           option_value_sp.reset();
7830b57cec5SDimitry Andric           return option_value_sp;
7840b57cec5SDimitry Andric         }
7850b57cec5SDimitry Andric       } else if (value[0] == '[') {
7860b57cec5SDimitry Andric         assert(value.size() == 1);
7870b57cec5SDimitry Andric         // value is an array
7880b57cec5SDimitry Andric         value_sp = ReadArray(in_file, out_stream, data_type);
7890b57cec5SDimitry Andric         if (!value_sp) {
7900b57cec5SDimitry Andric           option_value_sp.reset();
7910b57cec5SDimitry Andric           return option_value_sp;
7920b57cec5SDimitry Andric         }
7930b57cec5SDimitry Andric         // We've used the data_type to read an array; re-set the type to
7940b57cec5SDimitry Andric         // Invalid
7950b57cec5SDimitry Andric         data_type = OptionValue::eTypeInvalid;
7960b57cec5SDimitry Andric       } else if ((value[0] == '0') && (value[1] == 'x')) {
7970b57cec5SDimitry Andric         value_sp = std::make_shared<OptionValueUInt64>(0, 0);
7980b57cec5SDimitry Andric         value_sp->SetValueFromString(value);
7990b57cec5SDimitry Andric       } else {
8000b57cec5SDimitry Andric         size_t len = value.size();
8010b57cec5SDimitry Andric         if ((value[0] == '"') && (value[len - 1] == '"'))
8020b57cec5SDimitry Andric           value = value.substr(1, len - 2);
8030b57cec5SDimitry Andric         value_sp = std::make_shared<OptionValueString>(value.c_str(), "");
8040b57cec5SDimitry Andric       }
8050b57cec5SDimitry Andric 
8060b57cec5SDimitry Andric       if (const_key == encoding_key) {
8070b57cec5SDimitry Andric         // A 'data_encoding=..." is NOT a normal key-value pair; it is meta-data
8080b57cec5SDimitry Andric         // indicating the
8090b57cec5SDimitry Andric         // data type of an upcoming array (usually the next bit of data to be
8100b57cec5SDimitry Andric         // read in).
8110b57cec5SDimitry Andric         if (strcmp(value.c_str(), "uint32_t") == 0)
8120b57cec5SDimitry Andric           data_type = OptionValue::eTypeUInt64;
8130b57cec5SDimitry Andric       } else
8140b57cec5SDimitry Andric         option_value_sp->GetAsDictionary()->SetValueForKey(const_key, value_sp,
8150b57cec5SDimitry Andric                                                            false);
8160b57cec5SDimitry Andric     }
8170b57cec5SDimitry Andric   }
8180b57cec5SDimitry Andric 
8190b57cec5SDimitry Andric   return option_value_sp;
8200b57cec5SDimitry Andric }
8210b57cec5SDimitry Andric 
TestEmulation(Stream * out_stream,const char * file_name)8220b57cec5SDimitry Andric bool Instruction::TestEmulation(Stream *out_stream, const char *file_name) {
8230b57cec5SDimitry Andric   if (!out_stream)
8240b57cec5SDimitry Andric     return false;
8250b57cec5SDimitry Andric 
8260b57cec5SDimitry Andric   if (!file_name) {
8270b57cec5SDimitry Andric     out_stream->Printf("Instruction::TestEmulation:  Missing file_name.");
8280b57cec5SDimitry Andric     return false;
8290b57cec5SDimitry Andric   }
8300b57cec5SDimitry Andric   FILE *test_file = FileSystem::Instance().Fopen(file_name, "r");
8310b57cec5SDimitry Andric   if (!test_file) {
8320b57cec5SDimitry Andric     out_stream->Printf(
8330b57cec5SDimitry Andric         "Instruction::TestEmulation: Attempt to open test file failed.");
8340b57cec5SDimitry Andric     return false;
8350b57cec5SDimitry Andric   }
8360b57cec5SDimitry Andric 
8370b57cec5SDimitry Andric   char buffer[256];
8380b57cec5SDimitry Andric   if (!fgets(buffer, 255, test_file)) {
8390b57cec5SDimitry Andric     out_stream->Printf(
8400b57cec5SDimitry Andric         "Instruction::TestEmulation: Error reading first line of test file.\n");
8410b57cec5SDimitry Andric     fclose(test_file);
8420b57cec5SDimitry Andric     return false;
8430b57cec5SDimitry Andric   }
8440b57cec5SDimitry Andric 
8450b57cec5SDimitry Andric   if (strncmp(buffer, "InstructionEmulationState={", 27) != 0) {
8460b57cec5SDimitry Andric     out_stream->Printf("Instructin::TestEmulation: Test file does not contain "
8470b57cec5SDimitry Andric                        "emulation state dictionary\n");
8480b57cec5SDimitry Andric     fclose(test_file);
8490b57cec5SDimitry Andric     return false;
8500b57cec5SDimitry Andric   }
8510b57cec5SDimitry Andric 
8520b57cec5SDimitry Andric   // Read all the test information from the test file into an
8530b57cec5SDimitry Andric   // OptionValueDictionary.
8540b57cec5SDimitry Andric 
8550b57cec5SDimitry Andric   OptionValueSP data_dictionary_sp(ReadDictionary(test_file, out_stream));
8560b57cec5SDimitry Andric   if (!data_dictionary_sp) {
8570b57cec5SDimitry Andric     out_stream->Printf(
8580b57cec5SDimitry Andric         "Instruction::TestEmulation:  Error reading Dictionary Object.\n");
8590b57cec5SDimitry Andric     fclose(test_file);
8600b57cec5SDimitry Andric     return false;
8610b57cec5SDimitry Andric   }
8620b57cec5SDimitry Andric 
8630b57cec5SDimitry Andric   fclose(test_file);
8640b57cec5SDimitry Andric 
8650b57cec5SDimitry Andric   OptionValueDictionary *data_dictionary =
8660b57cec5SDimitry Andric       data_dictionary_sp->GetAsDictionary();
8670b57cec5SDimitry Andric   static ConstString description_key("assembly_string");
8680b57cec5SDimitry Andric   static ConstString triple_key("triple");
8690b57cec5SDimitry Andric 
8700b57cec5SDimitry Andric   OptionValueSP value_sp = data_dictionary->GetValueForKey(description_key);
8710b57cec5SDimitry Andric 
8720b57cec5SDimitry Andric   if (!value_sp) {
8730b57cec5SDimitry Andric     out_stream->Printf("Instruction::TestEmulation:  Test file does not "
8740b57cec5SDimitry Andric                        "contain description string.\n");
8750b57cec5SDimitry Andric     return false;
8760b57cec5SDimitry Andric   }
8770b57cec5SDimitry Andric 
8780b57cec5SDimitry Andric   SetDescription(value_sp->GetStringValue());
8790b57cec5SDimitry Andric 
8800b57cec5SDimitry Andric   value_sp = data_dictionary->GetValueForKey(triple_key);
8810b57cec5SDimitry Andric   if (!value_sp) {
8820b57cec5SDimitry Andric     out_stream->Printf(
8830b57cec5SDimitry Andric         "Instruction::TestEmulation: Test file does not contain triple.\n");
8840b57cec5SDimitry Andric     return false;
8850b57cec5SDimitry Andric   }
8860b57cec5SDimitry Andric 
8870b57cec5SDimitry Andric   ArchSpec arch;
8880b57cec5SDimitry Andric   arch.SetTriple(llvm::Triple(value_sp->GetStringValue()));
8890b57cec5SDimitry Andric 
8900b57cec5SDimitry Andric   bool success = false;
8910b57cec5SDimitry Andric   std::unique_ptr<EmulateInstruction> insn_emulator_up(
8920b57cec5SDimitry Andric       EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr));
8930b57cec5SDimitry Andric   if (insn_emulator_up)
8940b57cec5SDimitry Andric     success =
8950b57cec5SDimitry Andric         insn_emulator_up->TestEmulation(out_stream, arch, data_dictionary);
8960b57cec5SDimitry Andric 
8970b57cec5SDimitry Andric   if (success)
8980b57cec5SDimitry Andric     out_stream->Printf("Emulation test succeeded.");
8990b57cec5SDimitry Andric   else
9000b57cec5SDimitry Andric     out_stream->Printf("Emulation test failed.");
9010b57cec5SDimitry Andric 
9020b57cec5SDimitry Andric   return success;
9030b57cec5SDimitry Andric }
9040b57cec5SDimitry 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)9050b57cec5SDimitry Andric bool Instruction::Emulate(
9060b57cec5SDimitry Andric     const ArchSpec &arch, uint32_t evaluate_options, void *baton,
9070b57cec5SDimitry Andric     EmulateInstruction::ReadMemoryCallback read_mem_callback,
9080b57cec5SDimitry Andric     EmulateInstruction::WriteMemoryCallback write_mem_callback,
9090b57cec5SDimitry Andric     EmulateInstruction::ReadRegisterCallback read_reg_callback,
9100b57cec5SDimitry Andric     EmulateInstruction::WriteRegisterCallback write_reg_callback) {
9110b57cec5SDimitry Andric   std::unique_ptr<EmulateInstruction> insn_emulator_up(
9120b57cec5SDimitry Andric       EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr));
9130b57cec5SDimitry Andric   if (insn_emulator_up) {
9140b57cec5SDimitry Andric     insn_emulator_up->SetBaton(baton);
9150b57cec5SDimitry Andric     insn_emulator_up->SetCallbacks(read_mem_callback, write_mem_callback,
9160b57cec5SDimitry Andric                                    read_reg_callback, write_reg_callback);
9170b57cec5SDimitry Andric     insn_emulator_up->SetInstruction(GetOpcode(), GetAddress(), nullptr);
9180b57cec5SDimitry Andric     return insn_emulator_up->EvaluateInstruction(evaluate_options);
9190b57cec5SDimitry Andric   }
9200b57cec5SDimitry Andric 
9210b57cec5SDimitry Andric   return false;
9220b57cec5SDimitry Andric }
9230b57cec5SDimitry Andric 
GetData(DataExtractor & data)9240b57cec5SDimitry Andric uint32_t Instruction::GetData(DataExtractor &data) {
9250b57cec5SDimitry Andric   return m_opcode.GetData(data);
9260b57cec5SDimitry Andric }
9270b57cec5SDimitry Andric 
InstructionList()9280b57cec5SDimitry Andric InstructionList::InstructionList() : m_instructions() {}
9290b57cec5SDimitry Andric 
9300b57cec5SDimitry Andric InstructionList::~InstructionList() = default;
9310b57cec5SDimitry Andric 
GetSize() const9320b57cec5SDimitry Andric size_t InstructionList::GetSize() const { return m_instructions.size(); }
9330b57cec5SDimitry Andric 
GetMaxOpcocdeByteSize() const9340b57cec5SDimitry Andric uint32_t InstructionList::GetMaxOpcocdeByteSize() const {
9350b57cec5SDimitry Andric   uint32_t max_inst_size = 0;
9360b57cec5SDimitry Andric   collection::const_iterator pos, end;
9370b57cec5SDimitry Andric   for (pos = m_instructions.begin(), end = m_instructions.end(); pos != end;
9380b57cec5SDimitry Andric        ++pos) {
9390b57cec5SDimitry Andric     uint32_t inst_size = (*pos)->GetOpcode().GetByteSize();
9400b57cec5SDimitry Andric     if (max_inst_size < inst_size)
9410b57cec5SDimitry Andric       max_inst_size = inst_size;
9420b57cec5SDimitry Andric   }
9430b57cec5SDimitry Andric   return max_inst_size;
9440b57cec5SDimitry Andric }
9450b57cec5SDimitry Andric 
GetInstructionAtIndex(size_t idx) const9460b57cec5SDimitry Andric InstructionSP InstructionList::GetInstructionAtIndex(size_t idx) const {
9470b57cec5SDimitry Andric   InstructionSP inst_sp;
9480b57cec5SDimitry Andric   if (idx < m_instructions.size())
9490b57cec5SDimitry Andric     inst_sp = m_instructions[idx];
9500b57cec5SDimitry Andric   return inst_sp;
9510b57cec5SDimitry Andric }
9520b57cec5SDimitry Andric 
GetInstructionAtAddress(const Address & address)953af732203SDimitry Andric InstructionSP InstructionList::GetInstructionAtAddress(const Address &address) {
954af732203SDimitry Andric   uint32_t index = GetIndexOfInstructionAtAddress(address);
955af732203SDimitry Andric   if (index != UINT32_MAX)
956af732203SDimitry Andric     return GetInstructionAtIndex(index);
957af732203SDimitry Andric   return nullptr;
958af732203SDimitry Andric }
959af732203SDimitry Andric 
Dump(Stream * s,bool show_address,bool show_bytes,const ExecutionContext * exe_ctx)9600b57cec5SDimitry Andric void InstructionList::Dump(Stream *s, bool show_address, bool show_bytes,
9610b57cec5SDimitry Andric                            const ExecutionContext *exe_ctx) {
9620b57cec5SDimitry Andric   const uint32_t max_opcode_byte_size = GetMaxOpcocdeByteSize();
9630b57cec5SDimitry Andric   collection::const_iterator pos, begin, end;
9640b57cec5SDimitry Andric 
9650b57cec5SDimitry Andric   const FormatEntity::Entry *disassembly_format = nullptr;
9660b57cec5SDimitry Andric   FormatEntity::Entry format;
9670b57cec5SDimitry Andric   if (exe_ctx && exe_ctx->HasTargetScope()) {
9680b57cec5SDimitry Andric     disassembly_format =
9690b57cec5SDimitry Andric         exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat();
9700b57cec5SDimitry Andric   } else {
9710b57cec5SDimitry Andric     FormatEntity::Parse("${addr}: ", format);
9720b57cec5SDimitry Andric     disassembly_format = &format;
9730b57cec5SDimitry Andric   }
9740b57cec5SDimitry Andric 
9750b57cec5SDimitry Andric   for (begin = m_instructions.begin(), end = m_instructions.end(), pos = begin;
9760b57cec5SDimitry Andric        pos != end; ++pos) {
9770b57cec5SDimitry Andric     if (pos != begin)
9780b57cec5SDimitry Andric       s->EOL();
9790b57cec5SDimitry Andric     (*pos)->Dump(s, max_opcode_byte_size, show_address, show_bytes, exe_ctx,
9800b57cec5SDimitry Andric                  nullptr, nullptr, disassembly_format, 0);
9810b57cec5SDimitry Andric   }
9820b57cec5SDimitry Andric }
9830b57cec5SDimitry Andric 
Clear()9840b57cec5SDimitry Andric void InstructionList::Clear() { m_instructions.clear(); }
9850b57cec5SDimitry Andric 
Append(lldb::InstructionSP & inst_sp)9860b57cec5SDimitry Andric void InstructionList::Append(lldb::InstructionSP &inst_sp) {
9870b57cec5SDimitry Andric   if (inst_sp)
9880b57cec5SDimitry Andric     m_instructions.push_back(inst_sp);
9890b57cec5SDimitry Andric }
9900b57cec5SDimitry Andric 
9910b57cec5SDimitry Andric uint32_t
GetIndexOfNextBranchInstruction(uint32_t start,bool ignore_calls,bool * found_calls) const9920b57cec5SDimitry Andric InstructionList::GetIndexOfNextBranchInstruction(uint32_t start,
993480093f4SDimitry Andric                                                  bool ignore_calls,
994480093f4SDimitry Andric                                                  bool *found_calls) const {
9950b57cec5SDimitry Andric   size_t num_instructions = m_instructions.size();
9960b57cec5SDimitry Andric 
9970b57cec5SDimitry Andric   uint32_t next_branch = UINT32_MAX;
998480093f4SDimitry Andric 
999480093f4SDimitry Andric   if (found_calls)
1000480093f4SDimitry Andric     *found_calls = false;
1001af732203SDimitry Andric   for (size_t i = start; i < num_instructions; i++) {
10020b57cec5SDimitry Andric     if (m_instructions[i]->DoesBranch()) {
1003480093f4SDimitry Andric       if (ignore_calls && m_instructions[i]->IsCall()) {
1004480093f4SDimitry Andric         if (found_calls)
1005480093f4SDimitry Andric           *found_calls = true;
10060b57cec5SDimitry Andric         continue;
1007480093f4SDimitry Andric       }
10080b57cec5SDimitry Andric       next_branch = i;
10090b57cec5SDimitry Andric       break;
10100b57cec5SDimitry Andric     }
10110b57cec5SDimitry Andric   }
10120b57cec5SDimitry Andric 
10130b57cec5SDimitry Andric   return next_branch;
10140b57cec5SDimitry Andric }
10150b57cec5SDimitry Andric 
10160b57cec5SDimitry Andric uint32_t
GetIndexOfInstructionAtAddress(const Address & address)10170b57cec5SDimitry Andric InstructionList::GetIndexOfInstructionAtAddress(const Address &address) {
10180b57cec5SDimitry Andric   size_t num_instructions = m_instructions.size();
10190b57cec5SDimitry Andric   uint32_t index = UINT32_MAX;
10200b57cec5SDimitry Andric   for (size_t i = 0; i < num_instructions; i++) {
10210b57cec5SDimitry Andric     if (m_instructions[i]->GetAddress() == address) {
10220b57cec5SDimitry Andric       index = i;
10230b57cec5SDimitry Andric       break;
10240b57cec5SDimitry Andric     }
10250b57cec5SDimitry Andric   }
10260b57cec5SDimitry Andric   return index;
10270b57cec5SDimitry Andric }
10280b57cec5SDimitry Andric 
10290b57cec5SDimitry Andric uint32_t
GetIndexOfInstructionAtLoadAddress(lldb::addr_t load_addr,Target & target)10300b57cec5SDimitry Andric InstructionList::GetIndexOfInstructionAtLoadAddress(lldb::addr_t load_addr,
10310b57cec5SDimitry Andric                                                     Target &target) {
10320b57cec5SDimitry Andric   Address address;
10330b57cec5SDimitry Andric   address.SetLoadAddress(load_addr, &target);
10340b57cec5SDimitry Andric   return GetIndexOfInstructionAtAddress(address);
10350b57cec5SDimitry Andric }
10360b57cec5SDimitry Andric 
ParseInstructions(Target & target,Address start,Limit limit,Stream * error_strm_ptr,bool force_live_memory)10375ffd83dbSDimitry Andric size_t Disassembler::ParseInstructions(Target &target, Address start,
10385ffd83dbSDimitry Andric                                        Limit limit, Stream *error_strm_ptr,
1039*5f7ddb14SDimitry Andric                                        bool force_live_memory) {
10405ffd83dbSDimitry Andric   m_instruction_list.Clear();
10415ffd83dbSDimitry Andric 
10425ffd83dbSDimitry Andric   if (!start.IsValid())
10430b57cec5SDimitry Andric     return 0;
10440b57cec5SDimitry Andric 
10455ffd83dbSDimitry Andric   start = ResolveAddress(target, start);
10465ffd83dbSDimitry Andric 
10475ffd83dbSDimitry Andric   addr_t byte_size = limit.value;
10485ffd83dbSDimitry Andric   if (limit.kind == Limit::Instructions)
10495ffd83dbSDimitry Andric     byte_size *= m_arch.GetMaximumOpcodeByteSize();
10500b57cec5SDimitry Andric   auto data_sp = std::make_shared<DataBufferHeap>(byte_size, '\0');
10510b57cec5SDimitry Andric 
10520b57cec5SDimitry Andric   Status error;
10530b57cec5SDimitry Andric   lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
10545ffd83dbSDimitry Andric   const size_t bytes_read =
1055*5f7ddb14SDimitry Andric       target.ReadMemory(start, data_sp->GetBytes(), data_sp->GetByteSize(),
1056*5f7ddb14SDimitry Andric                         error, force_live_memory, &load_addr);
10575ffd83dbSDimitry Andric   const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS;
10580b57cec5SDimitry Andric 
10595ffd83dbSDimitry Andric   if (bytes_read == 0) {
10605ffd83dbSDimitry Andric     if (error_strm_ptr) {
10615ffd83dbSDimitry Andric       if (const char *error_cstr = error.AsCString())
10625ffd83dbSDimitry Andric         error_strm_ptr->Printf("error: %s\n", error_cstr);
10635ffd83dbSDimitry Andric     }
10645ffd83dbSDimitry Andric     return 0;
10655ffd83dbSDimitry Andric   }
10665ffd83dbSDimitry Andric 
10670b57cec5SDimitry Andric   if (bytes_read != data_sp->GetByteSize())
10680b57cec5SDimitry Andric     data_sp->SetByteSize(bytes_read);
10690b57cec5SDimitry Andric   DataExtractor data(data_sp, m_arch.GetByteOrder(),
10700b57cec5SDimitry Andric                      m_arch.GetAddressByteSize());
10715ffd83dbSDimitry Andric   return DecodeInstructions(start, data, 0,
10725ffd83dbSDimitry Andric                             limit.kind == Limit::Instructions ? limit.value
10735ffd83dbSDimitry Andric                                                               : UINT32_MAX,
10740b57cec5SDimitry Andric                             false, data_from_file);
10750b57cec5SDimitry Andric }
10760b57cec5SDimitry Andric 
10770b57cec5SDimitry Andric // Disassembler copy constructor
Disassembler(const ArchSpec & arch,const char * flavor)10780b57cec5SDimitry Andric Disassembler::Disassembler(const ArchSpec &arch, const char *flavor)
10790b57cec5SDimitry Andric     : m_arch(arch), m_instruction_list(), m_base_addr(LLDB_INVALID_ADDRESS),
10800b57cec5SDimitry Andric       m_flavor() {
10810b57cec5SDimitry Andric   if (flavor == nullptr)
10820b57cec5SDimitry Andric     m_flavor.assign("default");
10830b57cec5SDimitry Andric   else
10840b57cec5SDimitry Andric     m_flavor.assign(flavor);
10850b57cec5SDimitry Andric 
10860b57cec5SDimitry Andric   // If this is an arm variant that can only include thumb (T16, T32)
10870b57cec5SDimitry Andric   // instructions, force the arch triple to be "thumbv.." instead of "armv..."
10880b57cec5SDimitry Andric   if (arch.IsAlwaysThumbInstructions()) {
10890b57cec5SDimitry Andric     std::string thumb_arch_name(arch.GetTriple().getArchName().str());
10900b57cec5SDimitry Andric     // Replace "arm" with "thumb" so we get all thumb variants correct
10910b57cec5SDimitry Andric     if (thumb_arch_name.size() > 3) {
10920b57cec5SDimitry Andric       thumb_arch_name.erase(0, 3);
10930b57cec5SDimitry Andric       thumb_arch_name.insert(0, "thumb");
10940b57cec5SDimitry Andric     }
10950b57cec5SDimitry Andric     m_arch.SetTriple(thumb_arch_name.c_str());
10960b57cec5SDimitry Andric   }
10970b57cec5SDimitry Andric }
10980b57cec5SDimitry Andric 
10990b57cec5SDimitry Andric Disassembler::~Disassembler() = default;
11000b57cec5SDimitry Andric 
GetInstructionList()11010b57cec5SDimitry Andric InstructionList &Disassembler::GetInstructionList() {
11020b57cec5SDimitry Andric   return m_instruction_list;
11030b57cec5SDimitry Andric }
11040b57cec5SDimitry Andric 
GetInstructionList() const11050b57cec5SDimitry Andric const InstructionList &Disassembler::GetInstructionList() const {
11060b57cec5SDimitry Andric   return m_instruction_list;
11070b57cec5SDimitry Andric }
11080b57cec5SDimitry Andric 
11090b57cec5SDimitry Andric // Class PseudoInstruction
11100b57cec5SDimitry Andric 
PseudoInstruction()11110b57cec5SDimitry Andric PseudoInstruction::PseudoInstruction()
11120b57cec5SDimitry Andric     : Instruction(Address(), AddressClass::eUnknown), m_description() {}
11130b57cec5SDimitry Andric 
11140b57cec5SDimitry Andric PseudoInstruction::~PseudoInstruction() = default;
11150b57cec5SDimitry Andric 
DoesBranch()11160b57cec5SDimitry Andric bool PseudoInstruction::DoesBranch() {
11170b57cec5SDimitry Andric   // This is NOT a valid question for a pseudo instruction.
11180b57cec5SDimitry Andric   return false;
11190b57cec5SDimitry Andric }
11200b57cec5SDimitry Andric 
HasDelaySlot()11210b57cec5SDimitry Andric bool PseudoInstruction::HasDelaySlot() {
11220b57cec5SDimitry Andric   // This is NOT a valid question for a pseudo instruction.
11230b57cec5SDimitry Andric   return false;
11240b57cec5SDimitry Andric }
11250b57cec5SDimitry Andric 
Decode(const lldb_private::Disassembler & disassembler,const lldb_private::DataExtractor & data,lldb::offset_t data_offset)11260b57cec5SDimitry Andric size_t PseudoInstruction::Decode(const lldb_private::Disassembler &disassembler,
11270b57cec5SDimitry Andric                                  const lldb_private::DataExtractor &data,
11280b57cec5SDimitry Andric                                  lldb::offset_t data_offset) {
11290b57cec5SDimitry Andric   return m_opcode.GetByteSize();
11300b57cec5SDimitry Andric }
11310b57cec5SDimitry Andric 
SetOpcode(size_t opcode_size,void * opcode_data)11320b57cec5SDimitry Andric void PseudoInstruction::SetOpcode(size_t opcode_size, void *opcode_data) {
11330b57cec5SDimitry Andric   if (!opcode_data)
11340b57cec5SDimitry Andric     return;
11350b57cec5SDimitry Andric 
11360b57cec5SDimitry Andric   switch (opcode_size) {
11370b57cec5SDimitry Andric   case 8: {
11380b57cec5SDimitry Andric     uint8_t value8 = *((uint8_t *)opcode_data);
11390b57cec5SDimitry Andric     m_opcode.SetOpcode8(value8, eByteOrderInvalid);
11400b57cec5SDimitry Andric     break;
11410b57cec5SDimitry Andric   }
11420b57cec5SDimitry Andric   case 16: {
11430b57cec5SDimitry Andric     uint16_t value16 = *((uint16_t *)opcode_data);
11440b57cec5SDimitry Andric     m_opcode.SetOpcode16(value16, eByteOrderInvalid);
11450b57cec5SDimitry Andric     break;
11460b57cec5SDimitry Andric   }
11470b57cec5SDimitry Andric   case 32: {
11480b57cec5SDimitry Andric     uint32_t value32 = *((uint32_t *)opcode_data);
11490b57cec5SDimitry Andric     m_opcode.SetOpcode32(value32, eByteOrderInvalid);
11500b57cec5SDimitry Andric     break;
11510b57cec5SDimitry Andric   }
11520b57cec5SDimitry Andric   case 64: {
11530b57cec5SDimitry Andric     uint64_t value64 = *((uint64_t *)opcode_data);
11540b57cec5SDimitry Andric     m_opcode.SetOpcode64(value64, eByteOrderInvalid);
11550b57cec5SDimitry Andric     break;
11560b57cec5SDimitry Andric   }
11570b57cec5SDimitry Andric   default:
11580b57cec5SDimitry Andric     break;
11590b57cec5SDimitry Andric   }
11600b57cec5SDimitry Andric }
11610b57cec5SDimitry Andric 
SetDescription(llvm::StringRef description)11620b57cec5SDimitry Andric void PseudoInstruction::SetDescription(llvm::StringRef description) {
11635ffd83dbSDimitry Andric   m_description = std::string(description);
11640b57cec5SDimitry Andric }
11650b57cec5SDimitry Andric 
BuildRegister(ConstString & r)11660b57cec5SDimitry Andric Instruction::Operand Instruction::Operand::BuildRegister(ConstString &r) {
11670b57cec5SDimitry Andric   Operand ret;
11680b57cec5SDimitry Andric   ret.m_type = Type::Register;
11690b57cec5SDimitry Andric   ret.m_register = r;
11700b57cec5SDimitry Andric   return ret;
11710b57cec5SDimitry Andric }
11720b57cec5SDimitry Andric 
BuildImmediate(lldb::addr_t imm,bool neg)11730b57cec5SDimitry Andric Instruction::Operand Instruction::Operand::BuildImmediate(lldb::addr_t imm,
11740b57cec5SDimitry Andric                                                           bool neg) {
11750b57cec5SDimitry Andric   Operand ret;
11760b57cec5SDimitry Andric   ret.m_type = Type::Immediate;
11770b57cec5SDimitry Andric   ret.m_immediate = imm;
11780b57cec5SDimitry Andric   ret.m_negative = neg;
11790b57cec5SDimitry Andric   return ret;
11800b57cec5SDimitry Andric }
11810b57cec5SDimitry Andric 
BuildImmediate(int64_t imm)11820b57cec5SDimitry Andric Instruction::Operand Instruction::Operand::BuildImmediate(int64_t imm) {
11830b57cec5SDimitry Andric   Operand ret;
11840b57cec5SDimitry Andric   ret.m_type = Type::Immediate;
11850b57cec5SDimitry Andric   if (imm < 0) {
11860b57cec5SDimitry Andric     ret.m_immediate = -imm;
11870b57cec5SDimitry Andric     ret.m_negative = true;
11880b57cec5SDimitry Andric   } else {
11890b57cec5SDimitry Andric     ret.m_immediate = imm;
11900b57cec5SDimitry Andric     ret.m_negative = false;
11910b57cec5SDimitry Andric   }
11920b57cec5SDimitry Andric   return ret;
11930b57cec5SDimitry Andric }
11940b57cec5SDimitry Andric 
11950b57cec5SDimitry Andric Instruction::Operand
BuildDereference(const Operand & ref)11960b57cec5SDimitry Andric Instruction::Operand::BuildDereference(const Operand &ref) {
11970b57cec5SDimitry Andric   Operand ret;
11980b57cec5SDimitry Andric   ret.m_type = Type::Dereference;
11990b57cec5SDimitry Andric   ret.m_children = {ref};
12000b57cec5SDimitry Andric   return ret;
12010b57cec5SDimitry Andric }
12020b57cec5SDimitry Andric 
BuildSum(const Operand & lhs,const Operand & rhs)12030b57cec5SDimitry Andric Instruction::Operand Instruction::Operand::BuildSum(const Operand &lhs,
12040b57cec5SDimitry Andric                                                     const Operand &rhs) {
12050b57cec5SDimitry Andric   Operand ret;
12060b57cec5SDimitry Andric   ret.m_type = Type::Sum;
12070b57cec5SDimitry Andric   ret.m_children = {lhs, rhs};
12080b57cec5SDimitry Andric   return ret;
12090b57cec5SDimitry Andric }
12100b57cec5SDimitry Andric 
BuildProduct(const Operand & lhs,const Operand & rhs)12110b57cec5SDimitry Andric Instruction::Operand Instruction::Operand::BuildProduct(const Operand &lhs,
12120b57cec5SDimitry Andric                                                         const Operand &rhs) {
12130b57cec5SDimitry Andric   Operand ret;
12140b57cec5SDimitry Andric   ret.m_type = Type::Product;
12150b57cec5SDimitry Andric   ret.m_children = {lhs, rhs};
12160b57cec5SDimitry Andric   return ret;
12170b57cec5SDimitry Andric }
12180b57cec5SDimitry Andric 
12190b57cec5SDimitry 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)12200b57cec5SDimitry Andric lldb_private::OperandMatchers::MatchBinaryOp(
12210b57cec5SDimitry Andric     std::function<bool(const Instruction::Operand &)> base,
12220b57cec5SDimitry Andric     std::function<bool(const Instruction::Operand &)> left,
12230b57cec5SDimitry Andric     std::function<bool(const Instruction::Operand &)> right) {
12240b57cec5SDimitry Andric   return [base, left, right](const Instruction::Operand &op) -> bool {
12250b57cec5SDimitry Andric     return (base(op) && op.m_children.size() == 2 &&
12260b57cec5SDimitry Andric             ((left(op.m_children[0]) && right(op.m_children[1])) ||
12270b57cec5SDimitry Andric              (left(op.m_children[1]) && right(op.m_children[0]))));
12280b57cec5SDimitry Andric   };
12290b57cec5SDimitry Andric }
12300b57cec5SDimitry Andric 
12310b57cec5SDimitry Andric std::function<bool(const Instruction::Operand &)>
MatchUnaryOp(std::function<bool (const Instruction::Operand &)> base,std::function<bool (const Instruction::Operand &)> child)12320b57cec5SDimitry Andric lldb_private::OperandMatchers::MatchUnaryOp(
12330b57cec5SDimitry Andric     std::function<bool(const Instruction::Operand &)> base,
12340b57cec5SDimitry Andric     std::function<bool(const Instruction::Operand &)> child) {
12350b57cec5SDimitry Andric   return [base, child](const Instruction::Operand &op) -> bool {
12360b57cec5SDimitry Andric     return (base(op) && op.m_children.size() == 1 && child(op.m_children[0]));
12370b57cec5SDimitry Andric   };
12380b57cec5SDimitry Andric }
12390b57cec5SDimitry Andric 
12400b57cec5SDimitry Andric std::function<bool(const Instruction::Operand &)>
MatchRegOp(const RegisterInfo & info)12410b57cec5SDimitry Andric lldb_private::OperandMatchers::MatchRegOp(const RegisterInfo &info) {
12420b57cec5SDimitry Andric   return [&info](const Instruction::Operand &op) {
12430b57cec5SDimitry Andric     return (op.m_type == Instruction::Operand::Type::Register &&
12440b57cec5SDimitry Andric             (op.m_register == ConstString(info.name) ||
12450b57cec5SDimitry Andric              op.m_register == ConstString(info.alt_name)));
12460b57cec5SDimitry Andric   };
12470b57cec5SDimitry Andric }
12480b57cec5SDimitry Andric 
12490b57cec5SDimitry Andric std::function<bool(const Instruction::Operand &)>
FetchRegOp(ConstString & reg)12500b57cec5SDimitry Andric lldb_private::OperandMatchers::FetchRegOp(ConstString &reg) {
12510b57cec5SDimitry Andric   return [&reg](const Instruction::Operand &op) {
12520b57cec5SDimitry Andric     if (op.m_type != Instruction::Operand::Type::Register) {
12530b57cec5SDimitry Andric       return false;
12540b57cec5SDimitry Andric     }
12550b57cec5SDimitry Andric     reg = op.m_register;
12560b57cec5SDimitry Andric     return true;
12570b57cec5SDimitry Andric   };
12580b57cec5SDimitry Andric }
12590b57cec5SDimitry Andric 
12600b57cec5SDimitry Andric std::function<bool(const Instruction::Operand &)>
MatchImmOp(int64_t imm)12610b57cec5SDimitry Andric lldb_private::OperandMatchers::MatchImmOp(int64_t imm) {
12620b57cec5SDimitry Andric   return [imm](const Instruction::Operand &op) {
12630b57cec5SDimitry Andric     return (op.m_type == Instruction::Operand::Type::Immediate &&
12640b57cec5SDimitry Andric             ((op.m_negative && op.m_immediate == (uint64_t)-imm) ||
12650b57cec5SDimitry Andric              (!op.m_negative && op.m_immediate == (uint64_t)imm)));
12660b57cec5SDimitry Andric   };
12670b57cec5SDimitry Andric }
12680b57cec5SDimitry Andric 
12690b57cec5SDimitry Andric std::function<bool(const Instruction::Operand &)>
FetchImmOp(int64_t & imm)12700b57cec5SDimitry Andric lldb_private::OperandMatchers::FetchImmOp(int64_t &imm) {
12710b57cec5SDimitry Andric   return [&imm](const Instruction::Operand &op) {
12720b57cec5SDimitry Andric     if (op.m_type != Instruction::Operand::Type::Immediate) {
12730b57cec5SDimitry Andric       return false;
12740b57cec5SDimitry Andric     }
12750b57cec5SDimitry Andric     if (op.m_negative) {
12760b57cec5SDimitry Andric       imm = -((int64_t)op.m_immediate);
12770b57cec5SDimitry Andric     } else {
12780b57cec5SDimitry Andric       imm = ((int64_t)op.m_immediate);
12790b57cec5SDimitry Andric     }
12800b57cec5SDimitry Andric     return true;
12810b57cec5SDimitry Andric   };
12820b57cec5SDimitry Andric }
12830b57cec5SDimitry Andric 
12840b57cec5SDimitry Andric std::function<bool(const Instruction::Operand &)>
MatchOpType(Instruction::Operand::Type type)12850b57cec5SDimitry Andric lldb_private::OperandMatchers::MatchOpType(Instruction::Operand::Type type) {
12860b57cec5SDimitry Andric   return [type](const Instruction::Operand &op) { return op.m_type == type; };
12870b57cec5SDimitry Andric }
1288