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