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 9204592d5bSPavel Labath DisassemblerSP Disassembler::FindPluginForTarget(const Target &target, 93b9c1b51eSKate Stone const ArchSpec &arch, 94b9c1b51eSKate Stone const char *flavor, 95b9c1b51eSKate Stone const char *plugin_name) { 9604592d5bSPavel Labath if (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) 10204592d5bSPavel Labath flavor = target.GetDisassemblyFlavor(); 1030f063ba6SJim Ingham } 1040f063ba6SJim Ingham return FindPlugin(arch, flavor, plugin_name); 1050f063ba6SJim Ingham } 1060f063ba6SJim Ingham 10792c0cda9SPavel Labath static Address ResolveAddress(Target &target, const Address &addr) { 108b9c1b51eSKate Stone if (!addr.IsSectionOffset()) { 10992c0cda9SPavel Labath Address resolved_addr; 11005097246SAdrian Prantl // If we weren't passed in a section offset address range, try and resolve 11105097246SAdrian Prantl // it to something 11204592d5bSPavel Labath bool is_resolved = target.GetSectionLoadList().IsEmpty() 11304592d5bSPavel Labath ? target.GetImages().ResolveFileAddress( 11404592d5bSPavel Labath addr.GetOffset(), resolved_addr) 11504592d5bSPavel Labath : target.GetSectionLoadList().ResolveLoadAddress( 11604592d5bSPavel Labath addr.GetOffset(), resolved_addr); 117a0fa299dSTatyana Krasnukha 11805097246SAdrian Prantl // We weren't able to resolve the address, just treat it as a raw address 119a0fa299dSTatyana Krasnukha if (is_resolved && resolved_addr.IsValid()) 12092c0cda9SPavel Labath return resolved_addr; 121357132ebSGreg Clayton } 12292c0cda9SPavel Labath return addr; 123357132ebSGreg Clayton } 124dda4f7b5SGreg Clayton 125b9c1b51eSKate Stone lldb::DisassemblerSP Disassembler::DisassembleRange( 126b9c1b51eSKate Stone const ArchSpec &arch, const char *plugin_name, const char *flavor, 12704592d5bSPavel Labath Target &target, const AddressRange &range, bool prefer_file_cache) { 12804592d5bSPavel Labath if (range.GetByteSize() <= 0) 1294be6706eSJonas Devlieghere return {}; 1301d273166SGreg Clayton 1314be6706eSJonas Devlieghere if (!range.GetBaseAddress().IsValid()) 1324be6706eSJonas Devlieghere return {}; 1334be6706eSJonas Devlieghere 13404592d5bSPavel Labath lldb::DisassemblerSP disasm_sp = 13504592d5bSPavel Labath Disassembler::FindPluginForTarget(target, arch, flavor, plugin_name); 1364be6706eSJonas Devlieghere 1374be6706eSJonas Devlieghere if (!disasm_sp) 1384be6706eSJonas Devlieghere return {}; 1394be6706eSJonas Devlieghere 140af3db4e9SPavel Labath const size_t bytes_disassembled = disasm_sp->ParseInstructions( 141af3db4e9SPavel Labath target, range.GetBaseAddress(), {Limit::Bytes, range.GetByteSize()}, 142af3db4e9SPavel Labath nullptr, prefer_file_cache); 1431d273166SGreg Clayton if (bytes_disassembled == 0) 1444be6706eSJonas Devlieghere return {}; 1454be6706eSJonas Devlieghere 1461d273166SGreg Clayton return disasm_sp; 1471d273166SGreg Clayton } 1481d273166SGreg Clayton 14950952e95SSean Callanan lldb::DisassemblerSP 150b9c1b51eSKate Stone Disassembler::DisassembleBytes(const ArchSpec &arch, const char *plugin_name, 151b9c1b51eSKate Stone const char *flavor, const Address &start, 152b9c1b51eSKate Stone const void *src, size_t src_len, 153b9c1b51eSKate Stone uint32_t num_instructions, bool data_from_file) { 1544be6706eSJonas Devlieghere if (!src) 1554be6706eSJonas Devlieghere return {}; 15650952e95SSean Callanan 1574be6706eSJonas Devlieghere lldb::DisassemblerSP disasm_sp = 1584be6706eSJonas Devlieghere Disassembler::FindPlugin(arch, flavor, plugin_name); 15950952e95SSean Callanan 1604be6706eSJonas Devlieghere if (!disasm_sp) 1614be6706eSJonas Devlieghere return {}; 1624be6706eSJonas Devlieghere 163b9c1b51eSKate Stone DataExtractor data(src, src_len, arch.GetByteOrder(), 164b9c1b51eSKate Stone arch.GetAddressByteSize()); 16550952e95SSean Callanan 1664be6706eSJonas Devlieghere (void)disasm_sp->DecodeInstructions(start, data, 0, num_instructions, false, 1674be6706eSJonas Devlieghere data_from_file); 16850952e95SSean Callanan return disasm_sp; 16950952e95SSean Callanan } 17050952e95SSean Callanan 171b9c1b51eSKate Stone bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch, 172b9c1b51eSKate Stone const char *plugin_name, const char *flavor, 173dda4f7b5SGreg Clayton const ExecutionContext &exe_ctx, 174af3db4e9SPavel Labath const Address &address, Limit limit, 1750b4c26b2SJason Molenda bool mixed_source_and_assembly, 176dda4f7b5SGreg Clayton uint32_t num_mixed_context_lines, 177b9c1b51eSKate Stone uint32_t options, Stream &strm) { 178af3db4e9SPavel Labath if (!exe_ctx.GetTargetPtr()) 1790910e17dSJonas Devlieghere return false; 1800910e17dSJonas Devlieghere 181b9c1b51eSKate Stone lldb::DisassemblerSP disasm_sp(Disassembler::FindPluginForTarget( 18204592d5bSPavel Labath exe_ctx.GetTargetRef(), arch, flavor, plugin_name)); 1830910e17dSJonas Devlieghere if (!disasm_sp) 1840910e17dSJonas Devlieghere return false; 1850910e17dSJonas Devlieghere 1863faf47c4SGreg Clayton const bool prefer_file_cache = false; 187b9c1b51eSKate Stone size_t bytes_disassembled = disasm_sp->ParseInstructions( 188af3db4e9SPavel Labath exe_ctx.GetTargetRef(), address, limit, &strm, prefer_file_cache); 18937023b06SJim Ingham if (bytes_disassembled == 0) 19037023b06SJim Ingham return false; 1910910e17dSJonas Devlieghere 192af3db4e9SPavel Labath disasm_sp->PrintInstructions(debugger, arch, exe_ctx, 193ea68462eSPavel Labath mixed_source_and_assembly, 1940b4c26b2SJason Molenda num_mixed_context_lines, options, strm); 195ea68462eSPavel Labath return true; 19637023b06SJim Ingham } 19737023b06SJim Ingham 1980b4c26b2SJason Molenda Disassembler::SourceLine 1990b4c26b2SJason Molenda Disassembler::GetFunctionDeclLineEntry(const SymbolContext &sc) { 2000910e17dSJonas Devlieghere if (!sc.function) 2010910e17dSJonas Devlieghere return {}; 2020910e17dSJonas Devlieghere 2030910e17dSJonas Devlieghere if (!sc.line_entry.IsValid()) 2040910e17dSJonas Devlieghere return {}; 2050910e17dSJonas Devlieghere 2060b4c26b2SJason Molenda LineEntry prologue_end_line = sc.line_entry; 2070b4c26b2SJason Molenda FileSpec func_decl_file; 2080b4c26b2SJason Molenda uint32_t func_decl_line; 2090b4c26b2SJason Molenda sc.function->GetStartLineSourceInfo(func_decl_file, func_decl_line); 2100910e17dSJonas Devlieghere 2110910e17dSJonas Devlieghere if (func_decl_file != prologue_end_line.file && 2120910e17dSJonas Devlieghere func_decl_file != prologue_end_line.original_file) 2130910e17dSJonas Devlieghere return {}; 2140910e17dSJonas Devlieghere 2150910e17dSJonas Devlieghere SourceLine decl_line; 2160b4c26b2SJason Molenda decl_line.file = func_decl_file; 2170b4c26b2SJason Molenda decl_line.line = func_decl_line; 2180910e17dSJonas Devlieghere // TODO: Do we care about column on these entries? If so, we need to plumb 2190910e17dSJonas Devlieghere // that through GetStartLineSourceInfo. 2209666ba75STodd Fiala decl_line.column = 0; 2210b4c26b2SJason Molenda return decl_line; 2220b4c26b2SJason Molenda } 2230b4c26b2SJason Molenda 2240b4c26b2SJason Molenda void Disassembler::AddLineToSourceLineTables( 2250b4c26b2SJason Molenda SourceLine &line, 2260b4c26b2SJason Molenda std::map<FileSpec, std::set<uint32_t>> &source_lines_seen) { 2270b4c26b2SJason Molenda if (line.IsValid()) { 2280b4c26b2SJason Molenda auto source_lines_seen_pos = source_lines_seen.find(line.file); 2290b4c26b2SJason Molenda if (source_lines_seen_pos == source_lines_seen.end()) { 2300b4c26b2SJason Molenda std::set<uint32_t> lines; 2310b4c26b2SJason Molenda lines.insert(line.line); 2320b4c26b2SJason Molenda source_lines_seen.emplace(line.file, lines); 2330b4c26b2SJason Molenda } else { 2340b4c26b2SJason Molenda source_lines_seen_pos->second.insert(line.line); 2350b4c26b2SJason Molenda } 2360b4c26b2SJason Molenda } 2370b4c26b2SJason Molenda } 2380b4c26b2SJason Molenda 2390b4c26b2SJason Molenda bool Disassembler::ElideMixedSourceAndDisassemblyLine( 2400b4c26b2SJason Molenda const ExecutionContext &exe_ctx, const SymbolContext &sc, 2410b4c26b2SJason Molenda SourceLine &line) { 2420b4c26b2SJason Molenda 2430b4c26b2SJason Molenda // TODO: should we also check target.process.thread.step-avoid-libraries ? 2440b4c26b2SJason Molenda 2450b4c26b2SJason Molenda const RegularExpression *avoid_regex = nullptr; 2460b4c26b2SJason Molenda 2470b4c26b2SJason Molenda // Skip any line #0 entries - they are implementation details 2480b4c26b2SJason Molenda if (line.line == 0) 2490b4c26b2SJason Molenda return false; 2500b4c26b2SJason Molenda 2510b4c26b2SJason Molenda ThreadSP thread_sp = exe_ctx.GetThreadSP(); 2520b4c26b2SJason Molenda if (thread_sp) { 2530b4c26b2SJason Molenda avoid_regex = thread_sp->GetSymbolsToAvoidRegexp(); 2540b4c26b2SJason Molenda } else { 2550b4c26b2SJason Molenda TargetSP target_sp = exe_ctx.GetTargetSP(); 2560b4c26b2SJason Molenda if (target_sp) { 25797206d57SZachary Turner Status error; 2580b4c26b2SJason Molenda OptionValueSP value_sp = target_sp->GetDebugger().GetPropertyValue( 2590b4c26b2SJason Molenda &exe_ctx, "target.process.thread.step-avoid-regexp", false, error); 2600b4c26b2SJason Molenda if (value_sp && value_sp->GetType() == OptionValue::eTypeRegex) { 2610b4c26b2SJason Molenda OptionValueRegex *re = value_sp->GetAsRegex(); 2620b4c26b2SJason Molenda if (re) { 2630b4c26b2SJason Molenda avoid_regex = re->GetCurrentValue(); 2640b4c26b2SJason Molenda } 2650b4c26b2SJason Molenda } 2660b4c26b2SJason Molenda } 2670b4c26b2SJason Molenda } 2680b4c26b2SJason Molenda if (avoid_regex && sc.symbol != nullptr) { 2690b4c26b2SJason Molenda const char *function_name = 2700b4c26b2SJason Molenda sc.GetFunctionName(Mangled::ePreferDemangledWithoutArguments) 2710b4c26b2SJason Molenda .GetCString(); 2723af3f1e8SJonas Devlieghere if (function_name && avoid_regex->Execute(function_name)) { 2730b4c26b2SJason Molenda // skip this source line 2740b4c26b2SJason Molenda return true; 2750b4c26b2SJason Molenda } 2760b4c26b2SJason Molenda } 2770b4c26b2SJason Molenda // don't skip this source line 2780b4c26b2SJason Molenda return false; 2790b4c26b2SJason Molenda } 2800b4c26b2SJason Molenda 281ea68462eSPavel Labath void Disassembler::PrintInstructions(Debugger &debugger, const ArchSpec &arch, 282b9c1b51eSKate Stone const ExecutionContext &exe_ctx, 2830b4c26b2SJason Molenda bool mixed_source_and_assembly, 284b9c1b51eSKate Stone uint32_t num_mixed_context_lines, 285b9c1b51eSKate Stone uint32_t options, Stream &strm) { 28630fdc8d8SChris Lattner // We got some things disassembled... 287ea68462eSPavel Labath size_t num_instructions_found = GetInstructionList().GetSize(); 28837023b06SJim Ingham 289b9c1b51eSKate Stone const uint32_t max_opcode_byte_size = 290ea68462eSPavel Labath GetInstructionList().GetMaxOpcocdeByteSize(); 29130fdc8d8SChris Lattner SymbolContext sc; 29230fdc8d8SChris Lattner SymbolContext prev_sc; 2930b4c26b2SJason Molenda AddressRange current_source_line_range; 29434ede34aSEugene Zelenko const Address *pc_addr_ptr = nullptr; 295b57e4a1bSJason Molenda StackFrame *frame = exe_ctx.GetFramePtr(); 296c14ee32dSGreg Clayton 2974b2967ffSMichael Sartain TargetSP target_sp(exe_ctx.GetTargetSP()); 298b9c1b51eSKate Stone SourceManager &source_manager = 299b9c1b51eSKate Stone target_sp ? target_sp->GetSourceManager() : debugger.GetSourceManager(); 3004b2967ffSMichael Sartain 301b9c1b51eSKate Stone if (frame) { 302c14ee32dSGreg Clayton pc_addr_ptr = &frame->GetFrameCodeAddress(); 303aff1b357SJason Molenda } 304b9c1b51eSKate Stone const uint32_t scope = 305b9c1b51eSKate Stone eSymbolContextLineEntry | eSymbolContextFunction | eSymbolContextSymbol; 3067e14f91dSGreg Clayton const bool use_inline_block_range = false; 307c980fa92SJason Molenda 30834ede34aSEugene Zelenko const FormatEntity::Entry *disassembly_format = nullptr; 309c980fa92SJason Molenda FormatEntity::Entry format; 310b9c1b51eSKate Stone if (exe_ctx.HasTargetScope()) { 311b9c1b51eSKate Stone disassembly_format = 312b9c1b51eSKate Stone exe_ctx.GetTargetRef().GetDebugger().GetDisassemblyFormat(); 313b9c1b51eSKate Stone } else { 314c980fa92SJason Molenda FormatEntity::Parse("${addr}: ", format); 315c980fa92SJason Molenda disassembly_format = &format; 316c980fa92SJason Molenda } 317c980fa92SJason Molenda 31805097246SAdrian Prantl // First pass: step through the list of instructions, find how long the 31905097246SAdrian Prantl // initial addresses strings are, insert padding in the second pass so the 32005097246SAdrian Prantl // opcodes all line up nicely. 3210b4c26b2SJason Molenda 3220b4c26b2SJason Molenda // Also build up the source line mapping if this is mixed source & assembly 32305097246SAdrian Prantl // mode. Calculate the source line for each assembly instruction (eliding 32405097246SAdrian Prantl // inlined functions which the user wants to skip). 3250b4c26b2SJason Molenda 3260b4c26b2SJason Molenda std::map<FileSpec, std::set<uint32_t>> source_lines_seen; 3270b4c26b2SJason Molenda Symbol *previous_symbol = nullptr; 3280b4c26b2SJason Molenda 329c980fa92SJason Molenda size_t address_text_size = 0; 330b9c1b51eSKate Stone for (size_t i = 0; i < num_instructions_found; ++i) { 331ea68462eSPavel Labath Instruction *inst = GetInstructionList().GetInstructionAtIndex(i).get(); 332b9c1b51eSKate Stone if (inst) { 333c980fa92SJason Molenda const Address &addr = inst->GetAddress(); 334c980fa92SJason Molenda ModuleSP module_sp(addr.GetModule()); 335b9c1b51eSKate Stone if (module_sp) { 336991e4453SZachary Turner const SymbolContextItem resolve_mask = eSymbolContextFunction | 3370b4c26b2SJason Molenda eSymbolContextSymbol | 3380b4c26b2SJason Molenda eSymbolContextLineEntry; 339b9c1b51eSKate Stone uint32_t resolved_mask = 340b9c1b51eSKate Stone module_sp->ResolveSymbolContextForAddress(addr, resolve_mask, sc); 341b9c1b51eSKate Stone if (resolved_mask) { 342c980fa92SJason Molenda StreamString strmstr; 343b9c1b51eSKate Stone Debugger::FormatDisassemblerAddress(disassembly_format, &sc, nullptr, 344b9c1b51eSKate Stone &exe_ctx, &addr, strmstr); 345c980fa92SJason Molenda size_t cur_line = strmstr.GetSizeOfLastLine(); 346c980fa92SJason Molenda if (cur_line > address_text_size) 347c980fa92SJason Molenda address_text_size = cur_line; 3480b4c26b2SJason Molenda 3490b4c26b2SJason Molenda // Add entries to our "source_lines_seen" map+set which list which 3500b4c26b2SJason Molenda // sources lines occur in this disassembly session. We will print 3510b4c26b2SJason Molenda // lines of context around a source line, but we don't want to print 3520b4c26b2SJason Molenda // a source line that has a line table entry of its own - we'll leave 3530b4c26b2SJason Molenda // that source line to be printed when it actually occurs in the 3540b4c26b2SJason Molenda // disassembly. 3550b4c26b2SJason Molenda 3560b4c26b2SJason Molenda if (mixed_source_and_assembly && sc.line_entry.IsValid()) { 3570b4c26b2SJason Molenda if (sc.symbol != previous_symbol) { 3580b4c26b2SJason Molenda SourceLine decl_line = GetFunctionDeclLineEntry(sc); 359a6682a41SJonas Devlieghere if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, decl_line)) 3600b4c26b2SJason Molenda AddLineToSourceLineTables(decl_line, source_lines_seen); 3610b4c26b2SJason Molenda } 3620b4c26b2SJason Molenda if (sc.line_entry.IsValid()) { 3630b4c26b2SJason Molenda SourceLine this_line; 3640b4c26b2SJason Molenda this_line.file = sc.line_entry.file; 3650b4c26b2SJason Molenda this_line.line = sc.line_entry.line; 3669666ba75STodd Fiala this_line.column = sc.line_entry.column; 367a6682a41SJonas Devlieghere if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, this_line)) 3680b4c26b2SJason Molenda AddLineToSourceLineTables(this_line, source_lines_seen); 3690b4c26b2SJason Molenda } 3700b4c26b2SJason Molenda } 371c980fa92SJason Molenda } 372c980fa92SJason Molenda sc.Clear(false); 373c980fa92SJason Molenda } 374c980fa92SJason Molenda } 375c980fa92SJason Molenda } 376c980fa92SJason Molenda 3770b4c26b2SJason Molenda previous_symbol = nullptr; 3780b4c26b2SJason Molenda SourceLine previous_line; 379b9c1b51eSKate Stone for (size_t i = 0; i < num_instructions_found; ++i) { 380ea68462eSPavel Labath Instruction *inst = GetInstructionList().GetInstructionAtIndex(i).get(); 3810b4c26b2SJason Molenda 382b9c1b51eSKate Stone if (inst) { 38332e0a750SGreg Clayton const Address &addr = inst->GetAddress(); 38432e0a750SGreg Clayton const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr; 3850b4c26b2SJason Molenda SourceLinesToDisplay source_lines_to_display; 386dda4f7b5SGreg Clayton 38730fdc8d8SChris Lattner prev_sc = sc; 388dda4f7b5SGreg Clayton 389e72dfb32SGreg Clayton ModuleSP module_sp(addr.GetModule()); 390b9c1b51eSKate Stone if (module_sp) { 391b9c1b51eSKate Stone uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress( 392b9c1b51eSKate Stone addr, eSymbolContextEverything, sc); 393b9c1b51eSKate Stone if (resolved_mask) { 3940b4c26b2SJason Molenda if (mixed_source_and_assembly) { 395dda4f7b5SGreg Clayton 3960b4c26b2SJason Molenda // If we've started a new function (non-inlined), print all of the 39705097246SAdrian Prantl // source lines from the function declaration until the first line 39805097246SAdrian Prantl // table entry - typically the opening curly brace of the function. 3990b4c26b2SJason Molenda if (previous_symbol != sc.symbol) { 40005097246SAdrian Prantl // The default disassembly format puts an extra blank line 40105097246SAdrian Prantl // between functions - so when we're displaying the source 40205097246SAdrian Prantl // context for a function, we don't want to add a blank line 40305097246SAdrian Prantl // after the source context or we'll end up with two of them. 4040b4c26b2SJason Molenda if (previous_symbol != nullptr) 4050b4c26b2SJason Molenda source_lines_to_display.print_source_context_end_eol = false; 40630fdc8d8SChris Lattner 4070b4c26b2SJason Molenda previous_symbol = sc.symbol; 4080b4c26b2SJason Molenda if (sc.function && sc.line_entry.IsValid()) { 4090b4c26b2SJason Molenda LineEntry prologue_end_line = sc.line_entry; 410a6682a41SJonas Devlieghere if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, 411a6682a41SJonas Devlieghere prologue_end_line)) { 4120b4c26b2SJason Molenda FileSpec func_decl_file; 4130b4c26b2SJason Molenda uint32_t func_decl_line; 4140b4c26b2SJason Molenda sc.function->GetStartLineSourceInfo(func_decl_file, 4150b4c26b2SJason Molenda func_decl_line); 4160b4c26b2SJason Molenda if (func_decl_file == prologue_end_line.file || 4170b4c26b2SJason Molenda func_decl_file == prologue_end_line.original_file) { 41805097246SAdrian Prantl // Add all the lines between the function declaration and 41905097246SAdrian Prantl // the first non-prologue source line to the list of lines 42005097246SAdrian Prantl // to print. 4210b4c26b2SJason Molenda for (uint32_t lineno = func_decl_line; 4220b4c26b2SJason Molenda lineno <= prologue_end_line.line; lineno++) { 4230b4c26b2SJason Molenda SourceLine this_line; 4240b4c26b2SJason Molenda this_line.file = func_decl_file; 4250b4c26b2SJason Molenda this_line.line = lineno; 4260b4c26b2SJason Molenda source_lines_to_display.lines.push_back(this_line); 4270b4c26b2SJason Molenda } 42805097246SAdrian Prantl // Mark the last line as the "current" one. Usually this 42905097246SAdrian Prantl // is the open curly brace. 4300b4c26b2SJason Molenda if (source_lines_to_display.lines.size() > 0) 4310b4c26b2SJason Molenda source_lines_to_display.current_source_line = 4320b4c26b2SJason Molenda source_lines_to_display.lines.size() - 1; 4330b4c26b2SJason Molenda } 4340b4c26b2SJason Molenda } 4350b4c26b2SJason Molenda } 4360b4c26b2SJason Molenda sc.GetAddressRange(scope, 0, use_inline_block_range, 4370b4c26b2SJason Molenda current_source_line_range); 4380b4c26b2SJason Molenda } 43930fdc8d8SChris Lattner 44005097246SAdrian Prantl // If we've left a previous source line's address range, print a 44105097246SAdrian Prantl // new source line 4420b4c26b2SJason Molenda if (!current_source_line_range.ContainsFileAddress(addr)) { 4430b4c26b2SJason Molenda sc.GetAddressRange(scope, 0, use_inline_block_range, 4440b4c26b2SJason Molenda current_source_line_range); 4450b4c26b2SJason Molenda 4460b4c26b2SJason Molenda if (sc != prev_sc && sc.comp_unit && sc.line_entry.IsValid()) { 4470b4c26b2SJason Molenda SourceLine this_line; 4480b4c26b2SJason Molenda this_line.file = sc.line_entry.file; 4490b4c26b2SJason Molenda this_line.line = sc.line_entry.line; 4500b4c26b2SJason Molenda 451a6682a41SJonas Devlieghere if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, 452a6682a41SJonas Devlieghere this_line)) { 4530b4c26b2SJason Molenda // Only print this source line if it is different from the 4540b4c26b2SJason Molenda // last source line we printed. There may have been inlined 4550b4c26b2SJason Molenda // functions between these lines that we elided, resulting in 45605097246SAdrian Prantl // the same line being printed twice in a row for a 45705097246SAdrian Prantl // contiguous block of assembly instructions. 4580b4c26b2SJason Molenda if (this_line != previous_line) { 4590b4c26b2SJason Molenda 4600b4c26b2SJason Molenda std::vector<uint32_t> previous_lines; 4617771462bSEd Maste for (uint32_t i = 0; 4620b4c26b2SJason Molenda i < num_mixed_context_lines && 4630b4c26b2SJason Molenda (this_line.line - num_mixed_context_lines) > 0; 4640b4c26b2SJason Molenda i++) { 4650b4c26b2SJason Molenda uint32_t line = 4660b4c26b2SJason Molenda this_line.line - num_mixed_context_lines + i; 4670b4c26b2SJason Molenda auto pos = source_lines_seen.find(this_line.file); 4680b4c26b2SJason Molenda if (pos != source_lines_seen.end()) { 4690b4c26b2SJason Molenda if (pos->second.count(line) == 1) { 4700b4c26b2SJason Molenda previous_lines.clear(); 4710b4c26b2SJason Molenda } else { 4720b4c26b2SJason Molenda previous_lines.push_back(line); 4730b4c26b2SJason Molenda } 4740b4c26b2SJason Molenda } 4750b4c26b2SJason Molenda } 4760b4c26b2SJason Molenda for (size_t i = 0; i < previous_lines.size(); i++) { 4770b4c26b2SJason Molenda SourceLine previous_line; 4780b4c26b2SJason Molenda previous_line.file = this_line.file; 4790b4c26b2SJason Molenda previous_line.line = previous_lines[i]; 4800b4c26b2SJason Molenda auto pos = source_lines_seen.find(previous_line.file); 4810b4c26b2SJason Molenda if (pos != source_lines_seen.end()) { 4820b4c26b2SJason Molenda pos->second.insert(previous_line.line); 4830b4c26b2SJason Molenda } 4840b4c26b2SJason Molenda source_lines_to_display.lines.push_back(previous_line); 4850b4c26b2SJason Molenda } 4860b4c26b2SJason Molenda 4870b4c26b2SJason Molenda source_lines_to_display.lines.push_back(this_line); 4880b4c26b2SJason Molenda source_lines_to_display.current_source_line = 4890b4c26b2SJason Molenda source_lines_to_display.lines.size() - 1; 4900b4c26b2SJason Molenda 4917771462bSEd Maste for (uint32_t i = 0; i < num_mixed_context_lines; i++) { 4920b4c26b2SJason Molenda SourceLine next_line; 4930b4c26b2SJason Molenda next_line.file = this_line.file; 4940b4c26b2SJason Molenda next_line.line = this_line.line + i + 1; 4950b4c26b2SJason Molenda auto pos = source_lines_seen.find(next_line.file); 4960b4c26b2SJason Molenda if (pos != source_lines_seen.end()) { 4970b4c26b2SJason Molenda if (pos->second.count(next_line.line) == 1) 4980b4c26b2SJason Molenda break; 4990b4c26b2SJason Molenda pos->second.insert(next_line.line); 5000b4c26b2SJason Molenda } 5010b4c26b2SJason Molenda source_lines_to_display.lines.push_back(next_line); 5020b4c26b2SJason Molenda } 5030b4c26b2SJason Molenda } 5040b4c26b2SJason Molenda previous_line = this_line; 50530fdc8d8SChris Lattner } 50630fdc8d8SChris Lattner } 50730fdc8d8SChris Lattner } 50830fdc8d8SChris Lattner } 509b9c1b51eSKate Stone } else { 51072310355SGreg Clayton sc.Clear(true); 51130fdc8d8SChris Lattner } 51230fdc8d8SChris Lattner } 51332e0a750SGreg Clayton 5140b4c26b2SJason Molenda if (source_lines_to_display.lines.size() > 0) { 5150b4c26b2SJason Molenda strm.EOL(); 5160b4c26b2SJason Molenda for (size_t idx = 0; idx < source_lines_to_display.lines.size(); 5170b4c26b2SJason Molenda idx++) { 5180b4c26b2SJason Molenda SourceLine ln = source_lines_to_display.lines[idx]; 5190b4c26b2SJason Molenda const char *line_highlight = ""; 5200b4c26b2SJason Molenda if (inst_is_at_pc && (options & eOptionMarkPCSourceLine)) { 5210b4c26b2SJason Molenda line_highlight = "->"; 5220b4c26b2SJason Molenda } else if (idx == source_lines_to_display.current_source_line) { 5230b4c26b2SJason Molenda line_highlight = "**"; 5240b4c26b2SJason Molenda } 5250b4c26b2SJason Molenda source_manager.DisplaySourceLinesWithLineNumbers( 5269666ba75STodd Fiala ln.file, ln.line, ln.column, 0, 0, line_highlight, &strm); 5270b4c26b2SJason Molenda } 5280b4c26b2SJason Molenda if (source_lines_to_display.print_source_context_end_eol) 5290b4c26b2SJason Molenda strm.EOL(); 5300b4c26b2SJason Molenda } 5310b4c26b2SJason Molenda 5321da6f9d7SGreg Clayton const bool show_bytes = (options & eOptionShowBytes) != 0; 533b9c1b51eSKate Stone inst->Dump(&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx, &sc, 534b9c1b51eSKate Stone &prev_sc, nullptr, address_text_size); 53530fdc8d8SChris Lattner strm.EOL(); 536b9c1b51eSKate Stone } else { 53730fdc8d8SChris Lattner break; 53830fdc8d8SChris Lattner } 53930fdc8d8SChris Lattner } 54030fdc8d8SChris Lattner } 54130fdc8d8SChris Lattner 542b9c1b51eSKate Stone bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch, 543826997c4SJonas Devlieghere StackFrame &frame, Stream &strm) { 544dda4f7b5SGreg Clayton AddressRange range; 545b9c1b51eSKate Stone SymbolContext sc( 546826997c4SJonas Devlieghere frame.GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol)); 547b9c1b51eSKate Stone if (sc.function) { 548dda4f7b5SGreg Clayton range = sc.function->GetAddressRange(); 549b9c1b51eSKate Stone } else if (sc.symbol && sc.symbol->ValueIsAddress()) { 550358cf1eaSGreg Clayton range.GetBaseAddress() = sc.symbol->GetAddressRef(); 551e7612134SGreg Clayton range.SetByteSize(sc.symbol->GetByteSize()); 552b9c1b51eSKate Stone } else { 553826997c4SJonas Devlieghere range.GetBaseAddress() = frame.GetFrameCodeAddress(); 554dda4f7b5SGreg Clayton } 555dda4f7b5SGreg Clayton 556dda4f7b5SGreg Clayton if (range.GetBaseAddress().IsValid() && range.GetByteSize() == 0) 557dda4f7b5SGreg Clayton range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE); 558dda4f7b5SGreg Clayton 559826997c4SJonas Devlieghere Disassembler::Limit limit = {Disassembler::Limit::Bytes, 560826997c4SJonas Devlieghere range.GetByteSize()}; 561826997c4SJonas Devlieghere if (limit.value == 0) 562826997c4SJonas Devlieghere limit.value = DEFAULT_DISASM_BYTE_SIZE; 563826997c4SJonas Devlieghere 564826997c4SJonas Devlieghere return Disassemble(debugger, arch, nullptr, nullptr, frame, 565826997c4SJonas Devlieghere range.GetBaseAddress(), limit, false, 0, 0, strm); 566dda4f7b5SGreg Clayton } 567dda4f7b5SGreg Clayton 568b9c1b51eSKate Stone Instruction::Instruction(const Address &address, AddressClass addr_class) 569b9c1b51eSKate Stone : m_address(address), m_address_class(addr_class), m_opcode(), 570b9c1b51eSKate Stone m_calculated_strings(false) {} 57130fdc8d8SChris Lattner 57234ede34aSEugene Zelenko Instruction::~Instruction() = default; 57330fdc8d8SChris Lattner 574b9c1b51eSKate Stone AddressClass Instruction::GetAddressClass() { 57504803b3eSTatyana Krasnukha if (m_address_class == AddressClass::eInvalid) 576357132ebSGreg Clayton m_address_class = m_address.GetAddressClass(); 577357132ebSGreg Clayton return m_address_class; 578357132ebSGreg Clayton } 57930fdc8d8SChris Lattner 580b9c1b51eSKate Stone void Instruction::Dump(lldb_private::Stream *s, uint32_t max_opcode_byte_size, 581b9c1b51eSKate Stone bool show_address, bool show_bytes, 582aff1b357SJason Molenda const ExecutionContext *exe_ctx, 583aff1b357SJason Molenda const SymbolContext *sym_ctx, 584aff1b357SJason Molenda const SymbolContext *prev_sym_ctx, 585c980fa92SJason Molenda const FormatEntity::Entry *disassembly_addr_format, 586b9c1b51eSKate Stone size_t max_address_text_size) { 5877a37c1ecSJason Molenda size_t opcode_column_width = 7; 588ba812f42SGreg Clayton const size_t operand_column_width = 25; 589ba812f42SGreg Clayton 590ba812f42SGreg Clayton CalculateMnemonicOperandsAndCommentIfNeeded(exe_ctx); 591ba812f42SGreg Clayton 592ba812f42SGreg Clayton StreamString ss; 593ba812f42SGreg Clayton 594b9c1b51eSKate Stone if (show_address) { 595b9c1b51eSKate Stone Debugger::FormatDisassemblerAddress(disassembly_addr_format, sym_ctx, 596b9c1b51eSKate Stone prev_sym_ctx, exe_ctx, &m_address, ss); 597c980fa92SJason Molenda ss.FillLastLineToColumn(max_address_text_size, ' '); 598ba812f42SGreg Clayton } 599ba812f42SGreg Clayton 600b9c1b51eSKate Stone if (show_bytes) { 601b9c1b51eSKate Stone if (m_opcode.GetType() == Opcode::eTypeBytes) { 60205097246SAdrian Prantl // x86_64 and i386 are the only ones that use bytes right now so pad out 60305097246SAdrian Prantl // the byte dump to be able to always show 15 bytes (3 chars each) plus a 60405097246SAdrian Prantl // space 605ba812f42SGreg Clayton if (max_opcode_byte_size > 0) 606ba812f42SGreg Clayton m_opcode.Dump(&ss, max_opcode_byte_size * 3 + 1); 607ba812f42SGreg Clayton else 608ba812f42SGreg Clayton m_opcode.Dump(&ss, 15 * 3 + 1); 609b9c1b51eSKate Stone } else { 61005097246SAdrian Prantl // Else, we have ARM or MIPS which can show up to a uint32_t 0x00000000 61105097246SAdrian Prantl // (10 spaces) plus two for padding... 612ba812f42SGreg Clayton if (max_opcode_byte_size > 0) 613ba812f42SGreg Clayton m_opcode.Dump(&ss, max_opcode_byte_size * 3 + 1); 614ba812f42SGreg Clayton else 615ba812f42SGreg Clayton m_opcode.Dump(&ss, 12); 616ba812f42SGreg Clayton } 617ba812f42SGreg Clayton } 618ba812f42SGreg Clayton 619aff1b357SJason Molenda const size_t opcode_pos = ss.GetSizeOfLastLine(); 620ba812f42SGreg Clayton 6217a37c1ecSJason Molenda // The default opcode size of 7 characters is plenty for most architectures 6227a37c1ecSJason Molenda // but some like arm can pull out the occasional vqrshrun.s16. We won't get 6237a37c1ecSJason Molenda // consistent column spacing in these cases, unfortunately. 624b9c1b51eSKate Stone if (m_opcode_name.length() >= opcode_column_width) { 6257a37c1ecSJason Molenda opcode_column_width = m_opcode_name.length() + 1; 6267a37c1ecSJason Molenda } 6277a37c1ecSJason Molenda 628771ef6d4SMalcolm Parsons ss.PutCString(m_opcode_name); 629ba812f42SGreg Clayton ss.FillLastLineToColumn(opcode_pos + opcode_column_width, ' '); 630771ef6d4SMalcolm Parsons ss.PutCString(m_mnemonics); 631ba812f42SGreg Clayton 632b9c1b51eSKate Stone if (!m_comment.empty()) { 633b9c1b51eSKate Stone ss.FillLastLineToColumn( 634b9c1b51eSKate Stone opcode_pos + opcode_column_width + operand_column_width, ' '); 635ba812f42SGreg Clayton ss.PutCString(" ; "); 636771ef6d4SMalcolm Parsons ss.PutCString(m_comment); 637ba812f42SGreg Clayton } 638c156427dSZachary Turner s->PutCString(ss.GetString()); 639ba812f42SGreg Clayton } 640ba812f42SGreg Clayton 641b9c1b51eSKate Stone bool Instruction::DumpEmulation(const ArchSpec &arch) { 642d5b44036SJonas Devlieghere std::unique_ptr<EmulateInstruction> insn_emulator_up( 643b9c1b51eSKate Stone EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr)); 644d5b44036SJonas Devlieghere if (insn_emulator_up) { 645d5b44036SJonas Devlieghere insn_emulator_up->SetInstruction(GetOpcode(), GetAddress(), nullptr); 646d5b44036SJonas Devlieghere return insn_emulator_up->EvaluateInstruction(0); 6477c9dd3ceSCaroline Tice } 6487c9dd3ceSCaroline Tice 6497c9dd3ceSCaroline Tice return false; 6507c9dd3ceSCaroline Tice } 6517c9dd3ceSCaroline Tice 652dd125943SNitesh Jain bool Instruction::CanSetBreakpoint () { 653dd125943SNitesh Jain return !HasDelaySlot(); 654dd125943SNitesh Jain } 655dd125943SNitesh Jain 656b9c1b51eSKate Stone bool Instruction::HasDelaySlot() { 6577f3daedaSBhushan D. Attarde // Default is false. 6587f3daedaSBhushan D. Attarde return false; 6597f3daedaSBhushan D. Attarde } 6607f3daedaSBhushan D. Attarde 661b9c1b51eSKate Stone OptionValueSP Instruction::ReadArray(FILE *in_file, Stream *out_stream, 662b9c1b51eSKate Stone OptionValue::Type data_type) { 663de2fb9cfSCaroline Tice bool done = false; 664de2fb9cfSCaroline Tice char buffer[1024]; 665de2fb9cfSCaroline Tice 6662f3df613SZachary Turner auto option_value_sp = std::make_shared<OptionValueArray>(1u << data_type); 667de2fb9cfSCaroline Tice 668de2fb9cfSCaroline Tice int idx = 0; 669b9c1b51eSKate Stone while (!done) { 670b9c1b51eSKate Stone if (!fgets(buffer, 1023, in_file)) { 671b9c1b51eSKate Stone out_stream->Printf( 672b9c1b51eSKate Stone "Instruction::ReadArray: Error reading file (fgets).\n"); 673de2fb9cfSCaroline Tice option_value_sp.reset(); 674de2fb9cfSCaroline Tice return option_value_sp; 675de2fb9cfSCaroline Tice } 676de2fb9cfSCaroline Tice 677de2fb9cfSCaroline Tice std::string line(buffer); 678de2fb9cfSCaroline Tice 679c7bece56SGreg Clayton size_t len = line.size(); 680b9c1b51eSKate Stone if (line[len - 1] == '\n') { 681de2fb9cfSCaroline Tice line[len - 1] = '\0'; 682de2fb9cfSCaroline Tice line.resize(len - 1); 683de2fb9cfSCaroline Tice } 684de2fb9cfSCaroline Tice 685b9c1b51eSKate Stone if ((line.size() == 1) && line[0] == ']') { 686de2fb9cfSCaroline Tice done = true; 687de2fb9cfSCaroline Tice line.clear(); 688de2fb9cfSCaroline Tice } 689de2fb9cfSCaroline Tice 690b9c1b51eSKate Stone if (!line.empty()) { 691de2fb9cfSCaroline Tice std::string value; 69295eae423SZachary Turner static RegularExpression g_reg_exp( 69395eae423SZachary Turner llvm::StringRef("^[ \t]*([^ \t]+)[ \t]*$")); 6943af3f1e8SJonas Devlieghere llvm::SmallVector<llvm::StringRef, 2> matches; 6953af3f1e8SJonas Devlieghere if (g_reg_exp.Execute(line, &matches)) 6963af3f1e8SJonas Devlieghere value = matches[1].str(); 697de2fb9cfSCaroline Tice else 698de2fb9cfSCaroline Tice value = line; 699de2fb9cfSCaroline Tice 700de2fb9cfSCaroline Tice OptionValueSP data_value_sp; 701b9c1b51eSKate Stone switch (data_type) { 702de2fb9cfSCaroline Tice case OptionValue::eTypeUInt64: 7032f3df613SZachary Turner data_value_sp = std::make_shared<OptionValueUInt64>(0, 0); 704c95f7e2aSPavel Labath data_value_sp->SetValueFromString(value); 705de2fb9cfSCaroline Tice break; 706de2fb9cfSCaroline Tice // Other types can be added later as needed. 707de2fb9cfSCaroline Tice default: 7082f3df613SZachary Turner data_value_sp = std::make_shared<OptionValueString>(value.c_str(), ""); 709de2fb9cfSCaroline Tice break; 710de2fb9cfSCaroline Tice } 711de2fb9cfSCaroline Tice 71284c39663SGreg Clayton option_value_sp->GetAsArray()->InsertValue(idx, data_value_sp); 713de2fb9cfSCaroline Tice ++idx; 714de2fb9cfSCaroline Tice } 715de2fb9cfSCaroline Tice } 716de2fb9cfSCaroline Tice 717de2fb9cfSCaroline Tice return option_value_sp; 718de2fb9cfSCaroline Tice } 719de2fb9cfSCaroline Tice 720b9c1b51eSKate Stone OptionValueSP Instruction::ReadDictionary(FILE *in_file, Stream *out_stream) { 721de2fb9cfSCaroline Tice bool done = false; 722de2fb9cfSCaroline Tice char buffer[1024]; 723de2fb9cfSCaroline Tice 7242f3df613SZachary Turner auto option_value_sp = std::make_shared<OptionValueDictionary>(); 725de2fb9cfSCaroline Tice static ConstString encoding_key("data_encoding"); 726de2fb9cfSCaroline Tice OptionValue::Type data_type = OptionValue::eTypeInvalid; 727de2fb9cfSCaroline Tice 728b9c1b51eSKate Stone while (!done) { 729de2fb9cfSCaroline Tice // Read the next line in the file 730b9c1b51eSKate Stone if (!fgets(buffer, 1023, in_file)) { 731b9c1b51eSKate Stone out_stream->Printf( 732b9c1b51eSKate Stone "Instruction::ReadDictionary: Error reading file (fgets).\n"); 733de2fb9cfSCaroline Tice option_value_sp.reset(); 734de2fb9cfSCaroline Tice return option_value_sp; 735de2fb9cfSCaroline Tice } 736de2fb9cfSCaroline Tice 737de2fb9cfSCaroline Tice // Check to see if the line contains the end-of-dictionary marker ("}") 738de2fb9cfSCaroline Tice std::string line(buffer); 739de2fb9cfSCaroline Tice 740c7bece56SGreg Clayton size_t len = line.size(); 741b9c1b51eSKate Stone if (line[len - 1] == '\n') { 742de2fb9cfSCaroline Tice line[len - 1] = '\0'; 743de2fb9cfSCaroline Tice line.resize(len - 1); 744de2fb9cfSCaroline Tice } 745de2fb9cfSCaroline Tice 746b9c1b51eSKate Stone if ((line.size() == 1) && (line[0] == '}')) { 747de2fb9cfSCaroline Tice done = true; 748de2fb9cfSCaroline Tice line.clear(); 749de2fb9cfSCaroline Tice } 750de2fb9cfSCaroline Tice 751b9c1b51eSKate Stone // Try to find a key-value pair in the current line and add it to the 752b9c1b51eSKate Stone // dictionary. 753b9c1b51eSKate Stone if (!line.empty()) { 75495eae423SZachary Turner static RegularExpression g_reg_exp(llvm::StringRef( 75595eae423SZachary Turner "^[ \t]*([a-zA-Z_][a-zA-Z0-9_]*)[ \t]*=[ \t]*(.*)[ \t]*$")); 756bc43cab5SGreg Clayton 7573af3f1e8SJonas Devlieghere llvm::SmallVector<llvm::StringRef, 3> matches; 7583af3f1e8SJonas Devlieghere 7593af3f1e8SJonas Devlieghere bool reg_exp_success = g_reg_exp.Execute(line, &matches); 760de2fb9cfSCaroline Tice std::string key; 761de2fb9cfSCaroline Tice std::string value; 762b9c1b51eSKate Stone if (reg_exp_success) { 7633af3f1e8SJonas Devlieghere key = matches[1].str(); 7643af3f1e8SJonas Devlieghere value = matches[2].str(); 765b9c1b51eSKate Stone } else { 766b9c1b51eSKate Stone out_stream->Printf("Instruction::ReadDictionary: Failure executing " 767b9c1b51eSKate Stone "regular expression.\n"); 768de2fb9cfSCaroline Tice option_value_sp.reset(); 769de2fb9cfSCaroline Tice return option_value_sp; 770de2fb9cfSCaroline Tice } 771de2fb9cfSCaroline Tice 772de2fb9cfSCaroline Tice ConstString const_key(key.c_str()); 773de2fb9cfSCaroline Tice // Check value to see if it's the start of an array or dictionary. 774de2fb9cfSCaroline Tice 775de2fb9cfSCaroline Tice lldb::OptionValueSP value_sp; 776de2fb9cfSCaroline Tice assert(value.empty() == false); 777de2fb9cfSCaroline Tice assert(key.empty() == false); 778de2fb9cfSCaroline Tice 779b9c1b51eSKate Stone if (value[0] == '{') { 780de2fb9cfSCaroline Tice assert(value.size() == 1); 781de2fb9cfSCaroline Tice // value is a dictionary 782de2fb9cfSCaroline Tice value_sp = ReadDictionary(in_file, out_stream); 783b9c1b51eSKate Stone if (!value_sp) { 784de2fb9cfSCaroline Tice option_value_sp.reset(); 785de2fb9cfSCaroline Tice return option_value_sp; 786de2fb9cfSCaroline Tice } 787b9c1b51eSKate Stone } else if (value[0] == '[') { 788de2fb9cfSCaroline Tice assert(value.size() == 1); 789de2fb9cfSCaroline Tice // value is an array 790de2fb9cfSCaroline Tice value_sp = ReadArray(in_file, out_stream, data_type); 791b9c1b51eSKate Stone if (!value_sp) { 792de2fb9cfSCaroline Tice option_value_sp.reset(); 793de2fb9cfSCaroline Tice return option_value_sp; 794de2fb9cfSCaroline Tice } 79505097246SAdrian Prantl // We've used the data_type to read an array; re-set the type to 79605097246SAdrian Prantl // Invalid 797de2fb9cfSCaroline Tice data_type = OptionValue::eTypeInvalid; 798b9c1b51eSKate Stone } else if ((value[0] == '0') && (value[1] == 'x')) { 7992f3df613SZachary Turner value_sp = std::make_shared<OptionValueUInt64>(0, 0); 800c95f7e2aSPavel Labath value_sp->SetValueFromString(value); 801b9c1b51eSKate Stone } else { 802c7bece56SGreg Clayton size_t len = value.size(); 803de2fb9cfSCaroline Tice if ((value[0] == '"') && (value[len - 1] == '"')) 804de2fb9cfSCaroline Tice value = value.substr(1, len - 2); 8052f3df613SZachary Turner value_sp = std::make_shared<OptionValueString>(value.c_str(), ""); 806de2fb9cfSCaroline Tice } 807de2fb9cfSCaroline Tice 808b9c1b51eSKate Stone if (const_key == encoding_key) { 809b9c1b51eSKate Stone // A 'data_encoding=..." is NOT a normal key-value pair; it is meta-data 810b9c1b51eSKate Stone // indicating the 811b9c1b51eSKate Stone // data type of an upcoming array (usually the next bit of data to be 812b9c1b51eSKate Stone // read in). 813de2fb9cfSCaroline Tice if (strcmp(value.c_str(), "uint32_t") == 0) 814de2fb9cfSCaroline Tice data_type = OptionValue::eTypeUInt64; 815b9c1b51eSKate Stone } else 816b9c1b51eSKate Stone option_value_sp->GetAsDictionary()->SetValueForKey(const_key, value_sp, 817b9c1b51eSKate Stone false); 818de2fb9cfSCaroline Tice } 819de2fb9cfSCaroline Tice } 820de2fb9cfSCaroline Tice 821de2fb9cfSCaroline Tice return option_value_sp; 822de2fb9cfSCaroline Tice } 823de2fb9cfSCaroline Tice 824b9c1b51eSKate Stone bool Instruction::TestEmulation(Stream *out_stream, const char *file_name) { 8253ac6711aSCaroline Tice if (!out_stream) 8263ac6711aSCaroline Tice return false; 8273ac6711aSCaroline Tice 828b9c1b51eSKate Stone if (!file_name) { 829ea80ba8bSJohnny Chen out_stream->Printf("Instruction::TestEmulation: Missing file_name."); 8303ac6711aSCaroline Tice return false; 8313ac6711aSCaroline Tice } 83246376966SJonas Devlieghere FILE *test_file = FileSystem::Instance().Fopen(file_name, "r"); 833b9c1b51eSKate Stone if (!test_file) { 834b9c1b51eSKate Stone out_stream->Printf( 835b9c1b51eSKate Stone "Instruction::TestEmulation: Attempt to open test file failed."); 8363ac6711aSCaroline Tice return false; 8373ac6711aSCaroline Tice } 8383ac6711aSCaroline Tice 8393ac6711aSCaroline Tice char buffer[256]; 840b9c1b51eSKate Stone if (!fgets(buffer, 255, test_file)) { 841b9c1b51eSKate Stone out_stream->Printf( 842b9c1b51eSKate Stone "Instruction::TestEmulation: Error reading first line of test file.\n"); 8433ac6711aSCaroline Tice fclose(test_file); 8443ac6711aSCaroline Tice return false; 8453ac6711aSCaroline Tice } 8463ac6711aSCaroline Tice 847b9c1b51eSKate Stone if (strncmp(buffer, "InstructionEmulationState={", 27) != 0) { 848b9c1b51eSKate Stone out_stream->Printf("Instructin::TestEmulation: Test file does not contain " 849b9c1b51eSKate Stone "emulation state dictionary\n"); 850de2fb9cfSCaroline Tice fclose(test_file); 851de2fb9cfSCaroline Tice return false; 852de2fb9cfSCaroline Tice } 853de2fb9cfSCaroline Tice 854b9c1b51eSKate Stone // Read all the test information from the test file into an 855b9c1b51eSKate Stone // OptionValueDictionary. 856de2fb9cfSCaroline Tice 857de2fb9cfSCaroline Tice OptionValueSP data_dictionary_sp(ReadDictionary(test_file, out_stream)); 858b9c1b51eSKate Stone if (!data_dictionary_sp) { 859b9c1b51eSKate Stone out_stream->Printf( 860b9c1b51eSKate Stone "Instruction::TestEmulation: Error reading Dictionary Object.\n"); 861de2fb9cfSCaroline Tice fclose(test_file); 862de2fb9cfSCaroline Tice return false; 863de2fb9cfSCaroline Tice } 864de2fb9cfSCaroline Tice 865de2fb9cfSCaroline Tice fclose(test_file); 866de2fb9cfSCaroline Tice 867b9c1b51eSKate Stone OptionValueDictionary *data_dictionary = 868b9c1b51eSKate Stone data_dictionary_sp->GetAsDictionary(); 869de2fb9cfSCaroline Tice static ConstString description_key("assembly_string"); 870de2fb9cfSCaroline Tice static ConstString triple_key("triple"); 871de2fb9cfSCaroline Tice 872de2fb9cfSCaroline Tice OptionValueSP value_sp = data_dictionary->GetValueForKey(description_key); 873de2fb9cfSCaroline Tice 874b9c1b51eSKate Stone if (!value_sp) { 875b9c1b51eSKate Stone out_stream->Printf("Instruction::TestEmulation: Test file does not " 876b9c1b51eSKate Stone "contain description string.\n"); 877de2fb9cfSCaroline Tice return false; 878de2fb9cfSCaroline Tice } 879de2fb9cfSCaroline Tice 880de2fb9cfSCaroline Tice SetDescription(value_sp->GetStringValue()); 881de2fb9cfSCaroline Tice 882de2fb9cfSCaroline Tice value_sp = data_dictionary->GetValueForKey(triple_key); 883b9c1b51eSKate Stone if (!value_sp) { 884b9c1b51eSKate Stone out_stream->Printf( 885b9c1b51eSKate Stone "Instruction::TestEmulation: Test file does not contain triple.\n"); 886de2fb9cfSCaroline Tice return false; 887de2fb9cfSCaroline Tice } 888de2fb9cfSCaroline Tice 889de2fb9cfSCaroline Tice ArchSpec arch; 890de2fb9cfSCaroline Tice arch.SetTriple(llvm::Triple(value_sp->GetStringValue())); 8913ac6711aSCaroline Tice 8923ac6711aSCaroline Tice bool success = false; 893d5b44036SJonas Devlieghere std::unique_ptr<EmulateInstruction> insn_emulator_up( 894b9c1b51eSKate Stone EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr)); 895d5b44036SJonas Devlieghere if (insn_emulator_up) 896b9c1b51eSKate Stone success = 897d5b44036SJonas Devlieghere insn_emulator_up->TestEmulation(out_stream, arch, data_dictionary); 8983ac6711aSCaroline Tice 8993ac6711aSCaroline Tice if (success) 900ea80ba8bSJohnny Chen out_stream->Printf("Emulation test succeeded."); 9013ac6711aSCaroline Tice else 902ea80ba8bSJohnny Chen out_stream->Printf("Emulation test failed."); 9033ac6711aSCaroline Tice 9043ac6711aSCaroline Tice return success; 9053ac6711aSCaroline Tice } 9063ac6711aSCaroline Tice 907b9c1b51eSKate Stone bool Instruction::Emulate( 908b9c1b51eSKate Stone const ArchSpec &arch, uint32_t evaluate_options, void *baton, 9097349bd90SGreg Clayton EmulateInstruction::ReadMemoryCallback read_mem_callback, 9107349bd90SGreg Clayton EmulateInstruction::WriteMemoryCallback write_mem_callback, 9117349bd90SGreg Clayton EmulateInstruction::ReadRegisterCallback read_reg_callback, 912b9c1b51eSKate Stone EmulateInstruction::WriteRegisterCallback write_reg_callback) { 913d5b44036SJonas Devlieghere std::unique_ptr<EmulateInstruction> insn_emulator_up( 914b9c1b51eSKate Stone EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr)); 915d5b44036SJonas Devlieghere if (insn_emulator_up) { 916d5b44036SJonas Devlieghere insn_emulator_up->SetBaton(baton); 917d5b44036SJonas Devlieghere insn_emulator_up->SetCallbacks(read_mem_callback, write_mem_callback, 918b9c1b51eSKate Stone read_reg_callback, write_reg_callback); 919d5b44036SJonas Devlieghere insn_emulator_up->SetInstruction(GetOpcode(), GetAddress(), nullptr); 920d5b44036SJonas Devlieghere return insn_emulator_up->EvaluateInstruction(evaluate_options); 9217c9dd3ceSCaroline Tice } 9227c9dd3ceSCaroline Tice 9237c9dd3ceSCaroline Tice return false; 9247c9dd3ceSCaroline Tice } 9257c9dd3ceSCaroline Tice 926b9c1b51eSKate Stone uint32_t Instruction::GetData(DataExtractor &data) { 927cd4ae1abSSean Callanan return m_opcode.GetData(data); 928ba812f42SGreg Clayton } 929ba812f42SGreg Clayton 930b9c1b51eSKate Stone InstructionList::InstructionList() : m_instructions() {} 93130fdc8d8SChris Lattner 93234ede34aSEugene Zelenko InstructionList::~InstructionList() = default; 93330fdc8d8SChris Lattner 934b9c1b51eSKate Stone size_t InstructionList::GetSize() const { return m_instructions.size(); } 93530fdc8d8SChris Lattner 936b9c1b51eSKate Stone uint32_t InstructionList::GetMaxOpcocdeByteSize() const { 937357132ebSGreg Clayton uint32_t max_inst_size = 0; 938357132ebSGreg Clayton collection::const_iterator pos, end; 939b9c1b51eSKate Stone for (pos = m_instructions.begin(), end = m_instructions.end(); pos != end; 940b9c1b51eSKate Stone ++pos) { 941357132ebSGreg Clayton uint32_t inst_size = (*pos)->GetOpcode().GetByteSize(); 942357132ebSGreg Clayton if (max_inst_size < inst_size) 943357132ebSGreg Clayton max_inst_size = inst_size; 944357132ebSGreg Clayton } 945357132ebSGreg Clayton return max_inst_size; 946357132ebSGreg Clayton } 947357132ebSGreg Clayton 948b9c1b51eSKate Stone InstructionSP InstructionList::GetInstructionAtIndex(size_t idx) const { 9491d273166SGreg Clayton InstructionSP inst_sp; 95030fdc8d8SChris Lattner if (idx < m_instructions.size()) 9511d273166SGreg Clayton inst_sp = m_instructions[idx]; 9521d273166SGreg Clayton return inst_sp; 95330fdc8d8SChris Lattner } 95430fdc8d8SChris Lattner 955*cfd96f05SWalter Erquinigo InstructionSP InstructionList::GetInstructionAtAddress(const Address &address) { 956*cfd96f05SWalter Erquinigo uint32_t index = GetIndexOfInstructionAtAddress(address); 957*cfd96f05SWalter Erquinigo if (index != UINT32_MAX) 958*cfd96f05SWalter Erquinigo return GetInstructionAtIndex(index); 959*cfd96f05SWalter Erquinigo return nullptr; 960*cfd96f05SWalter Erquinigo } 961*cfd96f05SWalter Erquinigo 962b9c1b51eSKate Stone void InstructionList::Dump(Stream *s, bool show_address, bool show_bytes, 963b9c1b51eSKate Stone const ExecutionContext *exe_ctx) { 9645009f9d5SGreg Clayton const uint32_t max_opcode_byte_size = GetMaxOpcocdeByteSize(); 9655009f9d5SGreg Clayton collection::const_iterator pos, begin, end; 966554f68d3SGreg Clayton 96734ede34aSEugene Zelenko const FormatEntity::Entry *disassembly_format = nullptr; 968554f68d3SGreg Clayton FormatEntity::Entry format; 969b9c1b51eSKate Stone if (exe_ctx && exe_ctx->HasTargetScope()) { 970b9c1b51eSKate Stone disassembly_format = 971b9c1b51eSKate Stone exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat(); 972b9c1b51eSKate Stone } else { 973554f68d3SGreg Clayton FormatEntity::Parse("${addr}: ", format); 974554f68d3SGreg Clayton disassembly_format = &format; 975554f68d3SGreg Clayton } 976554f68d3SGreg Clayton 9775009f9d5SGreg Clayton for (begin = m_instructions.begin(), end = m_instructions.end(), pos = begin; 978b9c1b51eSKate Stone pos != end; ++pos) { 9795009f9d5SGreg Clayton if (pos != begin) 9805009f9d5SGreg Clayton s->EOL(); 981b9c1b51eSKate Stone (*pos)->Dump(s, max_opcode_byte_size, show_address, show_bytes, exe_ctx, 982b9c1b51eSKate Stone nullptr, nullptr, disassembly_format, 0); 9835009f9d5SGreg Clayton } 9845009f9d5SGreg Clayton } 9855009f9d5SGreg Clayton 986b9c1b51eSKate Stone void InstructionList::Clear() { m_instructions.clear(); } 98730fdc8d8SChris Lattner 988b9c1b51eSKate Stone void InstructionList::Append(lldb::InstructionSP &inst_sp) { 98930fdc8d8SChris Lattner if (inst_sp) 99030fdc8d8SChris Lattner m_instructions.push_back(inst_sp); 99130fdc8d8SChris Lattner } 99230fdc8d8SChris Lattner 993564d8bc2SJim Ingham uint32_t 994b9c1b51eSKate Stone InstructionList::GetIndexOfNextBranchInstruction(uint32_t start, 995434905b9SJim Ingham bool ignore_calls, 996434905b9SJim Ingham bool *found_calls) const { 997564d8bc2SJim Ingham size_t num_instructions = m_instructions.size(); 998564d8bc2SJim Ingham 999190636bcSJim Ingham uint32_t next_branch = UINT32_MAX; 1000434905b9SJim Ingham 1001434905b9SJim Ingham if (found_calls) 1002434905b9SJim Ingham *found_calls = false; 10033169d920STed Woodward for (size_t i = start; i < num_instructions; i++) { 1004b9c1b51eSKate Stone if (m_instructions[i]->DoesBranch()) { 1005434905b9SJim Ingham if (ignore_calls && m_instructions[i]->IsCall()) { 1006434905b9SJim Ingham if (found_calls) 1007434905b9SJim Ingham *found_calls = true; 100821929d49SPavel Labath continue; 1009434905b9SJim Ingham } 1010564d8bc2SJim Ingham next_branch = i; 1011564d8bc2SJim Ingham break; 1012564d8bc2SJim Ingham } 1013564d8bc2SJim Ingham } 1014e76e7e93STed Woodward 1015564d8bc2SJim Ingham return next_branch; 1016564d8bc2SJim Ingham } 1017564d8bc2SJim Ingham 1018564d8bc2SJim Ingham uint32_t 1019b9c1b51eSKate Stone InstructionList::GetIndexOfInstructionAtAddress(const Address &address) { 1020c7bece56SGreg Clayton size_t num_instructions = m_instructions.size(); 1021190636bcSJim Ingham uint32_t index = UINT32_MAX; 1022b9c1b51eSKate Stone for (size_t i = 0; i < num_instructions; i++) { 1023b9c1b51eSKate Stone if (m_instructions[i]->GetAddress() == address) { 1024564d8bc2SJim Ingham index = i; 1025564d8bc2SJim Ingham break; 1026564d8bc2SJim Ingham } 1027564d8bc2SJim Ingham } 1028564d8bc2SJim Ingham return index; 1029564d8bc2SJim Ingham } 103030fdc8d8SChris Lattner 103144d93782SGreg Clayton uint32_t 1032b9c1b51eSKate Stone InstructionList::GetIndexOfInstructionAtLoadAddress(lldb::addr_t load_addr, 1033b9c1b51eSKate Stone Target &target) { 103444d93782SGreg Clayton Address address; 103544d93782SGreg Clayton address.SetLoadAddress(load_addr, &target); 103644d93782SGreg Clayton return GetIndexOfInstructionAtAddress(address); 103744d93782SGreg Clayton } 103844d93782SGreg Clayton 103992c0cda9SPavel Labath size_t Disassembler::ParseInstructions(Target &target, Address start, 1040af3db4e9SPavel Labath Limit limit, Stream *error_strm_ptr, 1041b9c1b51eSKate Stone bool prefer_file_cache) { 1042357132ebSGreg Clayton m_instruction_list.Clear(); 104337023b06SJim Ingham 1044af3db4e9SPavel Labath if (!start.IsValid()) 104537023b06SJim Ingham return 0; 104637023b06SJim Ingham 104792c0cda9SPavel Labath start = ResolveAddress(target, start); 104892c0cda9SPavel Labath 1049af3db4e9SPavel Labath addr_t byte_size = limit.value; 1050af3db4e9SPavel Labath if (limit.kind == Limit::Instructions) 1051af3db4e9SPavel Labath byte_size *= m_arch.GetMaximumOpcodeByteSize(); 1052af3db4e9SPavel Labath auto data_sp = std::make_shared<DataBufferHeap>(byte_size, '\0'); 105337023b06SJim Ingham 105497206d57SZachary Turner Status error; 10553faf47c4SGreg Clayton lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; 1056b9c1b51eSKate Stone const size_t bytes_read = 1057af3db4e9SPavel Labath target.ReadMemory(start, prefer_file_cache, data_sp->GetBytes(), 1058af3db4e9SPavel Labath data_sp->GetByteSize(), error, &load_addr); 10593faf47c4SGreg Clayton const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS; 106037023b06SJim Ingham 1061af3db4e9SPavel Labath if (bytes_read == 0) { 1062af3db4e9SPavel Labath if (error_strm_ptr) { 1063af3db4e9SPavel Labath if (const char *error_cstr = error.AsCString()) 1064af3db4e9SPavel Labath error_strm_ptr->Printf("error: %s\n", error_cstr); 1065af3db4e9SPavel Labath } 1066357132ebSGreg Clayton return 0; 1067af3db4e9SPavel Labath } 1068af3db4e9SPavel Labath 1069af3db4e9SPavel Labath if (bytes_read != data_sp->GetByteSize()) 1070af3db4e9SPavel Labath data_sp->SetByteSize(bytes_read); 1071b9c1b51eSKate Stone DataExtractor data(data_sp, m_arch.GetByteOrder(), 1072357132ebSGreg Clayton m_arch.GetAddressByteSize()); 1073af3db4e9SPavel Labath return DecodeInstructions(start, data, 0, 1074af3db4e9SPavel Labath limit.kind == Limit::Instructions ? limit.value 1075af3db4e9SPavel Labath : UINT32_MAX, 1076af3db4e9SPavel Labath false, data_from_file); 107737023b06SJim Ingham } 107837023b06SJim Ingham 107930fdc8d8SChris Lattner // Disassembler copy constructor 1080b9c1b51eSKate Stone Disassembler::Disassembler(const ArchSpec &arch, const char *flavor) 1081b9c1b51eSKate Stone : m_arch(arch), m_instruction_list(), m_base_addr(LLDB_INVALID_ADDRESS), 1082b9c1b51eSKate Stone m_flavor() { 108334ede34aSEugene Zelenko if (flavor == nullptr) 10840f063ba6SJim Ingham m_flavor.assign("default"); 10850f063ba6SJim Ingham else 10860f063ba6SJim Ingham m_flavor.assign(flavor); 108775452e8cSJason Molenda 108875452e8cSJason Molenda // If this is an arm variant that can only include thumb (T16, T32) 108905097246SAdrian Prantl // instructions, force the arch triple to be "thumbv.." instead of "armv..." 1090b9c1b51eSKate Stone if (arch.IsAlwaysThumbInstructions()) { 109175452e8cSJason Molenda std::string thumb_arch_name(arch.GetTriple().getArchName().str()); 109275452e8cSJason Molenda // Replace "arm" with "thumb" so we get all thumb variants correct 1093b9c1b51eSKate Stone if (thumb_arch_name.size() > 3) { 109475452e8cSJason Molenda thumb_arch_name.erase(0, 3); 109575452e8cSJason Molenda thumb_arch_name.insert(0, "thumb"); 109675452e8cSJason Molenda } 109775452e8cSJason Molenda m_arch.SetTriple(thumb_arch_name.c_str()); 109875452e8cSJason Molenda } 109930fdc8d8SChris Lattner } 110030fdc8d8SChris Lattner 110134ede34aSEugene Zelenko Disassembler::~Disassembler() = default; 110230fdc8d8SChris Lattner 1103b9c1b51eSKate Stone InstructionList &Disassembler::GetInstructionList() { 110430fdc8d8SChris Lattner return m_instruction_list; 110530fdc8d8SChris Lattner } 110630fdc8d8SChris Lattner 1107b9c1b51eSKate Stone const InstructionList &Disassembler::GetInstructionList() const { 110830fdc8d8SChris Lattner return m_instruction_list; 110930fdc8d8SChris Lattner } 11103ac6711aSCaroline Tice 11113ac6711aSCaroline Tice // Class PseudoInstruction 111234ede34aSEugene Zelenko 1113b9c1b51eSKate Stone PseudoInstruction::PseudoInstruction() 111404803b3eSTatyana Krasnukha : Instruction(Address(), AddressClass::eUnknown), m_description() {} 11153ac6711aSCaroline Tice 111634ede34aSEugene Zelenko PseudoInstruction::~PseudoInstruction() = default; 11173ac6711aSCaroline Tice 1118b9c1b51eSKate Stone bool PseudoInstruction::DoesBranch() { 11193ac6711aSCaroline Tice // This is NOT a valid question for a pseudo instruction. 11203ac6711aSCaroline Tice return false; 11213ac6711aSCaroline Tice } 11223ac6711aSCaroline Tice 1123b9c1b51eSKate Stone bool PseudoInstruction::HasDelaySlot() { 11247f3daedaSBhushan D. Attarde // This is NOT a valid question for a pseudo instruction. 11257f3daedaSBhushan D. Attarde return false; 11267f3daedaSBhushan D. Attarde } 11277f3daedaSBhushan D. Attarde 1128b9c1b51eSKate Stone size_t PseudoInstruction::Decode(const lldb_private::Disassembler &disassembler, 11293ac6711aSCaroline Tice const lldb_private::DataExtractor &data, 1130b9c1b51eSKate Stone lldb::offset_t data_offset) { 11313ac6711aSCaroline Tice return m_opcode.GetByteSize(); 11323ac6711aSCaroline Tice } 11333ac6711aSCaroline Tice 1134b9c1b51eSKate Stone void PseudoInstruction::SetOpcode(size_t opcode_size, void *opcode_data) { 11353ac6711aSCaroline Tice if (!opcode_data) 11363ac6711aSCaroline Tice return; 11373ac6711aSCaroline Tice 1138b9c1b51eSKate Stone switch (opcode_size) { 1139b9c1b51eSKate Stone case 8: { 11403ac6711aSCaroline Tice uint8_t value8 = *((uint8_t *)opcode_data); 114190359963SEd Maste m_opcode.SetOpcode8(value8, eByteOrderInvalid); 11423ac6711aSCaroline Tice break; 11433ac6711aSCaroline Tice } 1144b9c1b51eSKate Stone case 16: { 11453ac6711aSCaroline Tice uint16_t value16 = *((uint16_t *)opcode_data); 114690359963SEd Maste m_opcode.SetOpcode16(value16, eByteOrderInvalid); 11473ac6711aSCaroline Tice break; 11483ac6711aSCaroline Tice } 1149b9c1b51eSKate Stone case 32: { 11503ac6711aSCaroline Tice uint32_t value32 = *((uint32_t *)opcode_data); 115190359963SEd Maste m_opcode.SetOpcode32(value32, eByteOrderInvalid); 11523ac6711aSCaroline Tice break; 11533ac6711aSCaroline Tice } 1154b9c1b51eSKate Stone case 64: { 11553ac6711aSCaroline Tice uint64_t value64 = *((uint64_t *)opcode_data); 115690359963SEd Maste m_opcode.SetOpcode64(value64, eByteOrderInvalid); 11573ac6711aSCaroline Tice break; 11583ac6711aSCaroline Tice } 11593ac6711aSCaroline Tice default: 11603ac6711aSCaroline Tice break; 11613ac6711aSCaroline Tice } 11623ac6711aSCaroline Tice } 11633ac6711aSCaroline Tice 116431d97a5cSZachary Turner void PseudoInstruction::SetDescription(llvm::StringRef description) { 1165adcd0268SBenjamin Kramer m_description = std::string(description); 11663ac6711aSCaroline Tice } 1167807ee2ffSSean Callanan 1168807ee2ffSSean Callanan Instruction::Operand Instruction::Operand::BuildRegister(ConstString &r) { 1169807ee2ffSSean Callanan Operand ret; 1170807ee2ffSSean Callanan ret.m_type = Type::Register; 1171807ee2ffSSean Callanan ret.m_register = r; 1172807ee2ffSSean Callanan return ret; 1173807ee2ffSSean Callanan } 1174807ee2ffSSean Callanan 1175807ee2ffSSean Callanan Instruction::Operand Instruction::Operand::BuildImmediate(lldb::addr_t imm, 1176807ee2ffSSean Callanan bool neg) { 1177807ee2ffSSean Callanan Operand ret; 1178807ee2ffSSean Callanan ret.m_type = Type::Immediate; 1179807ee2ffSSean Callanan ret.m_immediate = imm; 1180807ee2ffSSean Callanan ret.m_negative = neg; 1181807ee2ffSSean Callanan return ret; 1182807ee2ffSSean Callanan } 1183807ee2ffSSean Callanan 1184807ee2ffSSean Callanan Instruction::Operand Instruction::Operand::BuildImmediate(int64_t imm) { 1185807ee2ffSSean Callanan Operand ret; 1186807ee2ffSSean Callanan ret.m_type = Type::Immediate; 1187807ee2ffSSean Callanan if (imm < 0) { 1188807ee2ffSSean Callanan ret.m_immediate = -imm; 1189807ee2ffSSean Callanan ret.m_negative = true; 1190807ee2ffSSean Callanan } else { 1191807ee2ffSSean Callanan ret.m_immediate = imm; 1192807ee2ffSSean Callanan ret.m_negative = false; 1193807ee2ffSSean Callanan } 1194807ee2ffSSean Callanan return ret; 1195807ee2ffSSean Callanan } 1196807ee2ffSSean Callanan 1197807ee2ffSSean Callanan Instruction::Operand 1198807ee2ffSSean Callanan Instruction::Operand::BuildDereference(const Operand &ref) { 1199807ee2ffSSean Callanan Operand ret; 1200807ee2ffSSean Callanan ret.m_type = Type::Dereference; 1201807ee2ffSSean Callanan ret.m_children = {ref}; 1202807ee2ffSSean Callanan return ret; 1203807ee2ffSSean Callanan } 1204807ee2ffSSean Callanan 1205807ee2ffSSean Callanan Instruction::Operand Instruction::Operand::BuildSum(const Operand &lhs, 1206807ee2ffSSean Callanan const Operand &rhs) { 1207807ee2ffSSean Callanan Operand ret; 1208807ee2ffSSean Callanan ret.m_type = Type::Sum; 1209807ee2ffSSean Callanan ret.m_children = {lhs, rhs}; 1210807ee2ffSSean Callanan return ret; 1211807ee2ffSSean Callanan } 1212807ee2ffSSean Callanan 1213807ee2ffSSean Callanan Instruction::Operand Instruction::Operand::BuildProduct(const Operand &lhs, 1214807ee2ffSSean Callanan const Operand &rhs) { 1215807ee2ffSSean Callanan Operand ret; 1216807ee2ffSSean Callanan ret.m_type = Type::Product; 1217807ee2ffSSean Callanan ret.m_children = {lhs, rhs}; 1218807ee2ffSSean Callanan return ret; 1219807ee2ffSSean Callanan } 1220807ee2ffSSean Callanan 1221807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> 1222807ee2ffSSean Callanan lldb_private::OperandMatchers::MatchBinaryOp( 1223807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> base, 1224807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> left, 1225807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> right) { 1226807ee2ffSSean Callanan return [base, left, right](const Instruction::Operand &op) -> bool { 1227807ee2ffSSean Callanan return (base(op) && op.m_children.size() == 2 && 1228807ee2ffSSean Callanan ((left(op.m_children[0]) && right(op.m_children[1])) || 1229807ee2ffSSean Callanan (left(op.m_children[1]) && right(op.m_children[0])))); 1230807ee2ffSSean Callanan }; 1231807ee2ffSSean Callanan } 1232807ee2ffSSean Callanan 1233807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> 1234807ee2ffSSean Callanan lldb_private::OperandMatchers::MatchUnaryOp( 1235807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> base, 1236807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> child) { 1237807ee2ffSSean Callanan return [base, child](const Instruction::Operand &op) -> bool { 1238807ee2ffSSean Callanan return (base(op) && op.m_children.size() == 1 && child(op.m_children[0])); 1239807ee2ffSSean Callanan }; 1240807ee2ffSSean Callanan } 1241807ee2ffSSean Callanan 1242807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> 1243807ee2ffSSean Callanan lldb_private::OperandMatchers::MatchRegOp(const RegisterInfo &info) { 1244807ee2ffSSean Callanan return [&info](const Instruction::Operand &op) { 1245807ee2ffSSean Callanan return (op.m_type == Instruction::Operand::Type::Register && 1246807ee2ffSSean Callanan (op.m_register == ConstString(info.name) || 1247807ee2ffSSean Callanan op.m_register == ConstString(info.alt_name))); 1248807ee2ffSSean Callanan }; 1249807ee2ffSSean Callanan } 1250807ee2ffSSean Callanan 1251807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> 1252561a9bbfSSean Callanan lldb_private::OperandMatchers::FetchRegOp(ConstString ®) { 1253561a9bbfSSean Callanan return [®](const Instruction::Operand &op) { 1254561a9bbfSSean Callanan if (op.m_type != Instruction::Operand::Type::Register) { 1255561a9bbfSSean Callanan return false; 1256561a9bbfSSean Callanan } 1257561a9bbfSSean Callanan reg = op.m_register; 1258561a9bbfSSean Callanan return true; 1259561a9bbfSSean Callanan }; 1260561a9bbfSSean Callanan } 1261561a9bbfSSean Callanan 1262561a9bbfSSean Callanan std::function<bool(const Instruction::Operand &)> 1263807ee2ffSSean Callanan lldb_private::OperandMatchers::MatchImmOp(int64_t imm) { 1264807ee2ffSSean Callanan return [imm](const Instruction::Operand &op) { 1265807ee2ffSSean Callanan return (op.m_type == Instruction::Operand::Type::Immediate && 1266807ee2ffSSean Callanan ((op.m_negative && op.m_immediate == (uint64_t)-imm) || 1267807ee2ffSSean Callanan (!op.m_negative && op.m_immediate == (uint64_t)imm))); 1268807ee2ffSSean Callanan }; 1269807ee2ffSSean Callanan } 1270807ee2ffSSean Callanan 1271807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> 1272807ee2ffSSean Callanan lldb_private::OperandMatchers::FetchImmOp(int64_t &imm) { 1273807ee2ffSSean Callanan return [&imm](const Instruction::Operand &op) { 1274807ee2ffSSean Callanan if (op.m_type != Instruction::Operand::Type::Immediate) { 1275807ee2ffSSean Callanan return false; 1276807ee2ffSSean Callanan } 1277807ee2ffSSean Callanan if (op.m_negative) { 1278807ee2ffSSean Callanan imm = -((int64_t)op.m_immediate); 1279807ee2ffSSean Callanan } else { 1280807ee2ffSSean Callanan imm = ((int64_t)op.m_immediate); 1281807ee2ffSSean Callanan } 1282807ee2ffSSean Callanan return true; 1283807ee2ffSSean Callanan }; 1284807ee2ffSSean Callanan } 1285807ee2ffSSean Callanan 1286807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> 1287807ee2ffSSean Callanan lldb_private::OperandMatchers::MatchOpType(Instruction::Operand::Type type) { 1288807ee2ffSSean Callanan return [type](const Instruction::Operand &op) { return op.m_type == type; }; 1289807ee2ffSSean Callanan } 1290