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 1230fdc8d8SChris Lattner // C Includes 1330fdc8d8SChris Lattner // C++ Includes 1434ede34aSEugene Zelenko #include <cstdio> 1534ede34aSEugene Zelenko #include <cstring> 1634ede34aSEugene Zelenko 1730fdc8d8SChris Lattner // Other libraries and framework includes 1830fdc8d8SChris Lattner // Project includes 1930fdc8d8SChris Lattner #include "lldb/Core/DataBufferHeap.h" 2030fdc8d8SChris Lattner #include "lldb/Core/DataExtractor.h" 2130fdc8d8SChris Lattner #include "lldb/Core/Debugger.h" 22ad379efcSCaroline Tice #include "lldb/Core/EmulateInstruction.h" 23190fadcdSZachary Turner #include "lldb/Core/Error.h" 2430fdc8d8SChris Lattner #include "lldb/Core/Module.h" 2530fdc8d8SChris Lattner #include "lldb/Core/PluginManager.h" 26de2fb9cfSCaroline Tice #include "lldb/Core/RegularExpression.h" 2730fdc8d8SChris Lattner #include "lldb/Core/Timer.h" 28190fadcdSZachary Turner #include "lldb/Host/FileSystem.h" 2967cc0636SGreg Clayton #include "lldb/Interpreter/OptionValue.h" 3067cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueArray.h" 3167cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueDictionary.h" 320b4c26b2SJason Molenda #include "lldb/Interpreter/OptionValueRegex.h" 3367cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueString.h" 3467cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueUInt64.h" 351f746071SGreg Clayton #include "lldb/Symbol/Function.h" 3630fdc8d8SChris Lattner #include "lldb/Symbol/ObjectFile.h" 3730fdc8d8SChris Lattner #include "lldb/Target/ExecutionContext.h" 3830fdc8d8SChris Lattner #include "lldb/Target/Process.h" 39d5944cd1SGreg Clayton #include "lldb/Target/SectionLoadList.h" 40b57e4a1bSJason Molenda #include "lldb/Target/StackFrame.h" 4130fdc8d8SChris Lattner #include "lldb/Target/Target.h" 42190fadcdSZachary Turner #include "lldb/lldb-private.h" 4330fdc8d8SChris Lattner 4430fdc8d8SChris Lattner #define DEFAULT_DISASM_BYTE_SIZE 32 4530fdc8d8SChris Lattner 4630fdc8d8SChris Lattner using namespace lldb; 4730fdc8d8SChris Lattner using namespace lldb_private; 4830fdc8d8SChris Lattner 49b9c1b51eSKate Stone DisassemblerSP Disassembler::FindPlugin(const ArchSpec &arch, 50b9c1b51eSKate Stone const char *flavor, 51b9c1b51eSKate Stone const char *plugin_name) { 52f343968fSZachary Turner Timer scoped_timer(LLVM_PRETTY_FUNCTION, 531080edbcSGreg Clayton "Disassembler::FindPlugin (arch = %s, plugin_name = %s)", 54b9c1b51eSKate Stone arch.GetArchitectureName(), plugin_name); 5530fdc8d8SChris Lattner 5634ede34aSEugene Zelenko DisassemblerCreateInstance create_callback = nullptr; 571080edbcSGreg Clayton 58b9c1b51eSKate Stone if (plugin_name) { 5957abc5d6SGreg Clayton ConstString const_plugin_name(plugin_name); 60b9c1b51eSKate Stone create_callback = PluginManager::GetDisassemblerCreateCallbackForPluginName( 61b9c1b51eSKate Stone const_plugin_name); 62b9c1b51eSKate Stone if (create_callback) { 630f063ba6SJim Ingham DisassemblerSP disassembler_sp(create_callback(arch, flavor)); 641080edbcSGreg Clayton 6534ede34aSEugene Zelenko if (disassembler_sp) 667e6d4e5aSSean Callanan return disassembler_sp; 671080edbcSGreg Clayton } 68b9c1b51eSKate Stone } else { 69b9c1b51eSKate Stone for (uint32_t idx = 0; 70b9c1b51eSKate Stone (create_callback = PluginManager::GetDisassemblerCreateCallbackAtIndex( 71b9c1b51eSKate Stone idx)) != nullptr; 72b9c1b51eSKate Stone ++idx) { 730f063ba6SJim Ingham DisassemblerSP disassembler_sp(create_callback(arch, flavor)); 7430fdc8d8SChris Lattner 7534ede34aSEugene Zelenko if (disassembler_sp) 767e6d4e5aSSean Callanan return disassembler_sp; 7730fdc8d8SChris Lattner } 781080edbcSGreg Clayton } 797e6d4e5aSSean Callanan return DisassemblerSP(); 8030fdc8d8SChris Lattner } 8130fdc8d8SChris Lattner 82b9c1b51eSKate Stone DisassemblerSP Disassembler::FindPluginForTarget(const TargetSP target_sp, 83b9c1b51eSKate Stone const ArchSpec &arch, 84b9c1b51eSKate Stone const char *flavor, 85b9c1b51eSKate Stone const char *plugin_name) { 86b9c1b51eSKate Stone if (target_sp && flavor == nullptr) { 87b9c1b51eSKate Stone // FIXME - we don't have the mechanism in place to do per-architecture 88b9c1b51eSKate Stone // settings. But since we know that for now 890f063ba6SJim Ingham // we only support flavors on x86 & x86_64, 90b9c1b51eSKate Stone if (arch.GetTriple().getArch() == llvm::Triple::x86 || 91b9c1b51eSKate Stone arch.GetTriple().getArch() == llvm::Triple::x86_64) 920f063ba6SJim Ingham flavor = target_sp->GetDisassemblyFlavor(); 930f063ba6SJim Ingham } 940f063ba6SJim Ingham return FindPlugin(arch, flavor, plugin_name); 950f063ba6SJim Ingham } 960f063ba6SJim Ingham 97b9c1b51eSKate Stone static void ResolveAddress(const ExecutionContext &exe_ctx, const Address &addr, 98b9c1b51eSKate Stone Address &resolved_addr) { 99b9c1b51eSKate Stone if (!addr.IsSectionOffset()) { 100357132ebSGreg Clayton // If we weren't passed in a section offset address range, 101357132ebSGreg Clayton // try and resolve it to something 102c14ee32dSGreg Clayton Target *target = exe_ctx.GetTargetPtr(); 103b9c1b51eSKate Stone if (target) { 104b9c1b51eSKate Stone if (target->GetSectionLoadList().IsEmpty()) { 105c14ee32dSGreg Clayton target->GetImages().ResolveFileAddress(addr.GetOffset(), resolved_addr); 106b9c1b51eSKate Stone } else { 107b9c1b51eSKate Stone target->GetSectionLoadList().ResolveLoadAddress(addr.GetOffset(), 108b9c1b51eSKate Stone resolved_addr); 109357132ebSGreg Clayton } 110357132ebSGreg Clayton // We weren't able to resolve the address, just treat it as a 111357132ebSGreg Clayton // raw address 112357132ebSGreg Clayton if (resolved_addr.IsValid()) 113357132ebSGreg Clayton return; 114357132ebSGreg Clayton } 115357132ebSGreg Clayton } 116357132ebSGreg Clayton resolved_addr = addr; 117357132ebSGreg Clayton } 118dda4f7b5SGreg Clayton 119b9c1b51eSKate Stone size_t Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch, 120b9c1b51eSKate Stone const char *plugin_name, const char *flavor, 121dda4f7b5SGreg Clayton const ExecutionContext &exe_ctx, 122dda4f7b5SGreg Clayton SymbolContextList &sc_list, 12337023b06SJim Ingham uint32_t num_instructions, 1240b4c26b2SJason Molenda bool mixed_source_and_assembly, 125dda4f7b5SGreg Clayton uint32_t num_mixed_context_lines, 126b9c1b51eSKate Stone uint32_t options, Stream &strm) { 127dda4f7b5SGreg Clayton size_t success_count = 0; 128dda4f7b5SGreg Clayton const size_t count = sc_list.GetSize(); 129dda4f7b5SGreg Clayton SymbolContext sc; 130dda4f7b5SGreg Clayton AddressRange range; 131b9c1b51eSKate Stone const uint32_t scope = 132b9c1b51eSKate Stone eSymbolContextBlock | eSymbolContextFunction | eSymbolContextSymbol; 1337e14f91dSGreg Clayton const bool use_inline_block_range = true; 134b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 13534ede34aSEugene Zelenko if (!sc_list.GetContextAtIndex(i, sc)) 136dda4f7b5SGreg Clayton break; 137b9c1b51eSKate Stone for (uint32_t range_idx = 0; 138b9c1b51eSKate Stone sc.GetAddressRange(scope, range_idx, use_inline_block_range, range); 139b9c1b51eSKate Stone ++range_idx) { 140b9c1b51eSKate Stone if (Disassemble(debugger, arch, plugin_name, flavor, exe_ctx, range, 1410b4c26b2SJason Molenda num_instructions, mixed_source_and_assembly, 1420b4c26b2SJason Molenda num_mixed_context_lines, options, strm)) { 143dda4f7b5SGreg Clayton ++success_count; 144dda4f7b5SGreg Clayton strm.EOL(); 145dda4f7b5SGreg Clayton } 146dda4f7b5SGreg Clayton } 147dda4f7b5SGreg Clayton } 148dda4f7b5SGreg Clayton return success_count; 149dda4f7b5SGreg Clayton } 150dda4f7b5SGreg Clayton 151b9c1b51eSKate Stone bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch, 152b9c1b51eSKate Stone const char *plugin_name, const char *flavor, 15330fdc8d8SChris Lattner const ExecutionContext &exe_ctx, 154b9c1b51eSKate Stone const ConstString &name, Module *module, 15537023b06SJim Ingham uint32_t num_instructions, 1560b4c26b2SJason Molenda bool mixed_source_and_assembly, 157dda4f7b5SGreg Clayton uint32_t num_mixed_context_lines, 158b9c1b51eSKate Stone uint32_t options, Stream &strm) { 159dda4f7b5SGreg Clayton SymbolContextList sc_list; 160b9c1b51eSKate Stone if (name) { 161931180e6SGreg Clayton const bool include_symbols = true; 1629df05fbbSSean Callanan const bool include_inlines = true; 163b9c1b51eSKate Stone if (module) { 164b9c1b51eSKate Stone module->FindFunctions(name, nullptr, eFunctionNameTypeAuto, 165b9c1b51eSKate Stone include_symbols, include_inlines, true, sc_list); 166b9c1b51eSKate Stone } else if (exe_ctx.GetTargetPtr()) { 167b9c1b51eSKate Stone exe_ctx.GetTargetPtr()->GetImages().FindFunctions( 168b9c1b51eSKate Stone name, eFunctionNameTypeAuto, include_symbols, include_inlines, false, 169931180e6SGreg Clayton sc_list); 170dda4f7b5SGreg Clayton } 171dda4f7b5SGreg Clayton } 172931180e6SGreg Clayton 173b9c1b51eSKate Stone if (sc_list.GetSize()) { 174b9c1b51eSKate Stone return Disassemble(debugger, arch, plugin_name, flavor, exe_ctx, sc_list, 1750b4c26b2SJason Molenda num_instructions, mixed_source_and_assembly, 1760b4c26b2SJason Molenda num_mixed_context_lines, options, strm); 177dda4f7b5SGreg Clayton } 178dda4f7b5SGreg Clayton return false; 179dda4f7b5SGreg Clayton } 180dda4f7b5SGreg Clayton 181b9c1b51eSKate Stone lldb::DisassemblerSP Disassembler::DisassembleRange( 182b9c1b51eSKate Stone const ArchSpec &arch, const char *plugin_name, const char *flavor, 183b9c1b51eSKate Stone const ExecutionContext &exe_ctx, const AddressRange &range, 184b9c1b51eSKate Stone bool prefer_file_cache) { 1851d273166SGreg Clayton lldb::DisassemblerSP disasm_sp; 186b9c1b51eSKate Stone if (range.GetByteSize() > 0 && range.GetBaseAddress().IsValid()) { 187b9c1b51eSKate Stone disasm_sp = Disassembler::FindPluginForTarget(exe_ctx.GetTargetSP(), arch, 188b9c1b51eSKate Stone flavor, plugin_name); 1891d273166SGreg Clayton 190b9c1b51eSKate Stone if (disasm_sp) { 191b9c1b51eSKate Stone size_t bytes_disassembled = disasm_sp->ParseInstructions( 192b9c1b51eSKate Stone &exe_ctx, range, nullptr, prefer_file_cache); 1931d273166SGreg Clayton if (bytes_disassembled == 0) 1941d273166SGreg Clayton disasm_sp.reset(); 1951d273166SGreg Clayton } 1961d273166SGreg Clayton } 1971d273166SGreg Clayton return disasm_sp; 1981d273166SGreg Clayton } 1991d273166SGreg Clayton 20050952e95SSean Callanan lldb::DisassemblerSP 201b9c1b51eSKate Stone Disassembler::DisassembleBytes(const ArchSpec &arch, const char *plugin_name, 202b9c1b51eSKate Stone const char *flavor, const Address &start, 203b9c1b51eSKate Stone const void *src, size_t src_len, 204b9c1b51eSKate Stone uint32_t num_instructions, bool data_from_file) { 20550952e95SSean Callanan lldb::DisassemblerSP disasm_sp; 20650952e95SSean Callanan 207b9c1b51eSKate Stone if (src) { 2080f063ba6SJim Ingham disasm_sp = Disassembler::FindPlugin(arch, flavor, plugin_name); 20950952e95SSean Callanan 210b9c1b51eSKate Stone if (disasm_sp) { 211b9c1b51eSKate Stone DataExtractor data(src, src_len, arch.GetByteOrder(), 212b9c1b51eSKate Stone arch.GetAddressByteSize()); 21350952e95SSean Callanan 214b9c1b51eSKate Stone (void)disasm_sp->DecodeInstructions(start, data, 0, num_instructions, 215b9c1b51eSKate Stone false, data_from_file); 21650952e95SSean Callanan } 21750952e95SSean Callanan } 21850952e95SSean Callanan 21950952e95SSean Callanan return disasm_sp; 22050952e95SSean Callanan } 22150952e95SSean Callanan 222b9c1b51eSKate Stone bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch, 223b9c1b51eSKate Stone const char *plugin_name, const char *flavor, 224dda4f7b5SGreg Clayton const ExecutionContext &exe_ctx, 225dda4f7b5SGreg Clayton const AddressRange &disasm_range, 22637023b06SJim Ingham uint32_t num_instructions, 2270b4c26b2SJason Molenda bool mixed_source_and_assembly, 228dda4f7b5SGreg Clayton uint32_t num_mixed_context_lines, 229b9c1b51eSKate Stone uint32_t options, Stream &strm) { 230b9c1b51eSKate Stone if (disasm_range.GetByteSize()) { 231b9c1b51eSKate Stone lldb::DisassemblerSP disasm_sp(Disassembler::FindPluginForTarget( 232b9c1b51eSKate Stone exe_ctx.GetTargetSP(), arch, flavor, plugin_name)); 23330fdc8d8SChris Lattner 234b9c1b51eSKate Stone if (disasm_sp) { 235357132ebSGreg Clayton AddressRange range; 236b9c1b51eSKate Stone ResolveAddress(exe_ctx, disasm_range.GetBaseAddress(), 237b9c1b51eSKate Stone range.GetBaseAddress()); 238357132ebSGreg Clayton range.SetByteSize(disasm_range.GetByteSize()); 2393faf47c4SGreg Clayton const bool prefer_file_cache = false; 240b9c1b51eSKate Stone size_t bytes_disassembled = disasm_sp->ParseInstructions( 241b9c1b51eSKate Stone &exe_ctx, range, &strm, prefer_file_cache); 24230fdc8d8SChris Lattner if (bytes_disassembled == 0) 24330fdc8d8SChris Lattner return false; 2441080edbcSGreg Clayton 245b9c1b51eSKate Stone return PrintInstructions(disasm_sp.get(), debugger, arch, exe_ctx, 2460b4c26b2SJason Molenda num_instructions, mixed_source_and_assembly, 2470b4c26b2SJason Molenda num_mixed_context_lines, options, strm); 24837023b06SJim Ingham } 24937023b06SJim Ingham } 25037023b06SJim Ingham return false; 25137023b06SJim Ingham } 25237023b06SJim Ingham 253b9c1b51eSKate Stone bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch, 254b9c1b51eSKate Stone const char *plugin_name, const char *flavor, 25537023b06SJim Ingham const ExecutionContext &exe_ctx, 25637023b06SJim Ingham const Address &start_address, 25737023b06SJim Ingham uint32_t num_instructions, 2580b4c26b2SJason Molenda bool mixed_source_and_assembly, 25937023b06SJim Ingham uint32_t num_mixed_context_lines, 260b9c1b51eSKate Stone uint32_t options, Stream &strm) { 261b9c1b51eSKate Stone if (num_instructions > 0) { 262b9c1b51eSKate Stone lldb::DisassemblerSP disasm_sp(Disassembler::FindPluginForTarget( 263b9c1b51eSKate Stone exe_ctx.GetTargetSP(), arch, flavor, plugin_name)); 264b9c1b51eSKate Stone if (disasm_sp) { 265357132ebSGreg Clayton Address addr; 266357132ebSGreg Clayton ResolveAddress(exe_ctx, start_address, addr); 2673faf47c4SGreg Clayton const bool prefer_file_cache = false; 268b9c1b51eSKate Stone size_t bytes_disassembled = disasm_sp->ParseInstructions( 269b9c1b51eSKate Stone &exe_ctx, addr, num_instructions, prefer_file_cache); 27037023b06SJim Ingham if (bytes_disassembled == 0) 27137023b06SJim Ingham return false; 272b9c1b51eSKate Stone return PrintInstructions(disasm_sp.get(), debugger, arch, exe_ctx, 2730b4c26b2SJason Molenda num_instructions, mixed_source_and_assembly, 2740b4c26b2SJason Molenda num_mixed_context_lines, options, strm); 27537023b06SJim Ingham } 27637023b06SJim Ingham } 27737023b06SJim Ingham return false; 27837023b06SJim Ingham } 27937023b06SJim Ingham 2800b4c26b2SJason Molenda Disassembler::SourceLine 2810b4c26b2SJason Molenda Disassembler::GetFunctionDeclLineEntry(const SymbolContext &sc) { 2820b4c26b2SJason Molenda SourceLine decl_line; 2830b4c26b2SJason Molenda if (sc.function && sc.line_entry.IsValid()) { 2840b4c26b2SJason Molenda LineEntry prologue_end_line = sc.line_entry; 2850b4c26b2SJason Molenda FileSpec func_decl_file; 2860b4c26b2SJason Molenda uint32_t func_decl_line; 2870b4c26b2SJason Molenda sc.function->GetStartLineSourceInfo(func_decl_file, func_decl_line); 2880b4c26b2SJason Molenda if (func_decl_file == prologue_end_line.file || 2890b4c26b2SJason Molenda func_decl_file == prologue_end_line.original_file) { 2900b4c26b2SJason Molenda decl_line.file = func_decl_file; 2910b4c26b2SJason Molenda decl_line.line = func_decl_line; 2920b4c26b2SJason Molenda } 2930b4c26b2SJason Molenda } 2940b4c26b2SJason Molenda return decl_line; 2950b4c26b2SJason Molenda } 2960b4c26b2SJason Molenda 2970b4c26b2SJason Molenda void Disassembler::AddLineToSourceLineTables( 2980b4c26b2SJason Molenda SourceLine &line, 2990b4c26b2SJason Molenda std::map<FileSpec, std::set<uint32_t>> &source_lines_seen) { 3000b4c26b2SJason Molenda if (line.IsValid()) { 3010b4c26b2SJason Molenda auto source_lines_seen_pos = source_lines_seen.find(line.file); 3020b4c26b2SJason Molenda if (source_lines_seen_pos == source_lines_seen.end()) { 3030b4c26b2SJason Molenda std::set<uint32_t> lines; 3040b4c26b2SJason Molenda lines.insert(line.line); 3050b4c26b2SJason Molenda source_lines_seen.emplace(line.file, lines); 3060b4c26b2SJason Molenda } else { 3070b4c26b2SJason Molenda source_lines_seen_pos->second.insert(line.line); 3080b4c26b2SJason Molenda } 3090b4c26b2SJason Molenda } 3100b4c26b2SJason Molenda } 3110b4c26b2SJason Molenda 3120b4c26b2SJason Molenda bool Disassembler::ElideMixedSourceAndDisassemblyLine( 3130b4c26b2SJason Molenda const ExecutionContext &exe_ctx, const SymbolContext &sc, 3140b4c26b2SJason Molenda SourceLine &line) { 3150b4c26b2SJason Molenda 3160b4c26b2SJason Molenda // TODO: should we also check target.process.thread.step-avoid-libraries ? 3170b4c26b2SJason Molenda 3180b4c26b2SJason Molenda const RegularExpression *avoid_regex = nullptr; 3190b4c26b2SJason Molenda 3200b4c26b2SJason Molenda // Skip any line #0 entries - they are implementation details 3210b4c26b2SJason Molenda if (line.line == 0) 3220b4c26b2SJason Molenda return false; 3230b4c26b2SJason Molenda 3240b4c26b2SJason Molenda ThreadSP thread_sp = exe_ctx.GetThreadSP(); 3250b4c26b2SJason Molenda if (thread_sp) { 3260b4c26b2SJason Molenda avoid_regex = thread_sp->GetSymbolsToAvoidRegexp(); 3270b4c26b2SJason Molenda } else { 3280b4c26b2SJason Molenda TargetSP target_sp = exe_ctx.GetTargetSP(); 3290b4c26b2SJason Molenda if (target_sp) { 3300b4c26b2SJason Molenda Error error; 3310b4c26b2SJason Molenda OptionValueSP value_sp = target_sp->GetDebugger().GetPropertyValue( 3320b4c26b2SJason Molenda &exe_ctx, "target.process.thread.step-avoid-regexp", false, error); 3330b4c26b2SJason Molenda if (value_sp && value_sp->GetType() == OptionValue::eTypeRegex) { 3340b4c26b2SJason Molenda OptionValueRegex *re = value_sp->GetAsRegex(); 3350b4c26b2SJason Molenda if (re) { 3360b4c26b2SJason Molenda avoid_regex = re->GetCurrentValue(); 3370b4c26b2SJason Molenda } 3380b4c26b2SJason Molenda } 3390b4c26b2SJason Molenda } 3400b4c26b2SJason Molenda } 3410b4c26b2SJason Molenda if (avoid_regex && sc.symbol != nullptr) { 3420b4c26b2SJason Molenda const char *function_name = 3430b4c26b2SJason Molenda sc.GetFunctionName(Mangled::ePreferDemangledWithoutArguments) 3440b4c26b2SJason Molenda .GetCString(); 3450b4c26b2SJason Molenda if (function_name) { 3460b4c26b2SJason Molenda RegularExpression::Match regex_match(1); 3470b4c26b2SJason Molenda if (avoid_regex->Execute(function_name, ®ex_match)) { 3480b4c26b2SJason Molenda // skip this source line 3490b4c26b2SJason Molenda return true; 3500b4c26b2SJason Molenda } 3510b4c26b2SJason Molenda } 3520b4c26b2SJason Molenda } 3530b4c26b2SJason Molenda // don't skip this source line 3540b4c26b2SJason Molenda return false; 3550b4c26b2SJason Molenda } 3560b4c26b2SJason Molenda 357b9c1b51eSKate Stone bool Disassembler::PrintInstructions(Disassembler *disasm_ptr, 358b9c1b51eSKate Stone Debugger &debugger, const ArchSpec &arch, 359b9c1b51eSKate Stone const ExecutionContext &exe_ctx, 360b9c1b51eSKate Stone uint32_t num_instructions, 3610b4c26b2SJason Molenda bool mixed_source_and_assembly, 362b9c1b51eSKate Stone uint32_t num_mixed_context_lines, 363b9c1b51eSKate Stone uint32_t options, Stream &strm) { 36430fdc8d8SChris Lattner // We got some things disassembled... 36537023b06SJim Ingham size_t num_instructions_found = disasm_ptr->GetInstructionList().GetSize(); 36637023b06SJim Ingham 36737023b06SJim Ingham if (num_instructions > 0 && num_instructions < num_instructions_found) 36837023b06SJim Ingham num_instructions_found = num_instructions; 36937023b06SJim Ingham 370b9c1b51eSKate Stone const uint32_t max_opcode_byte_size = 371b9c1b51eSKate Stone disasm_ptr->GetInstructionList().GetMaxOpcocdeByteSize(); 37230fdc8d8SChris Lattner SymbolContext sc; 37330fdc8d8SChris Lattner SymbolContext prev_sc; 3740b4c26b2SJason Molenda AddressRange current_source_line_range; 37534ede34aSEugene Zelenko const Address *pc_addr_ptr = nullptr; 376b57e4a1bSJason Molenda StackFrame *frame = exe_ctx.GetFramePtr(); 377c14ee32dSGreg Clayton 3784b2967ffSMichael Sartain TargetSP target_sp(exe_ctx.GetTargetSP()); 379b9c1b51eSKate Stone SourceManager &source_manager = 380b9c1b51eSKate Stone target_sp ? target_sp->GetSourceManager() : debugger.GetSourceManager(); 3814b2967ffSMichael Sartain 382b9c1b51eSKate Stone if (frame) { 383c14ee32dSGreg Clayton pc_addr_ptr = &frame->GetFrameCodeAddress(); 384aff1b357SJason Molenda } 385b9c1b51eSKate Stone const uint32_t scope = 386b9c1b51eSKate Stone eSymbolContextLineEntry | eSymbolContextFunction | eSymbolContextSymbol; 3877e14f91dSGreg Clayton const bool use_inline_block_range = false; 388c980fa92SJason Molenda 38934ede34aSEugene Zelenko const FormatEntity::Entry *disassembly_format = nullptr; 390c980fa92SJason Molenda FormatEntity::Entry format; 391b9c1b51eSKate Stone if (exe_ctx.HasTargetScope()) { 392b9c1b51eSKate Stone disassembly_format = 393b9c1b51eSKate Stone exe_ctx.GetTargetRef().GetDebugger().GetDisassemblyFormat(); 394b9c1b51eSKate Stone } else { 395c980fa92SJason Molenda FormatEntity::Parse("${addr}: ", format); 396c980fa92SJason Molenda disassembly_format = &format; 397c980fa92SJason Molenda } 398c980fa92SJason Molenda 399c980fa92SJason Molenda // First pass: step through the list of instructions, 400c980fa92SJason Molenda // find how long the initial addresses strings are, insert padding 401c980fa92SJason Molenda // in the second pass so the opcodes all line up nicely. 4020b4c26b2SJason Molenda 4030b4c26b2SJason Molenda // Also build up the source line mapping if this is mixed source & assembly 4040b4c26b2SJason Molenda // mode. 4050b4c26b2SJason Molenda // Calculate the source line for each assembly instruction (eliding inlined 4060b4c26b2SJason Molenda // functions 4070b4c26b2SJason Molenda // which the user wants to skip). 4080b4c26b2SJason Molenda 4090b4c26b2SJason Molenda std::map<FileSpec, std::set<uint32_t>> source_lines_seen; 4100b4c26b2SJason Molenda Symbol *previous_symbol = nullptr; 4110b4c26b2SJason Molenda 412c980fa92SJason Molenda size_t address_text_size = 0; 413b9c1b51eSKate Stone for (size_t i = 0; i < num_instructions_found; ++i) { 414b9c1b51eSKate Stone Instruction *inst = 415b9c1b51eSKate Stone disasm_ptr->GetInstructionList().GetInstructionAtIndex(i).get(); 416b9c1b51eSKate Stone if (inst) { 417c980fa92SJason Molenda const Address &addr = inst->GetAddress(); 418c980fa92SJason Molenda ModuleSP module_sp(addr.GetModule()); 419b9c1b51eSKate Stone if (module_sp) { 4200b4c26b2SJason Molenda const uint32_t resolve_mask = eSymbolContextFunction | 4210b4c26b2SJason Molenda eSymbolContextSymbol | 4220b4c26b2SJason Molenda eSymbolContextLineEntry; 423b9c1b51eSKate Stone uint32_t resolved_mask = 424b9c1b51eSKate Stone module_sp->ResolveSymbolContextForAddress(addr, resolve_mask, sc); 425b9c1b51eSKate Stone if (resolved_mask) { 426c980fa92SJason Molenda StreamString strmstr; 427b9c1b51eSKate Stone Debugger::FormatDisassemblerAddress(disassembly_format, &sc, nullptr, 428b9c1b51eSKate Stone &exe_ctx, &addr, strmstr); 429c980fa92SJason Molenda size_t cur_line = strmstr.GetSizeOfLastLine(); 430c980fa92SJason Molenda if (cur_line > address_text_size) 431c980fa92SJason Molenda address_text_size = cur_line; 4320b4c26b2SJason Molenda 4330b4c26b2SJason Molenda // Add entries to our "source_lines_seen" map+set which list which 4340b4c26b2SJason Molenda // sources lines occur in this disassembly session. We will print 4350b4c26b2SJason Molenda // lines of context around a source line, but we don't want to print 4360b4c26b2SJason Molenda // a source line that has a line table entry of its own - we'll leave 4370b4c26b2SJason Molenda // that source line to be printed when it actually occurs in the 4380b4c26b2SJason Molenda // disassembly. 4390b4c26b2SJason Molenda 4400b4c26b2SJason Molenda if (mixed_source_and_assembly && sc.line_entry.IsValid()) { 4410b4c26b2SJason Molenda if (sc.symbol != previous_symbol) { 4420b4c26b2SJason Molenda SourceLine decl_line = GetFunctionDeclLineEntry(sc); 4430b4c26b2SJason Molenda if (ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, decl_line) == 4440b4c26b2SJason Molenda false) 4450b4c26b2SJason Molenda AddLineToSourceLineTables(decl_line, source_lines_seen); 4460b4c26b2SJason Molenda } 4470b4c26b2SJason Molenda if (sc.line_entry.IsValid()) { 4480b4c26b2SJason Molenda SourceLine this_line; 4490b4c26b2SJason Molenda this_line.file = sc.line_entry.file; 4500b4c26b2SJason Molenda this_line.line = sc.line_entry.line; 4510b4c26b2SJason Molenda if (ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, this_line) == 4520b4c26b2SJason Molenda false) 4530b4c26b2SJason Molenda AddLineToSourceLineTables(this_line, source_lines_seen); 4540b4c26b2SJason Molenda } 4550b4c26b2SJason Molenda } 456c980fa92SJason Molenda } 457c980fa92SJason Molenda sc.Clear(false); 458c980fa92SJason Molenda } 459c980fa92SJason Molenda } 460c980fa92SJason Molenda } 461c980fa92SJason Molenda 4620b4c26b2SJason Molenda previous_symbol = nullptr; 4630b4c26b2SJason Molenda SourceLine previous_line; 464b9c1b51eSKate Stone for (size_t i = 0; i < num_instructions_found; ++i) { 465b9c1b51eSKate Stone Instruction *inst = 466b9c1b51eSKate Stone disasm_ptr->GetInstructionList().GetInstructionAtIndex(i).get(); 4670b4c26b2SJason Molenda 468b9c1b51eSKate Stone if (inst) { 46932e0a750SGreg Clayton const Address &addr = inst->GetAddress(); 47032e0a750SGreg Clayton const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr; 4710b4c26b2SJason Molenda SourceLinesToDisplay source_lines_to_display; 472dda4f7b5SGreg Clayton 47330fdc8d8SChris Lattner prev_sc = sc; 474dda4f7b5SGreg Clayton 475e72dfb32SGreg Clayton ModuleSP module_sp(addr.GetModule()); 476b9c1b51eSKate Stone if (module_sp) { 477b9c1b51eSKate Stone uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress( 478b9c1b51eSKate Stone addr, eSymbolContextEverything, sc); 479b9c1b51eSKate Stone if (resolved_mask) { 4800b4c26b2SJason Molenda if (mixed_source_and_assembly) { 481dda4f7b5SGreg Clayton 4820b4c26b2SJason Molenda // If we've started a new function (non-inlined), print all of the 4830b4c26b2SJason Molenda // source lines from the 4840b4c26b2SJason Molenda // function declaration until the first line table entry - typically 4850b4c26b2SJason Molenda // the opening curly brace of 4860b4c26b2SJason Molenda // the function. 4870b4c26b2SJason Molenda if (previous_symbol != sc.symbol) { 4880b4c26b2SJason Molenda // The default disassembly format puts an extra blank line between 4890b4c26b2SJason Molenda // functions - so 4900b4c26b2SJason Molenda // when we're displaying the source context for a function, we 4910b4c26b2SJason Molenda // don't want to add 4920b4c26b2SJason Molenda // a blank line after the source context or we'll end up with two 4930b4c26b2SJason Molenda // of them. 4940b4c26b2SJason Molenda if (previous_symbol != nullptr) 4950b4c26b2SJason Molenda source_lines_to_display.print_source_context_end_eol = false; 49630fdc8d8SChris Lattner 4970b4c26b2SJason Molenda previous_symbol = sc.symbol; 4980b4c26b2SJason Molenda if (sc.function && sc.line_entry.IsValid()) { 4990b4c26b2SJason Molenda LineEntry prologue_end_line = sc.line_entry; 5000b4c26b2SJason Molenda if (ElideMixedSourceAndDisassemblyLine( 5010b4c26b2SJason Molenda exe_ctx, sc, prologue_end_line) == false) { 5020b4c26b2SJason Molenda FileSpec func_decl_file; 5030b4c26b2SJason Molenda uint32_t func_decl_line; 5040b4c26b2SJason Molenda sc.function->GetStartLineSourceInfo(func_decl_file, 5050b4c26b2SJason Molenda func_decl_line); 5060b4c26b2SJason Molenda if (func_decl_file == prologue_end_line.file || 5070b4c26b2SJason Molenda func_decl_file == prologue_end_line.original_file) { 5080b4c26b2SJason Molenda // Add all the lines between the function declaration 5090b4c26b2SJason Molenda // and the first non-prologue source line to the list 5100b4c26b2SJason Molenda // of lines to print. 5110b4c26b2SJason Molenda for (uint32_t lineno = func_decl_line; 5120b4c26b2SJason Molenda lineno <= prologue_end_line.line; lineno++) { 5130b4c26b2SJason Molenda SourceLine this_line; 5140b4c26b2SJason Molenda this_line.file = func_decl_file; 5150b4c26b2SJason Molenda this_line.line = lineno; 5160b4c26b2SJason Molenda source_lines_to_display.lines.push_back(this_line); 5170b4c26b2SJason Molenda } 5180b4c26b2SJason Molenda // Mark the last line as the "current" one. Usually 5190b4c26b2SJason Molenda // this is the open curly brace. 5200b4c26b2SJason Molenda if (source_lines_to_display.lines.size() > 0) 5210b4c26b2SJason Molenda source_lines_to_display.current_source_line = 5220b4c26b2SJason Molenda source_lines_to_display.lines.size() - 1; 5230b4c26b2SJason Molenda } 5240b4c26b2SJason Molenda } 5250b4c26b2SJason Molenda } 5260b4c26b2SJason Molenda sc.GetAddressRange(scope, 0, use_inline_block_range, 5270b4c26b2SJason Molenda current_source_line_range); 5280b4c26b2SJason Molenda } 52930fdc8d8SChris Lattner 5300b4c26b2SJason Molenda // If we've left a previous source line's address range, print a new 5310b4c26b2SJason Molenda // source line 5320b4c26b2SJason Molenda if (!current_source_line_range.ContainsFileAddress(addr)) { 5330b4c26b2SJason Molenda sc.GetAddressRange(scope, 0, use_inline_block_range, 5340b4c26b2SJason Molenda current_source_line_range); 5350b4c26b2SJason Molenda 5360b4c26b2SJason Molenda if (sc != prev_sc && sc.comp_unit && sc.line_entry.IsValid()) { 5370b4c26b2SJason Molenda SourceLine this_line; 5380b4c26b2SJason Molenda this_line.file = sc.line_entry.file; 5390b4c26b2SJason Molenda this_line.line = sc.line_entry.line; 5400b4c26b2SJason Molenda 5410b4c26b2SJason Molenda if (ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, 5420b4c26b2SJason Molenda this_line) == false) { 5430b4c26b2SJason Molenda // Only print this source line if it is different from the 5440b4c26b2SJason Molenda // last source line we printed. There may have been inlined 5450b4c26b2SJason Molenda // functions between these lines that we elided, resulting in 5460b4c26b2SJason Molenda // the same line being printed twice in a row for a contiguous 5470b4c26b2SJason Molenda // block of assembly instructions. 5480b4c26b2SJason Molenda if (this_line != previous_line) { 5490b4c26b2SJason Molenda 5500b4c26b2SJason Molenda std::vector<uint32_t> previous_lines; 5517771462bSEd Maste for (uint32_t i = 0; 5520b4c26b2SJason Molenda i < num_mixed_context_lines && 5530b4c26b2SJason Molenda (this_line.line - num_mixed_context_lines) > 0; 5540b4c26b2SJason Molenda i++) { 5550b4c26b2SJason Molenda uint32_t line = 5560b4c26b2SJason Molenda this_line.line - num_mixed_context_lines + i; 5570b4c26b2SJason Molenda auto pos = source_lines_seen.find(this_line.file); 5580b4c26b2SJason Molenda if (pos != source_lines_seen.end()) { 5590b4c26b2SJason Molenda if (pos->second.count(line) == 1) { 5600b4c26b2SJason Molenda previous_lines.clear(); 5610b4c26b2SJason Molenda } else { 5620b4c26b2SJason Molenda previous_lines.push_back(line); 5630b4c26b2SJason Molenda } 5640b4c26b2SJason Molenda } 5650b4c26b2SJason Molenda } 5660b4c26b2SJason Molenda for (size_t i = 0; i < previous_lines.size(); i++) { 5670b4c26b2SJason Molenda SourceLine previous_line; 5680b4c26b2SJason Molenda previous_line.file = this_line.file; 5690b4c26b2SJason Molenda previous_line.line = previous_lines[i]; 5700b4c26b2SJason Molenda auto pos = source_lines_seen.find(previous_line.file); 5710b4c26b2SJason Molenda if (pos != source_lines_seen.end()) { 5720b4c26b2SJason Molenda pos->second.insert(previous_line.line); 5730b4c26b2SJason Molenda } 5740b4c26b2SJason Molenda source_lines_to_display.lines.push_back(previous_line); 5750b4c26b2SJason Molenda } 5760b4c26b2SJason Molenda 5770b4c26b2SJason Molenda source_lines_to_display.lines.push_back(this_line); 5780b4c26b2SJason Molenda source_lines_to_display.current_source_line = 5790b4c26b2SJason Molenda source_lines_to_display.lines.size() - 1; 5800b4c26b2SJason Molenda 5817771462bSEd Maste for (uint32_t i = 0; i < num_mixed_context_lines; i++) { 5820b4c26b2SJason Molenda SourceLine next_line; 5830b4c26b2SJason Molenda next_line.file = this_line.file; 5840b4c26b2SJason Molenda next_line.line = this_line.line + i + 1; 5850b4c26b2SJason Molenda auto pos = source_lines_seen.find(next_line.file); 5860b4c26b2SJason Molenda if (pos != source_lines_seen.end()) { 5870b4c26b2SJason Molenda if (pos->second.count(next_line.line) == 1) 5880b4c26b2SJason Molenda break; 5890b4c26b2SJason Molenda pos->second.insert(next_line.line); 5900b4c26b2SJason Molenda } 5910b4c26b2SJason Molenda source_lines_to_display.lines.push_back(next_line); 5920b4c26b2SJason Molenda } 5930b4c26b2SJason Molenda } 5940b4c26b2SJason Molenda previous_line = this_line; 59530fdc8d8SChris Lattner } 59630fdc8d8SChris Lattner } 59730fdc8d8SChris Lattner } 59830fdc8d8SChris Lattner } 599b9c1b51eSKate Stone } else { 60072310355SGreg Clayton sc.Clear(true); 60130fdc8d8SChris Lattner } 60230fdc8d8SChris Lattner } 60332e0a750SGreg Clayton 6040b4c26b2SJason Molenda if (source_lines_to_display.lines.size() > 0) { 6050b4c26b2SJason Molenda strm.EOL(); 6060b4c26b2SJason Molenda for (size_t idx = 0; idx < source_lines_to_display.lines.size(); 6070b4c26b2SJason Molenda idx++) { 6080b4c26b2SJason Molenda SourceLine ln = source_lines_to_display.lines[idx]; 6090b4c26b2SJason Molenda const char *line_highlight = ""; 6100b4c26b2SJason Molenda if (inst_is_at_pc && (options & eOptionMarkPCSourceLine)) { 6110b4c26b2SJason Molenda line_highlight = "->"; 6120b4c26b2SJason Molenda } else if (idx == source_lines_to_display.current_source_line) { 6130b4c26b2SJason Molenda line_highlight = "**"; 6140b4c26b2SJason Molenda } 6150b4c26b2SJason Molenda source_manager.DisplaySourceLinesWithLineNumbers( 6160b4c26b2SJason Molenda ln.file, ln.line, 0, 0, line_highlight, &strm); 6170b4c26b2SJason Molenda } 6180b4c26b2SJason Molenda if (source_lines_to_display.print_source_context_end_eol) 6190b4c26b2SJason Molenda strm.EOL(); 6200b4c26b2SJason Molenda } 6210b4c26b2SJason Molenda 6221da6f9d7SGreg Clayton const bool show_bytes = (options & eOptionShowBytes) != 0; 623b9c1b51eSKate Stone inst->Dump(&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx, &sc, 624b9c1b51eSKate Stone &prev_sc, nullptr, address_text_size); 62530fdc8d8SChris Lattner strm.EOL(); 626b9c1b51eSKate Stone } else { 62730fdc8d8SChris Lattner break; 62830fdc8d8SChris Lattner } 62930fdc8d8SChris Lattner } 63030fdc8d8SChris Lattner 63130fdc8d8SChris Lattner return true; 63230fdc8d8SChris Lattner } 63330fdc8d8SChris Lattner 634b9c1b51eSKate Stone bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch, 635b9c1b51eSKate Stone const char *plugin_name, const char *flavor, 636dda4f7b5SGreg Clayton const ExecutionContext &exe_ctx, 63737023b06SJim Ingham uint32_t num_instructions, 6380b4c26b2SJason Molenda bool mixed_source_and_assembly, 639dda4f7b5SGreg Clayton uint32_t num_mixed_context_lines, 640b9c1b51eSKate Stone uint32_t options, Stream &strm) { 641dda4f7b5SGreg Clayton AddressRange range; 642b57e4a1bSJason Molenda StackFrame *frame = exe_ctx.GetFramePtr(); 643b9c1b51eSKate Stone if (frame) { 644b9c1b51eSKate Stone SymbolContext sc( 645b9c1b51eSKate Stone frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol)); 646b9c1b51eSKate Stone if (sc.function) { 647dda4f7b5SGreg Clayton range = sc.function->GetAddressRange(); 648b9c1b51eSKate Stone } else if (sc.symbol && sc.symbol->ValueIsAddress()) { 649358cf1eaSGreg Clayton range.GetBaseAddress() = sc.symbol->GetAddressRef(); 650e7612134SGreg Clayton range.SetByteSize(sc.symbol->GetByteSize()); 651b9c1b51eSKate Stone } else { 652c14ee32dSGreg Clayton range.GetBaseAddress() = frame->GetFrameCodeAddress(); 653dda4f7b5SGreg Clayton } 654dda4f7b5SGreg Clayton 655dda4f7b5SGreg Clayton if (range.GetBaseAddress().IsValid() && range.GetByteSize() == 0) 656dda4f7b5SGreg Clayton range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE); 657dda4f7b5SGreg Clayton } 658dda4f7b5SGreg Clayton 659b9c1b51eSKate Stone return Disassemble(debugger, arch, plugin_name, flavor, exe_ctx, range, 6600b4c26b2SJason Molenda num_instructions, mixed_source_and_assembly, 6610b4c26b2SJason Molenda num_mixed_context_lines, options, strm); 662dda4f7b5SGreg Clayton } 663dda4f7b5SGreg Clayton 664b9c1b51eSKate Stone Instruction::Instruction(const Address &address, AddressClass addr_class) 665b9c1b51eSKate Stone : m_address(address), m_address_class(addr_class), m_opcode(), 666b9c1b51eSKate Stone m_calculated_strings(false) {} 66730fdc8d8SChris Lattner 66834ede34aSEugene Zelenko Instruction::~Instruction() = default; 66930fdc8d8SChris Lattner 670b9c1b51eSKate Stone AddressClass Instruction::GetAddressClass() { 671357132ebSGreg Clayton if (m_address_class == eAddressClassInvalid) 672357132ebSGreg Clayton m_address_class = m_address.GetAddressClass(); 673357132ebSGreg Clayton return m_address_class; 674357132ebSGreg Clayton } 67530fdc8d8SChris Lattner 676b9c1b51eSKate Stone void Instruction::Dump(lldb_private::Stream *s, uint32_t max_opcode_byte_size, 677b9c1b51eSKate Stone bool show_address, bool show_bytes, 678aff1b357SJason Molenda const ExecutionContext *exe_ctx, 679aff1b357SJason Molenda const SymbolContext *sym_ctx, 680aff1b357SJason Molenda const SymbolContext *prev_sym_ctx, 681c980fa92SJason Molenda const FormatEntity::Entry *disassembly_addr_format, 682b9c1b51eSKate Stone size_t max_address_text_size) { 6837a37c1ecSJason Molenda size_t opcode_column_width = 7; 684ba812f42SGreg Clayton const size_t operand_column_width = 25; 685ba812f42SGreg Clayton 686ba812f42SGreg Clayton CalculateMnemonicOperandsAndCommentIfNeeded(exe_ctx); 687ba812f42SGreg Clayton 688ba812f42SGreg Clayton StreamString ss; 689ba812f42SGreg Clayton 690b9c1b51eSKate Stone if (show_address) { 691b9c1b51eSKate Stone Debugger::FormatDisassemblerAddress(disassembly_addr_format, sym_ctx, 692b9c1b51eSKate Stone prev_sym_ctx, exe_ctx, &m_address, ss); 693c980fa92SJason Molenda ss.FillLastLineToColumn(max_address_text_size, ' '); 694ba812f42SGreg Clayton } 695ba812f42SGreg Clayton 696b9c1b51eSKate Stone if (show_bytes) { 697b9c1b51eSKate Stone if (m_opcode.GetType() == Opcode::eTypeBytes) { 698ba812f42SGreg Clayton // x86_64 and i386 are the only ones that use bytes right now so 699ba812f42SGreg Clayton // pad out the byte dump to be able to always show 15 bytes (3 chars each) 700ba812f42SGreg Clayton // plus a space 701ba812f42SGreg Clayton if (max_opcode_byte_size > 0) 702ba812f42SGreg Clayton m_opcode.Dump(&ss, max_opcode_byte_size * 3 + 1); 703ba812f42SGreg Clayton else 704ba812f42SGreg Clayton m_opcode.Dump(&ss, 15 * 3 + 1); 705b9c1b51eSKate Stone } else { 706d616c97aSEd Maste // Else, we have ARM or MIPS which can show up to a uint32_t 707d616c97aSEd Maste // 0x00000000 (10 spaces) plus two for padding... 708ba812f42SGreg Clayton if (max_opcode_byte_size > 0) 709ba812f42SGreg Clayton m_opcode.Dump(&ss, max_opcode_byte_size * 3 + 1); 710ba812f42SGreg Clayton else 711ba812f42SGreg Clayton m_opcode.Dump(&ss, 12); 712ba812f42SGreg Clayton } 713ba812f42SGreg Clayton } 714ba812f42SGreg Clayton 715aff1b357SJason Molenda const size_t opcode_pos = ss.GetSizeOfLastLine(); 716ba812f42SGreg Clayton 7177a37c1ecSJason Molenda // The default opcode size of 7 characters is plenty for most architectures 7187a37c1ecSJason Molenda // but some like arm can pull out the occasional vqrshrun.s16. We won't get 7197a37c1ecSJason Molenda // consistent column spacing in these cases, unfortunately. 720b9c1b51eSKate Stone if (m_opcode_name.length() >= opcode_column_width) { 7217a37c1ecSJason Molenda opcode_column_width = m_opcode_name.length() + 1; 7227a37c1ecSJason Molenda } 7237a37c1ecSJason Molenda 724ba812f42SGreg Clayton ss.PutCString(m_opcode_name.c_str()); 725ba812f42SGreg Clayton ss.FillLastLineToColumn(opcode_pos + opcode_column_width, ' '); 7260f063ba6SJim Ingham ss.PutCString(m_mnemonics.c_str()); 727ba812f42SGreg Clayton 728b9c1b51eSKate Stone if (!m_comment.empty()) { 729b9c1b51eSKate Stone ss.FillLastLineToColumn( 730b9c1b51eSKate Stone opcode_pos + opcode_column_width + operand_column_width, ' '); 731ba812f42SGreg Clayton ss.PutCString(" ; "); 732ba812f42SGreg Clayton ss.PutCString(m_comment.c_str()); 733ba812f42SGreg Clayton } 734ba812f42SGreg Clayton s->Write(ss.GetData(), ss.GetSize()); 735ba812f42SGreg Clayton } 736ba812f42SGreg Clayton 737b9c1b51eSKate Stone bool Instruction::DumpEmulation(const ArchSpec &arch) { 738b9c1b51eSKate Stone std::unique_ptr<EmulateInstruction> insn_emulator_ap( 739b9c1b51eSKate Stone EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr)); 740b9c1b51eSKate Stone if (insn_emulator_ap) { 74134ede34aSEugene Zelenko insn_emulator_ap->SetInstruction(GetOpcode(), GetAddress(), nullptr); 7422ed751bdSGreg Clayton return insn_emulator_ap->EvaluateInstruction(0); 7437c9dd3ceSCaroline Tice } 7447c9dd3ceSCaroline Tice 7457c9dd3ceSCaroline Tice return false; 7467c9dd3ceSCaroline Tice } 7477c9dd3ceSCaroline Tice 748b9c1b51eSKate Stone bool Instruction::HasDelaySlot() { 7497f3daedaSBhushan D. Attarde // Default is false. 7507f3daedaSBhushan D. Attarde return false; 7517f3daedaSBhushan D. Attarde } 7527f3daedaSBhushan D. Attarde 753b9c1b51eSKate Stone OptionValueSP Instruction::ReadArray(FILE *in_file, Stream *out_stream, 754b9c1b51eSKate Stone OptionValue::Type data_type) { 755de2fb9cfSCaroline Tice bool done = false; 756de2fb9cfSCaroline Tice char buffer[1024]; 757de2fb9cfSCaroline Tice 758de2fb9cfSCaroline Tice OptionValueSP option_value_sp(new OptionValueArray(1u << data_type)); 759de2fb9cfSCaroline Tice 760de2fb9cfSCaroline Tice int idx = 0; 761b9c1b51eSKate Stone while (!done) { 762b9c1b51eSKate Stone if (!fgets(buffer, 1023, in_file)) { 763b9c1b51eSKate Stone out_stream->Printf( 764b9c1b51eSKate Stone "Instruction::ReadArray: Error reading file (fgets).\n"); 765de2fb9cfSCaroline Tice option_value_sp.reset(); 766de2fb9cfSCaroline Tice return option_value_sp; 767de2fb9cfSCaroline Tice } 768de2fb9cfSCaroline Tice 769de2fb9cfSCaroline Tice std::string line(buffer); 770de2fb9cfSCaroline Tice 771c7bece56SGreg Clayton size_t len = line.size(); 772b9c1b51eSKate Stone if (line[len - 1] == '\n') { 773de2fb9cfSCaroline Tice line[len - 1] = '\0'; 774de2fb9cfSCaroline Tice line.resize(len - 1); 775de2fb9cfSCaroline Tice } 776de2fb9cfSCaroline Tice 777b9c1b51eSKate Stone if ((line.size() == 1) && line[0] == ']') { 778de2fb9cfSCaroline Tice done = true; 779de2fb9cfSCaroline Tice line.clear(); 780de2fb9cfSCaroline Tice } 781de2fb9cfSCaroline Tice 782b9c1b51eSKate Stone if (!line.empty()) { 783de2fb9cfSCaroline Tice std::string value; 784bc43cab5SGreg Clayton static RegularExpression g_reg_exp("^[ \t]*([^ \t]+)[ \t]*$"); 785bc43cab5SGreg Clayton RegularExpression::Match regex_match(1); 786bc43cab5SGreg Clayton bool reg_exp_success = g_reg_exp.Execute(line.c_str(), ®ex_match); 787de2fb9cfSCaroline Tice if (reg_exp_success) 788bc43cab5SGreg Clayton regex_match.GetMatchAtIndex(line.c_str(), 1, value); 789de2fb9cfSCaroline Tice else 790de2fb9cfSCaroline Tice value = line; 791de2fb9cfSCaroline Tice 792de2fb9cfSCaroline Tice OptionValueSP data_value_sp; 793b9c1b51eSKate Stone switch (data_type) { 794de2fb9cfSCaroline Tice case OptionValue::eTypeUInt64: 795de2fb9cfSCaroline Tice data_value_sp.reset(new OptionValueUInt64(0, 0)); 796c95f7e2aSPavel Labath data_value_sp->SetValueFromString(value); 797de2fb9cfSCaroline Tice break; 798de2fb9cfSCaroline Tice // Other types can be added later as needed. 799de2fb9cfSCaroline Tice default: 800de2fb9cfSCaroline Tice data_value_sp.reset(new OptionValueString(value.c_str(), "")); 801de2fb9cfSCaroline Tice break; 802de2fb9cfSCaroline Tice } 803de2fb9cfSCaroline Tice 80484c39663SGreg Clayton option_value_sp->GetAsArray()->InsertValue(idx, data_value_sp); 805de2fb9cfSCaroline Tice ++idx; 806de2fb9cfSCaroline Tice } 807de2fb9cfSCaroline Tice } 808de2fb9cfSCaroline Tice 809de2fb9cfSCaroline Tice return option_value_sp; 810de2fb9cfSCaroline Tice } 811de2fb9cfSCaroline Tice 812b9c1b51eSKate Stone OptionValueSP Instruction::ReadDictionary(FILE *in_file, Stream *out_stream) { 813de2fb9cfSCaroline Tice bool done = false; 814de2fb9cfSCaroline Tice char buffer[1024]; 815de2fb9cfSCaroline Tice 816de2fb9cfSCaroline Tice OptionValueSP option_value_sp(new OptionValueDictionary()); 817de2fb9cfSCaroline Tice static ConstString encoding_key("data_encoding"); 818de2fb9cfSCaroline Tice OptionValue::Type data_type = OptionValue::eTypeInvalid; 819de2fb9cfSCaroline Tice 820b9c1b51eSKate Stone while (!done) { 821de2fb9cfSCaroline Tice // Read the next line in the file 822b9c1b51eSKate Stone if (!fgets(buffer, 1023, in_file)) { 823b9c1b51eSKate Stone out_stream->Printf( 824b9c1b51eSKate Stone "Instruction::ReadDictionary: Error reading file (fgets).\n"); 825de2fb9cfSCaroline Tice option_value_sp.reset(); 826de2fb9cfSCaroline Tice return option_value_sp; 827de2fb9cfSCaroline Tice } 828de2fb9cfSCaroline Tice 829de2fb9cfSCaroline Tice // Check to see if the line contains the end-of-dictionary marker ("}") 830de2fb9cfSCaroline Tice std::string line(buffer); 831de2fb9cfSCaroline Tice 832c7bece56SGreg Clayton size_t len = line.size(); 833b9c1b51eSKate Stone if (line[len - 1] == '\n') { 834de2fb9cfSCaroline Tice line[len - 1] = '\0'; 835de2fb9cfSCaroline Tice line.resize(len - 1); 836de2fb9cfSCaroline Tice } 837de2fb9cfSCaroline Tice 838b9c1b51eSKate Stone if ((line.size() == 1) && (line[0] == '}')) { 839de2fb9cfSCaroline Tice done = true; 840de2fb9cfSCaroline Tice line.clear(); 841de2fb9cfSCaroline Tice } 842de2fb9cfSCaroline Tice 843b9c1b51eSKate Stone // Try to find a key-value pair in the current line and add it to the 844b9c1b51eSKate Stone // dictionary. 845b9c1b51eSKate Stone if (!line.empty()) { 846b9c1b51eSKate Stone static RegularExpression g_reg_exp( 847b9c1b51eSKate Stone "^[ \t]*([a-zA-Z_][a-zA-Z0-9_]*)[ \t]*=[ \t]*(.*)[ \t]*$"); 848bc43cab5SGreg Clayton RegularExpression::Match regex_match(2); 849bc43cab5SGreg Clayton 850bc43cab5SGreg Clayton bool reg_exp_success = g_reg_exp.Execute(line.c_str(), ®ex_match); 851de2fb9cfSCaroline Tice std::string key; 852de2fb9cfSCaroline Tice std::string value; 853b9c1b51eSKate Stone if (reg_exp_success) { 854bc43cab5SGreg Clayton regex_match.GetMatchAtIndex(line.c_str(), 1, key); 855bc43cab5SGreg Clayton regex_match.GetMatchAtIndex(line.c_str(), 2, value); 856b9c1b51eSKate Stone } else { 857b9c1b51eSKate Stone out_stream->Printf("Instruction::ReadDictionary: Failure executing " 858b9c1b51eSKate Stone "regular expression.\n"); 859de2fb9cfSCaroline Tice option_value_sp.reset(); 860de2fb9cfSCaroline Tice return option_value_sp; 861de2fb9cfSCaroline Tice } 862de2fb9cfSCaroline Tice 863de2fb9cfSCaroline Tice ConstString const_key(key.c_str()); 864de2fb9cfSCaroline Tice // Check value to see if it's the start of an array or dictionary. 865de2fb9cfSCaroline Tice 866de2fb9cfSCaroline Tice lldb::OptionValueSP value_sp; 867de2fb9cfSCaroline Tice assert(value.empty() == false); 868de2fb9cfSCaroline Tice assert(key.empty() == false); 869de2fb9cfSCaroline Tice 870b9c1b51eSKate Stone if (value[0] == '{') { 871de2fb9cfSCaroline Tice assert(value.size() == 1); 872de2fb9cfSCaroline Tice // value is a dictionary 873de2fb9cfSCaroline Tice value_sp = ReadDictionary(in_file, out_stream); 874b9c1b51eSKate Stone if (!value_sp) { 875de2fb9cfSCaroline Tice option_value_sp.reset(); 876de2fb9cfSCaroline Tice return option_value_sp; 877de2fb9cfSCaroline Tice } 878b9c1b51eSKate Stone } else if (value[0] == '[') { 879de2fb9cfSCaroline Tice assert(value.size() == 1); 880de2fb9cfSCaroline Tice // value is an array 881de2fb9cfSCaroline Tice value_sp = ReadArray(in_file, out_stream, data_type); 882b9c1b51eSKate Stone if (!value_sp) { 883de2fb9cfSCaroline Tice option_value_sp.reset(); 884de2fb9cfSCaroline Tice return option_value_sp; 885de2fb9cfSCaroline Tice } 886de2fb9cfSCaroline Tice // We've used the data_type to read an array; re-set the type to Invalid 887de2fb9cfSCaroline Tice data_type = OptionValue::eTypeInvalid; 888b9c1b51eSKate Stone } else if ((value[0] == '0') && (value[1] == 'x')) { 889de2fb9cfSCaroline Tice value_sp.reset(new OptionValueUInt64(0, 0)); 890c95f7e2aSPavel Labath value_sp->SetValueFromString(value); 891b9c1b51eSKate Stone } else { 892c7bece56SGreg Clayton size_t len = value.size(); 893de2fb9cfSCaroline Tice if ((value[0] == '"') && (value[len - 1] == '"')) 894de2fb9cfSCaroline Tice value = value.substr(1, len - 2); 895de2fb9cfSCaroline Tice value_sp.reset(new OptionValueString(value.c_str(), "")); 896de2fb9cfSCaroline Tice } 897de2fb9cfSCaroline Tice 898b9c1b51eSKate Stone if (const_key == encoding_key) { 899b9c1b51eSKate Stone // A 'data_encoding=..." is NOT a normal key-value pair; it is meta-data 900b9c1b51eSKate Stone // indicating the 901b9c1b51eSKate Stone // data type of an upcoming array (usually the next bit of data to be 902b9c1b51eSKate Stone // read in). 903de2fb9cfSCaroline Tice if (strcmp(value.c_str(), "uint32_t") == 0) 904de2fb9cfSCaroline Tice data_type = OptionValue::eTypeUInt64; 905b9c1b51eSKate Stone } else 906b9c1b51eSKate Stone option_value_sp->GetAsDictionary()->SetValueForKey(const_key, value_sp, 907b9c1b51eSKate Stone false); 908de2fb9cfSCaroline Tice } 909de2fb9cfSCaroline Tice } 910de2fb9cfSCaroline Tice 911de2fb9cfSCaroline Tice return option_value_sp; 912de2fb9cfSCaroline Tice } 913de2fb9cfSCaroline Tice 914b9c1b51eSKate Stone bool Instruction::TestEmulation(Stream *out_stream, const char *file_name) { 9153ac6711aSCaroline Tice if (!out_stream) 9163ac6711aSCaroline Tice return false; 9173ac6711aSCaroline Tice 918b9c1b51eSKate Stone if (!file_name) { 919ea80ba8bSJohnny Chen out_stream->Printf("Instruction::TestEmulation: Missing file_name."); 9203ac6711aSCaroline Tice return false; 9213ac6711aSCaroline Tice } 922190fadcdSZachary Turner FILE *test_file = FileSystem::Fopen(file_name, "r"); 923b9c1b51eSKate Stone if (!test_file) { 924b9c1b51eSKate Stone out_stream->Printf( 925b9c1b51eSKate Stone "Instruction::TestEmulation: Attempt to open test file failed."); 9263ac6711aSCaroline Tice return false; 9273ac6711aSCaroline Tice } 9283ac6711aSCaroline Tice 9293ac6711aSCaroline Tice char buffer[256]; 930b9c1b51eSKate Stone if (!fgets(buffer, 255, test_file)) { 931b9c1b51eSKate Stone out_stream->Printf( 932b9c1b51eSKate Stone "Instruction::TestEmulation: Error reading first line of test file.\n"); 9333ac6711aSCaroline Tice fclose(test_file); 9343ac6711aSCaroline Tice return false; 9353ac6711aSCaroline Tice } 9363ac6711aSCaroline Tice 937b9c1b51eSKate Stone if (strncmp(buffer, "InstructionEmulationState={", 27) != 0) { 938b9c1b51eSKate Stone out_stream->Printf("Instructin::TestEmulation: Test file does not contain " 939b9c1b51eSKate Stone "emulation state dictionary\n"); 940de2fb9cfSCaroline Tice fclose(test_file); 941de2fb9cfSCaroline Tice return false; 942de2fb9cfSCaroline Tice } 943de2fb9cfSCaroline Tice 944b9c1b51eSKate Stone // Read all the test information from the test file into an 945b9c1b51eSKate Stone // OptionValueDictionary. 946de2fb9cfSCaroline Tice 947de2fb9cfSCaroline Tice OptionValueSP data_dictionary_sp(ReadDictionary(test_file, out_stream)); 948b9c1b51eSKate Stone if (!data_dictionary_sp) { 949b9c1b51eSKate Stone out_stream->Printf( 950b9c1b51eSKate Stone "Instruction::TestEmulation: Error reading Dictionary Object.\n"); 951de2fb9cfSCaroline Tice fclose(test_file); 952de2fb9cfSCaroline Tice return false; 953de2fb9cfSCaroline Tice } 954de2fb9cfSCaroline Tice 955de2fb9cfSCaroline Tice fclose(test_file); 956de2fb9cfSCaroline Tice 957b9c1b51eSKate Stone OptionValueDictionary *data_dictionary = 958b9c1b51eSKate Stone data_dictionary_sp->GetAsDictionary(); 959de2fb9cfSCaroline Tice static ConstString description_key("assembly_string"); 960de2fb9cfSCaroline Tice static ConstString triple_key("triple"); 961de2fb9cfSCaroline Tice 962de2fb9cfSCaroline Tice OptionValueSP value_sp = data_dictionary->GetValueForKey(description_key); 963de2fb9cfSCaroline Tice 964b9c1b51eSKate Stone if (!value_sp) { 965b9c1b51eSKate Stone out_stream->Printf("Instruction::TestEmulation: Test file does not " 966b9c1b51eSKate Stone "contain description string.\n"); 967de2fb9cfSCaroline Tice return false; 968de2fb9cfSCaroline Tice } 969de2fb9cfSCaroline Tice 970de2fb9cfSCaroline Tice SetDescription(value_sp->GetStringValue()); 971de2fb9cfSCaroline Tice 972de2fb9cfSCaroline Tice value_sp = data_dictionary->GetValueForKey(triple_key); 973b9c1b51eSKate Stone if (!value_sp) { 974b9c1b51eSKate Stone out_stream->Printf( 975b9c1b51eSKate Stone "Instruction::TestEmulation: Test file does not contain triple.\n"); 976de2fb9cfSCaroline Tice return false; 977de2fb9cfSCaroline Tice } 978de2fb9cfSCaroline Tice 979de2fb9cfSCaroline Tice ArchSpec arch; 980de2fb9cfSCaroline Tice arch.SetTriple(llvm::Triple(value_sp->GetStringValue())); 9813ac6711aSCaroline Tice 9823ac6711aSCaroline Tice bool success = false; 983b9c1b51eSKate Stone std::unique_ptr<EmulateInstruction> insn_emulator_ap( 984b9c1b51eSKate Stone EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr)); 98534ede34aSEugene Zelenko if (insn_emulator_ap) 986b9c1b51eSKate Stone success = 987b9c1b51eSKate Stone insn_emulator_ap->TestEmulation(out_stream, arch, data_dictionary); 9883ac6711aSCaroline Tice 9893ac6711aSCaroline Tice if (success) 990ea80ba8bSJohnny Chen out_stream->Printf("Emulation test succeeded."); 9913ac6711aSCaroline Tice else 992ea80ba8bSJohnny Chen out_stream->Printf("Emulation test failed."); 9933ac6711aSCaroline Tice 9943ac6711aSCaroline Tice return success; 9953ac6711aSCaroline Tice } 9963ac6711aSCaroline Tice 997b9c1b51eSKate Stone bool Instruction::Emulate( 998b9c1b51eSKate Stone const ArchSpec &arch, uint32_t evaluate_options, void *baton, 9997349bd90SGreg Clayton EmulateInstruction::ReadMemoryCallback read_mem_callback, 10007349bd90SGreg Clayton EmulateInstruction::WriteMemoryCallback write_mem_callback, 10017349bd90SGreg Clayton EmulateInstruction::ReadRegisterCallback read_reg_callback, 1002b9c1b51eSKate Stone EmulateInstruction::WriteRegisterCallback write_reg_callback) { 1003b9c1b51eSKate Stone std::unique_ptr<EmulateInstruction> insn_emulator_ap( 1004b9c1b51eSKate Stone EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr)); 1005b9c1b51eSKate Stone if (insn_emulator_ap) { 10067c9dd3ceSCaroline Tice insn_emulator_ap->SetBaton(baton); 1007b9c1b51eSKate Stone insn_emulator_ap->SetCallbacks(read_mem_callback, write_mem_callback, 1008b9c1b51eSKate Stone read_reg_callback, write_reg_callback); 100934ede34aSEugene Zelenko insn_emulator_ap->SetInstruction(GetOpcode(), GetAddress(), nullptr); 10102ed751bdSGreg Clayton return insn_emulator_ap->EvaluateInstruction(evaluate_options); 10117c9dd3ceSCaroline Tice } 10127c9dd3ceSCaroline Tice 10137c9dd3ceSCaroline Tice return false; 10147c9dd3ceSCaroline Tice } 10157c9dd3ceSCaroline Tice 1016b9c1b51eSKate Stone uint32_t Instruction::GetData(DataExtractor &data) { 1017cd4ae1abSSean Callanan return m_opcode.GetData(data); 1018ba812f42SGreg Clayton } 1019ba812f42SGreg Clayton 1020b9c1b51eSKate Stone InstructionList::InstructionList() : m_instructions() {} 102130fdc8d8SChris Lattner 102234ede34aSEugene Zelenko InstructionList::~InstructionList() = default; 102330fdc8d8SChris Lattner 1024b9c1b51eSKate Stone size_t InstructionList::GetSize() const { return m_instructions.size(); } 102530fdc8d8SChris Lattner 1026b9c1b51eSKate Stone uint32_t InstructionList::GetMaxOpcocdeByteSize() const { 1027357132ebSGreg Clayton uint32_t max_inst_size = 0; 1028357132ebSGreg Clayton collection::const_iterator pos, end; 1029b9c1b51eSKate Stone for (pos = m_instructions.begin(), end = m_instructions.end(); pos != end; 1030b9c1b51eSKate Stone ++pos) { 1031357132ebSGreg Clayton uint32_t inst_size = (*pos)->GetOpcode().GetByteSize(); 1032357132ebSGreg Clayton if (max_inst_size < inst_size) 1033357132ebSGreg Clayton max_inst_size = inst_size; 1034357132ebSGreg Clayton } 1035357132ebSGreg Clayton return max_inst_size; 1036357132ebSGreg Clayton } 1037357132ebSGreg Clayton 1038b9c1b51eSKate Stone InstructionSP InstructionList::GetInstructionAtIndex(size_t idx) const { 10391d273166SGreg Clayton InstructionSP inst_sp; 104030fdc8d8SChris Lattner if (idx < m_instructions.size()) 10411d273166SGreg Clayton inst_sp = m_instructions[idx]; 10421d273166SGreg Clayton return inst_sp; 104330fdc8d8SChris Lattner } 104430fdc8d8SChris Lattner 1045b9c1b51eSKate Stone void InstructionList::Dump(Stream *s, bool show_address, bool show_bytes, 1046b9c1b51eSKate Stone const ExecutionContext *exe_ctx) { 10475009f9d5SGreg Clayton const uint32_t max_opcode_byte_size = GetMaxOpcocdeByteSize(); 10485009f9d5SGreg Clayton collection::const_iterator pos, begin, end; 1049554f68d3SGreg Clayton 105034ede34aSEugene Zelenko const FormatEntity::Entry *disassembly_format = nullptr; 1051554f68d3SGreg Clayton FormatEntity::Entry format; 1052b9c1b51eSKate Stone if (exe_ctx && exe_ctx->HasTargetScope()) { 1053b9c1b51eSKate Stone disassembly_format = 1054b9c1b51eSKate Stone exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat(); 1055b9c1b51eSKate Stone } else { 1056554f68d3SGreg Clayton FormatEntity::Parse("${addr}: ", format); 1057554f68d3SGreg Clayton disassembly_format = &format; 1058554f68d3SGreg Clayton } 1059554f68d3SGreg Clayton 10605009f9d5SGreg Clayton for (begin = m_instructions.begin(), end = m_instructions.end(), pos = begin; 1061b9c1b51eSKate Stone pos != end; ++pos) { 10625009f9d5SGreg Clayton if (pos != begin) 10635009f9d5SGreg Clayton s->EOL(); 1064b9c1b51eSKate Stone (*pos)->Dump(s, max_opcode_byte_size, show_address, show_bytes, exe_ctx, 1065b9c1b51eSKate Stone nullptr, nullptr, disassembly_format, 0); 10665009f9d5SGreg Clayton } 10675009f9d5SGreg Clayton } 10685009f9d5SGreg Clayton 1069b9c1b51eSKate Stone void InstructionList::Clear() { m_instructions.clear(); } 107030fdc8d8SChris Lattner 1071b9c1b51eSKate Stone void InstructionList::Append(lldb::InstructionSP &inst_sp) { 107230fdc8d8SChris Lattner if (inst_sp) 107330fdc8d8SChris Lattner m_instructions.push_back(inst_sp); 107430fdc8d8SChris Lattner } 107530fdc8d8SChris Lattner 1076564d8bc2SJim Ingham uint32_t 1077b9c1b51eSKate Stone InstructionList::GetIndexOfNextBranchInstruction(uint32_t start, 1078b9c1b51eSKate Stone Target &target) const { 1079564d8bc2SJim Ingham size_t num_instructions = m_instructions.size(); 1080564d8bc2SJim Ingham 1081190636bcSJim Ingham uint32_t next_branch = UINT32_MAX; 1082e76e7e93STed Woodward size_t i; 1083b9c1b51eSKate Stone for (i = start; i < num_instructions; i++) { 1084b9c1b51eSKate Stone if (m_instructions[i]->DoesBranch()) { 1085564d8bc2SJim Ingham next_branch = i; 1086564d8bc2SJim Ingham break; 1087564d8bc2SJim Ingham } 1088564d8bc2SJim Ingham } 1089e76e7e93STed Woodward 1090e76e7e93STed Woodward // Hexagon needs the first instruction of the packet with the branch. 1091e76e7e93STed Woodward // Go backwards until we find an instruction marked end-of-packet, or 1092e76e7e93STed Woodward // until we hit start. 1093b9c1b51eSKate Stone if (target.GetArchitecture().GetTriple().getArch() == llvm::Triple::hexagon) { 1094e76e7e93STed Woodward // If we didn't find a branch, find the last packet start. 1095b9c1b51eSKate Stone if (next_branch == UINT32_MAX) { 1096e76e7e93STed Woodward i = num_instructions - 1; 1097e76e7e93STed Woodward } 1098e76e7e93STed Woodward 1099b9c1b51eSKate Stone while (i > start) { 1100e76e7e93STed Woodward --i; 1101e76e7e93STed Woodward 1102e76e7e93STed Woodward Error error; 1103e76e7e93STed Woodward uint32_t inst_bytes; 1104e76e7e93STed Woodward bool prefer_file_cache = false; // Read from process if process is running 1105e76e7e93STed Woodward lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; 1106b9c1b51eSKate Stone target.ReadMemory(m_instructions[i]->GetAddress(), prefer_file_cache, 1107b9c1b51eSKate Stone &inst_bytes, sizeof(inst_bytes), error, &load_addr); 1108e76e7e93STed Woodward // If we have an error reading memory, return start 1109e76e7e93STed Woodward if (!error.Success()) 1110e76e7e93STed Woodward return start; 1111e76e7e93STed Woodward // check if this is the last instruction in a packet 1112e76e7e93STed Woodward // bits 15:14 will be 11b or 00b for a duplex 1113e76e7e93STed Woodward if (((inst_bytes & 0xC000) == 0xC000) || 1114b9c1b51eSKate Stone ((inst_bytes & 0xC000) == 0x0000)) { 1115e76e7e93STed Woodward // instruction after this should be the start of next packet 1116e76e7e93STed Woodward next_branch = i + 1; 1117e76e7e93STed Woodward break; 1118e76e7e93STed Woodward } 1119e76e7e93STed Woodward } 1120e76e7e93STed Woodward 1121b9c1b51eSKate Stone if (next_branch == UINT32_MAX) { 1122e76e7e93STed Woodward // We couldn't find the previous packet, so return start 1123e76e7e93STed Woodward next_branch = start; 1124e76e7e93STed Woodward } 1125e76e7e93STed Woodward } 1126564d8bc2SJim Ingham return next_branch; 1127564d8bc2SJim Ingham } 1128564d8bc2SJim Ingham 1129564d8bc2SJim Ingham uint32_t 1130b9c1b51eSKate Stone InstructionList::GetIndexOfInstructionAtAddress(const Address &address) { 1131c7bece56SGreg Clayton size_t num_instructions = m_instructions.size(); 1132190636bcSJim Ingham uint32_t index = UINT32_MAX; 1133b9c1b51eSKate Stone for (size_t i = 0; i < num_instructions; i++) { 1134b9c1b51eSKate Stone if (m_instructions[i]->GetAddress() == address) { 1135564d8bc2SJim Ingham index = i; 1136564d8bc2SJim Ingham break; 1137564d8bc2SJim Ingham } 1138564d8bc2SJim Ingham } 1139564d8bc2SJim Ingham return index; 1140564d8bc2SJim Ingham } 114130fdc8d8SChris Lattner 114244d93782SGreg Clayton uint32_t 1143b9c1b51eSKate Stone InstructionList::GetIndexOfInstructionAtLoadAddress(lldb::addr_t load_addr, 1144b9c1b51eSKate Stone Target &target) { 114544d93782SGreg Clayton Address address; 114644d93782SGreg Clayton address.SetLoadAddress(load_addr, &target); 114744d93782SGreg Clayton return GetIndexOfInstructionAtAddress(address); 114844d93782SGreg Clayton } 114944d93782SGreg Clayton 1150b9c1b51eSKate Stone size_t Disassembler::ParseInstructions(const ExecutionContext *exe_ctx, 115157f0630cSGreg Clayton const AddressRange &range, 11523faf47c4SGreg Clayton Stream *error_strm_ptr, 1153b9c1b51eSKate Stone bool prefer_file_cache) { 1154b9c1b51eSKate Stone if (exe_ctx) { 1155c14ee32dSGreg Clayton Target *target = exe_ctx->GetTargetPtr(); 1156dda4f7b5SGreg Clayton const addr_t byte_size = range.GetByteSize(); 1157b9c1b51eSKate Stone if (target == nullptr || byte_size == 0 || 1158b9c1b51eSKate Stone !range.GetBaseAddress().IsValid()) 115930fdc8d8SChris Lattner return 0; 116030fdc8d8SChris Lattner 1161dda4f7b5SGreg Clayton DataBufferHeap *heap_buffer = new DataBufferHeap(byte_size, '\0'); 1162dda4f7b5SGreg Clayton DataBufferSP data_sp(heap_buffer); 116330fdc8d8SChris Lattner 116430fdc8d8SChris Lattner Error error; 11653faf47c4SGreg Clayton lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; 1166b9c1b51eSKate Stone const size_t bytes_read = target->ReadMemory( 1167b9c1b51eSKate Stone range.GetBaseAddress(), prefer_file_cache, heap_buffer->GetBytes(), 1168b9c1b51eSKate Stone heap_buffer->GetByteSize(), error, &load_addr); 1169dda4f7b5SGreg Clayton 1170b9c1b51eSKate Stone if (bytes_read > 0) { 1171dda4f7b5SGreg Clayton if (bytes_read != heap_buffer->GetByteSize()) 1172dda4f7b5SGreg Clayton heap_buffer->SetByteSize(bytes_read); 1173b9c1b51eSKate Stone DataExtractor data(data_sp, m_arch.GetByteOrder(), 1174357132ebSGreg Clayton m_arch.GetAddressByteSize()); 11753faf47c4SGreg Clayton const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS; 1176b9c1b51eSKate Stone return DecodeInstructions(range.GetBaseAddress(), data, 0, UINT32_MAX, 1177b9c1b51eSKate Stone false, data_from_file); 1178b9c1b51eSKate Stone } else if (error_strm_ptr) { 117957f0630cSGreg Clayton const char *error_cstr = error.AsCString(); 1180b9c1b51eSKate Stone if (error_cstr) { 118157f0630cSGreg Clayton error_strm_ptr->Printf("error: %s\n", error_cstr); 118257f0630cSGreg Clayton } 118357f0630cSGreg Clayton } 1184b9c1b51eSKate Stone } else if (error_strm_ptr) { 118557f0630cSGreg Clayton error_strm_ptr->PutCString("error: invalid execution context\n"); 1186c14ee32dSGreg Clayton } 118730fdc8d8SChris Lattner return 0; 118830fdc8d8SChris Lattner } 118930fdc8d8SChris Lattner 1190b9c1b51eSKate Stone size_t Disassembler::ParseInstructions(const ExecutionContext *exe_ctx, 119137023b06SJim Ingham const Address &start, 11923faf47c4SGreg Clayton uint32_t num_instructions, 1193b9c1b51eSKate Stone bool prefer_file_cache) { 1194357132ebSGreg Clayton m_instruction_list.Clear(); 119537023b06SJim Ingham 119634ede34aSEugene Zelenko if (exe_ctx == nullptr || num_instructions == 0 || !start.IsValid()) 119737023b06SJim Ingham return 0; 119837023b06SJim Ingham 1199c14ee32dSGreg Clayton Target *target = exe_ctx->GetTargetPtr(); 1200357132ebSGreg Clayton // Calculate the max buffer size we will need in order to disassemble 1201357132ebSGreg Clayton const addr_t byte_size = num_instructions * m_arch.GetMaximumOpcodeByteSize(); 120237023b06SJim Ingham 120334ede34aSEugene Zelenko if (target == nullptr || byte_size == 0) 120437023b06SJim Ingham return 0; 120537023b06SJim Ingham 120637023b06SJim Ingham DataBufferHeap *heap_buffer = new DataBufferHeap(byte_size, '\0'); 120737023b06SJim Ingham DataBufferSP data_sp(heap_buffer); 120837023b06SJim Ingham 120937023b06SJim Ingham Error error; 12103faf47c4SGreg Clayton lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; 1211b9c1b51eSKate Stone const size_t bytes_read = 1212b9c1b51eSKate Stone target->ReadMemory(start, prefer_file_cache, heap_buffer->GetBytes(), 1213b9c1b51eSKate Stone byte_size, error, &load_addr); 12143faf47c4SGreg Clayton 12153faf47c4SGreg Clayton const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS; 121637023b06SJim Ingham 121737023b06SJim Ingham if (bytes_read == 0) 1218357132ebSGreg Clayton return 0; 1219b9c1b51eSKate Stone DataExtractor data(data_sp, m_arch.GetByteOrder(), 1220357132ebSGreg Clayton m_arch.GetAddressByteSize()); 122137023b06SJim Ingham 1222357132ebSGreg Clayton const bool append_instructions = true; 1223b9c1b51eSKate Stone DecodeInstructions(start, data, 0, num_instructions, append_instructions, 12243faf47c4SGreg Clayton data_from_file); 122537023b06SJim Ingham 122637023b06SJim Ingham return m_instruction_list.GetSize(); 122737023b06SJim Ingham } 122837023b06SJim Ingham 122930fdc8d8SChris Lattner //---------------------------------------------------------------------- 123030fdc8d8SChris Lattner // Disassembler copy constructor 123130fdc8d8SChris Lattner //---------------------------------------------------------------------- 1232b9c1b51eSKate Stone Disassembler::Disassembler(const ArchSpec &arch, const char *flavor) 1233b9c1b51eSKate Stone : m_arch(arch), m_instruction_list(), m_base_addr(LLDB_INVALID_ADDRESS), 1234b9c1b51eSKate Stone m_flavor() { 123534ede34aSEugene Zelenko if (flavor == nullptr) 12360f063ba6SJim Ingham m_flavor.assign("default"); 12370f063ba6SJim Ingham else 12380f063ba6SJim Ingham m_flavor.assign(flavor); 123975452e8cSJason Molenda 124075452e8cSJason Molenda // If this is an arm variant that can only include thumb (T16, T32) 124175452e8cSJason Molenda // instructions, force the arch triple to be "thumbv.." instead of 124275452e8cSJason Molenda // "armv..." 1243b9c1b51eSKate Stone if (arch.IsAlwaysThumbInstructions()) { 124475452e8cSJason Molenda std::string thumb_arch_name(arch.GetTriple().getArchName().str()); 124575452e8cSJason Molenda // Replace "arm" with "thumb" so we get all thumb variants correct 1246b9c1b51eSKate Stone if (thumb_arch_name.size() > 3) { 124775452e8cSJason Molenda thumb_arch_name.erase(0, 3); 124875452e8cSJason Molenda thumb_arch_name.insert(0, "thumb"); 124975452e8cSJason Molenda } 125075452e8cSJason Molenda m_arch.SetTriple(thumb_arch_name.c_str()); 125175452e8cSJason Molenda } 125230fdc8d8SChris Lattner } 125330fdc8d8SChris Lattner 125434ede34aSEugene Zelenko Disassembler::~Disassembler() = default; 125530fdc8d8SChris Lattner 1256b9c1b51eSKate Stone InstructionList &Disassembler::GetInstructionList() { 125730fdc8d8SChris Lattner return m_instruction_list; 125830fdc8d8SChris Lattner } 125930fdc8d8SChris Lattner 1260b9c1b51eSKate Stone const InstructionList &Disassembler::GetInstructionList() const { 126130fdc8d8SChris Lattner return m_instruction_list; 126230fdc8d8SChris Lattner } 12633ac6711aSCaroline Tice 12643ac6711aSCaroline Tice //---------------------------------------------------------------------- 12653ac6711aSCaroline Tice // Class PseudoInstruction 12663ac6711aSCaroline Tice //---------------------------------------------------------------------- 126734ede34aSEugene Zelenko 1268b9c1b51eSKate Stone PseudoInstruction::PseudoInstruction() 1269b9c1b51eSKate Stone : Instruction(Address(), eAddressClassUnknown), m_description() {} 12703ac6711aSCaroline Tice 127134ede34aSEugene Zelenko PseudoInstruction::~PseudoInstruction() = default; 12723ac6711aSCaroline Tice 1273b9c1b51eSKate Stone bool PseudoInstruction::DoesBranch() { 12743ac6711aSCaroline Tice // This is NOT a valid question for a pseudo instruction. 12753ac6711aSCaroline Tice return false; 12763ac6711aSCaroline Tice } 12773ac6711aSCaroline Tice 1278b9c1b51eSKate Stone bool PseudoInstruction::HasDelaySlot() { 12797f3daedaSBhushan D. Attarde // This is NOT a valid question for a pseudo instruction. 12807f3daedaSBhushan D. Attarde return false; 12817f3daedaSBhushan D. Attarde } 12827f3daedaSBhushan D. Attarde 1283b9c1b51eSKate Stone size_t PseudoInstruction::Decode(const lldb_private::Disassembler &disassembler, 12843ac6711aSCaroline Tice const lldb_private::DataExtractor &data, 1285b9c1b51eSKate Stone lldb::offset_t data_offset) { 12863ac6711aSCaroline Tice return m_opcode.GetByteSize(); 12873ac6711aSCaroline Tice } 12883ac6711aSCaroline Tice 1289b9c1b51eSKate Stone void PseudoInstruction::SetOpcode(size_t opcode_size, void *opcode_data) { 12903ac6711aSCaroline Tice if (!opcode_data) 12913ac6711aSCaroline Tice return; 12923ac6711aSCaroline Tice 1293b9c1b51eSKate Stone switch (opcode_size) { 1294b9c1b51eSKate Stone case 8: { 12953ac6711aSCaroline Tice uint8_t value8 = *((uint8_t *)opcode_data); 129690359963SEd Maste m_opcode.SetOpcode8(value8, eByteOrderInvalid); 12973ac6711aSCaroline Tice break; 12983ac6711aSCaroline Tice } 1299b9c1b51eSKate Stone case 16: { 13003ac6711aSCaroline Tice uint16_t value16 = *((uint16_t *)opcode_data); 130190359963SEd Maste m_opcode.SetOpcode16(value16, eByteOrderInvalid); 13023ac6711aSCaroline Tice break; 13033ac6711aSCaroline Tice } 1304b9c1b51eSKate Stone case 32: { 13053ac6711aSCaroline Tice uint32_t value32 = *((uint32_t *)opcode_data); 130690359963SEd Maste m_opcode.SetOpcode32(value32, eByteOrderInvalid); 13073ac6711aSCaroline Tice break; 13083ac6711aSCaroline Tice } 1309b9c1b51eSKate Stone case 64: { 13103ac6711aSCaroline Tice uint64_t value64 = *((uint64_t *)opcode_data); 131190359963SEd Maste m_opcode.SetOpcode64(value64, eByteOrderInvalid); 13123ac6711aSCaroline Tice break; 13133ac6711aSCaroline Tice } 13143ac6711aSCaroline Tice default: 13153ac6711aSCaroline Tice break; 13163ac6711aSCaroline Tice } 13173ac6711aSCaroline Tice } 13183ac6711aSCaroline Tice 1319b9c1b51eSKate Stone void PseudoInstruction::SetDescription(const char *description) { 13203ac6711aSCaroline Tice if (description && strlen(description) > 0) 13213ac6711aSCaroline Tice m_description = description; 13223ac6711aSCaroline Tice } 1323*807ee2ffSSean Callanan 1324*807ee2ffSSean Callanan Instruction::Operand Instruction::Operand::BuildRegister(ConstString &r) { 1325*807ee2ffSSean Callanan Operand ret; 1326*807ee2ffSSean Callanan ret.m_type = Type::Register; 1327*807ee2ffSSean Callanan ret.m_register = r; 1328*807ee2ffSSean Callanan return ret; 1329*807ee2ffSSean Callanan } 1330*807ee2ffSSean Callanan 1331*807ee2ffSSean Callanan Instruction::Operand Instruction::Operand::BuildImmediate(lldb::addr_t imm, 1332*807ee2ffSSean Callanan bool neg) { 1333*807ee2ffSSean Callanan Operand ret; 1334*807ee2ffSSean Callanan ret.m_type = Type::Immediate; 1335*807ee2ffSSean Callanan ret.m_immediate = imm; 1336*807ee2ffSSean Callanan ret.m_negative = neg; 1337*807ee2ffSSean Callanan return ret; 1338*807ee2ffSSean Callanan } 1339*807ee2ffSSean Callanan 1340*807ee2ffSSean Callanan Instruction::Operand Instruction::Operand::BuildImmediate(int64_t imm) { 1341*807ee2ffSSean Callanan Operand ret; 1342*807ee2ffSSean Callanan ret.m_type = Type::Immediate; 1343*807ee2ffSSean Callanan if (imm < 0) { 1344*807ee2ffSSean Callanan ret.m_immediate = -imm; 1345*807ee2ffSSean Callanan ret.m_negative = true; 1346*807ee2ffSSean Callanan } else { 1347*807ee2ffSSean Callanan ret.m_immediate = imm; 1348*807ee2ffSSean Callanan ret.m_negative = false; 1349*807ee2ffSSean Callanan } 1350*807ee2ffSSean Callanan return ret; 1351*807ee2ffSSean Callanan } 1352*807ee2ffSSean Callanan 1353*807ee2ffSSean Callanan Instruction::Operand 1354*807ee2ffSSean Callanan Instruction::Operand::BuildDereference(const Operand &ref) { 1355*807ee2ffSSean Callanan Operand ret; 1356*807ee2ffSSean Callanan ret.m_type = Type::Dereference; 1357*807ee2ffSSean Callanan ret.m_children = {ref}; 1358*807ee2ffSSean Callanan return ret; 1359*807ee2ffSSean Callanan } 1360*807ee2ffSSean Callanan 1361*807ee2ffSSean Callanan Instruction::Operand Instruction::Operand::BuildSum(const Operand &lhs, 1362*807ee2ffSSean Callanan const Operand &rhs) { 1363*807ee2ffSSean Callanan Operand ret; 1364*807ee2ffSSean Callanan ret.m_type = Type::Sum; 1365*807ee2ffSSean Callanan ret.m_children = {lhs, rhs}; 1366*807ee2ffSSean Callanan return ret; 1367*807ee2ffSSean Callanan } 1368*807ee2ffSSean Callanan 1369*807ee2ffSSean Callanan Instruction::Operand Instruction::Operand::BuildProduct(const Operand &lhs, 1370*807ee2ffSSean Callanan const Operand &rhs) { 1371*807ee2ffSSean Callanan Operand ret; 1372*807ee2ffSSean Callanan ret.m_type = Type::Product; 1373*807ee2ffSSean Callanan ret.m_children = {lhs, rhs}; 1374*807ee2ffSSean Callanan return ret; 1375*807ee2ffSSean Callanan } 1376*807ee2ffSSean Callanan 1377*807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> 1378*807ee2ffSSean Callanan lldb_private::OperandMatchers::MatchBinaryOp( 1379*807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> base, 1380*807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> left, 1381*807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> right) { 1382*807ee2ffSSean Callanan return [base, left, right](const Instruction::Operand &op) -> bool { 1383*807ee2ffSSean Callanan return (base(op) && op.m_children.size() == 2 && 1384*807ee2ffSSean Callanan ((left(op.m_children[0]) && right(op.m_children[1])) || 1385*807ee2ffSSean Callanan (left(op.m_children[1]) && right(op.m_children[0])))); 1386*807ee2ffSSean Callanan }; 1387*807ee2ffSSean Callanan } 1388*807ee2ffSSean Callanan 1389*807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> 1390*807ee2ffSSean Callanan lldb_private::OperandMatchers::MatchUnaryOp( 1391*807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> base, 1392*807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> child) { 1393*807ee2ffSSean Callanan return [base, child](const Instruction::Operand &op) -> bool { 1394*807ee2ffSSean Callanan return (base(op) && op.m_children.size() == 1 && child(op.m_children[0])); 1395*807ee2ffSSean Callanan }; 1396*807ee2ffSSean Callanan } 1397*807ee2ffSSean Callanan 1398*807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> 1399*807ee2ffSSean Callanan lldb_private::OperandMatchers::MatchRegOp(const RegisterInfo &info) { 1400*807ee2ffSSean Callanan return [&info](const Instruction::Operand &op) { 1401*807ee2ffSSean Callanan return (op.m_type == Instruction::Operand::Type::Register && 1402*807ee2ffSSean Callanan (op.m_register == ConstString(info.name) || 1403*807ee2ffSSean Callanan op.m_register == ConstString(info.alt_name))); 1404*807ee2ffSSean Callanan }; 1405*807ee2ffSSean Callanan } 1406*807ee2ffSSean Callanan 1407*807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> 1408*807ee2ffSSean Callanan lldb_private::OperandMatchers::MatchImmOp(int64_t imm) { 1409*807ee2ffSSean Callanan return [imm](const Instruction::Operand &op) { 1410*807ee2ffSSean Callanan return (op.m_type == Instruction::Operand::Type::Immediate && 1411*807ee2ffSSean Callanan ((op.m_negative && op.m_immediate == (uint64_t)-imm) || 1412*807ee2ffSSean Callanan (!op.m_negative && op.m_immediate == (uint64_t)imm))); 1413*807ee2ffSSean Callanan }; 1414*807ee2ffSSean Callanan } 1415*807ee2ffSSean Callanan 1416*807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> 1417*807ee2ffSSean Callanan lldb_private::OperandMatchers::FetchImmOp(int64_t &imm) { 1418*807ee2ffSSean Callanan return [&imm](const Instruction::Operand &op) { 1419*807ee2ffSSean Callanan if (op.m_type != Instruction::Operand::Type::Immediate) { 1420*807ee2ffSSean Callanan return false; 1421*807ee2ffSSean Callanan } 1422*807ee2ffSSean Callanan if (op.m_negative) { 1423*807ee2ffSSean Callanan imm = -((int64_t)op.m_immediate); 1424*807ee2ffSSean Callanan } else { 1425*807ee2ffSSean Callanan imm = ((int64_t)op.m_immediate); 1426*807ee2ffSSean Callanan } 1427*807ee2ffSSean Callanan return true; 1428*807ee2ffSSean Callanan }; 1429*807ee2ffSSean Callanan } 1430*807ee2ffSSean Callanan 1431*807ee2ffSSean Callanan std::function<bool(const Instruction::Operand &)> 1432*807ee2ffSSean Callanan lldb_private::OperandMatchers::MatchOpType(Instruction::Operand::Type type) { 1433*807ee2ffSSean Callanan return [type](const Instruction::Operand &op) { return op.m_type == type; }; 1434*807ee2ffSSean Callanan } 1435*807ee2ffSSean Callanan 1436