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 5176e47d48SRaphael Isemann #include <cassert> 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) { 615c1c8443SJonas Devlieghere LLDB_SCOPED_TIMERF("Disassembler::FindPlugin (arch = %s, plugin_name = %s)", 62b9c1b51eSKate Stone arch.GetArchitectureName(), plugin_name); 6330fdc8d8SChris Lattner 6434ede34aSEugene Zelenko DisassemblerCreateInstance create_callback = nullptr; 651080edbcSGreg Clayton 66b9c1b51eSKate Stone if (plugin_name) { 67b5e9f83eSPavel Labath create_callback = 68b5e9f83eSPavel Labath PluginManager::GetDisassemblerCreateCallbackForPluginName(plugin_name); 69b9c1b51eSKate Stone if (create_callback) { 700f063ba6SJim Ingham DisassemblerSP disassembler_sp(create_callback(arch, flavor)); 711080edbcSGreg Clayton 7234ede34aSEugene Zelenko if (disassembler_sp) 737e6d4e5aSSean Callanan return disassembler_sp; 741080edbcSGreg Clayton } 75b9c1b51eSKate Stone } else { 76b9c1b51eSKate Stone for (uint32_t idx = 0; 77b9c1b51eSKate Stone (create_callback = PluginManager::GetDisassemblerCreateCallbackAtIndex( 78b9c1b51eSKate Stone idx)) != nullptr; 79b9c1b51eSKate Stone ++idx) { 800f063ba6SJim Ingham DisassemblerSP disassembler_sp(create_callback(arch, flavor)); 8130fdc8d8SChris Lattner 8234ede34aSEugene Zelenko if (disassembler_sp) 837e6d4e5aSSean Callanan return disassembler_sp; 8430fdc8d8SChris Lattner } 851080edbcSGreg Clayton } 867e6d4e5aSSean Callanan return DisassemblerSP(); 8730fdc8d8SChris Lattner } 8830fdc8d8SChris Lattner 8904592d5bSPavel Labath DisassemblerSP Disassembler::FindPluginForTarget(const Target &target, 90b9c1b51eSKate Stone const ArchSpec &arch, 91b9c1b51eSKate Stone const char *flavor, 92b9c1b51eSKate Stone const char *plugin_name) { 9304592d5bSPavel Labath if (flavor == nullptr) { 94b9c1b51eSKate Stone // FIXME - we don't have the mechanism in place to do per-architecture 9505097246SAdrian Prantl // settings. But since we know that for now we only support flavors on x86 9605097246SAdrian Prantl // & x86_64, 97b9c1b51eSKate Stone if (arch.GetTriple().getArch() == llvm::Triple::x86 || 98b9c1b51eSKate Stone arch.GetTriple().getArch() == llvm::Triple::x86_64) 9904592d5bSPavel Labath flavor = target.GetDisassemblyFlavor(); 1000f063ba6SJim Ingham } 1010f063ba6SJim Ingham return FindPlugin(arch, flavor, plugin_name); 1020f063ba6SJim Ingham } 1030f063ba6SJim Ingham 10492c0cda9SPavel Labath static Address ResolveAddress(Target &target, const Address &addr) { 105b9c1b51eSKate Stone if (!addr.IsSectionOffset()) { 10692c0cda9SPavel Labath Address resolved_addr; 10705097246SAdrian Prantl // If we weren't passed in a section offset address range, try and resolve 10805097246SAdrian Prantl // it to something 10904592d5bSPavel Labath bool is_resolved = target.GetSectionLoadList().IsEmpty() 11004592d5bSPavel Labath ? target.GetImages().ResolveFileAddress( 11104592d5bSPavel Labath addr.GetOffset(), resolved_addr) 11204592d5bSPavel Labath : target.GetSectionLoadList().ResolveLoadAddress( 11304592d5bSPavel Labath addr.GetOffset(), resolved_addr); 114a0fa299dSTatyana Krasnukha 11505097246SAdrian Prantl // We weren't able to resolve the address, just treat it as a raw address 116a0fa299dSTatyana Krasnukha if (is_resolved && resolved_addr.IsValid()) 11792c0cda9SPavel Labath return resolved_addr; 118357132ebSGreg Clayton } 11992c0cda9SPavel Labath return addr; 120357132ebSGreg Clayton } 121dda4f7b5SGreg Clayton 122b9c1b51eSKate Stone lldb::DisassemblerSP Disassembler::DisassembleRange( 123b9c1b51eSKate Stone const ArchSpec &arch, const char *plugin_name, const char *flavor, 124e9fe788dSJason Molenda Target &target, const AddressRange &range, bool force_live_memory) { 12504592d5bSPavel Labath if (range.GetByteSize() <= 0) 1264be6706eSJonas Devlieghere return {}; 1271d273166SGreg Clayton 1284be6706eSJonas Devlieghere if (!range.GetBaseAddress().IsValid()) 1294be6706eSJonas Devlieghere return {}; 1304be6706eSJonas Devlieghere 13104592d5bSPavel Labath lldb::DisassemblerSP disasm_sp = 13204592d5bSPavel Labath Disassembler::FindPluginForTarget(target, arch, flavor, plugin_name); 1334be6706eSJonas Devlieghere 1344be6706eSJonas Devlieghere if (!disasm_sp) 1354be6706eSJonas Devlieghere return {}; 1364be6706eSJonas Devlieghere 137af3db4e9SPavel Labath const size_t bytes_disassembled = disasm_sp->ParseInstructions( 138af3db4e9SPavel Labath target, range.GetBaseAddress(), {Limit::Bytes, range.GetByteSize()}, 139e9fe788dSJason Molenda nullptr, force_live_memory); 1401d273166SGreg Clayton if (bytes_disassembled == 0) 1414be6706eSJonas Devlieghere return {}; 1424be6706eSJonas Devlieghere 1431d273166SGreg Clayton return disasm_sp; 1441d273166SGreg Clayton } 1451d273166SGreg Clayton 14650952e95SSean Callanan lldb::DisassemblerSP 147b9c1b51eSKate Stone Disassembler::DisassembleBytes(const ArchSpec &arch, const char *plugin_name, 148b9c1b51eSKate Stone const char *flavor, const Address &start, 149b9c1b51eSKate Stone const void *src, size_t src_len, 150b9c1b51eSKate Stone uint32_t num_instructions, bool data_from_file) { 1514be6706eSJonas Devlieghere if (!src) 1524be6706eSJonas Devlieghere return {}; 15350952e95SSean Callanan 1544be6706eSJonas Devlieghere lldb::DisassemblerSP disasm_sp = 1554be6706eSJonas Devlieghere Disassembler::FindPlugin(arch, flavor, plugin_name); 15650952e95SSean Callanan 1574be6706eSJonas Devlieghere if (!disasm_sp) 1584be6706eSJonas Devlieghere return {}; 1594be6706eSJonas Devlieghere 160b9c1b51eSKate Stone DataExtractor data(src, src_len, arch.GetByteOrder(), 161b9c1b51eSKate Stone arch.GetAddressByteSize()); 16250952e95SSean Callanan 1634be6706eSJonas Devlieghere (void)disasm_sp->DecodeInstructions(start, data, 0, num_instructions, false, 1644be6706eSJonas Devlieghere data_from_file); 16550952e95SSean Callanan return disasm_sp; 16650952e95SSean Callanan } 16750952e95SSean Callanan 168b9c1b51eSKate Stone bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch, 169b9c1b51eSKate Stone const char *plugin_name, const char *flavor, 170dda4f7b5SGreg Clayton const ExecutionContext &exe_ctx, 171af3db4e9SPavel Labath const Address &address, Limit limit, 1720b4c26b2SJason Molenda bool mixed_source_and_assembly, 173dda4f7b5SGreg Clayton uint32_t num_mixed_context_lines, 174b9c1b51eSKate Stone uint32_t options, Stream &strm) { 175af3db4e9SPavel Labath if (!exe_ctx.GetTargetPtr()) 1760910e17dSJonas Devlieghere return false; 1770910e17dSJonas Devlieghere 178b9c1b51eSKate Stone lldb::DisassemblerSP disasm_sp(Disassembler::FindPluginForTarget( 17904592d5bSPavel Labath exe_ctx.GetTargetRef(), arch, flavor, plugin_name)); 1800910e17dSJonas Devlieghere if (!disasm_sp) 1810910e17dSJonas Devlieghere return false; 1820910e17dSJonas Devlieghere 183e9fe788dSJason Molenda const bool force_live_memory = true; 184b9c1b51eSKate Stone size_t bytes_disassembled = disasm_sp->ParseInstructions( 185e9fe788dSJason Molenda exe_ctx.GetTargetRef(), address, limit, &strm, force_live_memory); 18637023b06SJim Ingham if (bytes_disassembled == 0) 18737023b06SJim Ingham return false; 1880910e17dSJonas Devlieghere 189af3db4e9SPavel Labath disasm_sp->PrintInstructions(debugger, arch, exe_ctx, 190ea68462eSPavel Labath mixed_source_and_assembly, 1910b4c26b2SJason Molenda num_mixed_context_lines, options, strm); 192ea68462eSPavel Labath return true; 19337023b06SJim Ingham } 19437023b06SJim Ingham 1950b4c26b2SJason Molenda Disassembler::SourceLine 1960b4c26b2SJason Molenda Disassembler::GetFunctionDeclLineEntry(const SymbolContext &sc) { 1970910e17dSJonas Devlieghere if (!sc.function) 1980910e17dSJonas Devlieghere return {}; 1990910e17dSJonas Devlieghere 2000910e17dSJonas Devlieghere if (!sc.line_entry.IsValid()) 2010910e17dSJonas Devlieghere return {}; 2020910e17dSJonas Devlieghere 2030b4c26b2SJason Molenda LineEntry prologue_end_line = sc.line_entry; 2040b4c26b2SJason Molenda FileSpec func_decl_file; 2050b4c26b2SJason Molenda uint32_t func_decl_line; 2060b4c26b2SJason Molenda sc.function->GetStartLineSourceInfo(func_decl_file, func_decl_line); 2070910e17dSJonas Devlieghere 2080910e17dSJonas Devlieghere if (func_decl_file != prologue_end_line.file && 2090910e17dSJonas Devlieghere func_decl_file != prologue_end_line.original_file) 2100910e17dSJonas Devlieghere return {}; 2110910e17dSJonas Devlieghere 2120910e17dSJonas Devlieghere SourceLine decl_line; 2130b4c26b2SJason Molenda decl_line.file = func_decl_file; 2140b4c26b2SJason Molenda decl_line.line = func_decl_line; 2150910e17dSJonas Devlieghere // TODO: Do we care about column on these entries? If so, we need to plumb 2160910e17dSJonas Devlieghere // that through GetStartLineSourceInfo. 2179666ba75STodd Fiala decl_line.column = 0; 2180b4c26b2SJason Molenda return decl_line; 2190b4c26b2SJason Molenda } 2200b4c26b2SJason Molenda 2210b4c26b2SJason Molenda void Disassembler::AddLineToSourceLineTables( 2220b4c26b2SJason Molenda SourceLine &line, 2230b4c26b2SJason Molenda std::map<FileSpec, std::set<uint32_t>> &source_lines_seen) { 2240b4c26b2SJason Molenda if (line.IsValid()) { 2250b4c26b2SJason Molenda auto source_lines_seen_pos = source_lines_seen.find(line.file); 2260b4c26b2SJason Molenda if (source_lines_seen_pos == source_lines_seen.end()) { 2270b4c26b2SJason Molenda std::set<uint32_t> lines; 2280b4c26b2SJason Molenda lines.insert(line.line); 2290b4c26b2SJason Molenda source_lines_seen.emplace(line.file, lines); 2300b4c26b2SJason Molenda } else { 2310b4c26b2SJason Molenda source_lines_seen_pos->second.insert(line.line); 2320b4c26b2SJason Molenda } 2330b4c26b2SJason Molenda } 2340b4c26b2SJason Molenda } 2350b4c26b2SJason Molenda 2360b4c26b2SJason Molenda bool Disassembler::ElideMixedSourceAndDisassemblyLine( 2370b4c26b2SJason Molenda const ExecutionContext &exe_ctx, const SymbolContext &sc, 2380b4c26b2SJason Molenda SourceLine &line) { 2390b4c26b2SJason Molenda 2400b4c26b2SJason Molenda // TODO: should we also check target.process.thread.step-avoid-libraries ? 2410b4c26b2SJason Molenda 2420b4c26b2SJason Molenda const RegularExpression *avoid_regex = nullptr; 2430b4c26b2SJason Molenda 2440b4c26b2SJason Molenda // Skip any line #0 entries - they are implementation details 2450b4c26b2SJason Molenda if (line.line == 0) 2460b4c26b2SJason Molenda return false; 2470b4c26b2SJason Molenda 2480b4c26b2SJason Molenda ThreadSP thread_sp = exe_ctx.GetThreadSP(); 2490b4c26b2SJason Molenda if (thread_sp) { 2500b4c26b2SJason Molenda avoid_regex = thread_sp->GetSymbolsToAvoidRegexp(); 2510b4c26b2SJason Molenda } else { 2520b4c26b2SJason Molenda TargetSP target_sp = exe_ctx.GetTargetSP(); 2530b4c26b2SJason Molenda if (target_sp) { 25497206d57SZachary Turner Status error; 2550b4c26b2SJason Molenda OptionValueSP value_sp = target_sp->GetDebugger().GetPropertyValue( 2560b4c26b2SJason Molenda &exe_ctx, "target.process.thread.step-avoid-regexp", false, error); 2570b4c26b2SJason Molenda if (value_sp && value_sp->GetType() == OptionValue::eTypeRegex) { 2580b4c26b2SJason Molenda OptionValueRegex *re = value_sp->GetAsRegex(); 2590b4c26b2SJason Molenda if (re) { 2600b4c26b2SJason Molenda avoid_regex = re->GetCurrentValue(); 2610b4c26b2SJason Molenda } 2620b4c26b2SJason Molenda } 2630b4c26b2SJason Molenda } 2640b4c26b2SJason Molenda } 2650b4c26b2SJason Molenda if (avoid_regex && sc.symbol != nullptr) { 2660b4c26b2SJason Molenda const char *function_name = 2670b4c26b2SJason Molenda sc.GetFunctionName(Mangled::ePreferDemangledWithoutArguments) 2680b4c26b2SJason Molenda .GetCString(); 2693af3f1e8SJonas Devlieghere if (function_name && avoid_regex->Execute(function_name)) { 2700b4c26b2SJason Molenda // skip this source line 2710b4c26b2SJason Molenda return true; 2720b4c26b2SJason Molenda } 2730b4c26b2SJason Molenda } 2740b4c26b2SJason Molenda // don't skip this source line 2750b4c26b2SJason Molenda return false; 2760b4c26b2SJason Molenda } 2770b4c26b2SJason Molenda 278ea68462eSPavel Labath void Disassembler::PrintInstructions(Debugger &debugger, const ArchSpec &arch, 279b9c1b51eSKate Stone const ExecutionContext &exe_ctx, 2800b4c26b2SJason Molenda bool mixed_source_and_assembly, 281b9c1b51eSKate Stone uint32_t num_mixed_context_lines, 282b9c1b51eSKate Stone uint32_t options, Stream &strm) { 28330fdc8d8SChris Lattner // We got some things disassembled... 284ea68462eSPavel Labath size_t num_instructions_found = GetInstructionList().GetSize(); 28537023b06SJim Ingham 286b9c1b51eSKate Stone const uint32_t max_opcode_byte_size = 287ea68462eSPavel Labath GetInstructionList().GetMaxOpcocdeByteSize(); 28830fdc8d8SChris Lattner SymbolContext sc; 28930fdc8d8SChris Lattner SymbolContext prev_sc; 2900b4c26b2SJason Molenda AddressRange current_source_line_range; 29134ede34aSEugene Zelenko const Address *pc_addr_ptr = nullptr; 292b57e4a1bSJason Molenda StackFrame *frame = exe_ctx.GetFramePtr(); 293c14ee32dSGreg Clayton 2944b2967ffSMichael Sartain TargetSP target_sp(exe_ctx.GetTargetSP()); 295b9c1b51eSKate Stone SourceManager &source_manager = 296b9c1b51eSKate Stone target_sp ? target_sp->GetSourceManager() : debugger.GetSourceManager(); 2974b2967ffSMichael Sartain 298b9c1b51eSKate Stone if (frame) { 299c14ee32dSGreg Clayton pc_addr_ptr = &frame->GetFrameCodeAddress(); 300aff1b357SJason Molenda } 301b9c1b51eSKate Stone const uint32_t scope = 302b9c1b51eSKate Stone eSymbolContextLineEntry | eSymbolContextFunction | eSymbolContextSymbol; 3037e14f91dSGreg Clayton const bool use_inline_block_range = false; 304c980fa92SJason Molenda 30534ede34aSEugene Zelenko const FormatEntity::Entry *disassembly_format = nullptr; 306c980fa92SJason Molenda FormatEntity::Entry format; 307b9c1b51eSKate Stone if (exe_ctx.HasTargetScope()) { 308b9c1b51eSKate Stone disassembly_format = 309b9c1b51eSKate Stone exe_ctx.GetTargetRef().GetDebugger().GetDisassemblyFormat(); 310b9c1b51eSKate Stone } else { 311c980fa92SJason Molenda FormatEntity::Parse("${addr}: ", format); 312c980fa92SJason Molenda disassembly_format = &format; 313c980fa92SJason Molenda } 314c980fa92SJason Molenda 31505097246SAdrian Prantl // First pass: step through the list of instructions, find how long the 31605097246SAdrian Prantl // initial addresses strings are, insert padding in the second pass so the 31705097246SAdrian Prantl // opcodes all line up nicely. 3180b4c26b2SJason Molenda 3190b4c26b2SJason Molenda // Also build up the source line mapping if this is mixed source & assembly 32005097246SAdrian Prantl // mode. Calculate the source line for each assembly instruction (eliding 32105097246SAdrian Prantl // inlined functions which the user wants to skip). 3220b4c26b2SJason Molenda 3230b4c26b2SJason Molenda std::map<FileSpec, std::set<uint32_t>> source_lines_seen; 3240b4c26b2SJason Molenda Symbol *previous_symbol = nullptr; 3250b4c26b2SJason Molenda 326c980fa92SJason Molenda size_t address_text_size = 0; 327b9c1b51eSKate Stone for (size_t i = 0; i < num_instructions_found; ++i) { 328ea68462eSPavel Labath Instruction *inst = GetInstructionList().GetInstructionAtIndex(i).get(); 329b9c1b51eSKate Stone if (inst) { 330c980fa92SJason Molenda const Address &addr = inst->GetAddress(); 331c980fa92SJason Molenda ModuleSP module_sp(addr.GetModule()); 332b9c1b51eSKate Stone if (module_sp) { 333991e4453SZachary Turner const SymbolContextItem resolve_mask = eSymbolContextFunction | 3340b4c26b2SJason Molenda eSymbolContextSymbol | 3350b4c26b2SJason Molenda eSymbolContextLineEntry; 336b9c1b51eSKate Stone uint32_t resolved_mask = 337b9c1b51eSKate Stone module_sp->ResolveSymbolContextForAddress(addr, resolve_mask, sc); 338b9c1b51eSKate Stone if (resolved_mask) { 339c980fa92SJason Molenda StreamString strmstr; 340b9c1b51eSKate Stone Debugger::FormatDisassemblerAddress(disassembly_format, &sc, nullptr, 341b9c1b51eSKate Stone &exe_ctx, &addr, strmstr); 342c980fa92SJason Molenda size_t cur_line = strmstr.GetSizeOfLastLine(); 343c980fa92SJason Molenda if (cur_line > address_text_size) 344c980fa92SJason Molenda address_text_size = cur_line; 3450b4c26b2SJason Molenda 3460b4c26b2SJason Molenda // Add entries to our "source_lines_seen" map+set which list which 3470b4c26b2SJason Molenda // sources lines occur in this disassembly session. We will print 3480b4c26b2SJason Molenda // lines of context around a source line, but we don't want to print 3490b4c26b2SJason Molenda // a source line that has a line table entry of its own - we'll leave 3500b4c26b2SJason Molenda // that source line to be printed when it actually occurs in the 3510b4c26b2SJason Molenda // disassembly. 3520b4c26b2SJason Molenda 3530b4c26b2SJason Molenda if (mixed_source_and_assembly && sc.line_entry.IsValid()) { 3540b4c26b2SJason Molenda if (sc.symbol != previous_symbol) { 3550b4c26b2SJason Molenda SourceLine decl_line = GetFunctionDeclLineEntry(sc); 356a6682a41SJonas Devlieghere if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, decl_line)) 3570b4c26b2SJason Molenda AddLineToSourceLineTables(decl_line, source_lines_seen); 3580b4c26b2SJason Molenda } 3590b4c26b2SJason Molenda if (sc.line_entry.IsValid()) { 3600b4c26b2SJason Molenda SourceLine this_line; 3610b4c26b2SJason Molenda this_line.file = sc.line_entry.file; 3620b4c26b2SJason Molenda this_line.line = sc.line_entry.line; 3639666ba75STodd Fiala this_line.column = sc.line_entry.column; 364a6682a41SJonas Devlieghere if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, this_line)) 3650b4c26b2SJason Molenda AddLineToSourceLineTables(this_line, source_lines_seen); 3660b4c26b2SJason Molenda } 3670b4c26b2SJason Molenda } 368c980fa92SJason Molenda } 369c980fa92SJason Molenda sc.Clear(false); 370c980fa92SJason Molenda } 371c980fa92SJason Molenda } 372c980fa92SJason Molenda } 373c980fa92SJason Molenda 3740b4c26b2SJason Molenda previous_symbol = nullptr; 3750b4c26b2SJason Molenda SourceLine previous_line; 376b9c1b51eSKate Stone for (size_t i = 0; i < num_instructions_found; ++i) { 377ea68462eSPavel Labath Instruction *inst = GetInstructionList().GetInstructionAtIndex(i).get(); 3780b4c26b2SJason Molenda 379b9c1b51eSKate Stone if (inst) { 38032e0a750SGreg Clayton const Address &addr = inst->GetAddress(); 38132e0a750SGreg Clayton const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr; 3820b4c26b2SJason Molenda SourceLinesToDisplay source_lines_to_display; 383dda4f7b5SGreg Clayton 38430fdc8d8SChris Lattner prev_sc = sc; 385dda4f7b5SGreg Clayton 386e72dfb32SGreg Clayton ModuleSP module_sp(addr.GetModule()); 387b9c1b51eSKate Stone if (module_sp) { 388b9c1b51eSKate Stone uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress( 389b9c1b51eSKate Stone addr, eSymbolContextEverything, sc); 390b9c1b51eSKate Stone if (resolved_mask) { 3910b4c26b2SJason Molenda if (mixed_source_and_assembly) { 392dda4f7b5SGreg Clayton 3930b4c26b2SJason Molenda // If we've started a new function (non-inlined), print all of the 39405097246SAdrian Prantl // source lines from the function declaration until the first line 39505097246SAdrian Prantl // table entry - typically the opening curly brace of the function. 3960b4c26b2SJason Molenda if (previous_symbol != sc.symbol) { 39705097246SAdrian Prantl // The default disassembly format puts an extra blank line 39805097246SAdrian Prantl // between functions - so when we're displaying the source 39905097246SAdrian Prantl // context for a function, we don't want to add a blank line 40005097246SAdrian Prantl // after the source context or we'll end up with two of them. 4010b4c26b2SJason Molenda if (previous_symbol != nullptr) 4020b4c26b2SJason Molenda source_lines_to_display.print_source_context_end_eol = false; 40330fdc8d8SChris Lattner 4040b4c26b2SJason Molenda previous_symbol = sc.symbol; 4050b4c26b2SJason Molenda if (sc.function && sc.line_entry.IsValid()) { 4060b4c26b2SJason Molenda LineEntry prologue_end_line = sc.line_entry; 407a6682a41SJonas Devlieghere if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, 408a6682a41SJonas Devlieghere prologue_end_line)) { 4090b4c26b2SJason Molenda FileSpec func_decl_file; 4100b4c26b2SJason Molenda uint32_t func_decl_line; 4110b4c26b2SJason Molenda sc.function->GetStartLineSourceInfo(func_decl_file, 4120b4c26b2SJason Molenda func_decl_line); 4130b4c26b2SJason Molenda if (func_decl_file == prologue_end_line.file || 4140b4c26b2SJason Molenda func_decl_file == prologue_end_line.original_file) { 41505097246SAdrian Prantl // Add all the lines between the function declaration and 41605097246SAdrian Prantl // the first non-prologue source line to the list of lines 41705097246SAdrian Prantl // to print. 4180b4c26b2SJason Molenda for (uint32_t lineno = func_decl_line; 4190b4c26b2SJason Molenda lineno <= prologue_end_line.line; lineno++) { 4200b4c26b2SJason Molenda SourceLine this_line; 4210b4c26b2SJason Molenda this_line.file = func_decl_file; 4220b4c26b2SJason Molenda this_line.line = lineno; 4230b4c26b2SJason Molenda source_lines_to_display.lines.push_back(this_line); 4240b4c26b2SJason Molenda } 42505097246SAdrian Prantl // Mark the last line as the "current" one. Usually this 42605097246SAdrian Prantl // is the open curly brace. 4270b4c26b2SJason Molenda if (source_lines_to_display.lines.size() > 0) 4280b4c26b2SJason Molenda source_lines_to_display.current_source_line = 4290b4c26b2SJason Molenda source_lines_to_display.lines.size() - 1; 4300b4c26b2SJason Molenda } 4310b4c26b2SJason Molenda } 4320b4c26b2SJason Molenda } 4330b4c26b2SJason Molenda sc.GetAddressRange(scope, 0, use_inline_block_range, 4340b4c26b2SJason Molenda current_source_line_range); 4350b4c26b2SJason Molenda } 43630fdc8d8SChris Lattner 43705097246SAdrian Prantl // If we've left a previous source line's address range, print a 43805097246SAdrian Prantl // new source line 4390b4c26b2SJason Molenda if (!current_source_line_range.ContainsFileAddress(addr)) { 4400b4c26b2SJason Molenda sc.GetAddressRange(scope, 0, use_inline_block_range, 4410b4c26b2SJason Molenda current_source_line_range); 4420b4c26b2SJason Molenda 4430b4c26b2SJason Molenda if (sc != prev_sc && sc.comp_unit && sc.line_entry.IsValid()) { 4440b4c26b2SJason Molenda SourceLine this_line; 4450b4c26b2SJason Molenda this_line.file = sc.line_entry.file; 4460b4c26b2SJason Molenda this_line.line = sc.line_entry.line; 4470b4c26b2SJason Molenda 448a6682a41SJonas Devlieghere if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, 449a6682a41SJonas Devlieghere this_line)) { 4500b4c26b2SJason Molenda // Only print this source line if it is different from the 4510b4c26b2SJason Molenda // last source line we printed. There may have been inlined 4520b4c26b2SJason Molenda // functions between these lines that we elided, resulting in 45305097246SAdrian Prantl // the same line being printed twice in a row for a 45405097246SAdrian Prantl // contiguous block of assembly instructions. 4550b4c26b2SJason Molenda if (this_line != previous_line) { 4560b4c26b2SJason Molenda 4570b4c26b2SJason Molenda std::vector<uint32_t> previous_lines; 4587771462bSEd Maste for (uint32_t i = 0; 4590b4c26b2SJason Molenda i < num_mixed_context_lines && 4600b4c26b2SJason Molenda (this_line.line - num_mixed_context_lines) > 0; 4610b4c26b2SJason Molenda i++) { 4620b4c26b2SJason Molenda uint32_t line = 4630b4c26b2SJason Molenda this_line.line - num_mixed_context_lines + i; 4640b4c26b2SJason Molenda auto pos = source_lines_seen.find(this_line.file); 4650b4c26b2SJason Molenda if (pos != source_lines_seen.end()) { 4660b4c26b2SJason Molenda if (pos->second.count(line) == 1) { 4670b4c26b2SJason Molenda previous_lines.clear(); 4680b4c26b2SJason Molenda } else { 4690b4c26b2SJason Molenda previous_lines.push_back(line); 4700b4c26b2SJason Molenda } 4710b4c26b2SJason Molenda } 4720b4c26b2SJason Molenda } 4730b4c26b2SJason Molenda for (size_t i = 0; i < previous_lines.size(); i++) { 4740b4c26b2SJason Molenda SourceLine previous_line; 4750b4c26b2SJason Molenda previous_line.file = this_line.file; 4760b4c26b2SJason Molenda previous_line.line = previous_lines[i]; 4770b4c26b2SJason Molenda auto pos = source_lines_seen.find(previous_line.file); 4780b4c26b2SJason Molenda if (pos != source_lines_seen.end()) { 4790b4c26b2SJason Molenda pos->second.insert(previous_line.line); 4800b4c26b2SJason Molenda } 4810b4c26b2SJason Molenda source_lines_to_display.lines.push_back(previous_line); 4820b4c26b2SJason Molenda } 4830b4c26b2SJason Molenda 4840b4c26b2SJason Molenda source_lines_to_display.lines.push_back(this_line); 4850b4c26b2SJason Molenda source_lines_to_display.current_source_line = 4860b4c26b2SJason Molenda source_lines_to_display.lines.size() - 1; 4870b4c26b2SJason Molenda 4887771462bSEd Maste for (uint32_t i = 0; i < num_mixed_context_lines; i++) { 4890b4c26b2SJason Molenda SourceLine next_line; 4900b4c26b2SJason Molenda next_line.file = this_line.file; 4910b4c26b2SJason Molenda next_line.line = this_line.line + i + 1; 4920b4c26b2SJason Molenda auto pos = source_lines_seen.find(next_line.file); 4930b4c26b2SJason Molenda if (pos != source_lines_seen.end()) { 4940b4c26b2SJason Molenda if (pos->second.count(next_line.line) == 1) 4950b4c26b2SJason Molenda break; 4960b4c26b2SJason Molenda pos->second.insert(next_line.line); 4970b4c26b2SJason Molenda } 4980b4c26b2SJason Molenda source_lines_to_display.lines.push_back(next_line); 4990b4c26b2SJason Molenda } 5000b4c26b2SJason Molenda } 5010b4c26b2SJason Molenda previous_line = this_line; 50230fdc8d8SChris Lattner } 50330fdc8d8SChris Lattner } 50430fdc8d8SChris Lattner } 50530fdc8d8SChris Lattner } 506b9c1b51eSKate Stone } else { 50772310355SGreg Clayton sc.Clear(true); 50830fdc8d8SChris Lattner } 50930fdc8d8SChris Lattner } 51032e0a750SGreg Clayton 5110b4c26b2SJason Molenda if (source_lines_to_display.lines.size() > 0) { 5120b4c26b2SJason Molenda strm.EOL(); 5130b4c26b2SJason Molenda for (size_t idx = 0; idx < source_lines_to_display.lines.size(); 5140b4c26b2SJason Molenda idx++) { 5150b4c26b2SJason Molenda SourceLine ln = source_lines_to_display.lines[idx]; 5160b4c26b2SJason Molenda const char *line_highlight = ""; 5170b4c26b2SJason Molenda if (inst_is_at_pc && (options & eOptionMarkPCSourceLine)) { 5180b4c26b2SJason Molenda line_highlight = "->"; 5190b4c26b2SJason Molenda } else if (idx == source_lines_to_display.current_source_line) { 5200b4c26b2SJason Molenda line_highlight = "**"; 5210b4c26b2SJason Molenda } 5220b4c26b2SJason Molenda source_manager.DisplaySourceLinesWithLineNumbers( 5239666ba75STodd Fiala ln.file, ln.line, ln.column, 0, 0, line_highlight, &strm); 5240b4c26b2SJason Molenda } 5250b4c26b2SJason Molenda if (source_lines_to_display.print_source_context_end_eol) 5260b4c26b2SJason Molenda strm.EOL(); 5270b4c26b2SJason Molenda } 5280b4c26b2SJason Molenda 5291da6f9d7SGreg Clayton const bool show_bytes = (options & eOptionShowBytes) != 0; 530*ad7bcda9SWalter Erquinigo const bool show_control_flow_kind = 531*ad7bcda9SWalter Erquinigo (options & eOptionShowControlFlowKind) != 0; 532*ad7bcda9SWalter Erquinigo inst->Dump(&strm, max_opcode_byte_size, true, show_bytes, 533*ad7bcda9SWalter Erquinigo show_control_flow_kind, &exe_ctx, &sc, &prev_sc, nullptr, 534*ad7bcda9SWalter Erquinigo 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 574*ad7bcda9SWalter Erquinigo namespace x86 { 575*ad7bcda9SWalter Erquinigo 576*ad7bcda9SWalter Erquinigo /// These are the three values deciding instruction control flow kind. 577*ad7bcda9SWalter Erquinigo /// InstructionLengthDecode function decodes an instruction and get this struct. 578*ad7bcda9SWalter Erquinigo /// 579*ad7bcda9SWalter Erquinigo /// primary_opcode 580*ad7bcda9SWalter Erquinigo /// Primary opcode of the instruction. 581*ad7bcda9SWalter Erquinigo /// For one-byte opcode instruction, it's the first byte after prefix. 582*ad7bcda9SWalter Erquinigo /// For two- and three-byte opcodes, it's the second byte. 583*ad7bcda9SWalter Erquinigo /// 584*ad7bcda9SWalter Erquinigo /// opcode_len 585*ad7bcda9SWalter Erquinigo /// The length of opcode in bytes. Valid opcode lengths are 1, 2, or 3. 586*ad7bcda9SWalter Erquinigo /// 587*ad7bcda9SWalter Erquinigo /// modrm 588*ad7bcda9SWalter Erquinigo /// ModR/M byte of the instruction. 589*ad7bcda9SWalter Erquinigo /// Bits[7:6] indicate MOD. Bits[5:3] specify a register and R/M bits[2:0] 590*ad7bcda9SWalter Erquinigo /// may contain a register or specify an addressing mode, depending on MOD. 591*ad7bcda9SWalter Erquinigo struct InstructionOpcodeAndModrm { 592*ad7bcda9SWalter Erquinigo uint8_t primary_opcode; 593*ad7bcda9SWalter Erquinigo uint8_t opcode_len; 594*ad7bcda9SWalter Erquinigo uint8_t modrm; 595*ad7bcda9SWalter Erquinigo }; 596*ad7bcda9SWalter Erquinigo 597*ad7bcda9SWalter Erquinigo /// Determine the InstructionControlFlowKind based on opcode and modrm bytes. 598*ad7bcda9SWalter Erquinigo /// Refer to http://ref.x86asm.net/coder.html for the full list of opcode and 599*ad7bcda9SWalter Erquinigo /// instruction set. 600*ad7bcda9SWalter Erquinigo /// 601*ad7bcda9SWalter Erquinigo /// \param[in] opcode_and_modrm 602*ad7bcda9SWalter Erquinigo /// Contains primary_opcode byte, its length, and ModR/M byte. 603*ad7bcda9SWalter Erquinigo /// Refer to the struct InstructionOpcodeAndModrm for details. 604*ad7bcda9SWalter Erquinigo /// 605*ad7bcda9SWalter Erquinigo /// \return 606*ad7bcda9SWalter Erquinigo /// The control flow kind of the instruction or 607*ad7bcda9SWalter Erquinigo /// eInstructionControlFlowKindOther if the instruction doesn't affect 608*ad7bcda9SWalter Erquinigo /// the control flow of the program. 609*ad7bcda9SWalter Erquinigo lldb::InstructionControlFlowKind 610*ad7bcda9SWalter Erquinigo MapOpcodeIntoControlFlowKind(InstructionOpcodeAndModrm opcode_and_modrm) { 611*ad7bcda9SWalter Erquinigo uint8_t opcode = opcode_and_modrm.primary_opcode; 612*ad7bcda9SWalter Erquinigo uint8_t opcode_len = opcode_and_modrm.opcode_len; 613*ad7bcda9SWalter Erquinigo uint8_t modrm = opcode_and_modrm.modrm; 614*ad7bcda9SWalter Erquinigo 615*ad7bcda9SWalter Erquinigo if (opcode_len > 2) 616*ad7bcda9SWalter Erquinigo return lldb::eInstructionControlFlowKindOther; 617*ad7bcda9SWalter Erquinigo 618*ad7bcda9SWalter Erquinigo if (opcode >= 0x70 && opcode <= 0x7F) { 619*ad7bcda9SWalter Erquinigo if (opcode_len == 1) 620*ad7bcda9SWalter Erquinigo return lldb::eInstructionControlFlowKindCondJump; 621*ad7bcda9SWalter Erquinigo else 622*ad7bcda9SWalter Erquinigo return lldb::eInstructionControlFlowKindOther; 623*ad7bcda9SWalter Erquinigo } 624*ad7bcda9SWalter Erquinigo 625*ad7bcda9SWalter Erquinigo if (opcode >= 0x80 && opcode <= 0x8F) { 626*ad7bcda9SWalter Erquinigo if (opcode_len == 2) 627*ad7bcda9SWalter Erquinigo return lldb::eInstructionControlFlowKindCondJump; 628*ad7bcda9SWalter Erquinigo else 629*ad7bcda9SWalter Erquinigo return lldb::eInstructionControlFlowKindOther; 630*ad7bcda9SWalter Erquinigo } 631*ad7bcda9SWalter Erquinigo 632*ad7bcda9SWalter Erquinigo switch (opcode) { 633*ad7bcda9SWalter Erquinigo case 0x9A: 634*ad7bcda9SWalter Erquinigo if (opcode_len == 1) 635*ad7bcda9SWalter Erquinigo return lldb::eInstructionControlFlowKindFarCall; 636*ad7bcda9SWalter Erquinigo break; 637*ad7bcda9SWalter Erquinigo case 0xFF: 638*ad7bcda9SWalter Erquinigo if (opcode_len == 1) { 639*ad7bcda9SWalter Erquinigo uint8_t modrm_reg = (modrm >> 3) & 7; 640*ad7bcda9SWalter Erquinigo if (modrm_reg == 2) 641*ad7bcda9SWalter Erquinigo return lldb::eInstructionControlFlowKindCall; 642*ad7bcda9SWalter Erquinigo else if (modrm_reg == 3) 643*ad7bcda9SWalter Erquinigo return lldb::eInstructionControlFlowKindFarCall; 644*ad7bcda9SWalter Erquinigo else if (modrm_reg == 4) 645*ad7bcda9SWalter Erquinigo return lldb::eInstructionControlFlowKindJump; 646*ad7bcda9SWalter Erquinigo else if (modrm_reg == 5) 647*ad7bcda9SWalter Erquinigo return lldb::eInstructionControlFlowKindFarJump; 648*ad7bcda9SWalter Erquinigo } 649*ad7bcda9SWalter Erquinigo break; 650*ad7bcda9SWalter Erquinigo case 0xE8: 651*ad7bcda9SWalter Erquinigo if (opcode_len == 1) 652*ad7bcda9SWalter Erquinigo return lldb::eInstructionControlFlowKindCall; 653*ad7bcda9SWalter Erquinigo break; 654*ad7bcda9SWalter Erquinigo case 0xCD: 655*ad7bcda9SWalter Erquinigo case 0xCC: 656*ad7bcda9SWalter Erquinigo case 0xCE: 657*ad7bcda9SWalter Erquinigo case 0xF1: 658*ad7bcda9SWalter Erquinigo if (opcode_len == 1) 659*ad7bcda9SWalter Erquinigo return lldb::eInstructionControlFlowKindFarCall; 660*ad7bcda9SWalter Erquinigo break; 661*ad7bcda9SWalter Erquinigo case 0xCF: 662*ad7bcda9SWalter Erquinigo if (opcode_len == 1) 663*ad7bcda9SWalter Erquinigo return lldb::eInstructionControlFlowKindFarReturn; 664*ad7bcda9SWalter Erquinigo break; 665*ad7bcda9SWalter Erquinigo case 0xE9: 666*ad7bcda9SWalter Erquinigo case 0xEB: 667*ad7bcda9SWalter Erquinigo if (opcode_len == 1) 668*ad7bcda9SWalter Erquinigo return lldb::eInstructionControlFlowKindJump; 669*ad7bcda9SWalter Erquinigo break; 670*ad7bcda9SWalter Erquinigo case 0xEA: 671*ad7bcda9SWalter Erquinigo if (opcode_len == 1) 672*ad7bcda9SWalter Erquinigo return lldb::eInstructionControlFlowKindFarJump; 673*ad7bcda9SWalter Erquinigo break; 674*ad7bcda9SWalter Erquinigo case 0xE3: 675*ad7bcda9SWalter Erquinigo case 0xE0: 676*ad7bcda9SWalter Erquinigo case 0xE1: 677*ad7bcda9SWalter Erquinigo case 0xE2: 678*ad7bcda9SWalter Erquinigo if (opcode_len == 1) 679*ad7bcda9SWalter Erquinigo return lldb::eInstructionControlFlowKindCondJump; 680*ad7bcda9SWalter Erquinigo break; 681*ad7bcda9SWalter Erquinigo case 0xC3: 682*ad7bcda9SWalter Erquinigo case 0xC2: 683*ad7bcda9SWalter Erquinigo if (opcode_len == 1) 684*ad7bcda9SWalter Erquinigo return lldb::eInstructionControlFlowKindReturn; 685*ad7bcda9SWalter Erquinigo break; 686*ad7bcda9SWalter Erquinigo case 0xCB: 687*ad7bcda9SWalter Erquinigo case 0xCA: 688*ad7bcda9SWalter Erquinigo if (opcode_len == 1) 689*ad7bcda9SWalter Erquinigo return lldb::eInstructionControlFlowKindFarReturn; 690*ad7bcda9SWalter Erquinigo break; 691*ad7bcda9SWalter Erquinigo case 0x05: 692*ad7bcda9SWalter Erquinigo case 0x34: 693*ad7bcda9SWalter Erquinigo if (opcode_len == 2) 694*ad7bcda9SWalter Erquinigo return lldb::eInstructionControlFlowKindFarCall; 695*ad7bcda9SWalter Erquinigo break; 696*ad7bcda9SWalter Erquinigo case 0x35: 697*ad7bcda9SWalter Erquinigo case 0x07: 698*ad7bcda9SWalter Erquinigo if (opcode_len == 2) 699*ad7bcda9SWalter Erquinigo return lldb::eInstructionControlFlowKindFarReturn; 700*ad7bcda9SWalter Erquinigo break; 701*ad7bcda9SWalter Erquinigo case 0x01: 702*ad7bcda9SWalter Erquinigo if (opcode_len == 2) { 703*ad7bcda9SWalter Erquinigo switch (modrm) { 704*ad7bcda9SWalter Erquinigo case 0xc1: 705*ad7bcda9SWalter Erquinigo return lldb::eInstructionControlFlowKindFarCall; 706*ad7bcda9SWalter Erquinigo case 0xc2: 707*ad7bcda9SWalter Erquinigo case 0xc3: 708*ad7bcda9SWalter Erquinigo return lldb::eInstructionControlFlowKindFarReturn; 709*ad7bcda9SWalter Erquinigo default: 710*ad7bcda9SWalter Erquinigo break; 711*ad7bcda9SWalter Erquinigo } 712*ad7bcda9SWalter Erquinigo } 713*ad7bcda9SWalter Erquinigo break; 714*ad7bcda9SWalter Erquinigo default: 715*ad7bcda9SWalter Erquinigo break; 716*ad7bcda9SWalter Erquinigo } 717*ad7bcda9SWalter Erquinigo 718*ad7bcda9SWalter Erquinigo return lldb::eInstructionControlFlowKindOther; 719*ad7bcda9SWalter Erquinigo } 720*ad7bcda9SWalter Erquinigo 721*ad7bcda9SWalter Erquinigo /// Decode an instruction into opcode, modrm and opcode_len. 722*ad7bcda9SWalter Erquinigo /// Refer to http://ref.x86asm.net/coder.html for the instruction bytes layout. 723*ad7bcda9SWalter Erquinigo /// Opcodes in x86 are generally the first byte of instruction, though two-byte 724*ad7bcda9SWalter Erquinigo /// instructions and prefixes exist. ModR/M is the byte following the opcode 725*ad7bcda9SWalter Erquinigo /// and adds additional information for how the instruction is executed. 726*ad7bcda9SWalter Erquinigo /// 727*ad7bcda9SWalter Erquinigo /// \param[in] inst_bytes 728*ad7bcda9SWalter Erquinigo /// Raw bytes of the instruction 729*ad7bcda9SWalter Erquinigo /// 730*ad7bcda9SWalter Erquinigo /// 731*ad7bcda9SWalter Erquinigo /// \param[in] bytes_len 732*ad7bcda9SWalter Erquinigo /// The length of the inst_bytes array. 733*ad7bcda9SWalter Erquinigo /// 734*ad7bcda9SWalter Erquinigo /// \param[in] is_exec_mode_64b 735*ad7bcda9SWalter Erquinigo /// If true, the execution mode is 64 bit. 736*ad7bcda9SWalter Erquinigo /// 737*ad7bcda9SWalter Erquinigo /// \return 738*ad7bcda9SWalter Erquinigo /// Returns decoded instruction as struct InstructionOpcodeAndModrm, holding 739*ad7bcda9SWalter Erquinigo /// primary_opcode, opcode_len and modrm byte. Refer to the struct definition 740*ad7bcda9SWalter Erquinigo /// for more details. 741*ad7bcda9SWalter Erquinigo /// Otherwise if the given instruction is invalid, returns None. 742*ad7bcda9SWalter Erquinigo llvm::Optional<InstructionOpcodeAndModrm> 743*ad7bcda9SWalter Erquinigo InstructionLengthDecode(const uint8_t *inst_bytes, int bytes_len, 744*ad7bcda9SWalter Erquinigo bool is_exec_mode_64b) { 745*ad7bcda9SWalter Erquinigo int op_idx = 0; 746*ad7bcda9SWalter Erquinigo bool prefix_done = false; 747*ad7bcda9SWalter Erquinigo InstructionOpcodeAndModrm ret = {0, 0, 0}; 748*ad7bcda9SWalter Erquinigo 749*ad7bcda9SWalter Erquinigo // In most cases, the primary_opcode is the first byte of the instruction 750*ad7bcda9SWalter Erquinigo // but some instructions have a prefix to be skipped for these calculations. 751*ad7bcda9SWalter Erquinigo // The following mapping is inspired from libipt's instruction decoding logic 752*ad7bcda9SWalter Erquinigo // in `src/pt_ild.c` 753*ad7bcda9SWalter Erquinigo while (!prefix_done) { 754*ad7bcda9SWalter Erquinigo if (op_idx >= bytes_len) 755*ad7bcda9SWalter Erquinigo return llvm::None; 756*ad7bcda9SWalter Erquinigo 757*ad7bcda9SWalter Erquinigo ret.primary_opcode = inst_bytes[op_idx]; 758*ad7bcda9SWalter Erquinigo switch (ret.primary_opcode) { 759*ad7bcda9SWalter Erquinigo // prefix_ignore 760*ad7bcda9SWalter Erquinigo case 0x26: 761*ad7bcda9SWalter Erquinigo case 0x2e: 762*ad7bcda9SWalter Erquinigo case 0x36: 763*ad7bcda9SWalter Erquinigo case 0x3e: 764*ad7bcda9SWalter Erquinigo case 0x64: 765*ad7bcda9SWalter Erquinigo case 0x65: 766*ad7bcda9SWalter Erquinigo // prefix_osz, prefix_asz 767*ad7bcda9SWalter Erquinigo case 0x66: 768*ad7bcda9SWalter Erquinigo case 0x67: 769*ad7bcda9SWalter Erquinigo // prefix_lock, prefix_f2, prefix_f3 770*ad7bcda9SWalter Erquinigo case 0xf0: 771*ad7bcda9SWalter Erquinigo case 0xf2: 772*ad7bcda9SWalter Erquinigo case 0xf3: 773*ad7bcda9SWalter Erquinigo op_idx++; 774*ad7bcda9SWalter Erquinigo break; 775*ad7bcda9SWalter Erquinigo 776*ad7bcda9SWalter Erquinigo // prefix_rex 777*ad7bcda9SWalter Erquinigo case 0x40: 778*ad7bcda9SWalter Erquinigo case 0x41: 779*ad7bcda9SWalter Erquinigo case 0x42: 780*ad7bcda9SWalter Erquinigo case 0x43: 781*ad7bcda9SWalter Erquinigo case 0x44: 782*ad7bcda9SWalter Erquinigo case 0x45: 783*ad7bcda9SWalter Erquinigo case 0x46: 784*ad7bcda9SWalter Erquinigo case 0x47: 785*ad7bcda9SWalter Erquinigo case 0x48: 786*ad7bcda9SWalter Erquinigo case 0x49: 787*ad7bcda9SWalter Erquinigo case 0x4a: 788*ad7bcda9SWalter Erquinigo case 0x4b: 789*ad7bcda9SWalter Erquinigo case 0x4c: 790*ad7bcda9SWalter Erquinigo case 0x4d: 791*ad7bcda9SWalter Erquinigo case 0x4e: 792*ad7bcda9SWalter Erquinigo case 0x4f: 793*ad7bcda9SWalter Erquinigo if (is_exec_mode_64b) 794*ad7bcda9SWalter Erquinigo op_idx++; 795*ad7bcda9SWalter Erquinigo else 796*ad7bcda9SWalter Erquinigo prefix_done = true; 797*ad7bcda9SWalter Erquinigo break; 798*ad7bcda9SWalter Erquinigo 799*ad7bcda9SWalter Erquinigo // prefix_vex_c4, c5 800*ad7bcda9SWalter Erquinigo case 0xc5: 801*ad7bcda9SWalter Erquinigo if (!is_exec_mode_64b && (inst_bytes[op_idx + 1] & 0xc0) != 0xc0) { 802*ad7bcda9SWalter Erquinigo prefix_done = true; 803*ad7bcda9SWalter Erquinigo break; 804*ad7bcda9SWalter Erquinigo } 805*ad7bcda9SWalter Erquinigo 806*ad7bcda9SWalter Erquinigo ret.opcode_len = 2; 807*ad7bcda9SWalter Erquinigo ret.primary_opcode = inst_bytes[op_idx + 2]; 808*ad7bcda9SWalter Erquinigo ret.modrm = inst_bytes[op_idx + 3]; 809*ad7bcda9SWalter Erquinigo return ret; 810*ad7bcda9SWalter Erquinigo 811*ad7bcda9SWalter Erquinigo case 0xc4: 812*ad7bcda9SWalter Erquinigo if (!is_exec_mode_64b && (inst_bytes[op_idx + 1] & 0xc0) != 0xc0) { 813*ad7bcda9SWalter Erquinigo prefix_done = true; 814*ad7bcda9SWalter Erquinigo break; 815*ad7bcda9SWalter Erquinigo } 816*ad7bcda9SWalter Erquinigo ret.opcode_len = inst_bytes[op_idx + 1] & 0x1f; 817*ad7bcda9SWalter Erquinigo ret.primary_opcode = inst_bytes[op_idx + 3]; 818*ad7bcda9SWalter Erquinigo ret.modrm = inst_bytes[op_idx + 4]; 819*ad7bcda9SWalter Erquinigo return ret; 820*ad7bcda9SWalter Erquinigo 821*ad7bcda9SWalter Erquinigo // prefix_evex 822*ad7bcda9SWalter Erquinigo case 0x62: 823*ad7bcda9SWalter Erquinigo if (!is_exec_mode_64b && (inst_bytes[op_idx + 1] & 0xc0) != 0xc0) { 824*ad7bcda9SWalter Erquinigo prefix_done = true; 825*ad7bcda9SWalter Erquinigo break; 826*ad7bcda9SWalter Erquinigo } 827*ad7bcda9SWalter Erquinigo ret.opcode_len = inst_bytes[op_idx + 1] & 0x03; 828*ad7bcda9SWalter Erquinigo ret.primary_opcode = inst_bytes[op_idx + 4]; 829*ad7bcda9SWalter Erquinigo ret.modrm = inst_bytes[op_idx + 5]; 830*ad7bcda9SWalter Erquinigo return ret; 831*ad7bcda9SWalter Erquinigo 832*ad7bcda9SWalter Erquinigo default: 833*ad7bcda9SWalter Erquinigo prefix_done = true; 834*ad7bcda9SWalter Erquinigo break; 835*ad7bcda9SWalter Erquinigo } 836*ad7bcda9SWalter Erquinigo } // prefix done 837*ad7bcda9SWalter Erquinigo 838*ad7bcda9SWalter Erquinigo ret.primary_opcode = inst_bytes[op_idx]; 839*ad7bcda9SWalter Erquinigo ret.modrm = inst_bytes[op_idx + 1]; 840*ad7bcda9SWalter Erquinigo ret.opcode_len = 1; 841*ad7bcda9SWalter Erquinigo 842*ad7bcda9SWalter Erquinigo // If the first opcode is 0F, it's two- or three- byte opcodes. 843*ad7bcda9SWalter Erquinigo if (ret.primary_opcode == 0x0F) { 844*ad7bcda9SWalter Erquinigo ret.primary_opcode = inst_bytes[++op_idx]; // get the next byte 845*ad7bcda9SWalter Erquinigo 846*ad7bcda9SWalter Erquinigo if (ret.primary_opcode == 0x38) { 847*ad7bcda9SWalter Erquinigo ret.opcode_len = 3; 848*ad7bcda9SWalter Erquinigo ret.primary_opcode = inst_bytes[++op_idx]; // get the next byte 849*ad7bcda9SWalter Erquinigo ret.modrm = inst_bytes[op_idx + 1]; 850*ad7bcda9SWalter Erquinigo } else if (ret.primary_opcode == 0x3A) { 851*ad7bcda9SWalter Erquinigo ret.opcode_len = 3; 852*ad7bcda9SWalter Erquinigo ret.primary_opcode = inst_bytes[++op_idx]; 853*ad7bcda9SWalter Erquinigo ret.modrm = inst_bytes[op_idx + 1]; 854*ad7bcda9SWalter Erquinigo } else if ((ret.primary_opcode & 0xf8) == 0x38) { 855*ad7bcda9SWalter Erquinigo ret.opcode_len = 0; 856*ad7bcda9SWalter Erquinigo ret.primary_opcode = inst_bytes[++op_idx]; 857*ad7bcda9SWalter Erquinigo ret.modrm = inst_bytes[op_idx + 1]; 858*ad7bcda9SWalter Erquinigo } else if (ret.primary_opcode == 0x0F) { 859*ad7bcda9SWalter Erquinigo ret.opcode_len = 3; 860*ad7bcda9SWalter Erquinigo // opcode is 0x0F, no needs to update 861*ad7bcda9SWalter Erquinigo ret.modrm = inst_bytes[op_idx + 1]; 862*ad7bcda9SWalter Erquinigo } else { 863*ad7bcda9SWalter Erquinigo ret.opcode_len = 2; 864*ad7bcda9SWalter Erquinigo ret.modrm = inst_bytes[op_idx + 1]; 865*ad7bcda9SWalter Erquinigo } 866*ad7bcda9SWalter Erquinigo } 867*ad7bcda9SWalter Erquinigo 868*ad7bcda9SWalter Erquinigo return ret; 869*ad7bcda9SWalter Erquinigo } 870*ad7bcda9SWalter Erquinigo 871*ad7bcda9SWalter Erquinigo lldb::InstructionControlFlowKind GetControlFlowKind(bool is_exec_mode_64b, 872*ad7bcda9SWalter Erquinigo Opcode m_opcode) { 873*ad7bcda9SWalter Erquinigo llvm::Optional<InstructionOpcodeAndModrm> ret = llvm::None; 874*ad7bcda9SWalter Erquinigo 875*ad7bcda9SWalter Erquinigo if (m_opcode.GetOpcodeBytes() == nullptr || m_opcode.GetByteSize() <= 0) { 876*ad7bcda9SWalter Erquinigo // x86_64 and i386 instructions are categorized as Opcode::Type::eTypeBytes 877*ad7bcda9SWalter Erquinigo return lldb::eInstructionControlFlowKindUnknown; 878*ad7bcda9SWalter Erquinigo } 879*ad7bcda9SWalter Erquinigo 880*ad7bcda9SWalter Erquinigo // Opcode bytes will be decoded into primary_opcode, modrm and opcode length. 881*ad7bcda9SWalter Erquinigo // These are the three values deciding instruction control flow kind. 882*ad7bcda9SWalter Erquinigo ret = InstructionLengthDecode((const uint8_t *)m_opcode.GetOpcodeBytes(), 883*ad7bcda9SWalter Erquinigo m_opcode.GetByteSize(), is_exec_mode_64b); 884*ad7bcda9SWalter Erquinigo if (!ret) 885*ad7bcda9SWalter Erquinigo return lldb::eInstructionControlFlowKindUnknown; 886*ad7bcda9SWalter Erquinigo else 887*ad7bcda9SWalter Erquinigo return MapOpcodeIntoControlFlowKind(ret.value()); 888*ad7bcda9SWalter Erquinigo } 889*ad7bcda9SWalter Erquinigo 890*ad7bcda9SWalter Erquinigo } // namespace x86 891*ad7bcda9SWalter Erquinigo 892*ad7bcda9SWalter Erquinigo lldb::InstructionControlFlowKind 893*ad7bcda9SWalter Erquinigo Instruction::GetControlFlowKind(const ArchSpec &arch) { 894*ad7bcda9SWalter Erquinigo if (arch.GetTriple().getArch() == llvm::Triple::x86) 895*ad7bcda9SWalter Erquinigo return x86::GetControlFlowKind(/*is_exec_mode_64b=*/false, m_opcode); 896*ad7bcda9SWalter Erquinigo else if (arch.GetTriple().getArch() == llvm::Triple::x86_64) 897*ad7bcda9SWalter Erquinigo return x86::GetControlFlowKind(/*is_exec_mode_64b=*/true, m_opcode); 898*ad7bcda9SWalter Erquinigo else 899*ad7bcda9SWalter Erquinigo return eInstructionControlFlowKindUnknown; // not implemented 900*ad7bcda9SWalter Erquinigo } 901*ad7bcda9SWalter Erquinigo 902b9c1b51eSKate Stone AddressClass Instruction::GetAddressClass() { 90304803b3eSTatyana Krasnukha if (m_address_class == AddressClass::eInvalid) 904357132ebSGreg Clayton m_address_class = m_address.GetAddressClass(); 905357132ebSGreg Clayton return m_address_class; 906357132ebSGreg Clayton } 90730fdc8d8SChris Lattner 908b9c1b51eSKate Stone void Instruction::Dump(lldb_private::Stream *s, uint32_t max_opcode_byte_size, 909b9c1b51eSKate Stone bool show_address, bool show_bytes, 910*ad7bcda9SWalter Erquinigo bool show_control_flow_kind, 911aff1b357SJason Molenda const ExecutionContext *exe_ctx, 912aff1b357SJason Molenda const SymbolContext *sym_ctx, 913aff1b357SJason Molenda const SymbolContext *prev_sym_ctx, 914c980fa92SJason Molenda const FormatEntity::Entry *disassembly_addr_format, 915b9c1b51eSKate Stone size_t max_address_text_size) { 9167a37c1ecSJason Molenda size_t opcode_column_width = 7; 917ba812f42SGreg Clayton const size_t operand_column_width = 25; 918ba812f42SGreg Clayton 919ba812f42SGreg Clayton CalculateMnemonicOperandsAndCommentIfNeeded(exe_ctx); 920ba812f42SGreg Clayton 921ba812f42SGreg Clayton StreamString ss; 922ba812f42SGreg Clayton 923b9c1b51eSKate Stone if (show_address) { 924b9c1b51eSKate Stone Debugger::FormatDisassemblerAddress(disassembly_addr_format, sym_ctx, 925b9c1b51eSKate Stone prev_sym_ctx, exe_ctx, &m_address, ss); 926c980fa92SJason Molenda ss.FillLastLineToColumn(max_address_text_size, ' '); 927ba812f42SGreg Clayton } 928ba812f42SGreg Clayton 929b9c1b51eSKate Stone if (show_bytes) { 930b9c1b51eSKate Stone if (m_opcode.GetType() == Opcode::eTypeBytes) { 93105097246SAdrian Prantl // x86_64 and i386 are the only ones that use bytes right now so pad out 93205097246SAdrian Prantl // the byte dump to be able to always show 15 bytes (3 chars each) plus a 93305097246SAdrian Prantl // space 934ba812f42SGreg Clayton if (max_opcode_byte_size > 0) 935ba812f42SGreg Clayton m_opcode.Dump(&ss, max_opcode_byte_size * 3 + 1); 936ba812f42SGreg Clayton else 937ba812f42SGreg Clayton m_opcode.Dump(&ss, 15 * 3 + 1); 938b9c1b51eSKate Stone } else { 93905097246SAdrian Prantl // Else, we have ARM or MIPS which can show up to a uint32_t 0x00000000 94005097246SAdrian Prantl // (10 spaces) plus two for padding... 941ba812f42SGreg Clayton if (max_opcode_byte_size > 0) 942ba812f42SGreg Clayton m_opcode.Dump(&ss, max_opcode_byte_size * 3 + 1); 943ba812f42SGreg Clayton else 944ba812f42SGreg Clayton m_opcode.Dump(&ss, 12); 945ba812f42SGreg Clayton } 946ba812f42SGreg Clayton } 947ba812f42SGreg Clayton 948*ad7bcda9SWalter Erquinigo if (show_control_flow_kind) { 949*ad7bcda9SWalter Erquinigo switch (GetControlFlowKind(exe_ctx->GetTargetRef().GetArchitecture())) { 950*ad7bcda9SWalter Erquinigo case eInstructionControlFlowKindUnknown: 951*ad7bcda9SWalter Erquinigo ss.Printf("%-12s", "unknown"); 952*ad7bcda9SWalter Erquinigo break; 953*ad7bcda9SWalter Erquinigo case eInstructionControlFlowKindOther: 954*ad7bcda9SWalter Erquinigo ss.Printf("%-12s", "other"); 955*ad7bcda9SWalter Erquinigo break; 956*ad7bcda9SWalter Erquinigo case eInstructionControlFlowKindCall: 957*ad7bcda9SWalter Erquinigo ss.Printf("%-12s", "call"); 958*ad7bcda9SWalter Erquinigo break; 959*ad7bcda9SWalter Erquinigo case eInstructionControlFlowKindReturn: 960*ad7bcda9SWalter Erquinigo ss.Printf("%-12s", "return"); 961*ad7bcda9SWalter Erquinigo break; 962*ad7bcda9SWalter Erquinigo case eInstructionControlFlowKindJump: 963*ad7bcda9SWalter Erquinigo ss.Printf("%-12s", "jump"); 964*ad7bcda9SWalter Erquinigo break; 965*ad7bcda9SWalter Erquinigo case eInstructionControlFlowKindCondJump: 966*ad7bcda9SWalter Erquinigo ss.Printf("%-12s", "cond jump"); 967*ad7bcda9SWalter Erquinigo break; 968*ad7bcda9SWalter Erquinigo case eInstructionControlFlowKindFarCall: 969*ad7bcda9SWalter Erquinigo ss.Printf("%-12s", "far call"); 970*ad7bcda9SWalter Erquinigo break; 971*ad7bcda9SWalter Erquinigo case eInstructionControlFlowKindFarReturn: 972*ad7bcda9SWalter Erquinigo ss.Printf("%-12s", "far return"); 973*ad7bcda9SWalter Erquinigo break; 974*ad7bcda9SWalter Erquinigo case eInstructionControlFlowKindFarJump: 975*ad7bcda9SWalter Erquinigo ss.Printf("%-12s", "far jump"); 976*ad7bcda9SWalter Erquinigo break; 977*ad7bcda9SWalter Erquinigo } 978*ad7bcda9SWalter Erquinigo } 979*ad7bcda9SWalter Erquinigo 980aff1b357SJason Molenda const size_t opcode_pos = ss.GetSizeOfLastLine(); 981ba812f42SGreg Clayton 9827a37c1ecSJason Molenda // The default opcode size of 7 characters is plenty for most architectures 9837a37c1ecSJason Molenda // but some like arm can pull out the occasional vqrshrun.s16. We won't get 9847a37c1ecSJason Molenda // consistent column spacing in these cases, unfortunately. 985b9c1b51eSKate Stone if (m_opcode_name.length() >= opcode_column_width) { 9867a37c1ecSJason Molenda opcode_column_width = m_opcode_name.length() + 1; 9877a37c1ecSJason Molenda } 9887a37c1ecSJason Molenda 989771ef6d4SMalcolm Parsons ss.PutCString(m_opcode_name); 990ba812f42SGreg Clayton ss.FillLastLineToColumn(opcode_pos + opcode_column_width, ' '); 991771ef6d4SMalcolm Parsons ss.PutCString(m_mnemonics); 992ba812f42SGreg Clayton 993b9c1b51eSKate Stone if (!m_comment.empty()) { 994b9c1b51eSKate Stone ss.FillLastLineToColumn( 995b9c1b51eSKate Stone opcode_pos + opcode_column_width + operand_column_width, ' '); 996ba812f42SGreg Clayton ss.PutCString(" ; "); 997771ef6d4SMalcolm Parsons ss.PutCString(m_comment); 998ba812f42SGreg Clayton } 999c156427dSZachary Turner s->PutCString(ss.GetString()); 1000ba812f42SGreg Clayton } 1001ba812f42SGreg Clayton 1002b9c1b51eSKate Stone bool Instruction::DumpEmulation(const ArchSpec &arch) { 1003d5b44036SJonas Devlieghere std::unique_ptr<EmulateInstruction> insn_emulator_up( 1004b9c1b51eSKate Stone EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr)); 1005d5b44036SJonas Devlieghere if (insn_emulator_up) { 1006d5b44036SJonas Devlieghere insn_emulator_up->SetInstruction(GetOpcode(), GetAddress(), nullptr); 1007d5b44036SJonas Devlieghere return insn_emulator_up->EvaluateInstruction(0); 10087c9dd3ceSCaroline Tice } 10097c9dd3ceSCaroline Tice 10107c9dd3ceSCaroline Tice return false; 10117c9dd3ceSCaroline Tice } 10127c9dd3ceSCaroline Tice 1013dd125943SNitesh Jain bool Instruction::CanSetBreakpoint () { 1014dd125943SNitesh Jain return !HasDelaySlot(); 1015dd125943SNitesh Jain } 1016dd125943SNitesh Jain 1017b9c1b51eSKate Stone bool Instruction::HasDelaySlot() { 10187f3daedaSBhushan D. Attarde // Default is false. 10197f3daedaSBhushan D. Attarde return false; 10207f3daedaSBhushan D. Attarde } 10217f3daedaSBhushan D. Attarde 1022b9c1b51eSKate Stone OptionValueSP Instruction::ReadArray(FILE *in_file, Stream *out_stream, 1023b9c1b51eSKate Stone OptionValue::Type data_type) { 1024de2fb9cfSCaroline Tice bool done = false; 1025de2fb9cfSCaroline Tice char buffer[1024]; 1026de2fb9cfSCaroline Tice 10272f3df613SZachary Turner auto option_value_sp = std::make_shared<OptionValueArray>(1u << data_type); 1028de2fb9cfSCaroline Tice 1029de2fb9cfSCaroline Tice int idx = 0; 1030b9c1b51eSKate Stone while (!done) { 1031b9c1b51eSKate Stone if (!fgets(buffer, 1023, in_file)) { 1032b9c1b51eSKate Stone out_stream->Printf( 1033b9c1b51eSKate Stone "Instruction::ReadArray: Error reading file (fgets).\n"); 1034de2fb9cfSCaroline Tice option_value_sp.reset(); 1035de2fb9cfSCaroline Tice return option_value_sp; 1036de2fb9cfSCaroline Tice } 1037de2fb9cfSCaroline Tice 1038de2fb9cfSCaroline Tice std::string line(buffer); 1039de2fb9cfSCaroline Tice 1040c7bece56SGreg Clayton size_t len = line.size(); 1041b9c1b51eSKate Stone if (line[len - 1] == '\n') { 1042de2fb9cfSCaroline Tice line[len - 1] = '\0'; 1043de2fb9cfSCaroline Tice line.resize(len - 1); 1044de2fb9cfSCaroline Tice } 1045de2fb9cfSCaroline Tice 1046b9c1b51eSKate Stone if ((line.size() == 1) && line[0] == ']') { 1047de2fb9cfSCaroline Tice done = true; 1048de2fb9cfSCaroline Tice line.clear(); 1049de2fb9cfSCaroline Tice } 1050de2fb9cfSCaroline Tice 1051b9c1b51eSKate Stone if (!line.empty()) { 1052de2fb9cfSCaroline Tice std::string value; 105395eae423SZachary Turner static RegularExpression g_reg_exp( 105495eae423SZachary Turner llvm::StringRef("^[ \t]*([^ \t]+)[ \t]*$")); 10553af3f1e8SJonas Devlieghere llvm::SmallVector<llvm::StringRef, 2> matches; 10563af3f1e8SJonas Devlieghere if (g_reg_exp.Execute(line, &matches)) 10573af3f1e8SJonas Devlieghere value = matches[1].str(); 1058de2fb9cfSCaroline Tice else 1059de2fb9cfSCaroline Tice value = line; 1060de2fb9cfSCaroline Tice 1061de2fb9cfSCaroline Tice OptionValueSP data_value_sp; 1062b9c1b51eSKate Stone switch (data_type) { 1063de2fb9cfSCaroline Tice case OptionValue::eTypeUInt64: 10642f3df613SZachary Turner data_value_sp = std::make_shared<OptionValueUInt64>(0, 0); 1065c95f7e2aSPavel Labath data_value_sp->SetValueFromString(value); 1066de2fb9cfSCaroline Tice break; 1067de2fb9cfSCaroline Tice // Other types can be added later as needed. 1068de2fb9cfSCaroline Tice default: 10692f3df613SZachary Turner data_value_sp = std::make_shared<OptionValueString>(value.c_str(), ""); 1070de2fb9cfSCaroline Tice break; 1071de2fb9cfSCaroline Tice } 1072de2fb9cfSCaroline Tice 107384c39663SGreg Clayton option_value_sp->GetAsArray()->InsertValue(idx, data_value_sp); 1074de2fb9cfSCaroline Tice ++idx; 1075de2fb9cfSCaroline Tice } 1076de2fb9cfSCaroline Tice } 1077de2fb9cfSCaroline Tice 1078de2fb9cfSCaroline Tice return option_value_sp; 1079de2fb9cfSCaroline Tice } 1080de2fb9cfSCaroline Tice 1081b9c1b51eSKate Stone OptionValueSP Instruction::ReadDictionary(FILE *in_file, Stream *out_stream) { 1082de2fb9cfSCaroline Tice bool done = false; 1083de2fb9cfSCaroline Tice char buffer[1024]; 1084de2fb9cfSCaroline Tice 10852f3df613SZachary Turner auto option_value_sp = std::make_shared<OptionValueDictionary>(); 1086de2fb9cfSCaroline Tice static ConstString encoding_key("data_encoding"); 1087de2fb9cfSCaroline Tice OptionValue::Type data_type = OptionValue::eTypeInvalid; 1088de2fb9cfSCaroline Tice 1089b9c1b51eSKate Stone while (!done) { 1090de2fb9cfSCaroline Tice // Read the next line in the file 1091b9c1b51eSKate Stone if (!fgets(buffer, 1023, in_file)) { 1092b9c1b51eSKate Stone out_stream->Printf( 1093b9c1b51eSKate Stone "Instruction::ReadDictionary: Error reading file (fgets).\n"); 1094de2fb9cfSCaroline Tice option_value_sp.reset(); 1095de2fb9cfSCaroline Tice return option_value_sp; 1096de2fb9cfSCaroline Tice } 1097de2fb9cfSCaroline Tice 1098de2fb9cfSCaroline Tice // Check to see if the line contains the end-of-dictionary marker ("}") 1099de2fb9cfSCaroline Tice std::string line(buffer); 1100de2fb9cfSCaroline Tice 1101c7bece56SGreg Clayton size_t len = line.size(); 1102b9c1b51eSKate Stone if (line[len - 1] == '\n') { 1103de2fb9cfSCaroline Tice line[len - 1] = '\0'; 1104de2fb9cfSCaroline Tice line.resize(len - 1); 1105de2fb9cfSCaroline Tice } 1106de2fb9cfSCaroline Tice 1107b9c1b51eSKate Stone if ((line.size() == 1) && (line[0] == '}')) { 1108de2fb9cfSCaroline Tice done = true; 1109de2fb9cfSCaroline Tice line.clear(); 1110de2fb9cfSCaroline Tice } 1111de2fb9cfSCaroline Tice 1112b9c1b51eSKate Stone // Try to find a key-value pair in the current line and add it to the 1113b9c1b51eSKate Stone // dictionary. 1114b9c1b51eSKate Stone if (!line.empty()) { 111595eae423SZachary Turner static RegularExpression g_reg_exp(llvm::StringRef( 111695eae423SZachary Turner "^[ \t]*([a-zA-Z_][a-zA-Z0-9_]*)[ \t]*=[ \t]*(.*)[ \t]*$")); 1117bc43cab5SGreg Clayton 11183af3f1e8SJonas Devlieghere llvm::SmallVector<llvm::StringRef, 3> matches; 11193af3f1e8SJonas Devlieghere 11203af3f1e8SJonas Devlieghere bool reg_exp_success = g_reg_exp.Execute(line, &matches); 1121de2fb9cfSCaroline Tice std::string key; 1122de2fb9cfSCaroline Tice std::string value; 1123b9c1b51eSKate Stone if (reg_exp_success) { 11243af3f1e8SJonas Devlieghere key = matches[1].str(); 11253af3f1e8SJonas Devlieghere value = matches[2].str(); 1126b9c1b51eSKate Stone } else { 1127b9c1b51eSKate Stone out_stream->Printf("Instruction::ReadDictionary: Failure executing " 1128b9c1b51eSKate Stone "regular expression.\n"); 1129de2fb9cfSCaroline Tice option_value_sp.reset(); 1130de2fb9cfSCaroline Tice return option_value_sp; 1131de2fb9cfSCaroline Tice } 1132de2fb9cfSCaroline Tice 1133de2fb9cfSCaroline Tice ConstString const_key(key.c_str()); 1134de2fb9cfSCaroline Tice // Check value to see if it's the start of an array or dictionary. 1135de2fb9cfSCaroline Tice 1136de2fb9cfSCaroline Tice lldb::OptionValueSP value_sp; 1137de2fb9cfSCaroline Tice assert(value.empty() == false); 1138de2fb9cfSCaroline Tice assert(key.empty() == false); 1139de2fb9cfSCaroline Tice 1140b9c1b51eSKate Stone if (value[0] == '{') { 1141de2fb9cfSCaroline Tice assert(value.size() == 1); 1142de2fb9cfSCaroline Tice // value is a dictionary 1143de2fb9cfSCaroline Tice value_sp = ReadDictionary(in_file, out_stream); 1144b9c1b51eSKate Stone if (!value_sp) { 1145de2fb9cfSCaroline Tice option_value_sp.reset(); 1146de2fb9cfSCaroline Tice return option_value_sp; 1147de2fb9cfSCaroline Tice } 1148b9c1b51eSKate Stone } else if (value[0] == '[') { 1149de2fb9cfSCaroline Tice assert(value.size() == 1); 1150de2fb9cfSCaroline Tice // value is an array 1151de2fb9cfSCaroline Tice value_sp = ReadArray(in_file, out_stream, data_type); 1152b9c1b51eSKate Stone if (!value_sp) { 1153de2fb9cfSCaroline Tice option_value_sp.reset(); 1154de2fb9cfSCaroline Tice return option_value_sp; 1155de2fb9cfSCaroline Tice } 115605097246SAdrian Prantl // We've used the data_type to read an array; re-set the type to 115705097246SAdrian Prantl // Invalid 1158de2fb9cfSCaroline Tice data_type = OptionValue::eTypeInvalid; 1159b9c1b51eSKate Stone } else if ((value[0] == '0') && (value[1] == 'x')) { 11602f3df613SZachary Turner value_sp = std::make_shared<OptionValueUInt64>(0, 0); 1161c95f7e2aSPavel Labath value_sp->SetValueFromString(value); 1162b9c1b51eSKate Stone } else { 1163c7bece56SGreg Clayton size_t len = value.size(); 1164de2fb9cfSCaroline Tice if ((value[0] == '"') && (value[len - 1] == '"')) 1165de2fb9cfSCaroline Tice value = value.substr(1, len - 2); 11662f3df613SZachary Turner value_sp = std::make_shared<OptionValueString>(value.c_str(), ""); 1167de2fb9cfSCaroline Tice } 1168de2fb9cfSCaroline Tice 1169b9c1b51eSKate Stone if (const_key == encoding_key) { 1170b9c1b51eSKate Stone // A 'data_encoding=..." is NOT a normal key-value pair; it is meta-data 1171b9c1b51eSKate Stone // indicating the 1172b9c1b51eSKate Stone // data type of an upcoming array (usually the next bit of data to be 1173b9c1b51eSKate Stone // read in). 1174de2fb9cfSCaroline Tice if (strcmp(value.c_str(), "uint32_t") == 0) 1175de2fb9cfSCaroline Tice data_type = OptionValue::eTypeUInt64; 1176b9c1b51eSKate Stone } else 1177b9c1b51eSKate Stone option_value_sp->GetAsDictionary()->SetValueForKey(const_key, value_sp, 1178b9c1b51eSKate Stone false); 1179de2fb9cfSCaroline Tice } 1180de2fb9cfSCaroline Tice } 1181de2fb9cfSCaroline Tice 1182de2fb9cfSCaroline Tice return option_value_sp; 1183de2fb9cfSCaroline Tice } 1184de2fb9cfSCaroline Tice 1185b9c1b51eSKate Stone bool Instruction::TestEmulation(Stream *out_stream, const char *file_name) { 11863ac6711aSCaroline Tice if (!out_stream) 11873ac6711aSCaroline Tice return false; 11883ac6711aSCaroline Tice 1189b9c1b51eSKate Stone if (!file_name) { 1190ea80ba8bSJohnny Chen out_stream->Printf("Instruction::TestEmulation: Missing file_name."); 11913ac6711aSCaroline Tice return false; 11923ac6711aSCaroline Tice } 119346376966SJonas Devlieghere FILE *test_file = FileSystem::Instance().Fopen(file_name, "r"); 1194b9c1b51eSKate Stone if (!test_file) { 1195b9c1b51eSKate Stone out_stream->Printf( 1196b9c1b51eSKate Stone "Instruction::TestEmulation: Attempt to open test file failed."); 11973ac6711aSCaroline Tice return false; 11983ac6711aSCaroline Tice } 11993ac6711aSCaroline Tice 12003ac6711aSCaroline Tice char buffer[256]; 1201b9c1b51eSKate Stone if (!fgets(buffer, 255, test_file)) { 1202b9c1b51eSKate Stone out_stream->Printf( 1203b9c1b51eSKate Stone "Instruction::TestEmulation: Error reading first line of test file.\n"); 12043ac6711aSCaroline Tice fclose(test_file); 12053ac6711aSCaroline Tice return false; 12063ac6711aSCaroline Tice } 12073ac6711aSCaroline Tice 1208b9c1b51eSKate Stone if (strncmp(buffer, "InstructionEmulationState={", 27) != 0) { 1209b9c1b51eSKate Stone out_stream->Printf("Instructin::TestEmulation: Test file does not contain " 1210b9c1b51eSKate Stone "emulation state dictionary\n"); 1211de2fb9cfSCaroline Tice fclose(test_file); 1212de2fb9cfSCaroline Tice return false; 1213de2fb9cfSCaroline Tice } 1214de2fb9cfSCaroline Tice 1215b9c1b51eSKate Stone // Read all the test information from the test file into an 1216b9c1b51eSKate Stone // OptionValueDictionary. 1217de2fb9cfSCaroline Tice 1218de2fb9cfSCaroline Tice OptionValueSP data_dictionary_sp(ReadDictionary(test_file, out_stream)); 1219b9c1b51eSKate Stone if (!data_dictionary_sp) { 1220b9c1b51eSKate Stone out_stream->Printf( 1221b9c1b51eSKate Stone "Instruction::TestEmulation: Error reading Dictionary Object.\n"); 1222de2fb9cfSCaroline Tice fclose(test_file); 1223de2fb9cfSCaroline Tice return false; 1224de2fb9cfSCaroline Tice } 1225de2fb9cfSCaroline Tice 1226de2fb9cfSCaroline Tice fclose(test_file); 1227de2fb9cfSCaroline Tice 1228b9c1b51eSKate Stone OptionValueDictionary *data_dictionary = 1229b9c1b51eSKate Stone data_dictionary_sp->GetAsDictionary(); 1230de2fb9cfSCaroline Tice static ConstString description_key("assembly_string"); 1231de2fb9cfSCaroline Tice static ConstString triple_key("triple"); 1232de2fb9cfSCaroline Tice 1233de2fb9cfSCaroline Tice OptionValueSP value_sp = data_dictionary->GetValueForKey(description_key); 1234de2fb9cfSCaroline Tice 1235b9c1b51eSKate Stone if (!value_sp) { 1236b9c1b51eSKate Stone out_stream->Printf("Instruction::TestEmulation: Test file does not " 1237b9c1b51eSKate Stone "contain description string.\n"); 1238de2fb9cfSCaroline Tice return false; 1239de2fb9cfSCaroline Tice } 1240de2fb9cfSCaroline Tice 1241de2fb9cfSCaroline Tice SetDescription(value_sp->GetStringValue()); 1242de2fb9cfSCaroline Tice 1243de2fb9cfSCaroline Tice value_sp = data_dictionary->GetValueForKey(triple_key); 1244b9c1b51eSKate Stone if (!value_sp) { 1245b9c1b51eSKate Stone out_stream->Printf( 1246b9c1b51eSKate Stone "Instruction::TestEmulation: Test file does not contain triple.\n"); 1247de2fb9cfSCaroline Tice return false; 1248de2fb9cfSCaroline Tice } 1249de2fb9cfSCaroline Tice 1250de2fb9cfSCaroline Tice ArchSpec arch; 1251de2fb9cfSCaroline Tice arch.SetTriple(llvm::Triple(value_sp->GetStringValue())); 12523ac6711aSCaroline Tice 12533ac6711aSCaroline Tice bool success = false; 1254d5b44036SJonas Devlieghere std::unique_ptr<EmulateInstruction> insn_emulator_up( 1255b9c1b51eSKate Stone EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr)); 1256d5b44036SJonas Devlieghere if (insn_emulator_up) 1257b9c1b51eSKate Stone success = 1258d5b44036SJonas Devlieghere insn_emulator_up->TestEmulation(out_stream, arch, data_dictionary); 12593ac6711aSCaroline Tice 12603ac6711aSCaroline Tice if (success) 1261ea80ba8bSJohnny Chen out_stream->Printf("Emulation test succeeded."); 12623ac6711aSCaroline Tice else 1263ea80ba8bSJohnny Chen out_stream->Printf("Emulation test failed."); 12643ac6711aSCaroline Tice 12653ac6711aSCaroline Tice return success; 12663ac6711aSCaroline Tice } 12673ac6711aSCaroline Tice 1268b9c1b51eSKate Stone bool Instruction::Emulate( 1269b9c1b51eSKate Stone const ArchSpec &arch, uint32_t evaluate_options, void *baton, 12707349bd90SGreg Clayton EmulateInstruction::ReadMemoryCallback read_mem_callback, 12717349bd90SGreg Clayton EmulateInstruction::WriteMemoryCallback write_mem_callback, 12727349bd90SGreg Clayton EmulateInstruction::ReadRegisterCallback read_reg_callback, 1273b9c1b51eSKate Stone EmulateInstruction::WriteRegisterCallback write_reg_callback) { 1274d5b44036SJonas Devlieghere std::unique_ptr<EmulateInstruction> insn_emulator_up( 1275b9c1b51eSKate Stone EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr)); 1276d5b44036SJonas Devlieghere if (insn_emulator_up) { 1277d5b44036SJonas Devlieghere insn_emulator_up->SetBaton(baton); 1278d5b44036SJonas Devlieghere insn_emulator_up->SetCallbacks(read_mem_callback, write_mem_callback, 1279b9c1b51eSKate Stone read_reg_callback, write_reg_callback); 1280d5b44036SJonas Devlieghere insn_emulator_up->SetInstruction(GetOpcode(), GetAddress(), nullptr); 1281d5b44036SJonas Devlieghere return insn_emulator_up->EvaluateInstruction(evaluate_options); 12827c9dd3ceSCaroline Tice } 12837c9dd3ceSCaroline Tice 12847c9dd3ceSCaroline Tice return false; 12857c9dd3ceSCaroline Tice } 12867c9dd3ceSCaroline Tice 1287b9c1b51eSKate Stone uint32_t Instruction::GetData(DataExtractor &data) { 1288cd4ae1abSSean Callanan return m_opcode.GetData(data); 1289ba812f42SGreg Clayton } 1290ba812f42SGreg Clayton 1291b9c1b51eSKate Stone InstructionList::InstructionList() : m_instructions() {} 129230fdc8d8SChris Lattner 129334ede34aSEugene Zelenko InstructionList::~InstructionList() = default; 129430fdc8d8SChris Lattner 1295b9c1b51eSKate Stone size_t InstructionList::GetSize() const { return m_instructions.size(); } 129630fdc8d8SChris Lattner 1297b9c1b51eSKate Stone uint32_t InstructionList::GetMaxOpcocdeByteSize() const { 1298357132ebSGreg Clayton uint32_t max_inst_size = 0; 1299357132ebSGreg Clayton collection::const_iterator pos, end; 1300b9c1b51eSKate Stone for (pos = m_instructions.begin(), end = m_instructions.end(); pos != end; 1301b9c1b51eSKate Stone ++pos) { 1302357132ebSGreg Clayton uint32_t inst_size = (*pos)->GetOpcode().GetByteSize(); 1303357132ebSGreg Clayton if (max_inst_size < inst_size) 1304357132ebSGreg Clayton max_inst_size = inst_size; 1305357132ebSGreg Clayton } 1306357132ebSGreg Clayton return max_inst_size; 1307357132ebSGreg Clayton } 1308357132ebSGreg Clayton 1309b9c1b51eSKate Stone InstructionSP InstructionList::GetInstructionAtIndex(size_t idx) const { 13101d273166SGreg Clayton InstructionSP inst_sp; 131130fdc8d8SChris Lattner if (idx < m_instructions.size()) 13121d273166SGreg Clayton inst_sp = m_instructions[idx]; 13131d273166SGreg Clayton return inst_sp; 131430fdc8d8SChris Lattner } 131530fdc8d8SChris Lattner 1316cfd96f05SWalter Erquinigo InstructionSP InstructionList::GetInstructionAtAddress(const Address &address) { 1317cfd96f05SWalter Erquinigo uint32_t index = GetIndexOfInstructionAtAddress(address); 1318cfd96f05SWalter Erquinigo if (index != UINT32_MAX) 1319cfd96f05SWalter Erquinigo return GetInstructionAtIndex(index); 1320cfd96f05SWalter Erquinigo return nullptr; 1321cfd96f05SWalter Erquinigo } 1322cfd96f05SWalter Erquinigo 1323b9c1b51eSKate Stone void InstructionList::Dump(Stream *s, bool show_address, bool show_bytes, 1324*ad7bcda9SWalter Erquinigo bool show_control_flow_kind, 1325b9c1b51eSKate Stone const ExecutionContext *exe_ctx) { 13265009f9d5SGreg Clayton const uint32_t max_opcode_byte_size = GetMaxOpcocdeByteSize(); 13275009f9d5SGreg Clayton collection::const_iterator pos, begin, end; 1328554f68d3SGreg Clayton 132934ede34aSEugene Zelenko const FormatEntity::Entry *disassembly_format = nullptr; 1330554f68d3SGreg Clayton FormatEntity::Entry format; 1331b9c1b51eSKate Stone if (exe_ctx && exe_ctx->HasTargetScope()) { 1332b9c1b51eSKate Stone disassembly_format = 1333b9c1b51eSKate Stone exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat(); 1334b9c1b51eSKate Stone } else { 1335554f68d3SGreg Clayton FormatEntity::Parse("${addr}: ", format); 1336554f68d3SGreg Clayton disassembly_format = &format; 1337554f68d3SGreg Clayton } 1338554f68d3SGreg Clayton 13395009f9d5SGreg Clayton for (begin = m_instructions.begin(), end = m_instructions.end(), pos = begin; 1340b9c1b51eSKate Stone pos != end; ++pos) { 13415009f9d5SGreg Clayton if (pos != begin) 13425009f9d5SGreg Clayton s->EOL(); 1343*ad7bcda9SWalter Erquinigo (*pos)->Dump(s, max_opcode_byte_size, show_address, show_bytes, 1344*ad7bcda9SWalter Erquinigo show_control_flow_kind, exe_ctx, nullptr, nullptr, 1345*ad7bcda9SWalter Erquinigo disassembly_format, 0); 13465009f9d5SGreg Clayton } 13475009f9d5SGreg Clayton } 13485009f9d5SGreg Clayton 1349b9c1b51eSKate Stone void InstructionList::Clear() { m_instructions.clear(); } 135030fdc8d8SChris Lattner 1351b9c1b51eSKate Stone void InstructionList::Append(lldb::InstructionSP &inst_sp) { 135230fdc8d8SChris Lattner if (inst_sp) 135330fdc8d8SChris Lattner m_instructions.push_back(inst_sp); 135430fdc8d8SChris Lattner } 135530fdc8d8SChris Lattner 1356564d8bc2SJim Ingham uint32_t 1357b9c1b51eSKate Stone InstructionList::GetIndexOfNextBranchInstruction(uint32_t start, 1358434905b9SJim Ingham bool ignore_calls, 1359434905b9SJim Ingham bool *found_calls) const { 1360564d8bc2SJim Ingham size_t num_instructions = m_instructions.size(); 1361564d8bc2SJim Ingham 1362190636bcSJim Ingham uint32_t next_branch = UINT32_MAX; 1363434905b9SJim Ingham 1364434905b9SJim Ingham if (found_calls) 1365434905b9SJim Ingham *found_calls = false; 13663169d920STed Woodward for (size_t i = start; i < num_instructions; i++) { 1367b9c1b51eSKate Stone if (m_instructions[i]->DoesBranch()) { 1368434905b9SJim Ingham if (ignore_calls && m_instructions[i]->IsCall()) { 1369434905b9SJim Ingham if (found_calls) 1370434905b9SJim Ingham *found_calls = true; 137121929d49SPavel Labath continue; 1372434905b9SJim Ingham } 1373564d8bc2SJim Ingham next_branch = i; 1374564d8bc2SJim Ingham break; 1375564d8bc2SJim Ingham } 1376564d8bc2SJim Ingham } 1377e76e7e93STed Woodward 1378564d8bc2SJim Ingham return next_branch; 1379564d8bc2SJim Ingham } 1380564d8bc2SJim Ingham 1381564d8bc2SJim Ingham uint32_t 1382b9c1b51eSKate Stone InstructionList::GetIndexOfInstructionAtAddress(const Address &address) { 1383c7bece56SGreg Clayton size_t num_instructions = m_instructions.size(); 1384190636bcSJim Ingham uint32_t index = UINT32_MAX; 1385b9c1b51eSKate Stone for (size_t i = 0; i < num_instructions; i++) { 1386b9c1b51eSKate Stone if (m_instructions[i]->GetAddress() == address) { 1387564d8bc2SJim Ingham index = i; 1388564d8bc2SJim Ingham break; 1389564d8bc2SJim Ingham } 1390564d8bc2SJim Ingham } 1391564d8bc2SJim Ingham return index; 1392564d8bc2SJim Ingham } 139330fdc8d8SChris Lattner 139444d93782SGreg Clayton uint32_t 1395b9c1b51eSKate Stone InstructionList::GetIndexOfInstructionAtLoadAddress(lldb::addr_t load_addr, 1396b9c1b51eSKate Stone Target &target) { 139744d93782SGreg Clayton Address address; 139844d93782SGreg Clayton address.SetLoadAddress(load_addr, &target); 139944d93782SGreg Clayton return GetIndexOfInstructionAtAddress(address); 140044d93782SGreg Clayton } 140144d93782SGreg Clayton 140292c0cda9SPavel Labath size_t Disassembler::ParseInstructions(Target &target, Address start, 1403af3db4e9SPavel Labath Limit limit, Stream *error_strm_ptr, 1404e9fe788dSJason Molenda bool force_live_memory) { 1405357132ebSGreg Clayton m_instruction_list.Clear(); 140637023b06SJim Ingham 1407af3db4e9SPavel Labath if (!start.IsValid()) 140837023b06SJim Ingham return 0; 140937023b06SJim Ingham 141092c0cda9SPavel Labath start = ResolveAddress(target, start); 141192c0cda9SPavel Labath 1412af3db4e9SPavel Labath addr_t byte_size = limit.value; 1413af3db4e9SPavel Labath if (limit.kind == Limit::Instructions) 1414af3db4e9SPavel Labath byte_size *= m_arch.GetMaximumOpcodeByteSize(); 1415af3db4e9SPavel Labath auto data_sp = std::make_shared<DataBufferHeap>(byte_size, '\0'); 141637023b06SJim Ingham 141797206d57SZachary Turner Status error; 14183faf47c4SGreg Clayton lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; 1419b9c1b51eSKate Stone const size_t bytes_read = 1420e9fe788dSJason Molenda target.ReadMemory(start, data_sp->GetBytes(), data_sp->GetByteSize(), 1421e9fe788dSJason Molenda error, force_live_memory, &load_addr); 14223faf47c4SGreg Clayton const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS; 142337023b06SJim Ingham 1424af3db4e9SPavel Labath if (bytes_read == 0) { 1425af3db4e9SPavel Labath if (error_strm_ptr) { 1426af3db4e9SPavel Labath if (const char *error_cstr = error.AsCString()) 1427af3db4e9SPavel Labath error_strm_ptr->Printf("error: %s\n", error_cstr); 1428af3db4e9SPavel Labath } 1429357132ebSGreg Clayton return 0; 1430af3db4e9SPavel Labath } 1431af3db4e9SPavel Labath 1432af3db4e9SPavel Labath if (bytes_read != data_sp->GetByteSize()) 1433af3db4e9SPavel Labath data_sp->SetByteSize(bytes_read); 1434b9c1b51eSKate Stone DataExtractor data(data_sp, m_arch.GetByteOrder(), 1435357132ebSGreg Clayton m_arch.GetAddressByteSize()); 1436af3db4e9SPavel Labath return DecodeInstructions(start, data, 0, 1437af3db4e9SPavel Labath limit.kind == Limit::Instructions ? limit.value 1438af3db4e9SPavel Labath : UINT32_MAX, 1439af3db4e9SPavel Labath false, data_from_file); 144037023b06SJim Ingham } 144137023b06SJim Ingham 144230fdc8d8SChris Lattner // Disassembler copy constructor 1443b9c1b51eSKate Stone Disassembler::Disassembler(const ArchSpec &arch, const char *flavor) 1444b9c1b51eSKate Stone : m_arch(arch), m_instruction_list(), m_base_addr(LLDB_INVALID_ADDRESS), 1445b9c1b51eSKate Stone m_flavor() { 144634ede34aSEugene Zelenko if (flavor == nullptr) 14470f063ba6SJim Ingham m_flavor.assign("default"); 14480f063ba6SJim Ingham else 14490f063ba6SJim Ingham m_flavor.assign(flavor); 145075452e8cSJason Molenda 145175452e8cSJason Molenda // If this is an arm variant that can only include thumb (T16, T32) 145205097246SAdrian Prantl // instructions, force the arch triple to be "thumbv.." instead of "armv..." 1453b9c1b51eSKate Stone if (arch.IsAlwaysThumbInstructions()) { 145475452e8cSJason Molenda std::string thumb_arch_name(arch.GetTriple().getArchName().str()); 145575452e8cSJason Molenda // Replace "arm" with "thumb" so we get all thumb variants correct 1456b9c1b51eSKate Stone if (thumb_arch_name.size() > 3) { 145775452e8cSJason Molenda thumb_arch_name.erase(0, 3); 145875452e8cSJason Molenda thumb_arch_name.insert(0, "thumb"); 145975452e8cSJason Molenda } 146075452e8cSJason Molenda m_arch.SetTriple(thumb_arch_name.c_str()); 146175452e8cSJason Molenda } 146230fdc8d8SChris Lattner } 146330fdc8d8SChris Lattner 146434ede34aSEugene Zelenko Disassembler::~Disassembler() = default; 146530fdc8d8SChris Lattner 1466b9c1b51eSKate Stone InstructionList &Disassembler::GetInstructionList() { 146730fdc8d8SChris Lattner return m_instruction_list; 146830fdc8d8SChris Lattner } 146930fdc8d8SChris Lattner 1470b9c1b51eSKate Stone const InstructionList &Disassembler::GetInstructionList() const { 147130fdc8d8SChris Lattner return m_instruction_list; 147230fdc8d8SChris Lattner } 14733ac6711aSCaroline Tice 14743ac6711aSCaroline Tice // Class PseudoInstruction 147534ede34aSEugene Zelenko 1476b9c1b51eSKate Stone PseudoInstruction::PseudoInstruction() 147704803b3eSTatyana Krasnukha : Instruction(Address(), AddressClass::eUnknown), m_description() {} 14783ac6711aSCaroline Tice 147934ede34aSEugene Zelenko PseudoInstruction::~PseudoInstruction() = default; 14803ac6711aSCaroline Tice 1481b9c1b51eSKate Stone bool PseudoInstruction::DoesBranch() { 14823ac6711aSCaroline Tice // This is NOT a valid question for a pseudo instruction. 14833ac6711aSCaroline Tice return false; 14843ac6711aSCaroline Tice } 14853ac6711aSCaroline Tice 1486b9c1b51eSKate Stone bool PseudoInstruction::HasDelaySlot() { 14877f3daedaSBhushan D. Attarde // This is NOT a valid question for a pseudo instruction. 14887f3daedaSBhushan D. Attarde return false; 14897f3daedaSBhushan D. Attarde } 14907f3daedaSBhushan D. Attarde 149166902a32SVedant Kumar bool PseudoInstruction::IsLoad() { return false; } 149266902a32SVedant Kumar 149366902a32SVedant Kumar bool PseudoInstruction::IsAuthenticated() { return false; } 149466902a32SVedant Kumar 1495b9c1b51eSKate Stone size_t PseudoInstruction::Decode(const lldb_private::Disassembler &disassembler, 14963ac6711aSCaroline Tice const lldb_private::DataExtractor &data, 1497b9c1b51eSKate Stone lldb::offset_t data_offset) { 14983ac6711aSCaroline Tice return m_opcode.GetByteSize(); 14993ac6711aSCaroline Tice } 15003ac6711aSCaroline Tice 1501b9c1b51eSKate Stone void PseudoInstruction::SetOpcode(size_t opcode_size, void *opcode_data) { 15023ac6711aSCaroline Tice if (!opcode_data) 15033ac6711aSCaroline Tice return; 15043ac6711aSCaroline Tice 1505b9c1b51eSKate Stone switch (opcode_size) { 1506b9c1b51eSKate Stone case 8: { 15073ac6711aSCaroline Tice uint8_t value8 = *((uint8_t *)opcode_data); 150890359963SEd Maste m_opcode.SetOpcode8(value8, eByteOrderInvalid); 15093ac6711aSCaroline Tice break; 15103ac6711aSCaroline Tice } 1511b9c1b51eSKate Stone case 16: { 15123ac6711aSCaroline Tice uint16_t value16 = *((uint16_t *)opcode_data); 151390359963SEd Maste m_opcode.SetOpcode16(value16, eByteOrderInvalid); 15143ac6711aSCaroline Tice break; 15153ac6711aSCaroline Tice } 1516b9c1b51eSKate Stone case 32: { 15173ac6711aSCaroline Tice uint32_t value32 = *((uint32_t *)opcode_data); 151890359963SEd Maste m_opcode.SetOpcode32(value32, eByteOrderInvalid); 15193ac6711aSCaroline Tice break; 15203ac6711aSCaroline Tice } 1521b9c1b51eSKate Stone case 64: { 15223ac6711aSCaroline Tice uint64_t value64 = *((uint64_t *)opcode_data); 152390359963SEd Maste m_opcode.SetOpcode64(value64, eByteOrderInvalid); 15243ac6711aSCaroline Tice break; 15253ac6711aSCaroline Tice } 15263ac6711aSCaroline Tice default: 15273ac6711aSCaroline Tice break; 15283ac6711aSCaroline Tice } 15293ac6711aSCaroline Tice } 15303ac6711aSCaroline Tice 153131d97a5cSZachary Turner void PseudoInstruction::SetDescription(llvm::StringRef description) { 1532adcd0268SBenjamin Kramer m_description = std::string(description); 15333ac6711aSCaroline Tice } 1534807ee2ffSSean Callanan 1535807ee2ffSSean Callanan Instruction::Operand Instruction::Operand::BuildRegister(ConstString &r) { 1536807ee2ffSSean Callanan Operand ret; 1537807ee2ffSSean Callanan ret.m_type = Type::Register; 1538807ee2ffSSean Callanan ret.m_register = r; 1539807ee2ffSSean Callanan return ret; 1540807ee2ffSSean Callanan } 1541807ee2ffSSean Callanan 1542807ee2ffSSean Callanan Instruction::Operand Instruction::Operand::BuildImmediate(lldb::addr_t imm, 1543807ee2ffSSean Callanan bool neg) { 1544807ee2ffSSean Callanan Operand ret; 1545807ee2ffSSean Callanan ret.m_type = Type::Immediate; 1546807ee2ffSSean Callanan ret.m_immediate = imm; 1547807ee2ffSSean Callanan ret.m_negative = neg; 1548807ee2ffSSean Callanan return ret; 1549807ee2ffSSean Callanan } 1550807ee2ffSSean Callanan 1551807ee2ffSSean Callanan Instruction::Operand Instruction::Operand::BuildImmediate(int64_t imm) { 1552807ee2ffSSean Callanan Operand ret; 1553807ee2ffSSean Callanan ret.m_type = Type::Immediate; 1554807ee2ffSSean Callanan if (imm < 0) { 1555807ee2ffSSean Callanan ret.m_immediate = -imm; 1556807ee2ffSSean Callanan ret.m_negative = true; 1557807ee2ffSSean Callanan } else { 1558807ee2ffSSean Callanan ret.m_immediate = imm; 1559807ee2ffSSean Callanan ret.m_negative = false; 1560807ee2ffSSean Callanan } 1561807ee2ffSSean Callanan return ret; 1562807ee2ffSSean Callanan } 1563807ee2ffSSean Callanan 1564807ee2ffSSean Callanan Instruction::Operand 1565807ee2ffSSean Callanan Instruction::Operand::BuildDereference(const Operand &ref) { 1566807ee2ffSSean Callanan Operand ret; 1567807ee2ffSSean Callanan ret.m_type = Type::Dereference; 1568807ee2ffSSean Callanan ret.m_children = {ref}; 1569807ee2ffSSean Callanan return ret; 1570807ee2ffSSean Callanan } 1571807ee2ffSSean Callanan 1572807ee2ffSSean Callanan Instruction::Operand Instruction::Operand::BuildSum(const Operand &lhs, 1573807ee2ffSSean Callanan const Operand &rhs) { 1574807ee2ffSSean Callanan Operand ret; 1575807ee2ffSSean Callanan ret.m_type = Type::Sum; 1576807ee2ffSSean Callanan ret.m_children = {lhs, rhs}; 1577807ee2ffSSean Callanan return ret; 1578807ee2ffSSean Callanan } 1579807ee2ffSSean Callanan 1580807ee2ffSSean Callanan Instruction::Operand Instruction::Operand::BuildProduct(const Operand &lhs, 1581807ee2ffSSean Callanan const Operand &rhs) { 1582807ee2ffSSean Callanan Operand ret; 1583807ee2ffSSean Callanan ret.m_type = Type::Product; 1584807ee2ffSSean Callanan ret.m_children = {lhs, rhs}; 1585807ee2ffSSean Callanan return ret; 1586807ee2ffSSean Callanan } 1587807ee2ffSSean Callanan 1588807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> 1589807ee2ffSSean Callanan lldb_private::OperandMatchers::MatchBinaryOp( 1590807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> base, 1591807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> left, 1592807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> right) { 1593807ee2ffSSean Callanan return [base, left, right](const Instruction::Operand &op) -> bool { 1594807ee2ffSSean Callanan return (base(op) && op.m_children.size() == 2 && 1595807ee2ffSSean Callanan ((left(op.m_children[0]) && right(op.m_children[1])) || 1596807ee2ffSSean Callanan (left(op.m_children[1]) && right(op.m_children[0])))); 1597807ee2ffSSean Callanan }; 1598807ee2ffSSean Callanan } 1599807ee2ffSSean Callanan 1600807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> 1601807ee2ffSSean Callanan lldb_private::OperandMatchers::MatchUnaryOp( 1602807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> base, 1603807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> child) { 1604807ee2ffSSean Callanan return [base, child](const Instruction::Operand &op) -> bool { 1605807ee2ffSSean Callanan return (base(op) && op.m_children.size() == 1 && child(op.m_children[0])); 1606807ee2ffSSean Callanan }; 1607807ee2ffSSean Callanan } 1608807ee2ffSSean Callanan 1609807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> 1610807ee2ffSSean Callanan lldb_private::OperandMatchers::MatchRegOp(const RegisterInfo &info) { 1611807ee2ffSSean Callanan return [&info](const Instruction::Operand &op) { 1612807ee2ffSSean Callanan return (op.m_type == Instruction::Operand::Type::Register && 1613807ee2ffSSean Callanan (op.m_register == ConstString(info.name) || 1614807ee2ffSSean Callanan op.m_register == ConstString(info.alt_name))); 1615807ee2ffSSean Callanan }; 1616807ee2ffSSean Callanan } 1617807ee2ffSSean Callanan 1618807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> 1619561a9bbfSSean Callanan lldb_private::OperandMatchers::FetchRegOp(ConstString ®) { 1620561a9bbfSSean Callanan return [®](const Instruction::Operand &op) { 1621561a9bbfSSean Callanan if (op.m_type != Instruction::Operand::Type::Register) { 1622561a9bbfSSean Callanan return false; 1623561a9bbfSSean Callanan } 1624561a9bbfSSean Callanan reg = op.m_register; 1625561a9bbfSSean Callanan return true; 1626561a9bbfSSean Callanan }; 1627561a9bbfSSean Callanan } 1628561a9bbfSSean Callanan 1629561a9bbfSSean Callanan std::function<bool(const Instruction::Operand &)> 1630807ee2ffSSean Callanan lldb_private::OperandMatchers::MatchImmOp(int64_t imm) { 1631807ee2ffSSean Callanan return [imm](const Instruction::Operand &op) { 1632807ee2ffSSean Callanan return (op.m_type == Instruction::Operand::Type::Immediate && 1633807ee2ffSSean Callanan ((op.m_negative && op.m_immediate == (uint64_t)-imm) || 1634807ee2ffSSean Callanan (!op.m_negative && op.m_immediate == (uint64_t)imm))); 1635807ee2ffSSean Callanan }; 1636807ee2ffSSean Callanan } 1637807ee2ffSSean Callanan 1638807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> 1639807ee2ffSSean Callanan lldb_private::OperandMatchers::FetchImmOp(int64_t &imm) { 1640807ee2ffSSean Callanan return [&imm](const Instruction::Operand &op) { 1641807ee2ffSSean Callanan if (op.m_type != Instruction::Operand::Type::Immediate) { 1642807ee2ffSSean Callanan return false; 1643807ee2ffSSean Callanan } 1644807ee2ffSSean Callanan if (op.m_negative) { 1645807ee2ffSSean Callanan imm = -((int64_t)op.m_immediate); 1646807ee2ffSSean Callanan } else { 1647807ee2ffSSean Callanan imm = ((int64_t)op.m_immediate); 1648807ee2ffSSean Callanan } 1649807ee2ffSSean Callanan return true; 1650807ee2ffSSean Callanan }; 1651807ee2ffSSean Callanan } 1652807ee2ffSSean Callanan 1653807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> 1654807ee2ffSSean Callanan lldb_private::OperandMatchers::MatchOpType(Instruction::Operand::Type type) { 1655807ee2ffSSean Callanan return [type](const Instruction::Operand &op) { return op.m_type == type; }; 1656807ee2ffSSean Callanan } 1657