130fdc8d8SChris Lattner //===-- Disassembler.cpp ----------------------------------------*- C++ -*-===// 230fdc8d8SChris Lattner // 330fdc8d8SChris Lattner // The LLVM Compiler Infrastructure 430fdc8d8SChris Lattner // 530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source 630fdc8d8SChris Lattner // License. See LICENSE.TXT for details. 730fdc8d8SChris Lattner // 830fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 930fdc8d8SChris Lattner 1030fdc8d8SChris Lattner #include "lldb/Core/Disassembler.h" 1130fdc8d8SChris Lattner 122f3df613SZachary Turner #include "lldb/Core/AddressRange.h" // for AddressRange 1330fdc8d8SChris Lattner #include "lldb/Core/Debugger.h" 14ad379efcSCaroline Tice #include "lldb/Core/EmulateInstruction.h" 152f3df613SZachary Turner #include "lldb/Core/Mangled.h" // for Mangled, Mangled... 1630fdc8d8SChris Lattner #include "lldb/Core/Module.h" 172f3df613SZachary Turner #include "lldb/Core/ModuleList.h" // for ModuleList 1830fdc8d8SChris Lattner #include "lldb/Core/PluginManager.h" 192f3df613SZachary Turner #include "lldb/Core/SourceManager.h" // for SourceManager 20190fadcdSZachary Turner #include "lldb/Host/FileSystem.h" 2167cc0636SGreg Clayton #include "lldb/Interpreter/OptionValue.h" 2267cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueArray.h" 2367cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueDictionary.h" 240b4c26b2SJason Molenda #include "lldb/Interpreter/OptionValueRegex.h" 2567cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueString.h" 2667cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueUInt64.h" 271f746071SGreg Clayton #include "lldb/Symbol/Function.h" 282f3df613SZachary Turner #include "lldb/Symbol/Symbol.h" // for Symbol 292f3df613SZachary Turner #include "lldb/Symbol/SymbolContext.h" // for SymbolContext 3030fdc8d8SChris Lattner #include "lldb/Target/ExecutionContext.h" 31d5944cd1SGreg Clayton #include "lldb/Target/SectionLoadList.h" 32b57e4a1bSJason Molenda #include "lldb/Target/StackFrame.h" 3330fdc8d8SChris Lattner #include "lldb/Target/Target.h" 342f3df613SZachary Turner #include "lldb/Target/Thread.h" // for Thread 35666cc0b2SZachary Turner #include "lldb/Utility/DataBufferHeap.h" 36666cc0b2SZachary Turner #include "lldb/Utility/DataExtractor.h" 37bf9a7730SZachary Turner #include "lldb/Utility/RegularExpression.h" 3897206d57SZachary Turner #include "lldb/Utility/Status.h" 392f3df613SZachary Turner #include "lldb/Utility/Stream.h" // for Stream 402f3df613SZachary Turner #include "lldb/Utility/StreamString.h" // for StreamString 4138d0632eSPavel Labath #include "lldb/Utility/Timer.h" 422f3df613SZachary Turner #include "lldb/lldb-private-enumerations.h" // for InstructionType:... 432f3df613SZachary Turner #include "lldb/lldb-private-interfaces.h" // for DisassemblerCrea... 442f3df613SZachary Turner #include "lldb/lldb-private-types.h" // for RegisterInfo 452f3df613SZachary Turner #include "llvm/ADT/Triple.h" // for Triple, Triple::... 462f3df613SZachary Turner #include "llvm/Support/Compiler.h" // for LLVM_PRETTY_FUNC... 472f3df613SZachary Turner 482f3df613SZachary Turner #include <cstdint> // for uint32_t, UINT32... 492f3df613SZachary Turner #include <cstring> 502f3df613SZachary Turner #include <utility> // for pair 512f3df613SZachary Turner 522f3df613SZachary Turner #include <assert.h> // for assert 5330fdc8d8SChris Lattner 5430fdc8d8SChris Lattner #define DEFAULT_DISASM_BYTE_SIZE 32 5530fdc8d8SChris Lattner 5630fdc8d8SChris Lattner using namespace lldb; 5730fdc8d8SChris Lattner using namespace lldb_private; 5830fdc8d8SChris Lattner 59b9c1b51eSKate Stone DisassemblerSP Disassembler::FindPlugin(const ArchSpec &arch, 60b9c1b51eSKate Stone const char *flavor, 61b9c1b51eSKate Stone const char *plugin_name) { 62f9d16476SPavel Labath static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 63f9d16476SPavel Labath Timer scoped_timer(func_cat, 641080edbcSGreg Clayton "Disassembler::FindPlugin (arch = %s, plugin_name = %s)", 65b9c1b51eSKate Stone arch.GetArchitectureName(), plugin_name); 6630fdc8d8SChris Lattner 6734ede34aSEugene Zelenko DisassemblerCreateInstance create_callback = nullptr; 681080edbcSGreg Clayton 69b9c1b51eSKate Stone if (plugin_name) { 7057abc5d6SGreg Clayton ConstString const_plugin_name(plugin_name); 71b9c1b51eSKate Stone create_callback = PluginManager::GetDisassemblerCreateCallbackForPluginName( 72b9c1b51eSKate Stone const_plugin_name); 73b9c1b51eSKate Stone if (create_callback) { 740f063ba6SJim Ingham DisassemblerSP disassembler_sp(create_callback(arch, flavor)); 751080edbcSGreg Clayton 7634ede34aSEugene Zelenko if (disassembler_sp) 777e6d4e5aSSean Callanan return disassembler_sp; 781080edbcSGreg Clayton } 79b9c1b51eSKate Stone } else { 80b9c1b51eSKate Stone for (uint32_t idx = 0; 81b9c1b51eSKate Stone (create_callback = PluginManager::GetDisassemblerCreateCallbackAtIndex( 82b9c1b51eSKate Stone idx)) != nullptr; 83b9c1b51eSKate Stone ++idx) { 840f063ba6SJim Ingham DisassemblerSP disassembler_sp(create_callback(arch, flavor)); 8530fdc8d8SChris Lattner 8634ede34aSEugene Zelenko if (disassembler_sp) 877e6d4e5aSSean Callanan return disassembler_sp; 8830fdc8d8SChris Lattner } 891080edbcSGreg Clayton } 907e6d4e5aSSean Callanan return DisassemblerSP(); 9130fdc8d8SChris Lattner } 9230fdc8d8SChris Lattner 93b9c1b51eSKate Stone DisassemblerSP Disassembler::FindPluginForTarget(const TargetSP target_sp, 94b9c1b51eSKate Stone const ArchSpec &arch, 95b9c1b51eSKate Stone const char *flavor, 96b9c1b51eSKate Stone const char *plugin_name) { 97b9c1b51eSKate Stone if (target_sp && flavor == nullptr) { 98b9c1b51eSKate Stone // FIXME - we don't have the mechanism in place to do per-architecture 9905097246SAdrian Prantl // settings. But since we know that for now we only support flavors on x86 10005097246SAdrian Prantl // & x86_64, 101b9c1b51eSKate Stone if (arch.GetTriple().getArch() == llvm::Triple::x86 || 102b9c1b51eSKate Stone arch.GetTriple().getArch() == llvm::Triple::x86_64) 1030f063ba6SJim Ingham flavor = target_sp->GetDisassemblyFlavor(); 1040f063ba6SJim Ingham } 1050f063ba6SJim Ingham return FindPlugin(arch, flavor, plugin_name); 1060f063ba6SJim Ingham } 1070f063ba6SJim Ingham 108b9c1b51eSKate Stone static void ResolveAddress(const ExecutionContext &exe_ctx, const Address &addr, 109b9c1b51eSKate Stone Address &resolved_addr) { 110b9c1b51eSKate Stone if (!addr.IsSectionOffset()) { 11105097246SAdrian Prantl // If we weren't passed in a section offset address range, try and resolve 11205097246SAdrian Prantl // it to something 113c14ee32dSGreg Clayton Target *target = exe_ctx.GetTargetPtr(); 114b9c1b51eSKate Stone if (target) { 115*a0fa299dSTatyana Krasnukha bool is_resolved = 116*a0fa299dSTatyana Krasnukha target->GetSectionLoadList().IsEmpty() ? 117*a0fa299dSTatyana Krasnukha target->GetImages().ResolveFileAddress(addr.GetOffset(), 118*a0fa299dSTatyana Krasnukha resolved_addr) : 119b9c1b51eSKate Stone target->GetSectionLoadList().ResolveLoadAddress(addr.GetOffset(), 120b9c1b51eSKate Stone resolved_addr); 121*a0fa299dSTatyana Krasnukha 12205097246SAdrian Prantl // We weren't able to resolve the address, just treat it as a raw address 123*a0fa299dSTatyana Krasnukha if (is_resolved && resolved_addr.IsValid()) 124357132ebSGreg Clayton return; 125357132ebSGreg Clayton } 126357132ebSGreg Clayton } 127357132ebSGreg Clayton resolved_addr = addr; 128357132ebSGreg Clayton } 129dda4f7b5SGreg Clayton 130b9c1b51eSKate Stone size_t Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch, 131b9c1b51eSKate Stone const char *plugin_name, const char *flavor, 132dda4f7b5SGreg Clayton const ExecutionContext &exe_ctx, 133dda4f7b5SGreg Clayton SymbolContextList &sc_list, 13437023b06SJim Ingham uint32_t num_instructions, 1350b4c26b2SJason Molenda bool mixed_source_and_assembly, 136dda4f7b5SGreg Clayton uint32_t num_mixed_context_lines, 137b9c1b51eSKate Stone uint32_t options, Stream &strm) { 138dda4f7b5SGreg Clayton size_t success_count = 0; 139dda4f7b5SGreg Clayton const size_t count = sc_list.GetSize(); 140dda4f7b5SGreg Clayton SymbolContext sc; 141dda4f7b5SGreg Clayton AddressRange range; 142b9c1b51eSKate Stone const uint32_t scope = 143b9c1b51eSKate Stone eSymbolContextBlock | eSymbolContextFunction | eSymbolContextSymbol; 1447e14f91dSGreg Clayton const bool use_inline_block_range = true; 145b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 14634ede34aSEugene Zelenko if (!sc_list.GetContextAtIndex(i, sc)) 147dda4f7b5SGreg Clayton break; 148b9c1b51eSKate Stone for (uint32_t range_idx = 0; 149b9c1b51eSKate Stone sc.GetAddressRange(scope, range_idx, use_inline_block_range, range); 150b9c1b51eSKate Stone ++range_idx) { 151b9c1b51eSKate Stone if (Disassemble(debugger, arch, plugin_name, flavor, exe_ctx, range, 1520b4c26b2SJason Molenda num_instructions, mixed_source_and_assembly, 1530b4c26b2SJason Molenda num_mixed_context_lines, options, strm)) { 154dda4f7b5SGreg Clayton ++success_count; 155dda4f7b5SGreg Clayton strm.EOL(); 156dda4f7b5SGreg Clayton } 157dda4f7b5SGreg Clayton } 158dda4f7b5SGreg Clayton } 159dda4f7b5SGreg Clayton return success_count; 160dda4f7b5SGreg Clayton } 161dda4f7b5SGreg Clayton 162b9c1b51eSKate Stone bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch, 163b9c1b51eSKate Stone const char *plugin_name, const char *flavor, 16430fdc8d8SChris Lattner const ExecutionContext &exe_ctx, 165b9c1b51eSKate Stone const ConstString &name, Module *module, 16637023b06SJim Ingham uint32_t num_instructions, 1670b4c26b2SJason Molenda bool mixed_source_and_assembly, 168dda4f7b5SGreg Clayton uint32_t num_mixed_context_lines, 169b9c1b51eSKate Stone uint32_t options, Stream &strm) { 170dda4f7b5SGreg Clayton SymbolContextList sc_list; 171b9c1b51eSKate Stone if (name) { 172931180e6SGreg Clayton const bool include_symbols = true; 1739df05fbbSSean Callanan const bool include_inlines = true; 174b9c1b51eSKate Stone if (module) { 175b9c1b51eSKate Stone module->FindFunctions(name, nullptr, eFunctionNameTypeAuto, 176b9c1b51eSKate Stone include_symbols, include_inlines, true, sc_list); 177b9c1b51eSKate Stone } else if (exe_ctx.GetTargetPtr()) { 178b9c1b51eSKate Stone exe_ctx.GetTargetPtr()->GetImages().FindFunctions( 179b9c1b51eSKate Stone name, eFunctionNameTypeAuto, include_symbols, include_inlines, false, 180931180e6SGreg Clayton sc_list); 181dda4f7b5SGreg Clayton } 182dda4f7b5SGreg Clayton } 183931180e6SGreg Clayton 184b9c1b51eSKate Stone if (sc_list.GetSize()) { 185b9c1b51eSKate Stone return Disassemble(debugger, arch, plugin_name, flavor, exe_ctx, sc_list, 1860b4c26b2SJason Molenda num_instructions, mixed_source_and_assembly, 1870b4c26b2SJason Molenda num_mixed_context_lines, options, strm); 188dda4f7b5SGreg Clayton } 189dda4f7b5SGreg Clayton return false; 190dda4f7b5SGreg Clayton } 191dda4f7b5SGreg Clayton 192b9c1b51eSKate Stone lldb::DisassemblerSP Disassembler::DisassembleRange( 193b9c1b51eSKate Stone const ArchSpec &arch, const char *plugin_name, const char *flavor, 194b9c1b51eSKate Stone const ExecutionContext &exe_ctx, const AddressRange &range, 195b9c1b51eSKate Stone bool prefer_file_cache) { 1961d273166SGreg Clayton lldb::DisassemblerSP disasm_sp; 197b9c1b51eSKate Stone if (range.GetByteSize() > 0 && range.GetBaseAddress().IsValid()) { 198b9c1b51eSKate Stone disasm_sp = Disassembler::FindPluginForTarget(exe_ctx.GetTargetSP(), arch, 199b9c1b51eSKate Stone flavor, plugin_name); 2001d273166SGreg Clayton 201b9c1b51eSKate Stone if (disasm_sp) { 202b9c1b51eSKate Stone size_t bytes_disassembled = disasm_sp->ParseInstructions( 203b9c1b51eSKate Stone &exe_ctx, range, nullptr, prefer_file_cache); 2041d273166SGreg Clayton if (bytes_disassembled == 0) 2051d273166SGreg Clayton disasm_sp.reset(); 2061d273166SGreg Clayton } 2071d273166SGreg Clayton } 2081d273166SGreg Clayton return disasm_sp; 2091d273166SGreg Clayton } 2101d273166SGreg Clayton 21150952e95SSean Callanan lldb::DisassemblerSP 212b9c1b51eSKate Stone Disassembler::DisassembleBytes(const ArchSpec &arch, const char *plugin_name, 213b9c1b51eSKate Stone const char *flavor, const Address &start, 214b9c1b51eSKate Stone const void *src, size_t src_len, 215b9c1b51eSKate Stone uint32_t num_instructions, bool data_from_file) { 21650952e95SSean Callanan lldb::DisassemblerSP disasm_sp; 21750952e95SSean Callanan 218b9c1b51eSKate Stone if (src) { 2190f063ba6SJim Ingham disasm_sp = Disassembler::FindPlugin(arch, flavor, plugin_name); 22050952e95SSean Callanan 221b9c1b51eSKate Stone if (disasm_sp) { 222b9c1b51eSKate Stone DataExtractor data(src, src_len, arch.GetByteOrder(), 223b9c1b51eSKate Stone arch.GetAddressByteSize()); 22450952e95SSean Callanan 225b9c1b51eSKate Stone (void)disasm_sp->DecodeInstructions(start, data, 0, num_instructions, 226b9c1b51eSKate Stone false, data_from_file); 22750952e95SSean Callanan } 22850952e95SSean Callanan } 22950952e95SSean Callanan 23050952e95SSean Callanan return disasm_sp; 23150952e95SSean Callanan } 23250952e95SSean Callanan 233b9c1b51eSKate Stone bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch, 234b9c1b51eSKate Stone const char *plugin_name, const char *flavor, 235dda4f7b5SGreg Clayton const ExecutionContext &exe_ctx, 236dda4f7b5SGreg Clayton const AddressRange &disasm_range, 23737023b06SJim Ingham uint32_t num_instructions, 2380b4c26b2SJason Molenda bool mixed_source_and_assembly, 239dda4f7b5SGreg Clayton uint32_t num_mixed_context_lines, 240b9c1b51eSKate Stone uint32_t options, Stream &strm) { 241b9c1b51eSKate Stone if (disasm_range.GetByteSize()) { 242b9c1b51eSKate Stone lldb::DisassemblerSP disasm_sp(Disassembler::FindPluginForTarget( 243b9c1b51eSKate Stone exe_ctx.GetTargetSP(), arch, flavor, plugin_name)); 24430fdc8d8SChris Lattner 245b9c1b51eSKate Stone if (disasm_sp) { 246357132ebSGreg Clayton AddressRange range; 247b9c1b51eSKate Stone ResolveAddress(exe_ctx, disasm_range.GetBaseAddress(), 248b9c1b51eSKate Stone range.GetBaseAddress()); 249357132ebSGreg Clayton range.SetByteSize(disasm_range.GetByteSize()); 2503faf47c4SGreg Clayton const bool prefer_file_cache = false; 251b9c1b51eSKate Stone size_t bytes_disassembled = disasm_sp->ParseInstructions( 252b9c1b51eSKate Stone &exe_ctx, range, &strm, prefer_file_cache); 25330fdc8d8SChris Lattner if (bytes_disassembled == 0) 25430fdc8d8SChris Lattner return false; 2551080edbcSGreg Clayton 256b9c1b51eSKate Stone return PrintInstructions(disasm_sp.get(), debugger, arch, exe_ctx, 2570b4c26b2SJason Molenda num_instructions, mixed_source_and_assembly, 2580b4c26b2SJason Molenda num_mixed_context_lines, options, strm); 25937023b06SJim Ingham } 26037023b06SJim Ingham } 26137023b06SJim Ingham return false; 26237023b06SJim Ingham } 26337023b06SJim Ingham 264b9c1b51eSKate Stone bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch, 265b9c1b51eSKate Stone const char *plugin_name, const char *flavor, 26637023b06SJim Ingham const ExecutionContext &exe_ctx, 26737023b06SJim Ingham const Address &start_address, 26837023b06SJim Ingham uint32_t num_instructions, 2690b4c26b2SJason Molenda bool mixed_source_and_assembly, 27037023b06SJim Ingham uint32_t num_mixed_context_lines, 271b9c1b51eSKate Stone uint32_t options, Stream &strm) { 272b9c1b51eSKate Stone if (num_instructions > 0) { 273b9c1b51eSKate Stone lldb::DisassemblerSP disasm_sp(Disassembler::FindPluginForTarget( 274b9c1b51eSKate Stone exe_ctx.GetTargetSP(), arch, flavor, plugin_name)); 275b9c1b51eSKate Stone if (disasm_sp) { 276357132ebSGreg Clayton Address addr; 277357132ebSGreg Clayton ResolveAddress(exe_ctx, start_address, addr); 2783faf47c4SGreg Clayton const bool prefer_file_cache = false; 279b9c1b51eSKate Stone size_t bytes_disassembled = disasm_sp->ParseInstructions( 280b9c1b51eSKate Stone &exe_ctx, addr, num_instructions, prefer_file_cache); 28137023b06SJim Ingham if (bytes_disassembled == 0) 28237023b06SJim Ingham return false; 283b9c1b51eSKate Stone return PrintInstructions(disasm_sp.get(), debugger, arch, exe_ctx, 2840b4c26b2SJason Molenda num_instructions, mixed_source_and_assembly, 2850b4c26b2SJason Molenda num_mixed_context_lines, options, strm); 28637023b06SJim Ingham } 28737023b06SJim Ingham } 28837023b06SJim Ingham return false; 28937023b06SJim Ingham } 29037023b06SJim Ingham 2910b4c26b2SJason Molenda Disassembler::SourceLine 2920b4c26b2SJason Molenda Disassembler::GetFunctionDeclLineEntry(const SymbolContext &sc) { 2930b4c26b2SJason Molenda SourceLine decl_line; 2940b4c26b2SJason Molenda if (sc.function && sc.line_entry.IsValid()) { 2950b4c26b2SJason Molenda LineEntry prologue_end_line = sc.line_entry; 2960b4c26b2SJason Molenda FileSpec func_decl_file; 2970b4c26b2SJason Molenda uint32_t func_decl_line; 2980b4c26b2SJason Molenda sc.function->GetStartLineSourceInfo(func_decl_file, func_decl_line); 2990b4c26b2SJason Molenda if (func_decl_file == prologue_end_line.file || 3000b4c26b2SJason Molenda func_decl_file == prologue_end_line.original_file) { 3010b4c26b2SJason Molenda decl_line.file = func_decl_file; 3020b4c26b2SJason Molenda decl_line.line = func_decl_line; 3039666ba75STodd Fiala // TODO do we care about column on these entries? If so, we need to 3049666ba75STodd Fiala // plumb that through GetStartLineSourceInfo. 3059666ba75STodd Fiala decl_line.column = 0; 3060b4c26b2SJason Molenda } 3070b4c26b2SJason Molenda } 3080b4c26b2SJason Molenda return decl_line; 3090b4c26b2SJason Molenda } 3100b4c26b2SJason Molenda 3110b4c26b2SJason Molenda void Disassembler::AddLineToSourceLineTables( 3120b4c26b2SJason Molenda SourceLine &line, 3130b4c26b2SJason Molenda std::map<FileSpec, std::set<uint32_t>> &source_lines_seen) { 3140b4c26b2SJason Molenda if (line.IsValid()) { 3150b4c26b2SJason Molenda auto source_lines_seen_pos = source_lines_seen.find(line.file); 3160b4c26b2SJason Molenda if (source_lines_seen_pos == source_lines_seen.end()) { 3170b4c26b2SJason Molenda std::set<uint32_t> lines; 3180b4c26b2SJason Molenda lines.insert(line.line); 3190b4c26b2SJason Molenda source_lines_seen.emplace(line.file, lines); 3200b4c26b2SJason Molenda } else { 3210b4c26b2SJason Molenda source_lines_seen_pos->second.insert(line.line); 3220b4c26b2SJason Molenda } 3230b4c26b2SJason Molenda } 3240b4c26b2SJason Molenda } 3250b4c26b2SJason Molenda 3260b4c26b2SJason Molenda bool Disassembler::ElideMixedSourceAndDisassemblyLine( 3270b4c26b2SJason Molenda const ExecutionContext &exe_ctx, const SymbolContext &sc, 3280b4c26b2SJason Molenda SourceLine &line) { 3290b4c26b2SJason Molenda 3300b4c26b2SJason Molenda // TODO: should we also check target.process.thread.step-avoid-libraries ? 3310b4c26b2SJason Molenda 3320b4c26b2SJason Molenda const RegularExpression *avoid_regex = nullptr; 3330b4c26b2SJason Molenda 3340b4c26b2SJason Molenda // Skip any line #0 entries - they are implementation details 3350b4c26b2SJason Molenda if (line.line == 0) 3360b4c26b2SJason Molenda return false; 3370b4c26b2SJason Molenda 3380b4c26b2SJason Molenda ThreadSP thread_sp = exe_ctx.GetThreadSP(); 3390b4c26b2SJason Molenda if (thread_sp) { 3400b4c26b2SJason Molenda avoid_regex = thread_sp->GetSymbolsToAvoidRegexp(); 3410b4c26b2SJason Molenda } else { 3420b4c26b2SJason Molenda TargetSP target_sp = exe_ctx.GetTargetSP(); 3430b4c26b2SJason Molenda if (target_sp) { 34497206d57SZachary Turner Status error; 3450b4c26b2SJason Molenda OptionValueSP value_sp = target_sp->GetDebugger().GetPropertyValue( 3460b4c26b2SJason Molenda &exe_ctx, "target.process.thread.step-avoid-regexp", false, error); 3470b4c26b2SJason Molenda if (value_sp && value_sp->GetType() == OptionValue::eTypeRegex) { 3480b4c26b2SJason Molenda OptionValueRegex *re = value_sp->GetAsRegex(); 3490b4c26b2SJason Molenda if (re) { 3500b4c26b2SJason Molenda avoid_regex = re->GetCurrentValue(); 3510b4c26b2SJason Molenda } 3520b4c26b2SJason Molenda } 3530b4c26b2SJason Molenda } 3540b4c26b2SJason Molenda } 3550b4c26b2SJason Molenda if (avoid_regex && sc.symbol != nullptr) { 3560b4c26b2SJason Molenda const char *function_name = 3570b4c26b2SJason Molenda sc.GetFunctionName(Mangled::ePreferDemangledWithoutArguments) 3580b4c26b2SJason Molenda .GetCString(); 3590b4c26b2SJason Molenda if (function_name) { 3600b4c26b2SJason Molenda RegularExpression::Match regex_match(1); 3610b4c26b2SJason Molenda if (avoid_regex->Execute(function_name, ®ex_match)) { 3620b4c26b2SJason Molenda // skip this source line 3630b4c26b2SJason Molenda return true; 3640b4c26b2SJason Molenda } 3650b4c26b2SJason Molenda } 3660b4c26b2SJason Molenda } 3670b4c26b2SJason Molenda // don't skip this source line 3680b4c26b2SJason Molenda return false; 3690b4c26b2SJason Molenda } 3700b4c26b2SJason Molenda 371b9c1b51eSKate Stone bool Disassembler::PrintInstructions(Disassembler *disasm_ptr, 372b9c1b51eSKate Stone Debugger &debugger, const ArchSpec &arch, 373b9c1b51eSKate Stone const ExecutionContext &exe_ctx, 374b9c1b51eSKate Stone uint32_t num_instructions, 3750b4c26b2SJason Molenda bool mixed_source_and_assembly, 376b9c1b51eSKate Stone uint32_t num_mixed_context_lines, 377b9c1b51eSKate Stone uint32_t options, Stream &strm) { 37830fdc8d8SChris Lattner // We got some things disassembled... 37937023b06SJim Ingham size_t num_instructions_found = disasm_ptr->GetInstructionList().GetSize(); 38037023b06SJim Ingham 38137023b06SJim Ingham if (num_instructions > 0 && num_instructions < num_instructions_found) 38237023b06SJim Ingham num_instructions_found = num_instructions; 38337023b06SJim Ingham 384b9c1b51eSKate Stone const uint32_t max_opcode_byte_size = 385b9c1b51eSKate Stone disasm_ptr->GetInstructionList().GetMaxOpcocdeByteSize(); 38630fdc8d8SChris Lattner SymbolContext sc; 38730fdc8d8SChris Lattner SymbolContext prev_sc; 3880b4c26b2SJason Molenda AddressRange current_source_line_range; 38934ede34aSEugene Zelenko const Address *pc_addr_ptr = nullptr; 390b57e4a1bSJason Molenda StackFrame *frame = exe_ctx.GetFramePtr(); 391c14ee32dSGreg Clayton 3924b2967ffSMichael Sartain TargetSP target_sp(exe_ctx.GetTargetSP()); 393b9c1b51eSKate Stone SourceManager &source_manager = 394b9c1b51eSKate Stone target_sp ? target_sp->GetSourceManager() : debugger.GetSourceManager(); 3954b2967ffSMichael Sartain 396b9c1b51eSKate Stone if (frame) { 397c14ee32dSGreg Clayton pc_addr_ptr = &frame->GetFrameCodeAddress(); 398aff1b357SJason Molenda } 399b9c1b51eSKate Stone const uint32_t scope = 400b9c1b51eSKate Stone eSymbolContextLineEntry | eSymbolContextFunction | eSymbolContextSymbol; 4017e14f91dSGreg Clayton const bool use_inline_block_range = false; 402c980fa92SJason Molenda 40334ede34aSEugene Zelenko const FormatEntity::Entry *disassembly_format = nullptr; 404c980fa92SJason Molenda FormatEntity::Entry format; 405b9c1b51eSKate Stone if (exe_ctx.HasTargetScope()) { 406b9c1b51eSKate Stone disassembly_format = 407b9c1b51eSKate Stone exe_ctx.GetTargetRef().GetDebugger().GetDisassemblyFormat(); 408b9c1b51eSKate Stone } else { 409c980fa92SJason Molenda FormatEntity::Parse("${addr}: ", format); 410c980fa92SJason Molenda disassembly_format = &format; 411c980fa92SJason Molenda } 412c980fa92SJason Molenda 41305097246SAdrian Prantl // First pass: step through the list of instructions, find how long the 41405097246SAdrian Prantl // initial addresses strings are, insert padding in the second pass so the 41505097246SAdrian Prantl // opcodes all line up nicely. 4160b4c26b2SJason Molenda 4170b4c26b2SJason Molenda // Also build up the source line mapping if this is mixed source & assembly 41805097246SAdrian Prantl // mode. Calculate the source line for each assembly instruction (eliding 41905097246SAdrian Prantl // inlined functions which the user wants to skip). 4200b4c26b2SJason Molenda 4210b4c26b2SJason Molenda std::map<FileSpec, std::set<uint32_t>> source_lines_seen; 4220b4c26b2SJason Molenda Symbol *previous_symbol = nullptr; 4230b4c26b2SJason Molenda 424c980fa92SJason Molenda size_t address_text_size = 0; 425b9c1b51eSKate Stone for (size_t i = 0; i < num_instructions_found; ++i) { 426b9c1b51eSKate Stone Instruction *inst = 427b9c1b51eSKate Stone disasm_ptr->GetInstructionList().GetInstructionAtIndex(i).get(); 428b9c1b51eSKate Stone if (inst) { 429c980fa92SJason Molenda const Address &addr = inst->GetAddress(); 430c980fa92SJason Molenda ModuleSP module_sp(addr.GetModule()); 431b9c1b51eSKate Stone if (module_sp) { 4320b4c26b2SJason Molenda const uint32_t resolve_mask = eSymbolContextFunction | 4330b4c26b2SJason Molenda eSymbolContextSymbol | 4340b4c26b2SJason Molenda eSymbolContextLineEntry; 435b9c1b51eSKate Stone uint32_t resolved_mask = 436b9c1b51eSKate Stone module_sp->ResolveSymbolContextForAddress(addr, resolve_mask, sc); 437b9c1b51eSKate Stone if (resolved_mask) { 438c980fa92SJason Molenda StreamString strmstr; 439b9c1b51eSKate Stone Debugger::FormatDisassemblerAddress(disassembly_format, &sc, nullptr, 440b9c1b51eSKate Stone &exe_ctx, &addr, strmstr); 441c980fa92SJason Molenda size_t cur_line = strmstr.GetSizeOfLastLine(); 442c980fa92SJason Molenda if (cur_line > address_text_size) 443c980fa92SJason Molenda address_text_size = cur_line; 4440b4c26b2SJason Molenda 4450b4c26b2SJason Molenda // Add entries to our "source_lines_seen" map+set which list which 4460b4c26b2SJason Molenda // sources lines occur in this disassembly session. We will print 4470b4c26b2SJason Molenda // lines of context around a source line, but we don't want to print 4480b4c26b2SJason Molenda // a source line that has a line table entry of its own - we'll leave 4490b4c26b2SJason Molenda // that source line to be printed when it actually occurs in the 4500b4c26b2SJason Molenda // disassembly. 4510b4c26b2SJason Molenda 4520b4c26b2SJason Molenda if (mixed_source_and_assembly && sc.line_entry.IsValid()) { 4530b4c26b2SJason Molenda if (sc.symbol != previous_symbol) { 4540b4c26b2SJason Molenda SourceLine decl_line = GetFunctionDeclLineEntry(sc); 4550b4c26b2SJason Molenda if (ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, decl_line) == 4560b4c26b2SJason Molenda false) 4570b4c26b2SJason Molenda AddLineToSourceLineTables(decl_line, source_lines_seen); 4580b4c26b2SJason Molenda } 4590b4c26b2SJason Molenda if (sc.line_entry.IsValid()) { 4600b4c26b2SJason Molenda SourceLine this_line; 4610b4c26b2SJason Molenda this_line.file = sc.line_entry.file; 4620b4c26b2SJason Molenda this_line.line = sc.line_entry.line; 4639666ba75STodd Fiala this_line.column = sc.line_entry.column; 4640b4c26b2SJason Molenda if (ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, this_line) == 4650b4c26b2SJason Molenda false) 4660b4c26b2SJason Molenda AddLineToSourceLineTables(this_line, source_lines_seen); 4670b4c26b2SJason Molenda } 4680b4c26b2SJason Molenda } 469c980fa92SJason Molenda } 470c980fa92SJason Molenda sc.Clear(false); 471c980fa92SJason Molenda } 472c980fa92SJason Molenda } 473c980fa92SJason Molenda } 474c980fa92SJason Molenda 4750b4c26b2SJason Molenda previous_symbol = nullptr; 4760b4c26b2SJason Molenda SourceLine previous_line; 477b9c1b51eSKate Stone for (size_t i = 0; i < num_instructions_found; ++i) { 478b9c1b51eSKate Stone Instruction *inst = 479b9c1b51eSKate Stone disasm_ptr->GetInstructionList().GetInstructionAtIndex(i).get(); 4800b4c26b2SJason Molenda 481b9c1b51eSKate Stone if (inst) { 48232e0a750SGreg Clayton const Address &addr = inst->GetAddress(); 48332e0a750SGreg Clayton const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr; 4840b4c26b2SJason Molenda SourceLinesToDisplay source_lines_to_display; 485dda4f7b5SGreg Clayton 48630fdc8d8SChris Lattner prev_sc = sc; 487dda4f7b5SGreg Clayton 488e72dfb32SGreg Clayton ModuleSP module_sp(addr.GetModule()); 489b9c1b51eSKate Stone if (module_sp) { 490b9c1b51eSKate Stone uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress( 491b9c1b51eSKate Stone addr, eSymbolContextEverything, sc); 492b9c1b51eSKate Stone if (resolved_mask) { 4930b4c26b2SJason Molenda if (mixed_source_and_assembly) { 494dda4f7b5SGreg Clayton 4950b4c26b2SJason Molenda // If we've started a new function (non-inlined), print all of the 49605097246SAdrian Prantl // source lines from the function declaration until the first line 49705097246SAdrian Prantl // table entry - typically the opening curly brace of the function. 4980b4c26b2SJason Molenda if (previous_symbol != sc.symbol) { 49905097246SAdrian Prantl // The default disassembly format puts an extra blank line 50005097246SAdrian Prantl // between functions - so when we're displaying the source 50105097246SAdrian Prantl // context for a function, we don't want to add a blank line 50205097246SAdrian Prantl // after the source context or we'll end up with two of them. 5030b4c26b2SJason Molenda if (previous_symbol != nullptr) 5040b4c26b2SJason Molenda source_lines_to_display.print_source_context_end_eol = false; 50530fdc8d8SChris Lattner 5060b4c26b2SJason Molenda previous_symbol = sc.symbol; 5070b4c26b2SJason Molenda if (sc.function && sc.line_entry.IsValid()) { 5080b4c26b2SJason Molenda LineEntry prologue_end_line = sc.line_entry; 5090b4c26b2SJason Molenda if (ElideMixedSourceAndDisassemblyLine( 5100b4c26b2SJason Molenda exe_ctx, sc, prologue_end_line) == false) { 5110b4c26b2SJason Molenda FileSpec func_decl_file; 5120b4c26b2SJason Molenda uint32_t func_decl_line; 5130b4c26b2SJason Molenda sc.function->GetStartLineSourceInfo(func_decl_file, 5140b4c26b2SJason Molenda func_decl_line); 5150b4c26b2SJason Molenda if (func_decl_file == prologue_end_line.file || 5160b4c26b2SJason Molenda func_decl_file == prologue_end_line.original_file) { 51705097246SAdrian Prantl // Add all the lines between the function declaration and 51805097246SAdrian Prantl // the first non-prologue source line to the list of lines 51905097246SAdrian Prantl // to print. 5200b4c26b2SJason Molenda for (uint32_t lineno = func_decl_line; 5210b4c26b2SJason Molenda lineno <= prologue_end_line.line; lineno++) { 5220b4c26b2SJason Molenda SourceLine this_line; 5230b4c26b2SJason Molenda this_line.file = func_decl_file; 5240b4c26b2SJason Molenda this_line.line = lineno; 5250b4c26b2SJason Molenda source_lines_to_display.lines.push_back(this_line); 5260b4c26b2SJason Molenda } 52705097246SAdrian Prantl // Mark the last line as the "current" one. Usually this 52805097246SAdrian Prantl // is the open curly brace. 5290b4c26b2SJason Molenda if (source_lines_to_display.lines.size() > 0) 5300b4c26b2SJason Molenda source_lines_to_display.current_source_line = 5310b4c26b2SJason Molenda source_lines_to_display.lines.size() - 1; 5320b4c26b2SJason Molenda } 5330b4c26b2SJason Molenda } 5340b4c26b2SJason Molenda } 5350b4c26b2SJason Molenda sc.GetAddressRange(scope, 0, use_inline_block_range, 5360b4c26b2SJason Molenda current_source_line_range); 5370b4c26b2SJason Molenda } 53830fdc8d8SChris Lattner 53905097246SAdrian Prantl // If we've left a previous source line's address range, print a 54005097246SAdrian Prantl // new source line 5410b4c26b2SJason Molenda if (!current_source_line_range.ContainsFileAddress(addr)) { 5420b4c26b2SJason Molenda sc.GetAddressRange(scope, 0, use_inline_block_range, 5430b4c26b2SJason Molenda current_source_line_range); 5440b4c26b2SJason Molenda 5450b4c26b2SJason Molenda if (sc != prev_sc && sc.comp_unit && sc.line_entry.IsValid()) { 5460b4c26b2SJason Molenda SourceLine this_line; 5470b4c26b2SJason Molenda this_line.file = sc.line_entry.file; 5480b4c26b2SJason Molenda this_line.line = sc.line_entry.line; 5490b4c26b2SJason Molenda 5500b4c26b2SJason Molenda if (ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, 5510b4c26b2SJason Molenda this_line) == false) { 5520b4c26b2SJason Molenda // Only print this source line if it is different from the 5530b4c26b2SJason Molenda // last source line we printed. There may have been inlined 5540b4c26b2SJason Molenda // functions between these lines that we elided, resulting in 55505097246SAdrian Prantl // the same line being printed twice in a row for a 55605097246SAdrian Prantl // contiguous block of assembly instructions. 5570b4c26b2SJason Molenda if (this_line != previous_line) { 5580b4c26b2SJason Molenda 5590b4c26b2SJason Molenda std::vector<uint32_t> previous_lines; 5607771462bSEd Maste for (uint32_t i = 0; 5610b4c26b2SJason Molenda i < num_mixed_context_lines && 5620b4c26b2SJason Molenda (this_line.line - num_mixed_context_lines) > 0; 5630b4c26b2SJason Molenda i++) { 5640b4c26b2SJason Molenda uint32_t line = 5650b4c26b2SJason Molenda this_line.line - num_mixed_context_lines + i; 5660b4c26b2SJason Molenda auto pos = source_lines_seen.find(this_line.file); 5670b4c26b2SJason Molenda if (pos != source_lines_seen.end()) { 5680b4c26b2SJason Molenda if (pos->second.count(line) == 1) { 5690b4c26b2SJason Molenda previous_lines.clear(); 5700b4c26b2SJason Molenda } else { 5710b4c26b2SJason Molenda previous_lines.push_back(line); 5720b4c26b2SJason Molenda } 5730b4c26b2SJason Molenda } 5740b4c26b2SJason Molenda } 5750b4c26b2SJason Molenda for (size_t i = 0; i < previous_lines.size(); i++) { 5760b4c26b2SJason Molenda SourceLine previous_line; 5770b4c26b2SJason Molenda previous_line.file = this_line.file; 5780b4c26b2SJason Molenda previous_line.line = previous_lines[i]; 5790b4c26b2SJason Molenda auto pos = source_lines_seen.find(previous_line.file); 5800b4c26b2SJason Molenda if (pos != source_lines_seen.end()) { 5810b4c26b2SJason Molenda pos->second.insert(previous_line.line); 5820b4c26b2SJason Molenda } 5830b4c26b2SJason Molenda source_lines_to_display.lines.push_back(previous_line); 5840b4c26b2SJason Molenda } 5850b4c26b2SJason Molenda 5860b4c26b2SJason Molenda source_lines_to_display.lines.push_back(this_line); 5870b4c26b2SJason Molenda source_lines_to_display.current_source_line = 5880b4c26b2SJason Molenda source_lines_to_display.lines.size() - 1; 5890b4c26b2SJason Molenda 5907771462bSEd Maste for (uint32_t i = 0; i < num_mixed_context_lines; i++) { 5910b4c26b2SJason Molenda SourceLine next_line; 5920b4c26b2SJason Molenda next_line.file = this_line.file; 5930b4c26b2SJason Molenda next_line.line = this_line.line + i + 1; 5940b4c26b2SJason Molenda auto pos = source_lines_seen.find(next_line.file); 5950b4c26b2SJason Molenda if (pos != source_lines_seen.end()) { 5960b4c26b2SJason Molenda if (pos->second.count(next_line.line) == 1) 5970b4c26b2SJason Molenda break; 5980b4c26b2SJason Molenda pos->second.insert(next_line.line); 5990b4c26b2SJason Molenda } 6000b4c26b2SJason Molenda source_lines_to_display.lines.push_back(next_line); 6010b4c26b2SJason Molenda } 6020b4c26b2SJason Molenda } 6030b4c26b2SJason Molenda previous_line = this_line; 60430fdc8d8SChris Lattner } 60530fdc8d8SChris Lattner } 60630fdc8d8SChris Lattner } 60730fdc8d8SChris Lattner } 608b9c1b51eSKate Stone } else { 60972310355SGreg Clayton sc.Clear(true); 61030fdc8d8SChris Lattner } 61130fdc8d8SChris Lattner } 61232e0a750SGreg Clayton 6130b4c26b2SJason Molenda if (source_lines_to_display.lines.size() > 0) { 6140b4c26b2SJason Molenda strm.EOL(); 6150b4c26b2SJason Molenda for (size_t idx = 0; idx < source_lines_to_display.lines.size(); 6160b4c26b2SJason Molenda idx++) { 6170b4c26b2SJason Molenda SourceLine ln = source_lines_to_display.lines[idx]; 6180b4c26b2SJason Molenda const char *line_highlight = ""; 6190b4c26b2SJason Molenda if (inst_is_at_pc && (options & eOptionMarkPCSourceLine)) { 6200b4c26b2SJason Molenda line_highlight = "->"; 6210b4c26b2SJason Molenda } else if (idx == source_lines_to_display.current_source_line) { 6220b4c26b2SJason Molenda line_highlight = "**"; 6230b4c26b2SJason Molenda } 6240b4c26b2SJason Molenda source_manager.DisplaySourceLinesWithLineNumbers( 6259666ba75STodd Fiala ln.file, ln.line, ln.column, 0, 0, line_highlight, &strm); 6260b4c26b2SJason Molenda } 6270b4c26b2SJason Molenda if (source_lines_to_display.print_source_context_end_eol) 6280b4c26b2SJason Molenda strm.EOL(); 6290b4c26b2SJason Molenda } 6300b4c26b2SJason Molenda 6311da6f9d7SGreg Clayton const bool show_bytes = (options & eOptionShowBytes) != 0; 632b9c1b51eSKate Stone inst->Dump(&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx, &sc, 633b9c1b51eSKate Stone &prev_sc, nullptr, address_text_size); 63430fdc8d8SChris Lattner strm.EOL(); 635b9c1b51eSKate Stone } else { 63630fdc8d8SChris Lattner break; 63730fdc8d8SChris Lattner } 63830fdc8d8SChris Lattner } 63930fdc8d8SChris Lattner 64030fdc8d8SChris Lattner return true; 64130fdc8d8SChris Lattner } 64230fdc8d8SChris Lattner 643b9c1b51eSKate Stone bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch, 644b9c1b51eSKate Stone const char *plugin_name, const char *flavor, 645dda4f7b5SGreg Clayton const ExecutionContext &exe_ctx, 64637023b06SJim Ingham uint32_t num_instructions, 6470b4c26b2SJason Molenda bool mixed_source_and_assembly, 648dda4f7b5SGreg Clayton uint32_t num_mixed_context_lines, 649b9c1b51eSKate Stone uint32_t options, Stream &strm) { 650dda4f7b5SGreg Clayton AddressRange range; 651b57e4a1bSJason Molenda StackFrame *frame = exe_ctx.GetFramePtr(); 652b9c1b51eSKate Stone if (frame) { 653b9c1b51eSKate Stone SymbolContext sc( 654b9c1b51eSKate Stone frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol)); 655b9c1b51eSKate Stone if (sc.function) { 656dda4f7b5SGreg Clayton range = sc.function->GetAddressRange(); 657b9c1b51eSKate Stone } else if (sc.symbol && sc.symbol->ValueIsAddress()) { 658358cf1eaSGreg Clayton range.GetBaseAddress() = sc.symbol->GetAddressRef(); 659e7612134SGreg Clayton range.SetByteSize(sc.symbol->GetByteSize()); 660b9c1b51eSKate Stone } else { 661c14ee32dSGreg Clayton range.GetBaseAddress() = frame->GetFrameCodeAddress(); 662dda4f7b5SGreg Clayton } 663dda4f7b5SGreg Clayton 664dda4f7b5SGreg Clayton if (range.GetBaseAddress().IsValid() && range.GetByteSize() == 0) 665dda4f7b5SGreg Clayton range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE); 666dda4f7b5SGreg Clayton } 667dda4f7b5SGreg Clayton 668b9c1b51eSKate Stone return Disassemble(debugger, arch, plugin_name, flavor, exe_ctx, range, 6690b4c26b2SJason Molenda num_instructions, mixed_source_and_assembly, 6700b4c26b2SJason Molenda num_mixed_context_lines, options, strm); 671dda4f7b5SGreg Clayton } 672dda4f7b5SGreg Clayton 673b9c1b51eSKate Stone Instruction::Instruction(const Address &address, AddressClass addr_class) 674b9c1b51eSKate Stone : m_address(address), m_address_class(addr_class), m_opcode(), 675b9c1b51eSKate Stone m_calculated_strings(false) {} 67630fdc8d8SChris Lattner 67734ede34aSEugene Zelenko Instruction::~Instruction() = default; 67830fdc8d8SChris Lattner 679b9c1b51eSKate Stone AddressClass Instruction::GetAddressClass() { 680357132ebSGreg Clayton if (m_address_class == eAddressClassInvalid) 681357132ebSGreg Clayton m_address_class = m_address.GetAddressClass(); 682357132ebSGreg Clayton return m_address_class; 683357132ebSGreg Clayton } 68430fdc8d8SChris Lattner 685b9c1b51eSKate Stone void Instruction::Dump(lldb_private::Stream *s, uint32_t max_opcode_byte_size, 686b9c1b51eSKate Stone bool show_address, bool show_bytes, 687aff1b357SJason Molenda const ExecutionContext *exe_ctx, 688aff1b357SJason Molenda const SymbolContext *sym_ctx, 689aff1b357SJason Molenda const SymbolContext *prev_sym_ctx, 690c980fa92SJason Molenda const FormatEntity::Entry *disassembly_addr_format, 691b9c1b51eSKate Stone size_t max_address_text_size) { 6927a37c1ecSJason Molenda size_t opcode_column_width = 7; 693ba812f42SGreg Clayton const size_t operand_column_width = 25; 694ba812f42SGreg Clayton 695ba812f42SGreg Clayton CalculateMnemonicOperandsAndCommentIfNeeded(exe_ctx); 696ba812f42SGreg Clayton 697ba812f42SGreg Clayton StreamString ss; 698ba812f42SGreg Clayton 699b9c1b51eSKate Stone if (show_address) { 700b9c1b51eSKate Stone Debugger::FormatDisassemblerAddress(disassembly_addr_format, sym_ctx, 701b9c1b51eSKate Stone prev_sym_ctx, exe_ctx, &m_address, ss); 702c980fa92SJason Molenda ss.FillLastLineToColumn(max_address_text_size, ' '); 703ba812f42SGreg Clayton } 704ba812f42SGreg Clayton 705b9c1b51eSKate Stone if (show_bytes) { 706b9c1b51eSKate Stone if (m_opcode.GetType() == Opcode::eTypeBytes) { 70705097246SAdrian Prantl // x86_64 and i386 are the only ones that use bytes right now so pad out 70805097246SAdrian Prantl // the byte dump to be able to always show 15 bytes (3 chars each) plus a 70905097246SAdrian Prantl // space 710ba812f42SGreg Clayton if (max_opcode_byte_size > 0) 711ba812f42SGreg Clayton m_opcode.Dump(&ss, max_opcode_byte_size * 3 + 1); 712ba812f42SGreg Clayton else 713ba812f42SGreg Clayton m_opcode.Dump(&ss, 15 * 3 + 1); 714b9c1b51eSKate Stone } else { 71505097246SAdrian Prantl // Else, we have ARM or MIPS which can show up to a uint32_t 0x00000000 71605097246SAdrian Prantl // (10 spaces) plus two for padding... 717ba812f42SGreg Clayton if (max_opcode_byte_size > 0) 718ba812f42SGreg Clayton m_opcode.Dump(&ss, max_opcode_byte_size * 3 + 1); 719ba812f42SGreg Clayton else 720ba812f42SGreg Clayton m_opcode.Dump(&ss, 12); 721ba812f42SGreg Clayton } 722ba812f42SGreg Clayton } 723ba812f42SGreg Clayton 724aff1b357SJason Molenda const size_t opcode_pos = ss.GetSizeOfLastLine(); 725ba812f42SGreg Clayton 7267a37c1ecSJason Molenda // The default opcode size of 7 characters is plenty for most architectures 7277a37c1ecSJason Molenda // but some like arm can pull out the occasional vqrshrun.s16. We won't get 7287a37c1ecSJason Molenda // consistent column spacing in these cases, unfortunately. 729b9c1b51eSKate Stone if (m_opcode_name.length() >= opcode_column_width) { 7307a37c1ecSJason Molenda opcode_column_width = m_opcode_name.length() + 1; 7317a37c1ecSJason Molenda } 7327a37c1ecSJason Molenda 733771ef6d4SMalcolm Parsons ss.PutCString(m_opcode_name); 734ba812f42SGreg Clayton ss.FillLastLineToColumn(opcode_pos + opcode_column_width, ' '); 735771ef6d4SMalcolm Parsons ss.PutCString(m_mnemonics); 736ba812f42SGreg Clayton 737b9c1b51eSKate Stone if (!m_comment.empty()) { 738b9c1b51eSKate Stone ss.FillLastLineToColumn( 739b9c1b51eSKate Stone opcode_pos + opcode_column_width + operand_column_width, ' '); 740ba812f42SGreg Clayton ss.PutCString(" ; "); 741771ef6d4SMalcolm Parsons ss.PutCString(m_comment); 742ba812f42SGreg Clayton } 743c156427dSZachary Turner s->PutCString(ss.GetString()); 744ba812f42SGreg Clayton } 745ba812f42SGreg Clayton 746b9c1b51eSKate Stone bool Instruction::DumpEmulation(const ArchSpec &arch) { 747b9c1b51eSKate Stone std::unique_ptr<EmulateInstruction> insn_emulator_ap( 748b9c1b51eSKate Stone EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr)); 749b9c1b51eSKate Stone if (insn_emulator_ap) { 75034ede34aSEugene Zelenko insn_emulator_ap->SetInstruction(GetOpcode(), GetAddress(), nullptr); 7512ed751bdSGreg Clayton return insn_emulator_ap->EvaluateInstruction(0); 7527c9dd3ceSCaroline Tice } 7537c9dd3ceSCaroline Tice 7547c9dd3ceSCaroline Tice return false; 7557c9dd3ceSCaroline Tice } 7567c9dd3ceSCaroline Tice 757dd125943SNitesh Jain bool Instruction::CanSetBreakpoint () { 758dd125943SNitesh Jain return !HasDelaySlot(); 759dd125943SNitesh Jain } 760dd125943SNitesh Jain 761b9c1b51eSKate Stone bool Instruction::HasDelaySlot() { 7627f3daedaSBhushan D. Attarde // Default is false. 7637f3daedaSBhushan D. Attarde return false; 7647f3daedaSBhushan D. Attarde } 7657f3daedaSBhushan D. Attarde 766b9c1b51eSKate Stone OptionValueSP Instruction::ReadArray(FILE *in_file, Stream *out_stream, 767b9c1b51eSKate Stone OptionValue::Type data_type) { 768de2fb9cfSCaroline Tice bool done = false; 769de2fb9cfSCaroline Tice char buffer[1024]; 770de2fb9cfSCaroline Tice 7712f3df613SZachary Turner auto option_value_sp = std::make_shared<OptionValueArray>(1u << data_type); 772de2fb9cfSCaroline Tice 773de2fb9cfSCaroline Tice int idx = 0; 774b9c1b51eSKate Stone while (!done) { 775b9c1b51eSKate Stone if (!fgets(buffer, 1023, in_file)) { 776b9c1b51eSKate Stone out_stream->Printf( 777b9c1b51eSKate Stone "Instruction::ReadArray: Error reading file (fgets).\n"); 778de2fb9cfSCaroline Tice option_value_sp.reset(); 779de2fb9cfSCaroline Tice return option_value_sp; 780de2fb9cfSCaroline Tice } 781de2fb9cfSCaroline Tice 782de2fb9cfSCaroline Tice std::string line(buffer); 783de2fb9cfSCaroline Tice 784c7bece56SGreg Clayton size_t len = line.size(); 785b9c1b51eSKate Stone if (line[len - 1] == '\n') { 786de2fb9cfSCaroline Tice line[len - 1] = '\0'; 787de2fb9cfSCaroline Tice line.resize(len - 1); 788de2fb9cfSCaroline Tice } 789de2fb9cfSCaroline Tice 790b9c1b51eSKate Stone if ((line.size() == 1) && line[0] == ']') { 791de2fb9cfSCaroline Tice done = true; 792de2fb9cfSCaroline Tice line.clear(); 793de2fb9cfSCaroline Tice } 794de2fb9cfSCaroline Tice 795b9c1b51eSKate Stone if (!line.empty()) { 796de2fb9cfSCaroline Tice std::string value; 79795eae423SZachary Turner static RegularExpression g_reg_exp( 79895eae423SZachary Turner llvm::StringRef("^[ \t]*([^ \t]+)[ \t]*$")); 799bc43cab5SGreg Clayton RegularExpression::Match regex_match(1); 80095eae423SZachary Turner bool reg_exp_success = g_reg_exp.Execute(line, ®ex_match); 801de2fb9cfSCaroline Tice if (reg_exp_success) 802bc43cab5SGreg Clayton regex_match.GetMatchAtIndex(line.c_str(), 1, value); 803de2fb9cfSCaroline Tice else 804de2fb9cfSCaroline Tice value = line; 805de2fb9cfSCaroline Tice 806de2fb9cfSCaroline Tice OptionValueSP data_value_sp; 807b9c1b51eSKate Stone switch (data_type) { 808de2fb9cfSCaroline Tice case OptionValue::eTypeUInt64: 8092f3df613SZachary Turner data_value_sp = std::make_shared<OptionValueUInt64>(0, 0); 810c95f7e2aSPavel Labath data_value_sp->SetValueFromString(value); 811de2fb9cfSCaroline Tice break; 812de2fb9cfSCaroline Tice // Other types can be added later as needed. 813de2fb9cfSCaroline Tice default: 8142f3df613SZachary Turner data_value_sp = std::make_shared<OptionValueString>(value.c_str(), ""); 815de2fb9cfSCaroline Tice break; 816de2fb9cfSCaroline Tice } 817de2fb9cfSCaroline Tice 81884c39663SGreg Clayton option_value_sp->GetAsArray()->InsertValue(idx, data_value_sp); 819de2fb9cfSCaroline Tice ++idx; 820de2fb9cfSCaroline Tice } 821de2fb9cfSCaroline Tice } 822de2fb9cfSCaroline Tice 823de2fb9cfSCaroline Tice return option_value_sp; 824de2fb9cfSCaroline Tice } 825de2fb9cfSCaroline Tice 826b9c1b51eSKate Stone OptionValueSP Instruction::ReadDictionary(FILE *in_file, Stream *out_stream) { 827de2fb9cfSCaroline Tice bool done = false; 828de2fb9cfSCaroline Tice char buffer[1024]; 829de2fb9cfSCaroline Tice 8302f3df613SZachary Turner auto option_value_sp = std::make_shared<OptionValueDictionary>(); 831de2fb9cfSCaroline Tice static ConstString encoding_key("data_encoding"); 832de2fb9cfSCaroline Tice OptionValue::Type data_type = OptionValue::eTypeInvalid; 833de2fb9cfSCaroline Tice 834b9c1b51eSKate Stone while (!done) { 835de2fb9cfSCaroline Tice // Read the next line in the file 836b9c1b51eSKate Stone if (!fgets(buffer, 1023, in_file)) { 837b9c1b51eSKate Stone out_stream->Printf( 838b9c1b51eSKate Stone "Instruction::ReadDictionary: Error reading file (fgets).\n"); 839de2fb9cfSCaroline Tice option_value_sp.reset(); 840de2fb9cfSCaroline Tice return option_value_sp; 841de2fb9cfSCaroline Tice } 842de2fb9cfSCaroline Tice 843de2fb9cfSCaroline Tice // Check to see if the line contains the end-of-dictionary marker ("}") 844de2fb9cfSCaroline Tice std::string line(buffer); 845de2fb9cfSCaroline Tice 846c7bece56SGreg Clayton size_t len = line.size(); 847b9c1b51eSKate Stone if (line[len - 1] == '\n') { 848de2fb9cfSCaroline Tice line[len - 1] = '\0'; 849de2fb9cfSCaroline Tice line.resize(len - 1); 850de2fb9cfSCaroline Tice } 851de2fb9cfSCaroline Tice 852b9c1b51eSKate Stone if ((line.size() == 1) && (line[0] == '}')) { 853de2fb9cfSCaroline Tice done = true; 854de2fb9cfSCaroline Tice line.clear(); 855de2fb9cfSCaroline Tice } 856de2fb9cfSCaroline Tice 857b9c1b51eSKate Stone // Try to find a key-value pair in the current line and add it to the 858b9c1b51eSKate Stone // dictionary. 859b9c1b51eSKate Stone if (!line.empty()) { 86095eae423SZachary Turner static RegularExpression g_reg_exp(llvm::StringRef( 86195eae423SZachary Turner "^[ \t]*([a-zA-Z_][a-zA-Z0-9_]*)[ \t]*=[ \t]*(.*)[ \t]*$")); 862bc43cab5SGreg Clayton RegularExpression::Match regex_match(2); 863bc43cab5SGreg Clayton 86495eae423SZachary Turner bool reg_exp_success = g_reg_exp.Execute(line, ®ex_match); 865de2fb9cfSCaroline Tice std::string key; 866de2fb9cfSCaroline Tice std::string value; 867b9c1b51eSKate Stone if (reg_exp_success) { 868bc43cab5SGreg Clayton regex_match.GetMatchAtIndex(line.c_str(), 1, key); 869bc43cab5SGreg Clayton regex_match.GetMatchAtIndex(line.c_str(), 2, value); 870b9c1b51eSKate Stone } else { 871b9c1b51eSKate Stone out_stream->Printf("Instruction::ReadDictionary: Failure executing " 872b9c1b51eSKate Stone "regular expression.\n"); 873de2fb9cfSCaroline Tice option_value_sp.reset(); 874de2fb9cfSCaroline Tice return option_value_sp; 875de2fb9cfSCaroline Tice } 876de2fb9cfSCaroline Tice 877de2fb9cfSCaroline Tice ConstString const_key(key.c_str()); 878de2fb9cfSCaroline Tice // Check value to see if it's the start of an array or dictionary. 879de2fb9cfSCaroline Tice 880de2fb9cfSCaroline Tice lldb::OptionValueSP value_sp; 881de2fb9cfSCaroline Tice assert(value.empty() == false); 882de2fb9cfSCaroline Tice assert(key.empty() == false); 883de2fb9cfSCaroline Tice 884b9c1b51eSKate Stone if (value[0] == '{') { 885de2fb9cfSCaroline Tice assert(value.size() == 1); 886de2fb9cfSCaroline Tice // value is a dictionary 887de2fb9cfSCaroline Tice value_sp = ReadDictionary(in_file, out_stream); 888b9c1b51eSKate Stone if (!value_sp) { 889de2fb9cfSCaroline Tice option_value_sp.reset(); 890de2fb9cfSCaroline Tice return option_value_sp; 891de2fb9cfSCaroline Tice } 892b9c1b51eSKate Stone } else if (value[0] == '[') { 893de2fb9cfSCaroline Tice assert(value.size() == 1); 894de2fb9cfSCaroline Tice // value is an array 895de2fb9cfSCaroline Tice value_sp = ReadArray(in_file, out_stream, data_type); 896b9c1b51eSKate Stone if (!value_sp) { 897de2fb9cfSCaroline Tice option_value_sp.reset(); 898de2fb9cfSCaroline Tice return option_value_sp; 899de2fb9cfSCaroline Tice } 90005097246SAdrian Prantl // We've used the data_type to read an array; re-set the type to 90105097246SAdrian Prantl // Invalid 902de2fb9cfSCaroline Tice data_type = OptionValue::eTypeInvalid; 903b9c1b51eSKate Stone } else if ((value[0] == '0') && (value[1] == 'x')) { 9042f3df613SZachary Turner value_sp = std::make_shared<OptionValueUInt64>(0, 0); 905c95f7e2aSPavel Labath value_sp->SetValueFromString(value); 906b9c1b51eSKate Stone } else { 907c7bece56SGreg Clayton size_t len = value.size(); 908de2fb9cfSCaroline Tice if ((value[0] == '"') && (value[len - 1] == '"')) 909de2fb9cfSCaroline Tice value = value.substr(1, len - 2); 9102f3df613SZachary Turner value_sp = std::make_shared<OptionValueString>(value.c_str(), ""); 911de2fb9cfSCaroline Tice } 912de2fb9cfSCaroline Tice 913b9c1b51eSKate Stone if (const_key == encoding_key) { 914b9c1b51eSKate Stone // A 'data_encoding=..." is NOT a normal key-value pair; it is meta-data 915b9c1b51eSKate Stone // indicating the 916b9c1b51eSKate Stone // data type of an upcoming array (usually the next bit of data to be 917b9c1b51eSKate Stone // read in). 918de2fb9cfSCaroline Tice if (strcmp(value.c_str(), "uint32_t") == 0) 919de2fb9cfSCaroline Tice data_type = OptionValue::eTypeUInt64; 920b9c1b51eSKate Stone } else 921b9c1b51eSKate Stone option_value_sp->GetAsDictionary()->SetValueForKey(const_key, value_sp, 922b9c1b51eSKate Stone false); 923de2fb9cfSCaroline Tice } 924de2fb9cfSCaroline Tice } 925de2fb9cfSCaroline Tice 926de2fb9cfSCaroline Tice return option_value_sp; 927de2fb9cfSCaroline Tice } 928de2fb9cfSCaroline Tice 929b9c1b51eSKate Stone bool Instruction::TestEmulation(Stream *out_stream, const char *file_name) { 9303ac6711aSCaroline Tice if (!out_stream) 9313ac6711aSCaroline Tice return false; 9323ac6711aSCaroline Tice 933b9c1b51eSKate Stone if (!file_name) { 934ea80ba8bSJohnny Chen out_stream->Printf("Instruction::TestEmulation: Missing file_name."); 9353ac6711aSCaroline Tice return false; 9363ac6711aSCaroline Tice } 937190fadcdSZachary Turner FILE *test_file = FileSystem::Fopen(file_name, "r"); 938b9c1b51eSKate Stone if (!test_file) { 939b9c1b51eSKate Stone out_stream->Printf( 940b9c1b51eSKate Stone "Instruction::TestEmulation: Attempt to open test file failed."); 9413ac6711aSCaroline Tice return false; 9423ac6711aSCaroline Tice } 9433ac6711aSCaroline Tice 9443ac6711aSCaroline Tice char buffer[256]; 945b9c1b51eSKate Stone if (!fgets(buffer, 255, test_file)) { 946b9c1b51eSKate Stone out_stream->Printf( 947b9c1b51eSKate Stone "Instruction::TestEmulation: Error reading first line of test file.\n"); 9483ac6711aSCaroline Tice fclose(test_file); 9493ac6711aSCaroline Tice return false; 9503ac6711aSCaroline Tice } 9513ac6711aSCaroline Tice 952b9c1b51eSKate Stone if (strncmp(buffer, "InstructionEmulationState={", 27) != 0) { 953b9c1b51eSKate Stone out_stream->Printf("Instructin::TestEmulation: Test file does not contain " 954b9c1b51eSKate Stone "emulation state dictionary\n"); 955de2fb9cfSCaroline Tice fclose(test_file); 956de2fb9cfSCaroline Tice return false; 957de2fb9cfSCaroline Tice } 958de2fb9cfSCaroline Tice 959b9c1b51eSKate Stone // Read all the test information from the test file into an 960b9c1b51eSKate Stone // OptionValueDictionary. 961de2fb9cfSCaroline Tice 962de2fb9cfSCaroline Tice OptionValueSP data_dictionary_sp(ReadDictionary(test_file, out_stream)); 963b9c1b51eSKate Stone if (!data_dictionary_sp) { 964b9c1b51eSKate Stone out_stream->Printf( 965b9c1b51eSKate Stone "Instruction::TestEmulation: Error reading Dictionary Object.\n"); 966de2fb9cfSCaroline Tice fclose(test_file); 967de2fb9cfSCaroline Tice return false; 968de2fb9cfSCaroline Tice } 969de2fb9cfSCaroline Tice 970de2fb9cfSCaroline Tice fclose(test_file); 971de2fb9cfSCaroline Tice 972b9c1b51eSKate Stone OptionValueDictionary *data_dictionary = 973b9c1b51eSKate Stone data_dictionary_sp->GetAsDictionary(); 974de2fb9cfSCaroline Tice static ConstString description_key("assembly_string"); 975de2fb9cfSCaroline Tice static ConstString triple_key("triple"); 976de2fb9cfSCaroline Tice 977de2fb9cfSCaroline Tice OptionValueSP value_sp = data_dictionary->GetValueForKey(description_key); 978de2fb9cfSCaroline Tice 979b9c1b51eSKate Stone if (!value_sp) { 980b9c1b51eSKate Stone out_stream->Printf("Instruction::TestEmulation: Test file does not " 981b9c1b51eSKate Stone "contain description string.\n"); 982de2fb9cfSCaroline Tice return false; 983de2fb9cfSCaroline Tice } 984de2fb9cfSCaroline Tice 985de2fb9cfSCaroline Tice SetDescription(value_sp->GetStringValue()); 986de2fb9cfSCaroline Tice 987de2fb9cfSCaroline Tice value_sp = data_dictionary->GetValueForKey(triple_key); 988b9c1b51eSKate Stone if (!value_sp) { 989b9c1b51eSKate Stone out_stream->Printf( 990b9c1b51eSKate Stone "Instruction::TestEmulation: Test file does not contain triple.\n"); 991de2fb9cfSCaroline Tice return false; 992de2fb9cfSCaroline Tice } 993de2fb9cfSCaroline Tice 994de2fb9cfSCaroline Tice ArchSpec arch; 995de2fb9cfSCaroline Tice arch.SetTriple(llvm::Triple(value_sp->GetStringValue())); 9963ac6711aSCaroline Tice 9973ac6711aSCaroline Tice bool success = false; 998b9c1b51eSKate Stone std::unique_ptr<EmulateInstruction> insn_emulator_ap( 999b9c1b51eSKate Stone EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr)); 100034ede34aSEugene Zelenko if (insn_emulator_ap) 1001b9c1b51eSKate Stone success = 1002b9c1b51eSKate Stone insn_emulator_ap->TestEmulation(out_stream, arch, data_dictionary); 10033ac6711aSCaroline Tice 10043ac6711aSCaroline Tice if (success) 1005ea80ba8bSJohnny Chen out_stream->Printf("Emulation test succeeded."); 10063ac6711aSCaroline Tice else 1007ea80ba8bSJohnny Chen out_stream->Printf("Emulation test failed."); 10083ac6711aSCaroline Tice 10093ac6711aSCaroline Tice return success; 10103ac6711aSCaroline Tice } 10113ac6711aSCaroline Tice 1012b9c1b51eSKate Stone bool Instruction::Emulate( 1013b9c1b51eSKate Stone const ArchSpec &arch, uint32_t evaluate_options, void *baton, 10147349bd90SGreg Clayton EmulateInstruction::ReadMemoryCallback read_mem_callback, 10157349bd90SGreg Clayton EmulateInstruction::WriteMemoryCallback write_mem_callback, 10167349bd90SGreg Clayton EmulateInstruction::ReadRegisterCallback read_reg_callback, 1017b9c1b51eSKate Stone EmulateInstruction::WriteRegisterCallback write_reg_callback) { 1018b9c1b51eSKate Stone std::unique_ptr<EmulateInstruction> insn_emulator_ap( 1019b9c1b51eSKate Stone EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr)); 1020b9c1b51eSKate Stone if (insn_emulator_ap) { 10217c9dd3ceSCaroline Tice insn_emulator_ap->SetBaton(baton); 1022b9c1b51eSKate Stone insn_emulator_ap->SetCallbacks(read_mem_callback, write_mem_callback, 1023b9c1b51eSKate Stone read_reg_callback, write_reg_callback); 102434ede34aSEugene Zelenko insn_emulator_ap->SetInstruction(GetOpcode(), GetAddress(), nullptr); 10252ed751bdSGreg Clayton return insn_emulator_ap->EvaluateInstruction(evaluate_options); 10267c9dd3ceSCaroline Tice } 10277c9dd3ceSCaroline Tice 10287c9dd3ceSCaroline Tice return false; 10297c9dd3ceSCaroline Tice } 10307c9dd3ceSCaroline Tice 1031b9c1b51eSKate Stone uint32_t Instruction::GetData(DataExtractor &data) { 1032cd4ae1abSSean Callanan return m_opcode.GetData(data); 1033ba812f42SGreg Clayton } 1034ba812f42SGreg Clayton 1035b9c1b51eSKate Stone InstructionList::InstructionList() : m_instructions() {} 103630fdc8d8SChris Lattner 103734ede34aSEugene Zelenko InstructionList::~InstructionList() = default; 103830fdc8d8SChris Lattner 1039b9c1b51eSKate Stone size_t InstructionList::GetSize() const { return m_instructions.size(); } 104030fdc8d8SChris Lattner 1041b9c1b51eSKate Stone uint32_t InstructionList::GetMaxOpcocdeByteSize() const { 1042357132ebSGreg Clayton uint32_t max_inst_size = 0; 1043357132ebSGreg Clayton collection::const_iterator pos, end; 1044b9c1b51eSKate Stone for (pos = m_instructions.begin(), end = m_instructions.end(); pos != end; 1045b9c1b51eSKate Stone ++pos) { 1046357132ebSGreg Clayton uint32_t inst_size = (*pos)->GetOpcode().GetByteSize(); 1047357132ebSGreg Clayton if (max_inst_size < inst_size) 1048357132ebSGreg Clayton max_inst_size = inst_size; 1049357132ebSGreg Clayton } 1050357132ebSGreg Clayton return max_inst_size; 1051357132ebSGreg Clayton } 1052357132ebSGreg Clayton 1053b9c1b51eSKate Stone InstructionSP InstructionList::GetInstructionAtIndex(size_t idx) const { 10541d273166SGreg Clayton InstructionSP inst_sp; 105530fdc8d8SChris Lattner if (idx < m_instructions.size()) 10561d273166SGreg Clayton inst_sp = m_instructions[idx]; 10571d273166SGreg Clayton return inst_sp; 105830fdc8d8SChris Lattner } 105930fdc8d8SChris Lattner 1060b9c1b51eSKate Stone void InstructionList::Dump(Stream *s, bool show_address, bool show_bytes, 1061b9c1b51eSKate Stone const ExecutionContext *exe_ctx) { 10625009f9d5SGreg Clayton const uint32_t max_opcode_byte_size = GetMaxOpcocdeByteSize(); 10635009f9d5SGreg Clayton collection::const_iterator pos, begin, end; 1064554f68d3SGreg Clayton 106534ede34aSEugene Zelenko const FormatEntity::Entry *disassembly_format = nullptr; 1066554f68d3SGreg Clayton FormatEntity::Entry format; 1067b9c1b51eSKate Stone if (exe_ctx && exe_ctx->HasTargetScope()) { 1068b9c1b51eSKate Stone disassembly_format = 1069b9c1b51eSKate Stone exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat(); 1070b9c1b51eSKate Stone } else { 1071554f68d3SGreg Clayton FormatEntity::Parse("${addr}: ", format); 1072554f68d3SGreg Clayton disassembly_format = &format; 1073554f68d3SGreg Clayton } 1074554f68d3SGreg Clayton 10755009f9d5SGreg Clayton for (begin = m_instructions.begin(), end = m_instructions.end(), pos = begin; 1076b9c1b51eSKate Stone pos != end; ++pos) { 10775009f9d5SGreg Clayton if (pos != begin) 10785009f9d5SGreg Clayton s->EOL(); 1079b9c1b51eSKate Stone (*pos)->Dump(s, max_opcode_byte_size, show_address, show_bytes, exe_ctx, 1080b9c1b51eSKate Stone nullptr, nullptr, disassembly_format, 0); 10815009f9d5SGreg Clayton } 10825009f9d5SGreg Clayton } 10835009f9d5SGreg Clayton 1084b9c1b51eSKate Stone void InstructionList::Clear() { m_instructions.clear(); } 108530fdc8d8SChris Lattner 1086b9c1b51eSKate Stone void InstructionList::Append(lldb::InstructionSP &inst_sp) { 108730fdc8d8SChris Lattner if (inst_sp) 108830fdc8d8SChris Lattner m_instructions.push_back(inst_sp); 108930fdc8d8SChris Lattner } 109030fdc8d8SChris Lattner 1091564d8bc2SJim Ingham uint32_t 1092b9c1b51eSKate Stone InstructionList::GetIndexOfNextBranchInstruction(uint32_t start, 1093b9c1b51eSKate Stone Target &target) const { 1094564d8bc2SJim Ingham size_t num_instructions = m_instructions.size(); 1095564d8bc2SJim Ingham 1096190636bcSJim Ingham uint32_t next_branch = UINT32_MAX; 1097e76e7e93STed Woodward size_t i; 1098b9c1b51eSKate Stone for (i = start; i < num_instructions; i++) { 1099b9c1b51eSKate Stone if (m_instructions[i]->DoesBranch()) { 1100564d8bc2SJim Ingham next_branch = i; 1101564d8bc2SJim Ingham break; 1102564d8bc2SJim Ingham } 1103564d8bc2SJim Ingham } 1104e76e7e93STed Woodward 110505097246SAdrian Prantl // Hexagon needs the first instruction of the packet with the branch. Go 110605097246SAdrian Prantl // backwards until we find an instruction marked end-of-packet, or until we 110705097246SAdrian Prantl // hit start. 1108b9c1b51eSKate Stone if (target.GetArchitecture().GetTriple().getArch() == llvm::Triple::hexagon) { 1109e76e7e93STed Woodward // If we didn't find a branch, find the last packet start. 1110b9c1b51eSKate Stone if (next_branch == UINT32_MAX) { 1111e76e7e93STed Woodward i = num_instructions - 1; 1112e76e7e93STed Woodward } 1113e76e7e93STed Woodward 1114b9c1b51eSKate Stone while (i > start) { 1115e76e7e93STed Woodward --i; 1116e76e7e93STed Woodward 111797206d57SZachary Turner Status error; 1118e76e7e93STed Woodward uint32_t inst_bytes; 1119e76e7e93STed Woodward bool prefer_file_cache = false; // Read from process if process is running 1120e76e7e93STed Woodward lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; 1121b9c1b51eSKate Stone target.ReadMemory(m_instructions[i]->GetAddress(), prefer_file_cache, 1122b9c1b51eSKate Stone &inst_bytes, sizeof(inst_bytes), error, &load_addr); 1123e76e7e93STed Woodward // If we have an error reading memory, return start 1124e76e7e93STed Woodward if (!error.Success()) 1125e76e7e93STed Woodward return start; 112605097246SAdrian Prantl // check if this is the last instruction in a packet bits 15:14 will be 112705097246SAdrian Prantl // 11b or 00b for a duplex 1128e76e7e93STed Woodward if (((inst_bytes & 0xC000) == 0xC000) || 1129b9c1b51eSKate Stone ((inst_bytes & 0xC000) == 0x0000)) { 1130e76e7e93STed Woodward // instruction after this should be the start of next packet 1131e76e7e93STed Woodward next_branch = i + 1; 1132e76e7e93STed Woodward break; 1133e76e7e93STed Woodward } 1134e76e7e93STed Woodward } 1135e76e7e93STed Woodward 1136b9c1b51eSKate Stone if (next_branch == UINT32_MAX) { 1137e76e7e93STed Woodward // We couldn't find the previous packet, so return start 1138e76e7e93STed Woodward next_branch = start; 1139e76e7e93STed Woodward } 1140e76e7e93STed Woodward } 1141564d8bc2SJim Ingham return next_branch; 1142564d8bc2SJim Ingham } 1143564d8bc2SJim Ingham 1144564d8bc2SJim Ingham uint32_t 1145b9c1b51eSKate Stone InstructionList::GetIndexOfInstructionAtAddress(const Address &address) { 1146c7bece56SGreg Clayton size_t num_instructions = m_instructions.size(); 1147190636bcSJim Ingham uint32_t index = UINT32_MAX; 1148b9c1b51eSKate Stone for (size_t i = 0; i < num_instructions; i++) { 1149b9c1b51eSKate Stone if (m_instructions[i]->GetAddress() == address) { 1150564d8bc2SJim Ingham index = i; 1151564d8bc2SJim Ingham break; 1152564d8bc2SJim Ingham } 1153564d8bc2SJim Ingham } 1154564d8bc2SJim Ingham return index; 1155564d8bc2SJim Ingham } 115630fdc8d8SChris Lattner 115744d93782SGreg Clayton uint32_t 1158b9c1b51eSKate Stone InstructionList::GetIndexOfInstructionAtLoadAddress(lldb::addr_t load_addr, 1159b9c1b51eSKate Stone Target &target) { 116044d93782SGreg Clayton Address address; 116144d93782SGreg Clayton address.SetLoadAddress(load_addr, &target); 116244d93782SGreg Clayton return GetIndexOfInstructionAtAddress(address); 116344d93782SGreg Clayton } 116444d93782SGreg Clayton 1165b9c1b51eSKate Stone size_t Disassembler::ParseInstructions(const ExecutionContext *exe_ctx, 116657f0630cSGreg Clayton const AddressRange &range, 11673faf47c4SGreg Clayton Stream *error_strm_ptr, 1168b9c1b51eSKate Stone bool prefer_file_cache) { 1169b9c1b51eSKate Stone if (exe_ctx) { 1170c14ee32dSGreg Clayton Target *target = exe_ctx->GetTargetPtr(); 1171dda4f7b5SGreg Clayton const addr_t byte_size = range.GetByteSize(); 1172b9c1b51eSKate Stone if (target == nullptr || byte_size == 0 || 1173b9c1b51eSKate Stone !range.GetBaseAddress().IsValid()) 117430fdc8d8SChris Lattner return 0; 117530fdc8d8SChris Lattner 11762f3df613SZachary Turner auto data_sp = std::make_shared<DataBufferHeap>(byte_size, '\0'); 117730fdc8d8SChris Lattner 117897206d57SZachary Turner Status error; 11793faf47c4SGreg Clayton lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; 1180b9c1b51eSKate Stone const size_t bytes_read = target->ReadMemory( 11812f3df613SZachary Turner range.GetBaseAddress(), prefer_file_cache, data_sp->GetBytes(), 11822f3df613SZachary Turner data_sp->GetByteSize(), error, &load_addr); 1183dda4f7b5SGreg Clayton 1184b9c1b51eSKate Stone if (bytes_read > 0) { 11852f3df613SZachary Turner if (bytes_read != data_sp->GetByteSize()) 11862f3df613SZachary Turner data_sp->SetByteSize(bytes_read); 1187b9c1b51eSKate Stone DataExtractor data(data_sp, m_arch.GetByteOrder(), 1188357132ebSGreg Clayton m_arch.GetAddressByteSize()); 11893faf47c4SGreg Clayton const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS; 1190b9c1b51eSKate Stone return DecodeInstructions(range.GetBaseAddress(), data, 0, UINT32_MAX, 1191b9c1b51eSKate Stone false, data_from_file); 1192b9c1b51eSKate Stone } else if (error_strm_ptr) { 119357f0630cSGreg Clayton const char *error_cstr = error.AsCString(); 1194b9c1b51eSKate Stone if (error_cstr) { 119557f0630cSGreg Clayton error_strm_ptr->Printf("error: %s\n", error_cstr); 119657f0630cSGreg Clayton } 119757f0630cSGreg Clayton } 1198b9c1b51eSKate Stone } else if (error_strm_ptr) { 119957f0630cSGreg Clayton error_strm_ptr->PutCString("error: invalid execution context\n"); 1200c14ee32dSGreg Clayton } 120130fdc8d8SChris Lattner return 0; 120230fdc8d8SChris Lattner } 120330fdc8d8SChris Lattner 1204b9c1b51eSKate Stone size_t Disassembler::ParseInstructions(const ExecutionContext *exe_ctx, 120537023b06SJim Ingham const Address &start, 12063faf47c4SGreg Clayton uint32_t num_instructions, 1207b9c1b51eSKate Stone bool prefer_file_cache) { 1208357132ebSGreg Clayton m_instruction_list.Clear(); 120937023b06SJim Ingham 121034ede34aSEugene Zelenko if (exe_ctx == nullptr || num_instructions == 0 || !start.IsValid()) 121137023b06SJim Ingham return 0; 121237023b06SJim Ingham 1213c14ee32dSGreg Clayton Target *target = exe_ctx->GetTargetPtr(); 1214357132ebSGreg Clayton // Calculate the max buffer size we will need in order to disassemble 1215357132ebSGreg Clayton const addr_t byte_size = num_instructions * m_arch.GetMaximumOpcodeByteSize(); 121637023b06SJim Ingham 121734ede34aSEugene Zelenko if (target == nullptr || byte_size == 0) 121837023b06SJim Ingham return 0; 121937023b06SJim Ingham 122037023b06SJim Ingham DataBufferHeap *heap_buffer = new DataBufferHeap(byte_size, '\0'); 122137023b06SJim Ingham DataBufferSP data_sp(heap_buffer); 122237023b06SJim Ingham 122397206d57SZachary Turner Status error; 12243faf47c4SGreg Clayton lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; 1225b9c1b51eSKate Stone const size_t bytes_read = 1226b9c1b51eSKate Stone target->ReadMemory(start, prefer_file_cache, heap_buffer->GetBytes(), 1227b9c1b51eSKate Stone byte_size, error, &load_addr); 12283faf47c4SGreg Clayton 12293faf47c4SGreg Clayton const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS; 123037023b06SJim Ingham 123137023b06SJim Ingham if (bytes_read == 0) 1232357132ebSGreg Clayton return 0; 1233b9c1b51eSKate Stone DataExtractor data(data_sp, m_arch.GetByteOrder(), 1234357132ebSGreg Clayton m_arch.GetAddressByteSize()); 123537023b06SJim Ingham 1236357132ebSGreg Clayton const bool append_instructions = true; 1237b9c1b51eSKate Stone DecodeInstructions(start, data, 0, num_instructions, append_instructions, 12383faf47c4SGreg Clayton data_from_file); 123937023b06SJim Ingham 124037023b06SJim Ingham return m_instruction_list.GetSize(); 124137023b06SJim Ingham } 124237023b06SJim Ingham 124330fdc8d8SChris Lattner //---------------------------------------------------------------------- 124430fdc8d8SChris Lattner // Disassembler copy constructor 124530fdc8d8SChris Lattner //---------------------------------------------------------------------- 1246b9c1b51eSKate Stone Disassembler::Disassembler(const ArchSpec &arch, const char *flavor) 1247b9c1b51eSKate Stone : m_arch(arch), m_instruction_list(), m_base_addr(LLDB_INVALID_ADDRESS), 1248b9c1b51eSKate Stone m_flavor() { 124934ede34aSEugene Zelenko if (flavor == nullptr) 12500f063ba6SJim Ingham m_flavor.assign("default"); 12510f063ba6SJim Ingham else 12520f063ba6SJim Ingham m_flavor.assign(flavor); 125375452e8cSJason Molenda 125475452e8cSJason Molenda // If this is an arm variant that can only include thumb (T16, T32) 125505097246SAdrian Prantl // instructions, force the arch triple to be "thumbv.." instead of "armv..." 1256b9c1b51eSKate Stone if (arch.IsAlwaysThumbInstructions()) { 125775452e8cSJason Molenda std::string thumb_arch_name(arch.GetTriple().getArchName().str()); 125875452e8cSJason Molenda // Replace "arm" with "thumb" so we get all thumb variants correct 1259b9c1b51eSKate Stone if (thumb_arch_name.size() > 3) { 126075452e8cSJason Molenda thumb_arch_name.erase(0, 3); 126175452e8cSJason Molenda thumb_arch_name.insert(0, "thumb"); 126275452e8cSJason Molenda } 126375452e8cSJason Molenda m_arch.SetTriple(thumb_arch_name.c_str()); 126475452e8cSJason Molenda } 126530fdc8d8SChris Lattner } 126630fdc8d8SChris Lattner 126734ede34aSEugene Zelenko Disassembler::~Disassembler() = default; 126830fdc8d8SChris Lattner 1269b9c1b51eSKate Stone InstructionList &Disassembler::GetInstructionList() { 127030fdc8d8SChris Lattner return m_instruction_list; 127130fdc8d8SChris Lattner } 127230fdc8d8SChris Lattner 1273b9c1b51eSKate Stone const InstructionList &Disassembler::GetInstructionList() const { 127430fdc8d8SChris Lattner return m_instruction_list; 127530fdc8d8SChris Lattner } 12763ac6711aSCaroline Tice 12773ac6711aSCaroline Tice //---------------------------------------------------------------------- 12783ac6711aSCaroline Tice // Class PseudoInstruction 12793ac6711aSCaroline Tice //---------------------------------------------------------------------- 128034ede34aSEugene Zelenko 1281b9c1b51eSKate Stone PseudoInstruction::PseudoInstruction() 1282b9c1b51eSKate Stone : Instruction(Address(), eAddressClassUnknown), m_description() {} 12833ac6711aSCaroline Tice 128434ede34aSEugene Zelenko PseudoInstruction::~PseudoInstruction() = default; 12853ac6711aSCaroline Tice 1286b9c1b51eSKate Stone bool PseudoInstruction::DoesBranch() { 12873ac6711aSCaroline Tice // This is NOT a valid question for a pseudo instruction. 12883ac6711aSCaroline Tice return false; 12893ac6711aSCaroline Tice } 12903ac6711aSCaroline Tice 1291b9c1b51eSKate Stone bool PseudoInstruction::HasDelaySlot() { 12927f3daedaSBhushan D. Attarde // This is NOT a valid question for a pseudo instruction. 12937f3daedaSBhushan D. Attarde return false; 12947f3daedaSBhushan D. Attarde } 12957f3daedaSBhushan D. Attarde 1296b9c1b51eSKate Stone size_t PseudoInstruction::Decode(const lldb_private::Disassembler &disassembler, 12973ac6711aSCaroline Tice const lldb_private::DataExtractor &data, 1298b9c1b51eSKate Stone lldb::offset_t data_offset) { 12993ac6711aSCaroline Tice return m_opcode.GetByteSize(); 13003ac6711aSCaroline Tice } 13013ac6711aSCaroline Tice 1302b9c1b51eSKate Stone void PseudoInstruction::SetOpcode(size_t opcode_size, void *opcode_data) { 13033ac6711aSCaroline Tice if (!opcode_data) 13043ac6711aSCaroline Tice return; 13053ac6711aSCaroline Tice 1306b9c1b51eSKate Stone switch (opcode_size) { 1307b9c1b51eSKate Stone case 8: { 13083ac6711aSCaroline Tice uint8_t value8 = *((uint8_t *)opcode_data); 130990359963SEd Maste m_opcode.SetOpcode8(value8, eByteOrderInvalid); 13103ac6711aSCaroline Tice break; 13113ac6711aSCaroline Tice } 1312b9c1b51eSKate Stone case 16: { 13133ac6711aSCaroline Tice uint16_t value16 = *((uint16_t *)opcode_data); 131490359963SEd Maste m_opcode.SetOpcode16(value16, eByteOrderInvalid); 13153ac6711aSCaroline Tice break; 13163ac6711aSCaroline Tice } 1317b9c1b51eSKate Stone case 32: { 13183ac6711aSCaroline Tice uint32_t value32 = *((uint32_t *)opcode_data); 131990359963SEd Maste m_opcode.SetOpcode32(value32, eByteOrderInvalid); 13203ac6711aSCaroline Tice break; 13213ac6711aSCaroline Tice } 1322b9c1b51eSKate Stone case 64: { 13233ac6711aSCaroline Tice uint64_t value64 = *((uint64_t *)opcode_data); 132490359963SEd Maste m_opcode.SetOpcode64(value64, eByteOrderInvalid); 13253ac6711aSCaroline Tice break; 13263ac6711aSCaroline Tice } 13273ac6711aSCaroline Tice default: 13283ac6711aSCaroline Tice break; 13293ac6711aSCaroline Tice } 13303ac6711aSCaroline Tice } 13313ac6711aSCaroline Tice 133231d97a5cSZachary Turner void PseudoInstruction::SetDescription(llvm::StringRef description) { 13333ac6711aSCaroline Tice m_description = description; 13343ac6711aSCaroline Tice } 1335807ee2ffSSean Callanan 1336807ee2ffSSean Callanan Instruction::Operand Instruction::Operand::BuildRegister(ConstString &r) { 1337807ee2ffSSean Callanan Operand ret; 1338807ee2ffSSean Callanan ret.m_type = Type::Register; 1339807ee2ffSSean Callanan ret.m_register = r; 1340807ee2ffSSean Callanan return ret; 1341807ee2ffSSean Callanan } 1342807ee2ffSSean Callanan 1343807ee2ffSSean Callanan Instruction::Operand Instruction::Operand::BuildImmediate(lldb::addr_t imm, 1344807ee2ffSSean Callanan bool neg) { 1345807ee2ffSSean Callanan Operand ret; 1346807ee2ffSSean Callanan ret.m_type = Type::Immediate; 1347807ee2ffSSean Callanan ret.m_immediate = imm; 1348807ee2ffSSean Callanan ret.m_negative = neg; 1349807ee2ffSSean Callanan return ret; 1350807ee2ffSSean Callanan } 1351807ee2ffSSean Callanan 1352807ee2ffSSean Callanan Instruction::Operand Instruction::Operand::BuildImmediate(int64_t imm) { 1353807ee2ffSSean Callanan Operand ret; 1354807ee2ffSSean Callanan ret.m_type = Type::Immediate; 1355807ee2ffSSean Callanan if (imm < 0) { 1356807ee2ffSSean Callanan ret.m_immediate = -imm; 1357807ee2ffSSean Callanan ret.m_negative = true; 1358807ee2ffSSean Callanan } else { 1359807ee2ffSSean Callanan ret.m_immediate = imm; 1360807ee2ffSSean Callanan ret.m_negative = false; 1361807ee2ffSSean Callanan } 1362807ee2ffSSean Callanan return ret; 1363807ee2ffSSean Callanan } 1364807ee2ffSSean Callanan 1365807ee2ffSSean Callanan Instruction::Operand 1366807ee2ffSSean Callanan Instruction::Operand::BuildDereference(const Operand &ref) { 1367807ee2ffSSean Callanan Operand ret; 1368807ee2ffSSean Callanan ret.m_type = Type::Dereference; 1369807ee2ffSSean Callanan ret.m_children = {ref}; 1370807ee2ffSSean Callanan return ret; 1371807ee2ffSSean Callanan } 1372807ee2ffSSean Callanan 1373807ee2ffSSean Callanan Instruction::Operand Instruction::Operand::BuildSum(const Operand &lhs, 1374807ee2ffSSean Callanan const Operand &rhs) { 1375807ee2ffSSean Callanan Operand ret; 1376807ee2ffSSean Callanan ret.m_type = Type::Sum; 1377807ee2ffSSean Callanan ret.m_children = {lhs, rhs}; 1378807ee2ffSSean Callanan return ret; 1379807ee2ffSSean Callanan } 1380807ee2ffSSean Callanan 1381807ee2ffSSean Callanan Instruction::Operand Instruction::Operand::BuildProduct(const Operand &lhs, 1382807ee2ffSSean Callanan const Operand &rhs) { 1383807ee2ffSSean Callanan Operand ret; 1384807ee2ffSSean Callanan ret.m_type = Type::Product; 1385807ee2ffSSean Callanan ret.m_children = {lhs, rhs}; 1386807ee2ffSSean Callanan return ret; 1387807ee2ffSSean Callanan } 1388807ee2ffSSean Callanan 1389807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> 1390807ee2ffSSean Callanan lldb_private::OperandMatchers::MatchBinaryOp( 1391807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> base, 1392807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> left, 1393807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> right) { 1394807ee2ffSSean Callanan return [base, left, right](const Instruction::Operand &op) -> bool { 1395807ee2ffSSean Callanan return (base(op) && op.m_children.size() == 2 && 1396807ee2ffSSean Callanan ((left(op.m_children[0]) && right(op.m_children[1])) || 1397807ee2ffSSean Callanan (left(op.m_children[1]) && right(op.m_children[0])))); 1398807ee2ffSSean Callanan }; 1399807ee2ffSSean Callanan } 1400807ee2ffSSean Callanan 1401807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> 1402807ee2ffSSean Callanan lldb_private::OperandMatchers::MatchUnaryOp( 1403807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> base, 1404807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> child) { 1405807ee2ffSSean Callanan return [base, child](const Instruction::Operand &op) -> bool { 1406807ee2ffSSean Callanan return (base(op) && op.m_children.size() == 1 && child(op.m_children[0])); 1407807ee2ffSSean Callanan }; 1408807ee2ffSSean Callanan } 1409807ee2ffSSean Callanan 1410807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> 1411807ee2ffSSean Callanan lldb_private::OperandMatchers::MatchRegOp(const RegisterInfo &info) { 1412807ee2ffSSean Callanan return [&info](const Instruction::Operand &op) { 1413807ee2ffSSean Callanan return (op.m_type == Instruction::Operand::Type::Register && 1414807ee2ffSSean Callanan (op.m_register == ConstString(info.name) || 1415807ee2ffSSean Callanan op.m_register == ConstString(info.alt_name))); 1416807ee2ffSSean Callanan }; 1417807ee2ffSSean Callanan } 1418807ee2ffSSean Callanan 1419807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> 1420561a9bbfSSean Callanan lldb_private::OperandMatchers::FetchRegOp(ConstString ®) { 1421561a9bbfSSean Callanan return [®](const Instruction::Operand &op) { 1422561a9bbfSSean Callanan if (op.m_type != Instruction::Operand::Type::Register) { 1423561a9bbfSSean Callanan return false; 1424561a9bbfSSean Callanan } 1425561a9bbfSSean Callanan reg = op.m_register; 1426561a9bbfSSean Callanan return true; 1427561a9bbfSSean Callanan }; 1428561a9bbfSSean Callanan } 1429561a9bbfSSean Callanan 1430561a9bbfSSean Callanan std::function<bool(const Instruction::Operand &)> 1431807ee2ffSSean Callanan lldb_private::OperandMatchers::MatchImmOp(int64_t imm) { 1432807ee2ffSSean Callanan return [imm](const Instruction::Operand &op) { 1433807ee2ffSSean Callanan return (op.m_type == Instruction::Operand::Type::Immediate && 1434807ee2ffSSean Callanan ((op.m_negative && op.m_immediate == (uint64_t)-imm) || 1435807ee2ffSSean Callanan (!op.m_negative && op.m_immediate == (uint64_t)imm))); 1436807ee2ffSSean Callanan }; 1437807ee2ffSSean Callanan } 1438807ee2ffSSean Callanan 1439807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> 1440807ee2ffSSean Callanan lldb_private::OperandMatchers::FetchImmOp(int64_t &imm) { 1441807ee2ffSSean Callanan return [&imm](const Instruction::Operand &op) { 1442807ee2ffSSean Callanan if (op.m_type != Instruction::Operand::Type::Immediate) { 1443807ee2ffSSean Callanan return false; 1444807ee2ffSSean Callanan } 1445807ee2ffSSean Callanan if (op.m_negative) { 1446807ee2ffSSean Callanan imm = -((int64_t)op.m_immediate); 1447807ee2ffSSean Callanan } else { 1448807ee2ffSSean Callanan imm = ((int64_t)op.m_immediate); 1449807ee2ffSSean Callanan } 1450807ee2ffSSean Callanan return true; 1451807ee2ffSSean Callanan }; 1452807ee2ffSSean Callanan } 1453807ee2ffSSean Callanan 1454807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> 1455807ee2ffSSean Callanan lldb_private::OperandMatchers::MatchOpType(Instruction::Operand::Type type) { 1456807ee2ffSSean Callanan return [type](const Instruction::Operand &op) { return op.m_type == type; }; 1457807ee2ffSSean Callanan } 1458