180814287SRaphael Isemann //===-- Disassembler.cpp --------------------------------------------------===// 230fdc8d8SChris Lattner // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 630fdc8d8SChris Lattner // 730fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 830fdc8d8SChris Lattner 930fdc8d8SChris Lattner #include "lldb/Core/Disassembler.h" 1030fdc8d8SChris Lattner 11672d2c12SJonas Devlieghere #include "lldb/Core/AddressRange.h" 1230fdc8d8SChris Lattner #include "lldb/Core/Debugger.h" 13ad379efcSCaroline Tice #include "lldb/Core/EmulateInstruction.h" 14672d2c12SJonas Devlieghere #include "lldb/Core/Mangled.h" 1530fdc8d8SChris Lattner #include "lldb/Core/Module.h" 16672d2c12SJonas Devlieghere #include "lldb/Core/ModuleList.h" 1730fdc8d8SChris Lattner #include "lldb/Core/PluginManager.h" 18672d2c12SJonas Devlieghere #include "lldb/Core/SourceManager.h" 19190fadcdSZachary Turner #include "lldb/Host/FileSystem.h" 2067cc0636SGreg Clayton #include "lldb/Interpreter/OptionValue.h" 2167cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueArray.h" 2267cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueDictionary.h" 230b4c26b2SJason Molenda #include "lldb/Interpreter/OptionValueRegex.h" 2467cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueString.h" 2567cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueUInt64.h" 261f746071SGreg Clayton #include "lldb/Symbol/Function.h" 27672d2c12SJonas Devlieghere #include "lldb/Symbol/Symbol.h" 28672d2c12SJonas Devlieghere #include "lldb/Symbol/SymbolContext.h" 2930fdc8d8SChris Lattner #include "lldb/Target/ExecutionContext.h" 30d5944cd1SGreg Clayton #include "lldb/Target/SectionLoadList.h" 31b57e4a1bSJason Molenda #include "lldb/Target/StackFrame.h" 3230fdc8d8SChris Lattner #include "lldb/Target/Target.h" 33672d2c12SJonas Devlieghere #include "lldb/Target/Thread.h" 34666cc0b2SZachary Turner #include "lldb/Utility/DataBufferHeap.h" 35666cc0b2SZachary Turner #include "lldb/Utility/DataExtractor.h" 36bf9a7730SZachary Turner #include "lldb/Utility/RegularExpression.h" 3797206d57SZachary Turner #include "lldb/Utility/Status.h" 38672d2c12SJonas Devlieghere #include "lldb/Utility/Stream.h" 39672d2c12SJonas Devlieghere #include "lldb/Utility/StreamString.h" 4038d0632eSPavel Labath #include "lldb/Utility/Timer.h" 41672d2c12SJonas Devlieghere #include "lldb/lldb-private-enumerations.h" 42672d2c12SJonas Devlieghere #include "lldb/lldb-private-interfaces.h" 43672d2c12SJonas Devlieghere #include "lldb/lldb-private-types.h" 44672d2c12SJonas Devlieghere #include "llvm/ADT/Triple.h" 45672d2c12SJonas Devlieghere #include "llvm/Support/Compiler.h" 462f3df613SZachary Turner 47672d2c12SJonas Devlieghere #include <cstdint> 482f3df613SZachary Turner #include <cstring> 49672d2c12SJonas Devlieghere #include <utility> 502f3df613SZachary Turner 51672d2c12SJonas Devlieghere #include <assert.h> 5230fdc8d8SChris Lattner 5330fdc8d8SChris Lattner #define DEFAULT_DISASM_BYTE_SIZE 32 5430fdc8d8SChris Lattner 5530fdc8d8SChris Lattner using namespace lldb; 5630fdc8d8SChris Lattner using namespace lldb_private; 5730fdc8d8SChris Lattner 58b9c1b51eSKate Stone DisassemblerSP Disassembler::FindPlugin(const ArchSpec &arch, 59b9c1b51eSKate Stone const char *flavor, 60b9c1b51eSKate Stone const char *plugin_name) { 61f9d16476SPavel Labath static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 62f9d16476SPavel Labath Timer scoped_timer(func_cat, 631080edbcSGreg Clayton "Disassembler::FindPlugin (arch = %s, plugin_name = %s)", 64b9c1b51eSKate Stone arch.GetArchitectureName(), plugin_name); 6530fdc8d8SChris Lattner 6634ede34aSEugene Zelenko DisassemblerCreateInstance create_callback = nullptr; 671080edbcSGreg Clayton 68b9c1b51eSKate Stone if (plugin_name) { 6957abc5d6SGreg Clayton ConstString const_plugin_name(plugin_name); 70b9c1b51eSKate Stone create_callback = PluginManager::GetDisassemblerCreateCallbackForPluginName( 71b9c1b51eSKate Stone const_plugin_name); 72b9c1b51eSKate Stone if (create_callback) { 730f063ba6SJim Ingham DisassemblerSP disassembler_sp(create_callback(arch, flavor)); 741080edbcSGreg Clayton 7534ede34aSEugene Zelenko if (disassembler_sp) 767e6d4e5aSSean Callanan return disassembler_sp; 771080edbcSGreg Clayton } 78b9c1b51eSKate Stone } else { 79b9c1b51eSKate Stone for (uint32_t idx = 0; 80b9c1b51eSKate Stone (create_callback = PluginManager::GetDisassemblerCreateCallbackAtIndex( 81b9c1b51eSKate Stone idx)) != nullptr; 82b9c1b51eSKate Stone ++idx) { 830f063ba6SJim Ingham DisassemblerSP disassembler_sp(create_callback(arch, flavor)); 8430fdc8d8SChris Lattner 8534ede34aSEugene Zelenko if (disassembler_sp) 867e6d4e5aSSean Callanan return disassembler_sp; 8730fdc8d8SChris Lattner } 881080edbcSGreg Clayton } 897e6d4e5aSSean Callanan return DisassemblerSP(); 9030fdc8d8SChris Lattner } 9130fdc8d8SChris Lattner 92b9c1b51eSKate Stone DisassemblerSP Disassembler::FindPluginForTarget(const TargetSP target_sp, 93b9c1b51eSKate Stone const ArchSpec &arch, 94b9c1b51eSKate Stone const char *flavor, 95b9c1b51eSKate Stone const char *plugin_name) { 96b9c1b51eSKate Stone if (target_sp && flavor == nullptr) { 97b9c1b51eSKate Stone // FIXME - we don't have the mechanism in place to do per-architecture 9805097246SAdrian Prantl // settings. But since we know that for now we only support flavors on x86 9905097246SAdrian Prantl // & x86_64, 100b9c1b51eSKate Stone if (arch.GetTriple().getArch() == llvm::Triple::x86 || 101b9c1b51eSKate Stone arch.GetTriple().getArch() == llvm::Triple::x86_64) 1020f063ba6SJim Ingham flavor = target_sp->GetDisassemblyFlavor(); 1030f063ba6SJim Ingham } 1040f063ba6SJim Ingham return FindPlugin(arch, flavor, plugin_name); 1050f063ba6SJim Ingham } 1060f063ba6SJim Ingham 107b9c1b51eSKate Stone static void ResolveAddress(const ExecutionContext &exe_ctx, const Address &addr, 108b9c1b51eSKate Stone Address &resolved_addr) { 109b9c1b51eSKate Stone if (!addr.IsSectionOffset()) { 11005097246SAdrian Prantl // If we weren't passed in a section offset address range, try and resolve 11105097246SAdrian Prantl // it to something 112c14ee32dSGreg Clayton Target *target = exe_ctx.GetTargetPtr(); 113b9c1b51eSKate Stone if (target) { 114a0fa299dSTatyana Krasnukha bool is_resolved = 115a0fa299dSTatyana Krasnukha target->GetSectionLoadList().IsEmpty() ? 116a0fa299dSTatyana Krasnukha target->GetImages().ResolveFileAddress(addr.GetOffset(), 117a0fa299dSTatyana Krasnukha resolved_addr) : 118b9c1b51eSKate Stone target->GetSectionLoadList().ResolveLoadAddress(addr.GetOffset(), 119b9c1b51eSKate Stone resolved_addr); 120a0fa299dSTatyana Krasnukha 12105097246SAdrian Prantl // We weren't able to resolve the address, just treat it as a raw address 122a0fa299dSTatyana Krasnukha if (is_resolved && resolved_addr.IsValid()) 123357132ebSGreg Clayton return; 124357132ebSGreg Clayton } 125357132ebSGreg Clayton } 126357132ebSGreg Clayton resolved_addr = addr; 127357132ebSGreg Clayton } 128dda4f7b5SGreg Clayton 129b9c1b51eSKate Stone lldb::DisassemblerSP Disassembler::DisassembleRange( 130b9c1b51eSKate Stone const ArchSpec &arch, const char *plugin_name, const char *flavor, 131b9c1b51eSKate Stone const ExecutionContext &exe_ctx, const AddressRange &range, 132b9c1b51eSKate Stone bool prefer_file_cache) { 1331d6fa41fSPavel Labath if (range.GetByteSize() <= 0 || !exe_ctx.GetTargetPtr()) 1344be6706eSJonas Devlieghere return {}; 1351d273166SGreg Clayton 1364be6706eSJonas Devlieghere if (!range.GetBaseAddress().IsValid()) 1374be6706eSJonas Devlieghere return {}; 1384be6706eSJonas Devlieghere 1394be6706eSJonas Devlieghere lldb::DisassemblerSP disasm_sp = Disassembler::FindPluginForTarget( 1404be6706eSJonas Devlieghere exe_ctx.GetTargetSP(), arch, flavor, plugin_name); 1414be6706eSJonas Devlieghere 1424be6706eSJonas Devlieghere if (!disasm_sp) 1434be6706eSJonas Devlieghere return {}; 1444be6706eSJonas Devlieghere 1451d6fa41fSPavel Labath const size_t bytes_disassembled = disasm_sp->ParseInstructions( 1461d6fa41fSPavel Labath exe_ctx.GetTargetRef(), range, nullptr, prefer_file_cache); 1471d273166SGreg Clayton if (bytes_disassembled == 0) 1484be6706eSJonas Devlieghere return {}; 1494be6706eSJonas Devlieghere 1501d273166SGreg Clayton return disasm_sp; 1511d273166SGreg Clayton } 1521d273166SGreg Clayton 15350952e95SSean Callanan lldb::DisassemblerSP 154b9c1b51eSKate Stone Disassembler::DisassembleBytes(const ArchSpec &arch, const char *plugin_name, 155b9c1b51eSKate Stone const char *flavor, const Address &start, 156b9c1b51eSKate Stone const void *src, size_t src_len, 157b9c1b51eSKate Stone uint32_t num_instructions, bool data_from_file) { 1584be6706eSJonas Devlieghere if (!src) 1594be6706eSJonas Devlieghere return {}; 16050952e95SSean Callanan 1614be6706eSJonas Devlieghere lldb::DisassemblerSP disasm_sp = 1624be6706eSJonas Devlieghere Disassembler::FindPlugin(arch, flavor, plugin_name); 16350952e95SSean Callanan 1644be6706eSJonas Devlieghere if (!disasm_sp) 1654be6706eSJonas Devlieghere return {}; 1664be6706eSJonas Devlieghere 167b9c1b51eSKate Stone DataExtractor data(src, src_len, arch.GetByteOrder(), 168b9c1b51eSKate Stone arch.GetAddressByteSize()); 16950952e95SSean Callanan 1704be6706eSJonas Devlieghere (void)disasm_sp->DecodeInstructions(start, data, 0, num_instructions, false, 1714be6706eSJonas Devlieghere data_from_file); 17250952e95SSean Callanan return disasm_sp; 17350952e95SSean Callanan } 17450952e95SSean Callanan 175b9c1b51eSKate Stone bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch, 176b9c1b51eSKate Stone const char *plugin_name, const char *flavor, 177dda4f7b5SGreg Clayton const ExecutionContext &exe_ctx, 178dda4f7b5SGreg Clayton const AddressRange &disasm_range, 17937023b06SJim Ingham uint32_t num_instructions, 1800b4c26b2SJason Molenda bool mixed_source_and_assembly, 181dda4f7b5SGreg Clayton uint32_t num_mixed_context_lines, 182b9c1b51eSKate Stone uint32_t options, Stream &strm) { 1831d6fa41fSPavel Labath if (!disasm_range.GetByteSize() || !exe_ctx.GetTargetPtr()) 1840910e17dSJonas Devlieghere return false; 1850910e17dSJonas Devlieghere 186b9c1b51eSKate Stone lldb::DisassemblerSP disasm_sp(Disassembler::FindPluginForTarget( 187b9c1b51eSKate Stone exe_ctx.GetTargetSP(), arch, flavor, plugin_name)); 18830fdc8d8SChris Lattner 1890910e17dSJonas Devlieghere if (!disasm_sp) 1900910e17dSJonas Devlieghere return false; 1910910e17dSJonas Devlieghere 192357132ebSGreg Clayton AddressRange range; 193b9c1b51eSKate Stone ResolveAddress(exe_ctx, disasm_range.GetBaseAddress(), 194b9c1b51eSKate Stone range.GetBaseAddress()); 195357132ebSGreg Clayton range.SetByteSize(disasm_range.GetByteSize()); 1963faf47c4SGreg Clayton const bool prefer_file_cache = false; 1971d6fa41fSPavel Labath size_t bytes_disassembled = disasm_sp->ParseInstructions( 1981d6fa41fSPavel Labath exe_ctx.GetTargetRef(), range, &strm, prefer_file_cache); 19930fdc8d8SChris Lattner if (bytes_disassembled == 0) 20030fdc8d8SChris Lattner return false; 2011080edbcSGreg Clayton 202*ea68462eSPavel Labath disasm_sp->PrintInstructions(debugger, arch, exe_ctx, num_instructions, 203*ea68462eSPavel Labath mixed_source_and_assembly, 2040b4c26b2SJason Molenda num_mixed_context_lines, options, strm); 205*ea68462eSPavel Labath return true; 20637023b06SJim Ingham } 20737023b06SJim Ingham 208b9c1b51eSKate Stone bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch, 209b9c1b51eSKate Stone const char *plugin_name, const char *flavor, 21037023b06SJim Ingham const ExecutionContext &exe_ctx, 21137023b06SJim Ingham const Address &start_address, 21237023b06SJim Ingham uint32_t num_instructions, 2130b4c26b2SJason Molenda bool mixed_source_and_assembly, 21437023b06SJim Ingham uint32_t num_mixed_context_lines, 215b9c1b51eSKate Stone uint32_t options, Stream &strm) { 2161d6fa41fSPavel Labath if (num_instructions == 0 || !exe_ctx.GetTargetPtr()) 2170910e17dSJonas Devlieghere return false; 2180910e17dSJonas Devlieghere 219b9c1b51eSKate Stone lldb::DisassemblerSP disasm_sp(Disassembler::FindPluginForTarget( 220b9c1b51eSKate Stone exe_ctx.GetTargetSP(), arch, flavor, plugin_name)); 2210910e17dSJonas Devlieghere if (!disasm_sp) 2220910e17dSJonas Devlieghere return false; 2230910e17dSJonas Devlieghere 224357132ebSGreg Clayton Address addr; 225357132ebSGreg Clayton ResolveAddress(exe_ctx, start_address, addr); 2260910e17dSJonas Devlieghere 2273faf47c4SGreg Clayton const bool prefer_file_cache = false; 228b9c1b51eSKate Stone size_t bytes_disassembled = disasm_sp->ParseInstructions( 2291d6fa41fSPavel Labath exe_ctx.GetTargetRef(), addr, num_instructions, prefer_file_cache); 23037023b06SJim Ingham if (bytes_disassembled == 0) 23137023b06SJim Ingham return false; 2320910e17dSJonas Devlieghere 233*ea68462eSPavel Labath disasm_sp->PrintInstructions(debugger, arch, exe_ctx, num_instructions, 234*ea68462eSPavel Labath mixed_source_and_assembly, 2350b4c26b2SJason Molenda num_mixed_context_lines, options, strm); 236*ea68462eSPavel Labath return true; 23737023b06SJim Ingham } 23837023b06SJim Ingham 2390b4c26b2SJason Molenda Disassembler::SourceLine 2400b4c26b2SJason Molenda Disassembler::GetFunctionDeclLineEntry(const SymbolContext &sc) { 2410910e17dSJonas Devlieghere if (!sc.function) 2420910e17dSJonas Devlieghere return {}; 2430910e17dSJonas Devlieghere 2440910e17dSJonas Devlieghere if (!sc.line_entry.IsValid()) 2450910e17dSJonas Devlieghere return {}; 2460910e17dSJonas Devlieghere 2470b4c26b2SJason Molenda LineEntry prologue_end_line = sc.line_entry; 2480b4c26b2SJason Molenda FileSpec func_decl_file; 2490b4c26b2SJason Molenda uint32_t func_decl_line; 2500b4c26b2SJason Molenda sc.function->GetStartLineSourceInfo(func_decl_file, func_decl_line); 2510910e17dSJonas Devlieghere 2520910e17dSJonas Devlieghere if (func_decl_file != prologue_end_line.file && 2530910e17dSJonas Devlieghere func_decl_file != prologue_end_line.original_file) 2540910e17dSJonas Devlieghere return {}; 2550910e17dSJonas Devlieghere 2560910e17dSJonas Devlieghere SourceLine decl_line; 2570b4c26b2SJason Molenda decl_line.file = func_decl_file; 2580b4c26b2SJason Molenda decl_line.line = func_decl_line; 2590910e17dSJonas Devlieghere // TODO: Do we care about column on these entries? If so, we need to plumb 2600910e17dSJonas Devlieghere // that through GetStartLineSourceInfo. 2619666ba75STodd Fiala decl_line.column = 0; 2620b4c26b2SJason Molenda return decl_line; 2630b4c26b2SJason Molenda } 2640b4c26b2SJason Molenda 2650b4c26b2SJason Molenda void Disassembler::AddLineToSourceLineTables( 2660b4c26b2SJason Molenda SourceLine &line, 2670b4c26b2SJason Molenda std::map<FileSpec, std::set<uint32_t>> &source_lines_seen) { 2680b4c26b2SJason Molenda if (line.IsValid()) { 2690b4c26b2SJason Molenda auto source_lines_seen_pos = source_lines_seen.find(line.file); 2700b4c26b2SJason Molenda if (source_lines_seen_pos == source_lines_seen.end()) { 2710b4c26b2SJason Molenda std::set<uint32_t> lines; 2720b4c26b2SJason Molenda lines.insert(line.line); 2730b4c26b2SJason Molenda source_lines_seen.emplace(line.file, lines); 2740b4c26b2SJason Molenda } else { 2750b4c26b2SJason Molenda source_lines_seen_pos->second.insert(line.line); 2760b4c26b2SJason Molenda } 2770b4c26b2SJason Molenda } 2780b4c26b2SJason Molenda } 2790b4c26b2SJason Molenda 2800b4c26b2SJason Molenda bool Disassembler::ElideMixedSourceAndDisassemblyLine( 2810b4c26b2SJason Molenda const ExecutionContext &exe_ctx, const SymbolContext &sc, 2820b4c26b2SJason Molenda SourceLine &line) { 2830b4c26b2SJason Molenda 2840b4c26b2SJason Molenda // TODO: should we also check target.process.thread.step-avoid-libraries ? 2850b4c26b2SJason Molenda 2860b4c26b2SJason Molenda const RegularExpression *avoid_regex = nullptr; 2870b4c26b2SJason Molenda 2880b4c26b2SJason Molenda // Skip any line #0 entries - they are implementation details 2890b4c26b2SJason Molenda if (line.line == 0) 2900b4c26b2SJason Molenda return false; 2910b4c26b2SJason Molenda 2920b4c26b2SJason Molenda ThreadSP thread_sp = exe_ctx.GetThreadSP(); 2930b4c26b2SJason Molenda if (thread_sp) { 2940b4c26b2SJason Molenda avoid_regex = thread_sp->GetSymbolsToAvoidRegexp(); 2950b4c26b2SJason Molenda } else { 2960b4c26b2SJason Molenda TargetSP target_sp = exe_ctx.GetTargetSP(); 2970b4c26b2SJason Molenda if (target_sp) { 29897206d57SZachary Turner Status error; 2990b4c26b2SJason Molenda OptionValueSP value_sp = target_sp->GetDebugger().GetPropertyValue( 3000b4c26b2SJason Molenda &exe_ctx, "target.process.thread.step-avoid-regexp", false, error); 3010b4c26b2SJason Molenda if (value_sp && value_sp->GetType() == OptionValue::eTypeRegex) { 3020b4c26b2SJason Molenda OptionValueRegex *re = value_sp->GetAsRegex(); 3030b4c26b2SJason Molenda if (re) { 3040b4c26b2SJason Molenda avoid_regex = re->GetCurrentValue(); 3050b4c26b2SJason Molenda } 3060b4c26b2SJason Molenda } 3070b4c26b2SJason Molenda } 3080b4c26b2SJason Molenda } 3090b4c26b2SJason Molenda if (avoid_regex && sc.symbol != nullptr) { 3100b4c26b2SJason Molenda const char *function_name = 3110b4c26b2SJason Molenda sc.GetFunctionName(Mangled::ePreferDemangledWithoutArguments) 3120b4c26b2SJason Molenda .GetCString(); 3133af3f1e8SJonas Devlieghere if (function_name && avoid_regex->Execute(function_name)) { 3140b4c26b2SJason Molenda // skip this source line 3150b4c26b2SJason Molenda return true; 3160b4c26b2SJason Molenda } 3170b4c26b2SJason Molenda } 3180b4c26b2SJason Molenda // don't skip this source line 3190b4c26b2SJason Molenda return false; 3200b4c26b2SJason Molenda } 3210b4c26b2SJason Molenda 322*ea68462eSPavel Labath void Disassembler::PrintInstructions(Debugger &debugger, const ArchSpec &arch, 323b9c1b51eSKate Stone const ExecutionContext &exe_ctx, 324b9c1b51eSKate Stone uint32_t num_instructions, 3250b4c26b2SJason Molenda bool mixed_source_and_assembly, 326b9c1b51eSKate Stone uint32_t num_mixed_context_lines, 327b9c1b51eSKate Stone uint32_t options, Stream &strm) { 32830fdc8d8SChris Lattner // We got some things disassembled... 329*ea68462eSPavel Labath size_t num_instructions_found = GetInstructionList().GetSize(); 33037023b06SJim Ingham 33137023b06SJim Ingham if (num_instructions > 0 && num_instructions < num_instructions_found) 33237023b06SJim Ingham num_instructions_found = num_instructions; 33337023b06SJim Ingham 334b9c1b51eSKate Stone const uint32_t max_opcode_byte_size = 335*ea68462eSPavel Labath GetInstructionList().GetMaxOpcocdeByteSize(); 33630fdc8d8SChris Lattner SymbolContext sc; 33730fdc8d8SChris Lattner SymbolContext prev_sc; 3380b4c26b2SJason Molenda AddressRange current_source_line_range; 33934ede34aSEugene Zelenko const Address *pc_addr_ptr = nullptr; 340b57e4a1bSJason Molenda StackFrame *frame = exe_ctx.GetFramePtr(); 341c14ee32dSGreg Clayton 3424b2967ffSMichael Sartain TargetSP target_sp(exe_ctx.GetTargetSP()); 343b9c1b51eSKate Stone SourceManager &source_manager = 344b9c1b51eSKate Stone target_sp ? target_sp->GetSourceManager() : debugger.GetSourceManager(); 3454b2967ffSMichael Sartain 346b9c1b51eSKate Stone if (frame) { 347c14ee32dSGreg Clayton pc_addr_ptr = &frame->GetFrameCodeAddress(); 348aff1b357SJason Molenda } 349b9c1b51eSKate Stone const uint32_t scope = 350b9c1b51eSKate Stone eSymbolContextLineEntry | eSymbolContextFunction | eSymbolContextSymbol; 3517e14f91dSGreg Clayton const bool use_inline_block_range = false; 352c980fa92SJason Molenda 35334ede34aSEugene Zelenko const FormatEntity::Entry *disassembly_format = nullptr; 354c980fa92SJason Molenda FormatEntity::Entry format; 355b9c1b51eSKate Stone if (exe_ctx.HasTargetScope()) { 356b9c1b51eSKate Stone disassembly_format = 357b9c1b51eSKate Stone exe_ctx.GetTargetRef().GetDebugger().GetDisassemblyFormat(); 358b9c1b51eSKate Stone } else { 359c980fa92SJason Molenda FormatEntity::Parse("${addr}: ", format); 360c980fa92SJason Molenda disassembly_format = &format; 361c980fa92SJason Molenda } 362c980fa92SJason Molenda 36305097246SAdrian Prantl // First pass: step through the list of instructions, find how long the 36405097246SAdrian Prantl // initial addresses strings are, insert padding in the second pass so the 36505097246SAdrian Prantl // opcodes all line up nicely. 3660b4c26b2SJason Molenda 3670b4c26b2SJason Molenda // Also build up the source line mapping if this is mixed source & assembly 36805097246SAdrian Prantl // mode. Calculate the source line for each assembly instruction (eliding 36905097246SAdrian Prantl // inlined functions which the user wants to skip). 3700b4c26b2SJason Molenda 3710b4c26b2SJason Molenda std::map<FileSpec, std::set<uint32_t>> source_lines_seen; 3720b4c26b2SJason Molenda Symbol *previous_symbol = nullptr; 3730b4c26b2SJason Molenda 374c980fa92SJason Molenda size_t address_text_size = 0; 375b9c1b51eSKate Stone for (size_t i = 0; i < num_instructions_found; ++i) { 376*ea68462eSPavel Labath Instruction *inst = GetInstructionList().GetInstructionAtIndex(i).get(); 377b9c1b51eSKate Stone if (inst) { 378c980fa92SJason Molenda const Address &addr = inst->GetAddress(); 379c980fa92SJason Molenda ModuleSP module_sp(addr.GetModule()); 380b9c1b51eSKate Stone if (module_sp) { 381991e4453SZachary Turner const SymbolContextItem resolve_mask = eSymbolContextFunction | 3820b4c26b2SJason Molenda eSymbolContextSymbol | 3830b4c26b2SJason Molenda eSymbolContextLineEntry; 384b9c1b51eSKate Stone uint32_t resolved_mask = 385b9c1b51eSKate Stone module_sp->ResolveSymbolContextForAddress(addr, resolve_mask, sc); 386b9c1b51eSKate Stone if (resolved_mask) { 387c980fa92SJason Molenda StreamString strmstr; 388b9c1b51eSKate Stone Debugger::FormatDisassemblerAddress(disassembly_format, &sc, nullptr, 389b9c1b51eSKate Stone &exe_ctx, &addr, strmstr); 390c980fa92SJason Molenda size_t cur_line = strmstr.GetSizeOfLastLine(); 391c980fa92SJason Molenda if (cur_line > address_text_size) 392c980fa92SJason Molenda address_text_size = cur_line; 3930b4c26b2SJason Molenda 3940b4c26b2SJason Molenda // Add entries to our "source_lines_seen" map+set which list which 3950b4c26b2SJason Molenda // sources lines occur in this disassembly session. We will print 3960b4c26b2SJason Molenda // lines of context around a source line, but we don't want to print 3970b4c26b2SJason Molenda // a source line that has a line table entry of its own - we'll leave 3980b4c26b2SJason Molenda // that source line to be printed when it actually occurs in the 3990b4c26b2SJason Molenda // disassembly. 4000b4c26b2SJason Molenda 4010b4c26b2SJason Molenda if (mixed_source_and_assembly && sc.line_entry.IsValid()) { 4020b4c26b2SJason Molenda if (sc.symbol != previous_symbol) { 4030b4c26b2SJason Molenda SourceLine decl_line = GetFunctionDeclLineEntry(sc); 404a6682a41SJonas Devlieghere if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, decl_line)) 4050b4c26b2SJason Molenda AddLineToSourceLineTables(decl_line, source_lines_seen); 4060b4c26b2SJason Molenda } 4070b4c26b2SJason Molenda if (sc.line_entry.IsValid()) { 4080b4c26b2SJason Molenda SourceLine this_line; 4090b4c26b2SJason Molenda this_line.file = sc.line_entry.file; 4100b4c26b2SJason Molenda this_line.line = sc.line_entry.line; 4119666ba75STodd Fiala this_line.column = sc.line_entry.column; 412a6682a41SJonas Devlieghere if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, this_line)) 4130b4c26b2SJason Molenda AddLineToSourceLineTables(this_line, source_lines_seen); 4140b4c26b2SJason Molenda } 4150b4c26b2SJason Molenda } 416c980fa92SJason Molenda } 417c980fa92SJason Molenda sc.Clear(false); 418c980fa92SJason Molenda } 419c980fa92SJason Molenda } 420c980fa92SJason Molenda } 421c980fa92SJason Molenda 4220b4c26b2SJason Molenda previous_symbol = nullptr; 4230b4c26b2SJason Molenda SourceLine previous_line; 424b9c1b51eSKate Stone for (size_t i = 0; i < num_instructions_found; ++i) { 425*ea68462eSPavel Labath Instruction *inst = GetInstructionList().GetInstructionAtIndex(i).get(); 4260b4c26b2SJason Molenda 427b9c1b51eSKate Stone if (inst) { 42832e0a750SGreg Clayton const Address &addr = inst->GetAddress(); 42932e0a750SGreg Clayton const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr; 4300b4c26b2SJason Molenda SourceLinesToDisplay source_lines_to_display; 431dda4f7b5SGreg Clayton 43230fdc8d8SChris Lattner prev_sc = sc; 433dda4f7b5SGreg Clayton 434e72dfb32SGreg Clayton ModuleSP module_sp(addr.GetModule()); 435b9c1b51eSKate Stone if (module_sp) { 436b9c1b51eSKate Stone uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress( 437b9c1b51eSKate Stone addr, eSymbolContextEverything, sc); 438b9c1b51eSKate Stone if (resolved_mask) { 4390b4c26b2SJason Molenda if (mixed_source_and_assembly) { 440dda4f7b5SGreg Clayton 4410b4c26b2SJason Molenda // If we've started a new function (non-inlined), print all of the 44205097246SAdrian Prantl // source lines from the function declaration until the first line 44305097246SAdrian Prantl // table entry - typically the opening curly brace of the function. 4440b4c26b2SJason Molenda if (previous_symbol != sc.symbol) { 44505097246SAdrian Prantl // The default disassembly format puts an extra blank line 44605097246SAdrian Prantl // between functions - so when we're displaying the source 44705097246SAdrian Prantl // context for a function, we don't want to add a blank line 44805097246SAdrian Prantl // after the source context or we'll end up with two of them. 4490b4c26b2SJason Molenda if (previous_symbol != nullptr) 4500b4c26b2SJason Molenda source_lines_to_display.print_source_context_end_eol = false; 45130fdc8d8SChris Lattner 4520b4c26b2SJason Molenda previous_symbol = sc.symbol; 4530b4c26b2SJason Molenda if (sc.function && sc.line_entry.IsValid()) { 4540b4c26b2SJason Molenda LineEntry prologue_end_line = sc.line_entry; 455a6682a41SJonas Devlieghere if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, 456a6682a41SJonas Devlieghere prologue_end_line)) { 4570b4c26b2SJason Molenda FileSpec func_decl_file; 4580b4c26b2SJason Molenda uint32_t func_decl_line; 4590b4c26b2SJason Molenda sc.function->GetStartLineSourceInfo(func_decl_file, 4600b4c26b2SJason Molenda func_decl_line); 4610b4c26b2SJason Molenda if (func_decl_file == prologue_end_line.file || 4620b4c26b2SJason Molenda func_decl_file == prologue_end_line.original_file) { 46305097246SAdrian Prantl // Add all the lines between the function declaration and 46405097246SAdrian Prantl // the first non-prologue source line to the list of lines 46505097246SAdrian Prantl // to print. 4660b4c26b2SJason Molenda for (uint32_t lineno = func_decl_line; 4670b4c26b2SJason Molenda lineno <= prologue_end_line.line; lineno++) { 4680b4c26b2SJason Molenda SourceLine this_line; 4690b4c26b2SJason Molenda this_line.file = func_decl_file; 4700b4c26b2SJason Molenda this_line.line = lineno; 4710b4c26b2SJason Molenda source_lines_to_display.lines.push_back(this_line); 4720b4c26b2SJason Molenda } 47305097246SAdrian Prantl // Mark the last line as the "current" one. Usually this 47405097246SAdrian Prantl // is the open curly brace. 4750b4c26b2SJason Molenda if (source_lines_to_display.lines.size() > 0) 4760b4c26b2SJason Molenda source_lines_to_display.current_source_line = 4770b4c26b2SJason Molenda source_lines_to_display.lines.size() - 1; 4780b4c26b2SJason Molenda } 4790b4c26b2SJason Molenda } 4800b4c26b2SJason Molenda } 4810b4c26b2SJason Molenda sc.GetAddressRange(scope, 0, use_inline_block_range, 4820b4c26b2SJason Molenda current_source_line_range); 4830b4c26b2SJason Molenda } 48430fdc8d8SChris Lattner 48505097246SAdrian Prantl // If we've left a previous source line's address range, print a 48605097246SAdrian Prantl // new source line 4870b4c26b2SJason Molenda if (!current_source_line_range.ContainsFileAddress(addr)) { 4880b4c26b2SJason Molenda sc.GetAddressRange(scope, 0, use_inline_block_range, 4890b4c26b2SJason Molenda current_source_line_range); 4900b4c26b2SJason Molenda 4910b4c26b2SJason Molenda if (sc != prev_sc && sc.comp_unit && sc.line_entry.IsValid()) { 4920b4c26b2SJason Molenda SourceLine this_line; 4930b4c26b2SJason Molenda this_line.file = sc.line_entry.file; 4940b4c26b2SJason Molenda this_line.line = sc.line_entry.line; 4950b4c26b2SJason Molenda 496a6682a41SJonas Devlieghere if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, 497a6682a41SJonas Devlieghere this_line)) { 4980b4c26b2SJason Molenda // Only print this source line if it is different from the 4990b4c26b2SJason Molenda // last source line we printed. There may have been inlined 5000b4c26b2SJason Molenda // functions between these lines that we elided, resulting in 50105097246SAdrian Prantl // the same line being printed twice in a row for a 50205097246SAdrian Prantl // contiguous block of assembly instructions. 5030b4c26b2SJason Molenda if (this_line != previous_line) { 5040b4c26b2SJason Molenda 5050b4c26b2SJason Molenda std::vector<uint32_t> previous_lines; 5067771462bSEd Maste for (uint32_t i = 0; 5070b4c26b2SJason Molenda i < num_mixed_context_lines && 5080b4c26b2SJason Molenda (this_line.line - num_mixed_context_lines) > 0; 5090b4c26b2SJason Molenda i++) { 5100b4c26b2SJason Molenda uint32_t line = 5110b4c26b2SJason Molenda this_line.line - num_mixed_context_lines + i; 5120b4c26b2SJason Molenda auto pos = source_lines_seen.find(this_line.file); 5130b4c26b2SJason Molenda if (pos != source_lines_seen.end()) { 5140b4c26b2SJason Molenda if (pos->second.count(line) == 1) { 5150b4c26b2SJason Molenda previous_lines.clear(); 5160b4c26b2SJason Molenda } else { 5170b4c26b2SJason Molenda previous_lines.push_back(line); 5180b4c26b2SJason Molenda } 5190b4c26b2SJason Molenda } 5200b4c26b2SJason Molenda } 5210b4c26b2SJason Molenda for (size_t i = 0; i < previous_lines.size(); i++) { 5220b4c26b2SJason Molenda SourceLine previous_line; 5230b4c26b2SJason Molenda previous_line.file = this_line.file; 5240b4c26b2SJason Molenda previous_line.line = previous_lines[i]; 5250b4c26b2SJason Molenda auto pos = source_lines_seen.find(previous_line.file); 5260b4c26b2SJason Molenda if (pos != source_lines_seen.end()) { 5270b4c26b2SJason Molenda pos->second.insert(previous_line.line); 5280b4c26b2SJason Molenda } 5290b4c26b2SJason Molenda source_lines_to_display.lines.push_back(previous_line); 5300b4c26b2SJason Molenda } 5310b4c26b2SJason Molenda 5320b4c26b2SJason Molenda source_lines_to_display.lines.push_back(this_line); 5330b4c26b2SJason Molenda source_lines_to_display.current_source_line = 5340b4c26b2SJason Molenda source_lines_to_display.lines.size() - 1; 5350b4c26b2SJason Molenda 5367771462bSEd Maste for (uint32_t i = 0; i < num_mixed_context_lines; i++) { 5370b4c26b2SJason Molenda SourceLine next_line; 5380b4c26b2SJason Molenda next_line.file = this_line.file; 5390b4c26b2SJason Molenda next_line.line = this_line.line + i + 1; 5400b4c26b2SJason Molenda auto pos = source_lines_seen.find(next_line.file); 5410b4c26b2SJason Molenda if (pos != source_lines_seen.end()) { 5420b4c26b2SJason Molenda if (pos->second.count(next_line.line) == 1) 5430b4c26b2SJason Molenda break; 5440b4c26b2SJason Molenda pos->second.insert(next_line.line); 5450b4c26b2SJason Molenda } 5460b4c26b2SJason Molenda source_lines_to_display.lines.push_back(next_line); 5470b4c26b2SJason Molenda } 5480b4c26b2SJason Molenda } 5490b4c26b2SJason Molenda previous_line = this_line; 55030fdc8d8SChris Lattner } 55130fdc8d8SChris Lattner } 55230fdc8d8SChris Lattner } 55330fdc8d8SChris Lattner } 554b9c1b51eSKate Stone } else { 55572310355SGreg Clayton sc.Clear(true); 55630fdc8d8SChris Lattner } 55730fdc8d8SChris Lattner } 55832e0a750SGreg Clayton 5590b4c26b2SJason Molenda if (source_lines_to_display.lines.size() > 0) { 5600b4c26b2SJason Molenda strm.EOL(); 5610b4c26b2SJason Molenda for (size_t idx = 0; idx < source_lines_to_display.lines.size(); 5620b4c26b2SJason Molenda idx++) { 5630b4c26b2SJason Molenda SourceLine ln = source_lines_to_display.lines[idx]; 5640b4c26b2SJason Molenda const char *line_highlight = ""; 5650b4c26b2SJason Molenda if (inst_is_at_pc && (options & eOptionMarkPCSourceLine)) { 5660b4c26b2SJason Molenda line_highlight = "->"; 5670b4c26b2SJason Molenda } else if (idx == source_lines_to_display.current_source_line) { 5680b4c26b2SJason Molenda line_highlight = "**"; 5690b4c26b2SJason Molenda } 5700b4c26b2SJason Molenda source_manager.DisplaySourceLinesWithLineNumbers( 5719666ba75STodd Fiala ln.file, ln.line, ln.column, 0, 0, line_highlight, &strm); 5720b4c26b2SJason Molenda } 5730b4c26b2SJason Molenda if (source_lines_to_display.print_source_context_end_eol) 5740b4c26b2SJason Molenda strm.EOL(); 5750b4c26b2SJason Molenda } 5760b4c26b2SJason Molenda 5771da6f9d7SGreg Clayton const bool show_bytes = (options & eOptionShowBytes) != 0; 578b9c1b51eSKate Stone inst->Dump(&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx, &sc, 579b9c1b51eSKate Stone &prev_sc, nullptr, address_text_size); 58030fdc8d8SChris Lattner strm.EOL(); 581b9c1b51eSKate Stone } else { 58230fdc8d8SChris Lattner break; 58330fdc8d8SChris Lattner } 58430fdc8d8SChris Lattner } 58530fdc8d8SChris Lattner } 58630fdc8d8SChris Lattner 587b9c1b51eSKate Stone bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch, 588b9c1b51eSKate Stone const char *plugin_name, const char *flavor, 589dda4f7b5SGreg Clayton const ExecutionContext &exe_ctx, 59037023b06SJim Ingham uint32_t num_instructions, 5910b4c26b2SJason Molenda bool mixed_source_and_assembly, 592dda4f7b5SGreg Clayton uint32_t num_mixed_context_lines, 593b9c1b51eSKate Stone uint32_t options, Stream &strm) { 594dda4f7b5SGreg Clayton AddressRange range; 595b57e4a1bSJason Molenda StackFrame *frame = exe_ctx.GetFramePtr(); 596b9c1b51eSKate Stone if (frame) { 597b9c1b51eSKate Stone SymbolContext sc( 598b9c1b51eSKate Stone frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol)); 599b9c1b51eSKate Stone if (sc.function) { 600dda4f7b5SGreg Clayton range = sc.function->GetAddressRange(); 601b9c1b51eSKate Stone } else if (sc.symbol && sc.symbol->ValueIsAddress()) { 602358cf1eaSGreg Clayton range.GetBaseAddress() = sc.symbol->GetAddressRef(); 603e7612134SGreg Clayton range.SetByteSize(sc.symbol->GetByteSize()); 604b9c1b51eSKate Stone } else { 605c14ee32dSGreg Clayton range.GetBaseAddress() = frame->GetFrameCodeAddress(); 606dda4f7b5SGreg Clayton } 607dda4f7b5SGreg Clayton 608dda4f7b5SGreg Clayton if (range.GetBaseAddress().IsValid() && range.GetByteSize() == 0) 609dda4f7b5SGreg Clayton range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE); 610dda4f7b5SGreg Clayton } 611dda4f7b5SGreg Clayton 612b9c1b51eSKate Stone return Disassemble(debugger, arch, plugin_name, flavor, exe_ctx, range, 6130b4c26b2SJason Molenda num_instructions, mixed_source_and_assembly, 6140b4c26b2SJason Molenda num_mixed_context_lines, options, strm); 615dda4f7b5SGreg Clayton } 616dda4f7b5SGreg Clayton 617b9c1b51eSKate Stone Instruction::Instruction(const Address &address, AddressClass addr_class) 618b9c1b51eSKate Stone : m_address(address), m_address_class(addr_class), m_opcode(), 619b9c1b51eSKate Stone m_calculated_strings(false) {} 62030fdc8d8SChris Lattner 62134ede34aSEugene Zelenko Instruction::~Instruction() = default; 62230fdc8d8SChris Lattner 623b9c1b51eSKate Stone AddressClass Instruction::GetAddressClass() { 62404803b3eSTatyana Krasnukha if (m_address_class == AddressClass::eInvalid) 625357132ebSGreg Clayton m_address_class = m_address.GetAddressClass(); 626357132ebSGreg Clayton return m_address_class; 627357132ebSGreg Clayton } 62830fdc8d8SChris Lattner 629b9c1b51eSKate Stone void Instruction::Dump(lldb_private::Stream *s, uint32_t max_opcode_byte_size, 630b9c1b51eSKate Stone bool show_address, bool show_bytes, 631aff1b357SJason Molenda const ExecutionContext *exe_ctx, 632aff1b357SJason Molenda const SymbolContext *sym_ctx, 633aff1b357SJason Molenda const SymbolContext *prev_sym_ctx, 634c980fa92SJason Molenda const FormatEntity::Entry *disassembly_addr_format, 635b9c1b51eSKate Stone size_t max_address_text_size) { 6367a37c1ecSJason Molenda size_t opcode_column_width = 7; 637ba812f42SGreg Clayton const size_t operand_column_width = 25; 638ba812f42SGreg Clayton 639ba812f42SGreg Clayton CalculateMnemonicOperandsAndCommentIfNeeded(exe_ctx); 640ba812f42SGreg Clayton 641ba812f42SGreg Clayton StreamString ss; 642ba812f42SGreg Clayton 643b9c1b51eSKate Stone if (show_address) { 644b9c1b51eSKate Stone Debugger::FormatDisassemblerAddress(disassembly_addr_format, sym_ctx, 645b9c1b51eSKate Stone prev_sym_ctx, exe_ctx, &m_address, ss); 646c980fa92SJason Molenda ss.FillLastLineToColumn(max_address_text_size, ' '); 647ba812f42SGreg Clayton } 648ba812f42SGreg Clayton 649b9c1b51eSKate Stone if (show_bytes) { 650b9c1b51eSKate Stone if (m_opcode.GetType() == Opcode::eTypeBytes) { 65105097246SAdrian Prantl // x86_64 and i386 are the only ones that use bytes right now so pad out 65205097246SAdrian Prantl // the byte dump to be able to always show 15 bytes (3 chars each) plus a 65305097246SAdrian Prantl // space 654ba812f42SGreg Clayton if (max_opcode_byte_size > 0) 655ba812f42SGreg Clayton m_opcode.Dump(&ss, max_opcode_byte_size * 3 + 1); 656ba812f42SGreg Clayton else 657ba812f42SGreg Clayton m_opcode.Dump(&ss, 15 * 3 + 1); 658b9c1b51eSKate Stone } else { 65905097246SAdrian Prantl // Else, we have ARM or MIPS which can show up to a uint32_t 0x00000000 66005097246SAdrian Prantl // (10 spaces) plus two for padding... 661ba812f42SGreg Clayton if (max_opcode_byte_size > 0) 662ba812f42SGreg Clayton m_opcode.Dump(&ss, max_opcode_byte_size * 3 + 1); 663ba812f42SGreg Clayton else 664ba812f42SGreg Clayton m_opcode.Dump(&ss, 12); 665ba812f42SGreg Clayton } 666ba812f42SGreg Clayton } 667ba812f42SGreg Clayton 668aff1b357SJason Molenda const size_t opcode_pos = ss.GetSizeOfLastLine(); 669ba812f42SGreg Clayton 6707a37c1ecSJason Molenda // The default opcode size of 7 characters is plenty for most architectures 6717a37c1ecSJason Molenda // but some like arm can pull out the occasional vqrshrun.s16. We won't get 6727a37c1ecSJason Molenda // consistent column spacing in these cases, unfortunately. 673b9c1b51eSKate Stone if (m_opcode_name.length() >= opcode_column_width) { 6747a37c1ecSJason Molenda opcode_column_width = m_opcode_name.length() + 1; 6757a37c1ecSJason Molenda } 6767a37c1ecSJason Molenda 677771ef6d4SMalcolm Parsons ss.PutCString(m_opcode_name); 678ba812f42SGreg Clayton ss.FillLastLineToColumn(opcode_pos + opcode_column_width, ' '); 679771ef6d4SMalcolm Parsons ss.PutCString(m_mnemonics); 680ba812f42SGreg Clayton 681b9c1b51eSKate Stone if (!m_comment.empty()) { 682b9c1b51eSKate Stone ss.FillLastLineToColumn( 683b9c1b51eSKate Stone opcode_pos + opcode_column_width + operand_column_width, ' '); 684ba812f42SGreg Clayton ss.PutCString(" ; "); 685771ef6d4SMalcolm Parsons ss.PutCString(m_comment); 686ba812f42SGreg Clayton } 687c156427dSZachary Turner s->PutCString(ss.GetString()); 688ba812f42SGreg Clayton } 689ba812f42SGreg Clayton 690b9c1b51eSKate Stone bool Instruction::DumpEmulation(const ArchSpec &arch) { 691d5b44036SJonas Devlieghere std::unique_ptr<EmulateInstruction> insn_emulator_up( 692b9c1b51eSKate Stone EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr)); 693d5b44036SJonas Devlieghere if (insn_emulator_up) { 694d5b44036SJonas Devlieghere insn_emulator_up->SetInstruction(GetOpcode(), GetAddress(), nullptr); 695d5b44036SJonas Devlieghere return insn_emulator_up->EvaluateInstruction(0); 6967c9dd3ceSCaroline Tice } 6977c9dd3ceSCaroline Tice 6987c9dd3ceSCaroline Tice return false; 6997c9dd3ceSCaroline Tice } 7007c9dd3ceSCaroline Tice 701dd125943SNitesh Jain bool Instruction::CanSetBreakpoint () { 702dd125943SNitesh Jain return !HasDelaySlot(); 703dd125943SNitesh Jain } 704dd125943SNitesh Jain 705b9c1b51eSKate Stone bool Instruction::HasDelaySlot() { 7067f3daedaSBhushan D. Attarde // Default is false. 7077f3daedaSBhushan D. Attarde return false; 7087f3daedaSBhushan D. Attarde } 7097f3daedaSBhushan D. Attarde 710b9c1b51eSKate Stone OptionValueSP Instruction::ReadArray(FILE *in_file, Stream *out_stream, 711b9c1b51eSKate Stone OptionValue::Type data_type) { 712de2fb9cfSCaroline Tice bool done = false; 713de2fb9cfSCaroline Tice char buffer[1024]; 714de2fb9cfSCaroline Tice 7152f3df613SZachary Turner auto option_value_sp = std::make_shared<OptionValueArray>(1u << data_type); 716de2fb9cfSCaroline Tice 717de2fb9cfSCaroline Tice int idx = 0; 718b9c1b51eSKate Stone while (!done) { 719b9c1b51eSKate Stone if (!fgets(buffer, 1023, in_file)) { 720b9c1b51eSKate Stone out_stream->Printf( 721b9c1b51eSKate Stone "Instruction::ReadArray: Error reading file (fgets).\n"); 722de2fb9cfSCaroline Tice option_value_sp.reset(); 723de2fb9cfSCaroline Tice return option_value_sp; 724de2fb9cfSCaroline Tice } 725de2fb9cfSCaroline Tice 726de2fb9cfSCaroline Tice std::string line(buffer); 727de2fb9cfSCaroline Tice 728c7bece56SGreg Clayton size_t len = line.size(); 729b9c1b51eSKate Stone if (line[len - 1] == '\n') { 730de2fb9cfSCaroline Tice line[len - 1] = '\0'; 731de2fb9cfSCaroline Tice line.resize(len - 1); 732de2fb9cfSCaroline Tice } 733de2fb9cfSCaroline Tice 734b9c1b51eSKate Stone if ((line.size() == 1) && line[0] == ']') { 735de2fb9cfSCaroline Tice done = true; 736de2fb9cfSCaroline Tice line.clear(); 737de2fb9cfSCaroline Tice } 738de2fb9cfSCaroline Tice 739b9c1b51eSKate Stone if (!line.empty()) { 740de2fb9cfSCaroline Tice std::string value; 74195eae423SZachary Turner static RegularExpression g_reg_exp( 74295eae423SZachary Turner llvm::StringRef("^[ \t]*([^ \t]+)[ \t]*$")); 7433af3f1e8SJonas Devlieghere llvm::SmallVector<llvm::StringRef, 2> matches; 7443af3f1e8SJonas Devlieghere if (g_reg_exp.Execute(line, &matches)) 7453af3f1e8SJonas Devlieghere value = matches[1].str(); 746de2fb9cfSCaroline Tice else 747de2fb9cfSCaroline Tice value = line; 748de2fb9cfSCaroline Tice 749de2fb9cfSCaroline Tice OptionValueSP data_value_sp; 750b9c1b51eSKate Stone switch (data_type) { 751de2fb9cfSCaroline Tice case OptionValue::eTypeUInt64: 7522f3df613SZachary Turner data_value_sp = std::make_shared<OptionValueUInt64>(0, 0); 753c95f7e2aSPavel Labath data_value_sp->SetValueFromString(value); 754de2fb9cfSCaroline Tice break; 755de2fb9cfSCaroline Tice // Other types can be added later as needed. 756de2fb9cfSCaroline Tice default: 7572f3df613SZachary Turner data_value_sp = std::make_shared<OptionValueString>(value.c_str(), ""); 758de2fb9cfSCaroline Tice break; 759de2fb9cfSCaroline Tice } 760de2fb9cfSCaroline Tice 76184c39663SGreg Clayton option_value_sp->GetAsArray()->InsertValue(idx, data_value_sp); 762de2fb9cfSCaroline Tice ++idx; 763de2fb9cfSCaroline Tice } 764de2fb9cfSCaroline Tice } 765de2fb9cfSCaroline Tice 766de2fb9cfSCaroline Tice return option_value_sp; 767de2fb9cfSCaroline Tice } 768de2fb9cfSCaroline Tice 769b9c1b51eSKate Stone OptionValueSP Instruction::ReadDictionary(FILE *in_file, Stream *out_stream) { 770de2fb9cfSCaroline Tice bool done = false; 771de2fb9cfSCaroline Tice char buffer[1024]; 772de2fb9cfSCaroline Tice 7732f3df613SZachary Turner auto option_value_sp = std::make_shared<OptionValueDictionary>(); 774de2fb9cfSCaroline Tice static ConstString encoding_key("data_encoding"); 775de2fb9cfSCaroline Tice OptionValue::Type data_type = OptionValue::eTypeInvalid; 776de2fb9cfSCaroline Tice 777b9c1b51eSKate Stone while (!done) { 778de2fb9cfSCaroline Tice // Read the next line in the file 779b9c1b51eSKate Stone if (!fgets(buffer, 1023, in_file)) { 780b9c1b51eSKate Stone out_stream->Printf( 781b9c1b51eSKate Stone "Instruction::ReadDictionary: Error reading file (fgets).\n"); 782de2fb9cfSCaroline Tice option_value_sp.reset(); 783de2fb9cfSCaroline Tice return option_value_sp; 784de2fb9cfSCaroline Tice } 785de2fb9cfSCaroline Tice 786de2fb9cfSCaroline Tice // Check to see if the line contains the end-of-dictionary marker ("}") 787de2fb9cfSCaroline Tice std::string line(buffer); 788de2fb9cfSCaroline Tice 789c7bece56SGreg Clayton size_t len = line.size(); 790b9c1b51eSKate Stone if (line[len - 1] == '\n') { 791de2fb9cfSCaroline Tice line[len - 1] = '\0'; 792de2fb9cfSCaroline Tice line.resize(len - 1); 793de2fb9cfSCaroline Tice } 794de2fb9cfSCaroline Tice 795b9c1b51eSKate Stone if ((line.size() == 1) && (line[0] == '}')) { 796de2fb9cfSCaroline Tice done = true; 797de2fb9cfSCaroline Tice line.clear(); 798de2fb9cfSCaroline Tice } 799de2fb9cfSCaroline Tice 800b9c1b51eSKate Stone // Try to find a key-value pair in the current line and add it to the 801b9c1b51eSKate Stone // dictionary. 802b9c1b51eSKate Stone if (!line.empty()) { 80395eae423SZachary Turner static RegularExpression g_reg_exp(llvm::StringRef( 80495eae423SZachary Turner "^[ \t]*([a-zA-Z_][a-zA-Z0-9_]*)[ \t]*=[ \t]*(.*)[ \t]*$")); 805bc43cab5SGreg Clayton 8063af3f1e8SJonas Devlieghere llvm::SmallVector<llvm::StringRef, 3> matches; 8073af3f1e8SJonas Devlieghere 8083af3f1e8SJonas Devlieghere bool reg_exp_success = g_reg_exp.Execute(line, &matches); 809de2fb9cfSCaroline Tice std::string key; 810de2fb9cfSCaroline Tice std::string value; 811b9c1b51eSKate Stone if (reg_exp_success) { 8123af3f1e8SJonas Devlieghere key = matches[1].str(); 8133af3f1e8SJonas Devlieghere value = matches[2].str(); 814b9c1b51eSKate Stone } else { 815b9c1b51eSKate Stone out_stream->Printf("Instruction::ReadDictionary: Failure executing " 816b9c1b51eSKate Stone "regular expression.\n"); 817de2fb9cfSCaroline Tice option_value_sp.reset(); 818de2fb9cfSCaroline Tice return option_value_sp; 819de2fb9cfSCaroline Tice } 820de2fb9cfSCaroline Tice 821de2fb9cfSCaroline Tice ConstString const_key(key.c_str()); 822de2fb9cfSCaroline Tice // Check value to see if it's the start of an array or dictionary. 823de2fb9cfSCaroline Tice 824de2fb9cfSCaroline Tice lldb::OptionValueSP value_sp; 825de2fb9cfSCaroline Tice assert(value.empty() == false); 826de2fb9cfSCaroline Tice assert(key.empty() == false); 827de2fb9cfSCaroline Tice 828b9c1b51eSKate Stone if (value[0] == '{') { 829de2fb9cfSCaroline Tice assert(value.size() == 1); 830de2fb9cfSCaroline Tice // value is a dictionary 831de2fb9cfSCaroline Tice value_sp = ReadDictionary(in_file, out_stream); 832b9c1b51eSKate Stone if (!value_sp) { 833de2fb9cfSCaroline Tice option_value_sp.reset(); 834de2fb9cfSCaroline Tice return option_value_sp; 835de2fb9cfSCaroline Tice } 836b9c1b51eSKate Stone } else if (value[0] == '[') { 837de2fb9cfSCaroline Tice assert(value.size() == 1); 838de2fb9cfSCaroline Tice // value is an array 839de2fb9cfSCaroline Tice value_sp = ReadArray(in_file, out_stream, data_type); 840b9c1b51eSKate Stone if (!value_sp) { 841de2fb9cfSCaroline Tice option_value_sp.reset(); 842de2fb9cfSCaroline Tice return option_value_sp; 843de2fb9cfSCaroline Tice } 84405097246SAdrian Prantl // We've used the data_type to read an array; re-set the type to 84505097246SAdrian Prantl // Invalid 846de2fb9cfSCaroline Tice data_type = OptionValue::eTypeInvalid; 847b9c1b51eSKate Stone } else if ((value[0] == '0') && (value[1] == 'x')) { 8482f3df613SZachary Turner value_sp = std::make_shared<OptionValueUInt64>(0, 0); 849c95f7e2aSPavel Labath value_sp->SetValueFromString(value); 850b9c1b51eSKate Stone } else { 851c7bece56SGreg Clayton size_t len = value.size(); 852de2fb9cfSCaroline Tice if ((value[0] == '"') && (value[len - 1] == '"')) 853de2fb9cfSCaroline Tice value = value.substr(1, len - 2); 8542f3df613SZachary Turner value_sp = std::make_shared<OptionValueString>(value.c_str(), ""); 855de2fb9cfSCaroline Tice } 856de2fb9cfSCaroline Tice 857b9c1b51eSKate Stone if (const_key == encoding_key) { 858b9c1b51eSKate Stone // A 'data_encoding=..." is NOT a normal key-value pair; it is meta-data 859b9c1b51eSKate Stone // indicating the 860b9c1b51eSKate Stone // data type of an upcoming array (usually the next bit of data to be 861b9c1b51eSKate Stone // read in). 862de2fb9cfSCaroline Tice if (strcmp(value.c_str(), "uint32_t") == 0) 863de2fb9cfSCaroline Tice data_type = OptionValue::eTypeUInt64; 864b9c1b51eSKate Stone } else 865b9c1b51eSKate Stone option_value_sp->GetAsDictionary()->SetValueForKey(const_key, value_sp, 866b9c1b51eSKate Stone false); 867de2fb9cfSCaroline Tice } 868de2fb9cfSCaroline Tice } 869de2fb9cfSCaroline Tice 870de2fb9cfSCaroline Tice return option_value_sp; 871de2fb9cfSCaroline Tice } 872de2fb9cfSCaroline Tice 873b9c1b51eSKate Stone bool Instruction::TestEmulation(Stream *out_stream, const char *file_name) { 8743ac6711aSCaroline Tice if (!out_stream) 8753ac6711aSCaroline Tice return false; 8763ac6711aSCaroline Tice 877b9c1b51eSKate Stone if (!file_name) { 878ea80ba8bSJohnny Chen out_stream->Printf("Instruction::TestEmulation: Missing file_name."); 8793ac6711aSCaroline Tice return false; 8803ac6711aSCaroline Tice } 88146376966SJonas Devlieghere FILE *test_file = FileSystem::Instance().Fopen(file_name, "r"); 882b9c1b51eSKate Stone if (!test_file) { 883b9c1b51eSKate Stone out_stream->Printf( 884b9c1b51eSKate Stone "Instruction::TestEmulation: Attempt to open test file failed."); 8853ac6711aSCaroline Tice return false; 8863ac6711aSCaroline Tice } 8873ac6711aSCaroline Tice 8883ac6711aSCaroline Tice char buffer[256]; 889b9c1b51eSKate Stone if (!fgets(buffer, 255, test_file)) { 890b9c1b51eSKate Stone out_stream->Printf( 891b9c1b51eSKate Stone "Instruction::TestEmulation: Error reading first line of test file.\n"); 8923ac6711aSCaroline Tice fclose(test_file); 8933ac6711aSCaroline Tice return false; 8943ac6711aSCaroline Tice } 8953ac6711aSCaroline Tice 896b9c1b51eSKate Stone if (strncmp(buffer, "InstructionEmulationState={", 27) != 0) { 897b9c1b51eSKate Stone out_stream->Printf("Instructin::TestEmulation: Test file does not contain " 898b9c1b51eSKate Stone "emulation state dictionary\n"); 899de2fb9cfSCaroline Tice fclose(test_file); 900de2fb9cfSCaroline Tice return false; 901de2fb9cfSCaroline Tice } 902de2fb9cfSCaroline Tice 903b9c1b51eSKate Stone // Read all the test information from the test file into an 904b9c1b51eSKate Stone // OptionValueDictionary. 905de2fb9cfSCaroline Tice 906de2fb9cfSCaroline Tice OptionValueSP data_dictionary_sp(ReadDictionary(test_file, out_stream)); 907b9c1b51eSKate Stone if (!data_dictionary_sp) { 908b9c1b51eSKate Stone out_stream->Printf( 909b9c1b51eSKate Stone "Instruction::TestEmulation: Error reading Dictionary Object.\n"); 910de2fb9cfSCaroline Tice fclose(test_file); 911de2fb9cfSCaroline Tice return false; 912de2fb9cfSCaroline Tice } 913de2fb9cfSCaroline Tice 914de2fb9cfSCaroline Tice fclose(test_file); 915de2fb9cfSCaroline Tice 916b9c1b51eSKate Stone OptionValueDictionary *data_dictionary = 917b9c1b51eSKate Stone data_dictionary_sp->GetAsDictionary(); 918de2fb9cfSCaroline Tice static ConstString description_key("assembly_string"); 919de2fb9cfSCaroline Tice static ConstString triple_key("triple"); 920de2fb9cfSCaroline Tice 921de2fb9cfSCaroline Tice OptionValueSP value_sp = data_dictionary->GetValueForKey(description_key); 922de2fb9cfSCaroline Tice 923b9c1b51eSKate Stone if (!value_sp) { 924b9c1b51eSKate Stone out_stream->Printf("Instruction::TestEmulation: Test file does not " 925b9c1b51eSKate Stone "contain description string.\n"); 926de2fb9cfSCaroline Tice return false; 927de2fb9cfSCaroline Tice } 928de2fb9cfSCaroline Tice 929de2fb9cfSCaroline Tice SetDescription(value_sp->GetStringValue()); 930de2fb9cfSCaroline Tice 931de2fb9cfSCaroline Tice value_sp = data_dictionary->GetValueForKey(triple_key); 932b9c1b51eSKate Stone if (!value_sp) { 933b9c1b51eSKate Stone out_stream->Printf( 934b9c1b51eSKate Stone "Instruction::TestEmulation: Test file does not contain triple.\n"); 935de2fb9cfSCaroline Tice return false; 936de2fb9cfSCaroline Tice } 937de2fb9cfSCaroline Tice 938de2fb9cfSCaroline Tice ArchSpec arch; 939de2fb9cfSCaroline Tice arch.SetTriple(llvm::Triple(value_sp->GetStringValue())); 9403ac6711aSCaroline Tice 9413ac6711aSCaroline Tice bool success = false; 942d5b44036SJonas Devlieghere std::unique_ptr<EmulateInstruction> insn_emulator_up( 943b9c1b51eSKate Stone EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr)); 944d5b44036SJonas Devlieghere if (insn_emulator_up) 945b9c1b51eSKate Stone success = 946d5b44036SJonas Devlieghere insn_emulator_up->TestEmulation(out_stream, arch, data_dictionary); 9473ac6711aSCaroline Tice 9483ac6711aSCaroline Tice if (success) 949ea80ba8bSJohnny Chen out_stream->Printf("Emulation test succeeded."); 9503ac6711aSCaroline Tice else 951ea80ba8bSJohnny Chen out_stream->Printf("Emulation test failed."); 9523ac6711aSCaroline Tice 9533ac6711aSCaroline Tice return success; 9543ac6711aSCaroline Tice } 9553ac6711aSCaroline Tice 956b9c1b51eSKate Stone bool Instruction::Emulate( 957b9c1b51eSKate Stone const ArchSpec &arch, uint32_t evaluate_options, void *baton, 9587349bd90SGreg Clayton EmulateInstruction::ReadMemoryCallback read_mem_callback, 9597349bd90SGreg Clayton EmulateInstruction::WriteMemoryCallback write_mem_callback, 9607349bd90SGreg Clayton EmulateInstruction::ReadRegisterCallback read_reg_callback, 961b9c1b51eSKate Stone EmulateInstruction::WriteRegisterCallback write_reg_callback) { 962d5b44036SJonas Devlieghere std::unique_ptr<EmulateInstruction> insn_emulator_up( 963b9c1b51eSKate Stone EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr)); 964d5b44036SJonas Devlieghere if (insn_emulator_up) { 965d5b44036SJonas Devlieghere insn_emulator_up->SetBaton(baton); 966d5b44036SJonas Devlieghere insn_emulator_up->SetCallbacks(read_mem_callback, write_mem_callback, 967b9c1b51eSKate Stone read_reg_callback, write_reg_callback); 968d5b44036SJonas Devlieghere insn_emulator_up->SetInstruction(GetOpcode(), GetAddress(), nullptr); 969d5b44036SJonas Devlieghere return insn_emulator_up->EvaluateInstruction(evaluate_options); 9707c9dd3ceSCaroline Tice } 9717c9dd3ceSCaroline Tice 9727c9dd3ceSCaroline Tice return false; 9737c9dd3ceSCaroline Tice } 9747c9dd3ceSCaroline Tice 975b9c1b51eSKate Stone uint32_t Instruction::GetData(DataExtractor &data) { 976cd4ae1abSSean Callanan return m_opcode.GetData(data); 977ba812f42SGreg Clayton } 978ba812f42SGreg Clayton 979b9c1b51eSKate Stone InstructionList::InstructionList() : m_instructions() {} 98030fdc8d8SChris Lattner 98134ede34aSEugene Zelenko InstructionList::~InstructionList() = default; 98230fdc8d8SChris Lattner 983b9c1b51eSKate Stone size_t InstructionList::GetSize() const { return m_instructions.size(); } 98430fdc8d8SChris Lattner 985b9c1b51eSKate Stone uint32_t InstructionList::GetMaxOpcocdeByteSize() const { 986357132ebSGreg Clayton uint32_t max_inst_size = 0; 987357132ebSGreg Clayton collection::const_iterator pos, end; 988b9c1b51eSKate Stone for (pos = m_instructions.begin(), end = m_instructions.end(); pos != end; 989b9c1b51eSKate Stone ++pos) { 990357132ebSGreg Clayton uint32_t inst_size = (*pos)->GetOpcode().GetByteSize(); 991357132ebSGreg Clayton if (max_inst_size < inst_size) 992357132ebSGreg Clayton max_inst_size = inst_size; 993357132ebSGreg Clayton } 994357132ebSGreg Clayton return max_inst_size; 995357132ebSGreg Clayton } 996357132ebSGreg Clayton 997b9c1b51eSKate Stone InstructionSP InstructionList::GetInstructionAtIndex(size_t idx) const { 9981d273166SGreg Clayton InstructionSP inst_sp; 99930fdc8d8SChris Lattner if (idx < m_instructions.size()) 10001d273166SGreg Clayton inst_sp = m_instructions[idx]; 10011d273166SGreg Clayton return inst_sp; 100230fdc8d8SChris Lattner } 100330fdc8d8SChris Lattner 1004b9c1b51eSKate Stone void InstructionList::Dump(Stream *s, bool show_address, bool show_bytes, 1005b9c1b51eSKate Stone const ExecutionContext *exe_ctx) { 10065009f9d5SGreg Clayton const uint32_t max_opcode_byte_size = GetMaxOpcocdeByteSize(); 10075009f9d5SGreg Clayton collection::const_iterator pos, begin, end; 1008554f68d3SGreg Clayton 100934ede34aSEugene Zelenko const FormatEntity::Entry *disassembly_format = nullptr; 1010554f68d3SGreg Clayton FormatEntity::Entry format; 1011b9c1b51eSKate Stone if (exe_ctx && exe_ctx->HasTargetScope()) { 1012b9c1b51eSKate Stone disassembly_format = 1013b9c1b51eSKate Stone exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat(); 1014b9c1b51eSKate Stone } else { 1015554f68d3SGreg Clayton FormatEntity::Parse("${addr}: ", format); 1016554f68d3SGreg Clayton disassembly_format = &format; 1017554f68d3SGreg Clayton } 1018554f68d3SGreg Clayton 10195009f9d5SGreg Clayton for (begin = m_instructions.begin(), end = m_instructions.end(), pos = begin; 1020b9c1b51eSKate Stone pos != end; ++pos) { 10215009f9d5SGreg Clayton if (pos != begin) 10225009f9d5SGreg Clayton s->EOL(); 1023b9c1b51eSKate Stone (*pos)->Dump(s, max_opcode_byte_size, show_address, show_bytes, exe_ctx, 1024b9c1b51eSKate Stone nullptr, nullptr, disassembly_format, 0); 10255009f9d5SGreg Clayton } 10265009f9d5SGreg Clayton } 10275009f9d5SGreg Clayton 1028b9c1b51eSKate Stone void InstructionList::Clear() { m_instructions.clear(); } 102930fdc8d8SChris Lattner 1030b9c1b51eSKate Stone void InstructionList::Append(lldb::InstructionSP &inst_sp) { 103130fdc8d8SChris Lattner if (inst_sp) 103230fdc8d8SChris Lattner m_instructions.push_back(inst_sp); 103330fdc8d8SChris Lattner } 103430fdc8d8SChris Lattner 1035564d8bc2SJim Ingham uint32_t 1036b9c1b51eSKate Stone InstructionList::GetIndexOfNextBranchInstruction(uint32_t start, 1037df225764SGreg Clayton Target &target, 1038434905b9SJim Ingham bool ignore_calls, 1039434905b9SJim Ingham bool *found_calls) const { 1040564d8bc2SJim Ingham size_t num_instructions = m_instructions.size(); 1041564d8bc2SJim Ingham 1042190636bcSJim Ingham uint32_t next_branch = UINT32_MAX; 1043e76e7e93STed Woodward size_t i; 1044434905b9SJim Ingham 1045434905b9SJim Ingham if (found_calls) 1046434905b9SJim Ingham *found_calls = false; 1047b9c1b51eSKate Stone for (i = start; i < num_instructions; i++) { 1048b9c1b51eSKate Stone if (m_instructions[i]->DoesBranch()) { 1049434905b9SJim Ingham if (ignore_calls && m_instructions[i]->IsCall()) { 1050434905b9SJim Ingham if (found_calls) 1051434905b9SJim Ingham *found_calls = true; 105221929d49SPavel Labath continue; 1053434905b9SJim Ingham } 1054564d8bc2SJim Ingham next_branch = i; 1055564d8bc2SJim Ingham break; 1056564d8bc2SJim Ingham } 1057564d8bc2SJim Ingham } 1058e76e7e93STed Woodward 105905097246SAdrian Prantl // Hexagon needs the first instruction of the packet with the branch. Go 106005097246SAdrian Prantl // backwards until we find an instruction marked end-of-packet, or until we 106105097246SAdrian Prantl // hit start. 1062b9c1b51eSKate Stone if (target.GetArchitecture().GetTriple().getArch() == llvm::Triple::hexagon) { 1063e76e7e93STed Woodward // If we didn't find a branch, find the last packet start. 1064b9c1b51eSKate Stone if (next_branch == UINT32_MAX) { 1065e76e7e93STed Woodward i = num_instructions - 1; 1066e76e7e93STed Woodward } 1067e76e7e93STed Woodward 1068b9c1b51eSKate Stone while (i > start) { 1069e76e7e93STed Woodward --i; 1070e76e7e93STed Woodward 107197206d57SZachary Turner Status error; 1072e76e7e93STed Woodward uint32_t inst_bytes; 1073e76e7e93STed Woodward bool prefer_file_cache = false; // Read from process if process is running 1074e76e7e93STed Woodward lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; 1075b9c1b51eSKate Stone target.ReadMemory(m_instructions[i]->GetAddress(), prefer_file_cache, 1076b9c1b51eSKate Stone &inst_bytes, sizeof(inst_bytes), error, &load_addr); 1077e76e7e93STed Woodward // If we have an error reading memory, return start 1078e76e7e93STed Woodward if (!error.Success()) 1079e76e7e93STed Woodward return start; 108005097246SAdrian Prantl // check if this is the last instruction in a packet bits 15:14 will be 108105097246SAdrian Prantl // 11b or 00b for a duplex 1082e76e7e93STed Woodward if (((inst_bytes & 0xC000) == 0xC000) || 1083b9c1b51eSKate Stone ((inst_bytes & 0xC000) == 0x0000)) { 1084e76e7e93STed Woodward // instruction after this should be the start of next packet 1085e76e7e93STed Woodward next_branch = i + 1; 1086e76e7e93STed Woodward break; 1087e76e7e93STed Woodward } 1088e76e7e93STed Woodward } 1089e76e7e93STed Woodward 1090b9c1b51eSKate Stone if (next_branch == UINT32_MAX) { 1091e76e7e93STed Woodward // We couldn't find the previous packet, so return start 1092e76e7e93STed Woodward next_branch = start; 1093e76e7e93STed Woodward } 1094e76e7e93STed Woodward } 1095564d8bc2SJim Ingham return next_branch; 1096564d8bc2SJim Ingham } 1097564d8bc2SJim Ingham 1098564d8bc2SJim Ingham uint32_t 1099b9c1b51eSKate Stone InstructionList::GetIndexOfInstructionAtAddress(const Address &address) { 1100c7bece56SGreg Clayton size_t num_instructions = m_instructions.size(); 1101190636bcSJim Ingham uint32_t index = UINT32_MAX; 1102b9c1b51eSKate Stone for (size_t i = 0; i < num_instructions; i++) { 1103b9c1b51eSKate Stone if (m_instructions[i]->GetAddress() == address) { 1104564d8bc2SJim Ingham index = i; 1105564d8bc2SJim Ingham break; 1106564d8bc2SJim Ingham } 1107564d8bc2SJim Ingham } 1108564d8bc2SJim Ingham return index; 1109564d8bc2SJim Ingham } 111030fdc8d8SChris Lattner 111144d93782SGreg Clayton uint32_t 1112b9c1b51eSKate Stone InstructionList::GetIndexOfInstructionAtLoadAddress(lldb::addr_t load_addr, 1113b9c1b51eSKate Stone Target &target) { 111444d93782SGreg Clayton Address address; 111544d93782SGreg Clayton address.SetLoadAddress(load_addr, &target); 111644d93782SGreg Clayton return GetIndexOfInstructionAtAddress(address); 111744d93782SGreg Clayton } 111844d93782SGreg Clayton 11191d6fa41fSPavel Labath size_t Disassembler::ParseInstructions(Target &target, 112057f0630cSGreg Clayton const AddressRange &range, 11213faf47c4SGreg Clayton Stream *error_strm_ptr, 1122b9c1b51eSKate Stone bool prefer_file_cache) { 1123dda4f7b5SGreg Clayton const addr_t byte_size = range.GetByteSize(); 11241d6fa41fSPavel Labath if (byte_size == 0 || !range.GetBaseAddress().IsValid()) 112530fdc8d8SChris Lattner return 0; 112630fdc8d8SChris Lattner 11272f3df613SZachary Turner auto data_sp = std::make_shared<DataBufferHeap>(byte_size, '\0'); 112830fdc8d8SChris Lattner 112997206d57SZachary Turner Status error; 11303faf47c4SGreg Clayton lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; 11311d6fa41fSPavel Labath const size_t bytes_read = target.ReadMemory( 11322f3df613SZachary Turner range.GetBaseAddress(), prefer_file_cache, data_sp->GetBytes(), 11332f3df613SZachary Turner data_sp->GetByteSize(), error, &load_addr); 1134dda4f7b5SGreg Clayton 1135b9c1b51eSKate Stone if (bytes_read > 0) { 11362f3df613SZachary Turner if (bytes_read != data_sp->GetByteSize()) 11372f3df613SZachary Turner data_sp->SetByteSize(bytes_read); 1138b9c1b51eSKate Stone DataExtractor data(data_sp, m_arch.GetByteOrder(), 1139357132ebSGreg Clayton m_arch.GetAddressByteSize()); 11403faf47c4SGreg Clayton const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS; 1141b9c1b51eSKate Stone return DecodeInstructions(range.GetBaseAddress(), data, 0, UINT32_MAX, 1142b9c1b51eSKate Stone false, data_from_file); 1143b9c1b51eSKate Stone } else if (error_strm_ptr) { 114457f0630cSGreg Clayton const char *error_cstr = error.AsCString(); 1145b9c1b51eSKate Stone if (error_cstr) { 114657f0630cSGreg Clayton error_strm_ptr->Printf("error: %s\n", error_cstr); 114757f0630cSGreg Clayton } 114857f0630cSGreg Clayton } 114930fdc8d8SChris Lattner return 0; 115030fdc8d8SChris Lattner } 115130fdc8d8SChris Lattner 11521d6fa41fSPavel Labath size_t Disassembler::ParseInstructions(Target &target, const Address &start, 11533faf47c4SGreg Clayton uint32_t num_instructions, 1154b9c1b51eSKate Stone bool prefer_file_cache) { 1155357132ebSGreg Clayton m_instruction_list.Clear(); 115637023b06SJim Ingham 11571d6fa41fSPavel Labath if (num_instructions == 0 || !start.IsValid()) 115837023b06SJim Ingham return 0; 115937023b06SJim Ingham 1160357132ebSGreg Clayton // Calculate the max buffer size we will need in order to disassemble 1161357132ebSGreg Clayton const addr_t byte_size = num_instructions * m_arch.GetMaximumOpcodeByteSize(); 116237023b06SJim Ingham 11631d6fa41fSPavel Labath if (byte_size == 0) 116437023b06SJim Ingham return 0; 116537023b06SJim Ingham 116637023b06SJim Ingham DataBufferHeap *heap_buffer = new DataBufferHeap(byte_size, '\0'); 116737023b06SJim Ingham DataBufferSP data_sp(heap_buffer); 116837023b06SJim Ingham 116997206d57SZachary Turner Status error; 11703faf47c4SGreg Clayton lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; 1171b9c1b51eSKate Stone const size_t bytes_read = 11721d6fa41fSPavel Labath target.ReadMemory(start, prefer_file_cache, heap_buffer->GetBytes(), 1173b9c1b51eSKate Stone byte_size, error, &load_addr); 11743faf47c4SGreg Clayton 11753faf47c4SGreg Clayton const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS; 117637023b06SJim Ingham 117737023b06SJim Ingham if (bytes_read == 0) 1178357132ebSGreg Clayton return 0; 1179b9c1b51eSKate Stone DataExtractor data(data_sp, m_arch.GetByteOrder(), 1180357132ebSGreg Clayton m_arch.GetAddressByteSize()); 118137023b06SJim Ingham 1182357132ebSGreg Clayton const bool append_instructions = true; 1183b9c1b51eSKate Stone DecodeInstructions(start, data, 0, num_instructions, append_instructions, 11843faf47c4SGreg Clayton data_from_file); 118537023b06SJim Ingham 118637023b06SJim Ingham return m_instruction_list.GetSize(); 118737023b06SJim Ingham } 118837023b06SJim Ingham 118930fdc8d8SChris Lattner // Disassembler copy constructor 1190b9c1b51eSKate Stone Disassembler::Disassembler(const ArchSpec &arch, const char *flavor) 1191b9c1b51eSKate Stone : m_arch(arch), m_instruction_list(), m_base_addr(LLDB_INVALID_ADDRESS), 1192b9c1b51eSKate Stone m_flavor() { 119334ede34aSEugene Zelenko if (flavor == nullptr) 11940f063ba6SJim Ingham m_flavor.assign("default"); 11950f063ba6SJim Ingham else 11960f063ba6SJim Ingham m_flavor.assign(flavor); 119775452e8cSJason Molenda 119875452e8cSJason Molenda // If this is an arm variant that can only include thumb (T16, T32) 119905097246SAdrian Prantl // instructions, force the arch triple to be "thumbv.." instead of "armv..." 1200b9c1b51eSKate Stone if (arch.IsAlwaysThumbInstructions()) { 120175452e8cSJason Molenda std::string thumb_arch_name(arch.GetTriple().getArchName().str()); 120275452e8cSJason Molenda // Replace "arm" with "thumb" so we get all thumb variants correct 1203b9c1b51eSKate Stone if (thumb_arch_name.size() > 3) { 120475452e8cSJason Molenda thumb_arch_name.erase(0, 3); 120575452e8cSJason Molenda thumb_arch_name.insert(0, "thumb"); 120675452e8cSJason Molenda } 120775452e8cSJason Molenda m_arch.SetTriple(thumb_arch_name.c_str()); 120875452e8cSJason Molenda } 120930fdc8d8SChris Lattner } 121030fdc8d8SChris Lattner 121134ede34aSEugene Zelenko Disassembler::~Disassembler() = default; 121230fdc8d8SChris Lattner 1213b9c1b51eSKate Stone InstructionList &Disassembler::GetInstructionList() { 121430fdc8d8SChris Lattner return m_instruction_list; 121530fdc8d8SChris Lattner } 121630fdc8d8SChris Lattner 1217b9c1b51eSKate Stone const InstructionList &Disassembler::GetInstructionList() const { 121830fdc8d8SChris Lattner return m_instruction_list; 121930fdc8d8SChris Lattner } 12203ac6711aSCaroline Tice 12213ac6711aSCaroline Tice // Class PseudoInstruction 122234ede34aSEugene Zelenko 1223b9c1b51eSKate Stone PseudoInstruction::PseudoInstruction() 122404803b3eSTatyana Krasnukha : Instruction(Address(), AddressClass::eUnknown), m_description() {} 12253ac6711aSCaroline Tice 122634ede34aSEugene Zelenko PseudoInstruction::~PseudoInstruction() = default; 12273ac6711aSCaroline Tice 1228b9c1b51eSKate Stone bool PseudoInstruction::DoesBranch() { 12293ac6711aSCaroline Tice // This is NOT a valid question for a pseudo instruction. 12303ac6711aSCaroline Tice return false; 12313ac6711aSCaroline Tice } 12323ac6711aSCaroline Tice 1233b9c1b51eSKate Stone bool PseudoInstruction::HasDelaySlot() { 12347f3daedaSBhushan D. Attarde // This is NOT a valid question for a pseudo instruction. 12357f3daedaSBhushan D. Attarde return false; 12367f3daedaSBhushan D. Attarde } 12377f3daedaSBhushan D. Attarde 1238b9c1b51eSKate Stone size_t PseudoInstruction::Decode(const lldb_private::Disassembler &disassembler, 12393ac6711aSCaroline Tice const lldb_private::DataExtractor &data, 1240b9c1b51eSKate Stone lldb::offset_t data_offset) { 12413ac6711aSCaroline Tice return m_opcode.GetByteSize(); 12423ac6711aSCaroline Tice } 12433ac6711aSCaroline Tice 1244b9c1b51eSKate Stone void PseudoInstruction::SetOpcode(size_t opcode_size, void *opcode_data) { 12453ac6711aSCaroline Tice if (!opcode_data) 12463ac6711aSCaroline Tice return; 12473ac6711aSCaroline Tice 1248b9c1b51eSKate Stone switch (opcode_size) { 1249b9c1b51eSKate Stone case 8: { 12503ac6711aSCaroline Tice uint8_t value8 = *((uint8_t *)opcode_data); 125190359963SEd Maste m_opcode.SetOpcode8(value8, eByteOrderInvalid); 12523ac6711aSCaroline Tice break; 12533ac6711aSCaroline Tice } 1254b9c1b51eSKate Stone case 16: { 12553ac6711aSCaroline Tice uint16_t value16 = *((uint16_t *)opcode_data); 125690359963SEd Maste m_opcode.SetOpcode16(value16, eByteOrderInvalid); 12573ac6711aSCaroline Tice break; 12583ac6711aSCaroline Tice } 1259b9c1b51eSKate Stone case 32: { 12603ac6711aSCaroline Tice uint32_t value32 = *((uint32_t *)opcode_data); 126190359963SEd Maste m_opcode.SetOpcode32(value32, eByteOrderInvalid); 12623ac6711aSCaroline Tice break; 12633ac6711aSCaroline Tice } 1264b9c1b51eSKate Stone case 64: { 12653ac6711aSCaroline Tice uint64_t value64 = *((uint64_t *)opcode_data); 126690359963SEd Maste m_opcode.SetOpcode64(value64, eByteOrderInvalid); 12673ac6711aSCaroline Tice break; 12683ac6711aSCaroline Tice } 12693ac6711aSCaroline Tice default: 12703ac6711aSCaroline Tice break; 12713ac6711aSCaroline Tice } 12723ac6711aSCaroline Tice } 12733ac6711aSCaroline Tice 127431d97a5cSZachary Turner void PseudoInstruction::SetDescription(llvm::StringRef description) { 1275adcd0268SBenjamin Kramer m_description = std::string(description); 12763ac6711aSCaroline Tice } 1277807ee2ffSSean Callanan 1278807ee2ffSSean Callanan Instruction::Operand Instruction::Operand::BuildRegister(ConstString &r) { 1279807ee2ffSSean Callanan Operand ret; 1280807ee2ffSSean Callanan ret.m_type = Type::Register; 1281807ee2ffSSean Callanan ret.m_register = r; 1282807ee2ffSSean Callanan return ret; 1283807ee2ffSSean Callanan } 1284807ee2ffSSean Callanan 1285807ee2ffSSean Callanan Instruction::Operand Instruction::Operand::BuildImmediate(lldb::addr_t imm, 1286807ee2ffSSean Callanan bool neg) { 1287807ee2ffSSean Callanan Operand ret; 1288807ee2ffSSean Callanan ret.m_type = Type::Immediate; 1289807ee2ffSSean Callanan ret.m_immediate = imm; 1290807ee2ffSSean Callanan ret.m_negative = neg; 1291807ee2ffSSean Callanan return ret; 1292807ee2ffSSean Callanan } 1293807ee2ffSSean Callanan 1294807ee2ffSSean Callanan Instruction::Operand Instruction::Operand::BuildImmediate(int64_t imm) { 1295807ee2ffSSean Callanan Operand ret; 1296807ee2ffSSean Callanan ret.m_type = Type::Immediate; 1297807ee2ffSSean Callanan if (imm < 0) { 1298807ee2ffSSean Callanan ret.m_immediate = -imm; 1299807ee2ffSSean Callanan ret.m_negative = true; 1300807ee2ffSSean Callanan } else { 1301807ee2ffSSean Callanan ret.m_immediate = imm; 1302807ee2ffSSean Callanan ret.m_negative = false; 1303807ee2ffSSean Callanan } 1304807ee2ffSSean Callanan return ret; 1305807ee2ffSSean Callanan } 1306807ee2ffSSean Callanan 1307807ee2ffSSean Callanan Instruction::Operand 1308807ee2ffSSean Callanan Instruction::Operand::BuildDereference(const Operand &ref) { 1309807ee2ffSSean Callanan Operand ret; 1310807ee2ffSSean Callanan ret.m_type = Type::Dereference; 1311807ee2ffSSean Callanan ret.m_children = {ref}; 1312807ee2ffSSean Callanan return ret; 1313807ee2ffSSean Callanan } 1314807ee2ffSSean Callanan 1315807ee2ffSSean Callanan Instruction::Operand Instruction::Operand::BuildSum(const Operand &lhs, 1316807ee2ffSSean Callanan const Operand &rhs) { 1317807ee2ffSSean Callanan Operand ret; 1318807ee2ffSSean Callanan ret.m_type = Type::Sum; 1319807ee2ffSSean Callanan ret.m_children = {lhs, rhs}; 1320807ee2ffSSean Callanan return ret; 1321807ee2ffSSean Callanan } 1322807ee2ffSSean Callanan 1323807ee2ffSSean Callanan Instruction::Operand Instruction::Operand::BuildProduct(const Operand &lhs, 1324807ee2ffSSean Callanan const Operand &rhs) { 1325807ee2ffSSean Callanan Operand ret; 1326807ee2ffSSean Callanan ret.m_type = Type::Product; 1327807ee2ffSSean Callanan ret.m_children = {lhs, rhs}; 1328807ee2ffSSean Callanan return ret; 1329807ee2ffSSean Callanan } 1330807ee2ffSSean Callanan 1331807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> 1332807ee2ffSSean Callanan lldb_private::OperandMatchers::MatchBinaryOp( 1333807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> base, 1334807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> left, 1335807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> right) { 1336807ee2ffSSean Callanan return [base, left, right](const Instruction::Operand &op) -> bool { 1337807ee2ffSSean Callanan return (base(op) && op.m_children.size() == 2 && 1338807ee2ffSSean Callanan ((left(op.m_children[0]) && right(op.m_children[1])) || 1339807ee2ffSSean Callanan (left(op.m_children[1]) && right(op.m_children[0])))); 1340807ee2ffSSean Callanan }; 1341807ee2ffSSean Callanan } 1342807ee2ffSSean Callanan 1343807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> 1344807ee2ffSSean Callanan lldb_private::OperandMatchers::MatchUnaryOp( 1345807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> base, 1346807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> child) { 1347807ee2ffSSean Callanan return [base, child](const Instruction::Operand &op) -> bool { 1348807ee2ffSSean Callanan return (base(op) && op.m_children.size() == 1 && child(op.m_children[0])); 1349807ee2ffSSean Callanan }; 1350807ee2ffSSean Callanan } 1351807ee2ffSSean Callanan 1352807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> 1353807ee2ffSSean Callanan lldb_private::OperandMatchers::MatchRegOp(const RegisterInfo &info) { 1354807ee2ffSSean Callanan return [&info](const Instruction::Operand &op) { 1355807ee2ffSSean Callanan return (op.m_type == Instruction::Operand::Type::Register && 1356807ee2ffSSean Callanan (op.m_register == ConstString(info.name) || 1357807ee2ffSSean Callanan op.m_register == ConstString(info.alt_name))); 1358807ee2ffSSean Callanan }; 1359807ee2ffSSean Callanan } 1360807ee2ffSSean Callanan 1361807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> 1362561a9bbfSSean Callanan lldb_private::OperandMatchers::FetchRegOp(ConstString ®) { 1363561a9bbfSSean Callanan return [®](const Instruction::Operand &op) { 1364561a9bbfSSean Callanan if (op.m_type != Instruction::Operand::Type::Register) { 1365561a9bbfSSean Callanan return false; 1366561a9bbfSSean Callanan } 1367561a9bbfSSean Callanan reg = op.m_register; 1368561a9bbfSSean Callanan return true; 1369561a9bbfSSean Callanan }; 1370561a9bbfSSean Callanan } 1371561a9bbfSSean Callanan 1372561a9bbfSSean Callanan std::function<bool(const Instruction::Operand &)> 1373807ee2ffSSean Callanan lldb_private::OperandMatchers::MatchImmOp(int64_t imm) { 1374807ee2ffSSean Callanan return [imm](const Instruction::Operand &op) { 1375807ee2ffSSean Callanan return (op.m_type == Instruction::Operand::Type::Immediate && 1376807ee2ffSSean Callanan ((op.m_negative && op.m_immediate == (uint64_t)-imm) || 1377807ee2ffSSean Callanan (!op.m_negative && op.m_immediate == (uint64_t)imm))); 1378807ee2ffSSean Callanan }; 1379807ee2ffSSean Callanan } 1380807ee2ffSSean Callanan 1381807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> 1382807ee2ffSSean Callanan lldb_private::OperandMatchers::FetchImmOp(int64_t &imm) { 1383807ee2ffSSean Callanan return [&imm](const Instruction::Operand &op) { 1384807ee2ffSSean Callanan if (op.m_type != Instruction::Operand::Type::Immediate) { 1385807ee2ffSSean Callanan return false; 1386807ee2ffSSean Callanan } 1387807ee2ffSSean Callanan if (op.m_negative) { 1388807ee2ffSSean Callanan imm = -((int64_t)op.m_immediate); 1389807ee2ffSSean Callanan } else { 1390807ee2ffSSean Callanan imm = ((int64_t)op.m_immediate); 1391807ee2ffSSean Callanan } 1392807ee2ffSSean Callanan return true; 1393807ee2ffSSean Callanan }; 1394807ee2ffSSean Callanan } 1395807ee2ffSSean Callanan 1396807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> 1397807ee2ffSSean Callanan lldb_private::OperandMatchers::MatchOpType(Instruction::Operand::Type type) { 1398807ee2ffSSean Callanan return [type](const Instruction::Operand &op) { return op.m_type == type; }; 1399807ee2ffSSean Callanan } 1400