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" 23*190fadcdSZachary 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" 28*190fadcdSZachary 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" 3267cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueString.h" 3367cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueUInt64.h" 341f746071SGreg Clayton #include "lldb/Symbol/Function.h" 3530fdc8d8SChris Lattner #include "lldb/Symbol/ObjectFile.h" 3630fdc8d8SChris Lattner #include "lldb/Target/ExecutionContext.h" 3730fdc8d8SChris Lattner #include "lldb/Target/Process.h" 38d5944cd1SGreg Clayton #include "lldb/Target/SectionLoadList.h" 39b57e4a1bSJason Molenda #include "lldb/Target/StackFrame.h" 4030fdc8d8SChris Lattner #include "lldb/Target/Target.h" 41*190fadcdSZachary Turner #include "lldb/lldb-private.h" 4230fdc8d8SChris Lattner 4330fdc8d8SChris Lattner #define DEFAULT_DISASM_BYTE_SIZE 32 4430fdc8d8SChris Lattner 4530fdc8d8SChris Lattner using namespace lldb; 4630fdc8d8SChris Lattner using namespace lldb_private; 4730fdc8d8SChris Lattner 487e6d4e5aSSean Callanan DisassemblerSP 490f063ba6SJim Ingham Disassembler::FindPlugin (const ArchSpec &arch, const char *flavor, const char *plugin_name) 5030fdc8d8SChris Lattner { 5130fdc8d8SChris Lattner Timer scoped_timer (__PRETTY_FUNCTION__, 521080edbcSGreg Clayton "Disassembler::FindPlugin (arch = %s, plugin_name = %s)", 531080edbcSGreg Clayton arch.GetArchitectureName(), 541080edbcSGreg Clayton plugin_name); 5530fdc8d8SChris Lattner 5634ede34aSEugene Zelenko DisassemblerCreateInstance create_callback = nullptr; 571080edbcSGreg Clayton 581080edbcSGreg Clayton if (plugin_name) 591080edbcSGreg Clayton { 6057abc5d6SGreg Clayton ConstString const_plugin_name (plugin_name); 6157abc5d6SGreg Clayton create_callback = PluginManager::GetDisassemblerCreateCallbackForPluginName (const_plugin_name); 621080edbcSGreg Clayton if (create_callback) 631080edbcSGreg Clayton { 640f063ba6SJim Ingham DisassemblerSP disassembler_sp(create_callback(arch, flavor)); 651080edbcSGreg Clayton 6634ede34aSEugene Zelenko if (disassembler_sp) 677e6d4e5aSSean Callanan return disassembler_sp; 681080edbcSGreg Clayton } 691080edbcSGreg Clayton } 701080edbcSGreg Clayton else 711080edbcSGreg Clayton { 7234ede34aSEugene Zelenko for (uint32_t idx = 0; (create_callback = PluginManager::GetDisassemblerCreateCallbackAtIndex(idx)) != nullptr; ++idx) 7330fdc8d8SChris Lattner { 740f063ba6SJim Ingham DisassemblerSP disassembler_sp(create_callback(arch, flavor)); 7530fdc8d8SChris Lattner 7634ede34aSEugene Zelenko if (disassembler_sp) 777e6d4e5aSSean Callanan return disassembler_sp; 7830fdc8d8SChris Lattner } 791080edbcSGreg Clayton } 807e6d4e5aSSean Callanan return DisassemblerSP(); 8130fdc8d8SChris Lattner } 8230fdc8d8SChris Lattner 830f063ba6SJim Ingham DisassemblerSP 840f063ba6SJim Ingham Disassembler::FindPluginForTarget(const TargetSP target_sp, const ArchSpec &arch, const char *flavor, const char *plugin_name) 850f063ba6SJim Ingham { 8634ede34aSEugene Zelenko if (target_sp && flavor == nullptr) 870f063ba6SJim Ingham { 880f063ba6SJim Ingham // FIXME - we don't have the mechanism in place to do per-architecture settings. But since we know that for now 890f063ba6SJim Ingham // we only support flavors on x86 & x86_64, 900f063ba6SJim Ingham if (arch.GetTriple().getArch() == llvm::Triple::x86 910f063ba6SJim Ingham || 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 97357132ebSGreg Clayton static void 98357132ebSGreg Clayton ResolveAddress (const ExecutionContext &exe_ctx, 99357132ebSGreg Clayton const Address &addr, 100357132ebSGreg Clayton Address &resolved_addr) 101357132ebSGreg Clayton { 102357132ebSGreg Clayton if (!addr.IsSectionOffset()) 103357132ebSGreg Clayton { 104357132ebSGreg Clayton // If we weren't passed in a section offset address range, 105357132ebSGreg Clayton // try and resolve it to something 106c14ee32dSGreg Clayton Target *target = exe_ctx.GetTargetPtr(); 107c14ee32dSGreg Clayton if (target) 108357132ebSGreg Clayton { 109c14ee32dSGreg Clayton if (target->GetSectionLoadList().IsEmpty()) 110357132ebSGreg Clayton { 111c14ee32dSGreg Clayton target->GetImages().ResolveFileAddress (addr.GetOffset(), resolved_addr); 112357132ebSGreg Clayton } 113357132ebSGreg Clayton else 114357132ebSGreg Clayton { 115c14ee32dSGreg Clayton target->GetSectionLoadList().ResolveLoadAddress (addr.GetOffset(), resolved_addr); 116357132ebSGreg Clayton } 117357132ebSGreg Clayton // We weren't able to resolve the address, just treat it as a 118357132ebSGreg Clayton // raw address 119357132ebSGreg Clayton if (resolved_addr.IsValid()) 120357132ebSGreg Clayton return; 121357132ebSGreg Clayton } 122357132ebSGreg Clayton } 123357132ebSGreg Clayton resolved_addr = addr; 124357132ebSGreg Clayton } 125dda4f7b5SGreg Clayton 126dda4f7b5SGreg Clayton size_t 12734ede34aSEugene Zelenko Disassembler::Disassemble(Debugger &debugger, 128dda4f7b5SGreg Clayton const ArchSpec &arch, 1291080edbcSGreg Clayton const char *plugin_name, 1300f063ba6SJim Ingham const char *flavor, 131dda4f7b5SGreg Clayton const ExecutionContext &exe_ctx, 132dda4f7b5SGreg Clayton SymbolContextList &sc_list, 13337023b06SJim Ingham uint32_t num_instructions, 134dda4f7b5SGreg Clayton uint32_t num_mixed_context_lines, 1351da6f9d7SGreg Clayton uint32_t options, 13634ede34aSEugene Zelenko Stream &strm) 137dda4f7b5SGreg Clayton { 138dda4f7b5SGreg Clayton size_t success_count = 0; 139dda4f7b5SGreg Clayton const size_t count = sc_list.GetSize(); 140dda4f7b5SGreg Clayton SymbolContext sc; 141dda4f7b5SGreg Clayton AddressRange range; 1427e14f91dSGreg Clayton const uint32_t scope = eSymbolContextBlock | eSymbolContextFunction | eSymbolContextSymbol; 1437e14f91dSGreg Clayton const bool use_inline_block_range = true; 144dda4f7b5SGreg Clayton for (size_t i = 0; i < count; ++i) 145dda4f7b5SGreg Clayton { 14634ede34aSEugene Zelenko if (!sc_list.GetContextAtIndex(i, sc)) 147dda4f7b5SGreg Clayton break; 1487e14f91dSGreg Clayton for (uint32_t range_idx = 0; sc.GetAddressRange(scope, range_idx, use_inline_block_range, range); ++range_idx) 149dda4f7b5SGreg Clayton { 1501080edbcSGreg Clayton if (Disassemble (debugger, 1511080edbcSGreg Clayton arch, 1521080edbcSGreg Clayton plugin_name, 1530f063ba6SJim Ingham flavor, 1541080edbcSGreg Clayton exe_ctx, 1551080edbcSGreg Clayton range, 1561080edbcSGreg Clayton num_instructions, 1571080edbcSGreg Clayton num_mixed_context_lines, 1581da6f9d7SGreg Clayton options, 1591080edbcSGreg Clayton strm)) 160dda4f7b5SGreg Clayton { 161dda4f7b5SGreg Clayton ++success_count; 162dda4f7b5SGreg Clayton strm.EOL(); 163dda4f7b5SGreg Clayton } 164dda4f7b5SGreg Clayton } 165dda4f7b5SGreg Clayton } 166dda4f7b5SGreg Clayton return success_count; 167dda4f7b5SGreg Clayton } 168dda4f7b5SGreg Clayton 16930fdc8d8SChris Lattner bool 17034ede34aSEugene Zelenko Disassembler::Disassemble(Debugger &debugger, 17130fdc8d8SChris Lattner const ArchSpec &arch, 1721080edbcSGreg Clayton const char *plugin_name, 1730f063ba6SJim Ingham const char *flavor, 17430fdc8d8SChris Lattner const ExecutionContext &exe_ctx, 175dda4f7b5SGreg Clayton const ConstString &name, 176dda4f7b5SGreg Clayton Module *module, 17737023b06SJim Ingham uint32_t num_instructions, 178dda4f7b5SGreg Clayton uint32_t num_mixed_context_lines, 1791da6f9d7SGreg Clayton uint32_t options, 18034ede34aSEugene Zelenko Stream &strm) 18130fdc8d8SChris Lattner { 182dda4f7b5SGreg Clayton SymbolContextList sc_list; 183931180e6SGreg Clayton if (name) 184931180e6SGreg Clayton { 185931180e6SGreg Clayton const bool include_symbols = true; 1869df05fbbSSean Callanan const bool include_inlines = true; 187dda4f7b5SGreg Clayton if (module) 188dda4f7b5SGreg Clayton { 189931180e6SGreg Clayton module->FindFunctions(name, 19034ede34aSEugene Zelenko nullptr, 1916ecb232bSGreg Clayton eFunctionNameTypeAuto, 192931180e6SGreg Clayton include_symbols, 1939df05fbbSSean Callanan include_inlines, 194dda4f7b5SGreg Clayton true, 195931180e6SGreg Clayton sc_list); 196dda4f7b5SGreg Clayton } 197c14ee32dSGreg Clayton else if (exe_ctx.GetTargetPtr()) 198dda4f7b5SGreg Clayton { 199c14ee32dSGreg Clayton exe_ctx.GetTargetPtr()->GetImages().FindFunctions (name, 2006ecb232bSGreg Clayton eFunctionNameTypeAuto, 201931180e6SGreg Clayton include_symbols, 2029df05fbbSSean Callanan include_inlines, 2038ade104aSSean Callanan false, 204931180e6SGreg Clayton sc_list); 205dda4f7b5SGreg Clayton } 206dda4f7b5SGreg Clayton } 207931180e6SGreg Clayton 208931180e6SGreg Clayton if (sc_list.GetSize ()) 209931180e6SGreg Clayton { 210931180e6SGreg Clayton return Disassemble (debugger, 211931180e6SGreg Clayton arch, 2121080edbcSGreg Clayton plugin_name, 2130f063ba6SJim Ingham flavor, 214931180e6SGreg Clayton exe_ctx, 215931180e6SGreg Clayton sc_list, 21637023b06SJim Ingham num_instructions, 217931180e6SGreg Clayton num_mixed_context_lines, 2181da6f9d7SGreg Clayton options, 219931180e6SGreg Clayton strm); 220dda4f7b5SGreg Clayton } 221dda4f7b5SGreg Clayton return false; 222dda4f7b5SGreg Clayton } 223dda4f7b5SGreg Clayton 2241d273166SGreg Clayton lldb::DisassemblerSP 22534ede34aSEugene Zelenko Disassembler::DisassembleRange(const ArchSpec &arch, 2261080edbcSGreg Clayton const char *plugin_name, 2270f063ba6SJim Ingham const char *flavor, 2281d273166SGreg Clayton const ExecutionContext &exe_ctx, 2296b3e6d54SJason Molenda const AddressRange &range, 23034ede34aSEugene Zelenko bool prefer_file_cache) 2311d273166SGreg Clayton { 2321d273166SGreg Clayton lldb::DisassemblerSP disasm_sp; 2331d273166SGreg Clayton if (range.GetByteSize() > 0 && range.GetBaseAddress().IsValid()) 2341d273166SGreg Clayton { 2350f063ba6SJim Ingham disasm_sp = Disassembler::FindPluginForTarget(exe_ctx.GetTargetSP(), arch, flavor, plugin_name); 2361d273166SGreg Clayton 2371d273166SGreg Clayton if (disasm_sp) 2381d273166SGreg Clayton { 23934ede34aSEugene Zelenko size_t bytes_disassembled = disasm_sp->ParseInstructions(&exe_ctx, range, nullptr, prefer_file_cache); 2401d273166SGreg Clayton if (bytes_disassembled == 0) 2411d273166SGreg Clayton disasm_sp.reset(); 2421d273166SGreg Clayton } 2431d273166SGreg Clayton } 2441d273166SGreg Clayton return disasm_sp; 2451d273166SGreg Clayton } 2461d273166SGreg Clayton 24750952e95SSean Callanan lldb::DisassemblerSP 2483faf47c4SGreg Clayton Disassembler::DisassembleBytes (const ArchSpec &arch, 24950952e95SSean Callanan const char *plugin_name, 2500f063ba6SJim Ingham const char *flavor, 25150952e95SSean Callanan const Address &start, 2523faf47c4SGreg Clayton const void *src, 2533faf47c4SGreg Clayton size_t src_len, 2543faf47c4SGreg Clayton uint32_t num_instructions, 2553faf47c4SGreg Clayton bool data_from_file) 25650952e95SSean Callanan { 25750952e95SSean Callanan lldb::DisassemblerSP disasm_sp; 25850952e95SSean Callanan 2593faf47c4SGreg Clayton if (src) 26050952e95SSean Callanan { 2610f063ba6SJim Ingham disasm_sp = Disassembler::FindPlugin(arch, flavor, plugin_name); 26250952e95SSean Callanan 26350952e95SSean Callanan if (disasm_sp) 26450952e95SSean Callanan { 2653faf47c4SGreg Clayton DataExtractor data(src, src_len, arch.GetByteOrder(), arch.GetAddressByteSize()); 26650952e95SSean Callanan 26750952e95SSean Callanan (void)disasm_sp->DecodeInstructions (start, 26850952e95SSean Callanan data, 26950952e95SSean Callanan 0, 2709c766110SGreg Clayton num_instructions, 2713faf47c4SGreg Clayton false, 2723faf47c4SGreg Clayton data_from_file); 27350952e95SSean Callanan } 27450952e95SSean Callanan } 27550952e95SSean Callanan 27650952e95SSean Callanan return disasm_sp; 27750952e95SSean Callanan } 27850952e95SSean Callanan 279dda4f7b5SGreg Clayton bool 28034ede34aSEugene Zelenko Disassembler::Disassemble(Debugger &debugger, 281dda4f7b5SGreg Clayton const ArchSpec &arch, 2821080edbcSGreg Clayton const char *plugin_name, 2830f063ba6SJim Ingham const char *flavor, 284dda4f7b5SGreg Clayton const ExecutionContext &exe_ctx, 285dda4f7b5SGreg Clayton const AddressRange &disasm_range, 28637023b06SJim Ingham uint32_t num_instructions, 287dda4f7b5SGreg Clayton uint32_t num_mixed_context_lines, 2881da6f9d7SGreg Clayton uint32_t options, 28934ede34aSEugene Zelenko Stream &strm) 290dda4f7b5SGreg Clayton { 291dda4f7b5SGreg Clayton if (disasm_range.GetByteSize()) 292dda4f7b5SGreg Clayton { 2930f063ba6SJim Ingham lldb::DisassemblerSP disasm_sp (Disassembler::FindPluginForTarget(exe_ctx.GetTargetSP(), arch, flavor, plugin_name)); 29430fdc8d8SChris Lattner 29534ede34aSEugene Zelenko if (disasm_sp) 29630fdc8d8SChris Lattner { 297357132ebSGreg Clayton AddressRange range; 298357132ebSGreg Clayton ResolveAddress (exe_ctx, disasm_range.GetBaseAddress(), range.GetBaseAddress()); 299357132ebSGreg Clayton range.SetByteSize (disasm_range.GetByteSize()); 3003faf47c4SGreg Clayton const bool prefer_file_cache = false; 3013faf47c4SGreg Clayton size_t bytes_disassembled = disasm_sp->ParseInstructions (&exe_ctx, range, &strm, prefer_file_cache); 30230fdc8d8SChris Lattner if (bytes_disassembled == 0) 30330fdc8d8SChris Lattner return false; 3041080edbcSGreg Clayton 30556d40428SJim Ingham bool result = PrintInstructions (disasm_sp.get(), 30637023b06SJim Ingham debugger, 30737023b06SJim Ingham arch, 30837023b06SJim Ingham exe_ctx, 30937023b06SJim Ingham num_instructions, 31037023b06SJim Ingham num_mixed_context_lines, 3111da6f9d7SGreg Clayton options, 31237023b06SJim Ingham strm); 31356d40428SJim Ingham 31456d40428SJim Ingham // FIXME: The DisassemblerLLVMC has a reference cycle and won't go away if it has any active instructions. 31556d40428SJim Ingham // I'll fix that but for now, just clear the list and it will go away nicely. 31656d40428SJim Ingham disasm_sp->GetInstructionList().Clear(); 31756d40428SJim Ingham return result; 31837023b06SJim Ingham } 31937023b06SJim Ingham } 32037023b06SJim Ingham return false; 32137023b06SJim Ingham } 32237023b06SJim Ingham 32337023b06SJim Ingham bool 32434ede34aSEugene Zelenko Disassembler::Disassemble(Debugger &debugger, 32537023b06SJim Ingham const ArchSpec &arch, 3261080edbcSGreg Clayton const char *plugin_name, 3270f063ba6SJim Ingham const char *flavor, 32837023b06SJim Ingham const ExecutionContext &exe_ctx, 32937023b06SJim Ingham const Address &start_address, 33037023b06SJim Ingham uint32_t num_instructions, 33137023b06SJim Ingham uint32_t num_mixed_context_lines, 3321da6f9d7SGreg Clayton uint32_t options, 33334ede34aSEugene Zelenko Stream &strm) 33437023b06SJim Ingham { 33537023b06SJim Ingham if (num_instructions > 0) 33637023b06SJim Ingham { 3373faf47c4SGreg Clayton lldb::DisassemblerSP disasm_sp (Disassembler::FindPluginForTarget(exe_ctx.GetTargetSP(), 3383faf47c4SGreg Clayton arch, 3393faf47c4SGreg Clayton flavor, 3403faf47c4SGreg Clayton plugin_name)); 34134ede34aSEugene Zelenko if (disasm_sp) 34237023b06SJim Ingham { 343357132ebSGreg Clayton Address addr; 344357132ebSGreg Clayton ResolveAddress (exe_ctx, start_address, addr); 3453faf47c4SGreg Clayton const bool prefer_file_cache = false; 3463faf47c4SGreg Clayton size_t bytes_disassembled = disasm_sp->ParseInstructions (&exe_ctx, 3473faf47c4SGreg Clayton addr, 3483faf47c4SGreg Clayton num_instructions, 3493faf47c4SGreg Clayton prefer_file_cache); 35037023b06SJim Ingham if (bytes_disassembled == 0) 35137023b06SJim Ingham return false; 35256d40428SJim Ingham bool result = PrintInstructions (disasm_sp.get(), 35337023b06SJim Ingham debugger, 35437023b06SJim Ingham arch, 35537023b06SJim Ingham exe_ctx, 35637023b06SJim Ingham num_instructions, 35737023b06SJim Ingham num_mixed_context_lines, 3581da6f9d7SGreg Clayton options, 35937023b06SJim Ingham strm); 36056d40428SJim Ingham 36156d40428SJim Ingham // FIXME: The DisassemblerLLVMC has a reference cycle and won't go away if it has any active instructions. 36256d40428SJim Ingham // I'll fix that but for now, just clear the list and it will go away nicely. 36356d40428SJim Ingham disasm_sp->GetInstructionList().Clear(); 36456d40428SJim Ingham return result; 36537023b06SJim Ingham } 36637023b06SJim Ingham } 36737023b06SJim Ingham return false; 36837023b06SJim Ingham } 36937023b06SJim Ingham 37037023b06SJim Ingham bool 37134ede34aSEugene Zelenko Disassembler::PrintInstructions(Disassembler *disasm_ptr, 37237023b06SJim Ingham Debugger &debugger, 37337023b06SJim Ingham const ArchSpec &arch, 37437023b06SJim Ingham const ExecutionContext &exe_ctx, 37537023b06SJim Ingham uint32_t num_instructions, 37637023b06SJim Ingham uint32_t num_mixed_context_lines, 3771da6f9d7SGreg Clayton uint32_t options, 37834ede34aSEugene Zelenko Stream &strm) 37937023b06SJim Ingham { 38030fdc8d8SChris Lattner // We got some things disassembled... 38137023b06SJim Ingham size_t num_instructions_found = disasm_ptr->GetInstructionList().GetSize(); 38237023b06SJim Ingham 38337023b06SJim Ingham if (num_instructions > 0 && num_instructions < num_instructions_found) 38437023b06SJim Ingham num_instructions_found = num_instructions; 38537023b06SJim Ingham 386357132ebSGreg Clayton const uint32_t max_opcode_byte_size = disasm_ptr->GetInstructionList().GetMaxOpcocdeByteSize (); 38730fdc8d8SChris Lattner uint32_t offset = 0; 38830fdc8d8SChris Lattner SymbolContext sc; 38930fdc8d8SChris Lattner SymbolContext prev_sc; 39030fdc8d8SChris Lattner AddressRange sc_range; 39134ede34aSEugene Zelenko const Address *pc_addr_ptr = nullptr; 392b57e4a1bSJason Molenda StackFrame *frame = exe_ctx.GetFramePtr(); 393c14ee32dSGreg Clayton 3944b2967ffSMichael Sartain TargetSP target_sp (exe_ctx.GetTargetSP()); 3954b2967ffSMichael Sartain SourceManager &source_manager = target_sp ? target_sp->GetSourceManager() : debugger.GetSourceManager(); 3964b2967ffSMichael Sartain 397c14ee32dSGreg Clayton if (frame) 398aff1b357SJason Molenda { 399c14ee32dSGreg Clayton pc_addr_ptr = &frame->GetFrameCodeAddress(); 400aff1b357SJason Molenda } 4017e14f91dSGreg Clayton const uint32_t scope = eSymbolContextLineEntry | eSymbolContextFunction | eSymbolContextSymbol; 4027e14f91dSGreg Clayton const bool use_inline_block_range = false; 403c980fa92SJason Molenda 40434ede34aSEugene Zelenko const FormatEntity::Entry *disassembly_format = nullptr; 405c980fa92SJason Molenda FormatEntity::Entry format; 406c980fa92SJason Molenda if (exe_ctx.HasTargetScope()) 407c980fa92SJason Molenda { 408c980fa92SJason Molenda disassembly_format = exe_ctx.GetTargetRef().GetDebugger().GetDisassemblyFormat (); 409c980fa92SJason Molenda } 410c980fa92SJason Molenda else 411c980fa92SJason Molenda { 412c980fa92SJason Molenda FormatEntity::Parse("${addr}: ", format); 413c980fa92SJason Molenda disassembly_format = &format; 414c980fa92SJason Molenda } 415c980fa92SJason Molenda 416c980fa92SJason Molenda // First pass: step through the list of instructions, 417c980fa92SJason Molenda // find how long the initial addresses strings are, insert padding 418c980fa92SJason Molenda // in the second pass so the opcodes all line up nicely. 419c980fa92SJason Molenda size_t address_text_size = 0; 420c980fa92SJason Molenda for (size_t i = 0; i < num_instructions_found; ++i) 421c980fa92SJason Molenda { 422c980fa92SJason Molenda Instruction *inst = disasm_ptr->GetInstructionList().GetInstructionAtIndex (i).get(); 423c980fa92SJason Molenda if (inst) 424c980fa92SJason Molenda { 425c980fa92SJason Molenda const Address &addr = inst->GetAddress(); 426c980fa92SJason Molenda ModuleSP module_sp (addr.GetModule()); 427c980fa92SJason Molenda if (module_sp) 428c980fa92SJason Molenda { 429c980fa92SJason Molenda const uint32_t resolve_mask = eSymbolContextFunction | eSymbolContextSymbol; 430c980fa92SJason Molenda uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress(addr, resolve_mask, sc); 431c980fa92SJason Molenda if (resolved_mask) 432c980fa92SJason Molenda { 433c980fa92SJason Molenda StreamString strmstr; 43434ede34aSEugene Zelenko Debugger::FormatDisassemblerAddress(disassembly_format, &sc, nullptr, &exe_ctx, &addr, strmstr); 435c980fa92SJason Molenda size_t cur_line = strmstr.GetSizeOfLastLine(); 436c980fa92SJason Molenda if (cur_line > address_text_size) 437c980fa92SJason Molenda address_text_size = cur_line; 438c980fa92SJason Molenda } 439c980fa92SJason Molenda sc.Clear(false); 440c980fa92SJason Molenda } 441c980fa92SJason Molenda } 442c980fa92SJason Molenda } 443c980fa92SJason Molenda 44437023b06SJim Ingham for (size_t i = 0; i < num_instructions_found; ++i) 44530fdc8d8SChris Lattner { 44637023b06SJim Ingham Instruction *inst = disasm_ptr->GetInstructionList().GetInstructionAtIndex (i).get(); 44730fdc8d8SChris Lattner if (inst) 44830fdc8d8SChris Lattner { 44932e0a750SGreg Clayton const Address &addr = inst->GetAddress(); 45032e0a750SGreg Clayton const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr; 451dda4f7b5SGreg Clayton 45230fdc8d8SChris Lattner prev_sc = sc; 453dda4f7b5SGreg Clayton 454e72dfb32SGreg Clayton ModuleSP module_sp (addr.GetModule()); 455e72dfb32SGreg Clayton if (module_sp) 45630fdc8d8SChris Lattner { 457e72dfb32SGreg Clayton uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc); 45830fdc8d8SChris Lattner if (resolved_mask) 45930fdc8d8SChris Lattner { 46032e0a750SGreg Clayton if (num_mixed_context_lines) 461dda4f7b5SGreg Clayton { 46232e0a750SGreg Clayton if (!sc_range.ContainsFileAddress (addr)) 463dda4f7b5SGreg Clayton { 4647e14f91dSGreg Clayton sc.GetAddressRange (scope, 0, use_inline_block_range, sc_range); 465dda4f7b5SGreg Clayton 46630fdc8d8SChris Lattner if (sc != prev_sc) 46730fdc8d8SChris Lattner { 46830fdc8d8SChris Lattner if (offset != 0) 46930fdc8d8SChris Lattner strm.EOL(); 47030fdc8d8SChris Lattner 471c980fa92SJason Molenda sc.DumpStopContext(&strm, exe_ctx.GetProcessPtr(), addr, false, true, false, false, true); 4726dbd3983SGreg Clayton strm.EOL(); 47330fdc8d8SChris Lattner 47430fdc8d8SChris Lattner if (sc.comp_unit && sc.line_entry.IsValid()) 47530fdc8d8SChris Lattner { 4764b2967ffSMichael Sartain source_manager.DisplaySourceLinesWithLineNumbers (sc.line_entry.file, 47730fdc8d8SChris Lattner sc.line_entry.line, 478dda4f7b5SGreg Clayton num_mixed_context_lines, 479dda4f7b5SGreg Clayton num_mixed_context_lines, 480b10d72f0SGreg Clayton ((inst_is_at_pc && (options & eOptionMarkPCSourceLine)) ? "->" : ""), 48130fdc8d8SChris Lattner &strm); 48230fdc8d8SChris Lattner } 48330fdc8d8SChris Lattner } 48430fdc8d8SChris Lattner } 48530fdc8d8SChris Lattner } 48632e0a750SGreg Clayton } 487dda4f7b5SGreg Clayton else 488dda4f7b5SGreg Clayton { 48972310355SGreg Clayton sc.Clear(true); 49030fdc8d8SChris Lattner } 49130fdc8d8SChris Lattner } 49232e0a750SGreg Clayton 4931da6f9d7SGreg Clayton const bool show_bytes = (options & eOptionShowBytes) != 0; 49434ede34aSEugene Zelenko inst->Dump(&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx, &sc, &prev_sc, nullptr, address_text_size); 49530fdc8d8SChris Lattner strm.EOL(); 49630fdc8d8SChris Lattner } 49730fdc8d8SChris Lattner else 49830fdc8d8SChris Lattner { 49930fdc8d8SChris Lattner break; 50030fdc8d8SChris Lattner } 50130fdc8d8SChris Lattner } 50230fdc8d8SChris Lattner 50330fdc8d8SChris Lattner return true; 50430fdc8d8SChris Lattner } 50530fdc8d8SChris Lattner 506dda4f7b5SGreg Clayton bool 50734ede34aSEugene Zelenko Disassembler::Disassemble(Debugger &debugger, 508dda4f7b5SGreg Clayton const ArchSpec &arch, 5091080edbcSGreg Clayton const char *plugin_name, 5100f063ba6SJim Ingham const char *flavor, 511dda4f7b5SGreg Clayton const ExecutionContext &exe_ctx, 51237023b06SJim Ingham uint32_t num_instructions, 513dda4f7b5SGreg Clayton uint32_t num_mixed_context_lines, 5141da6f9d7SGreg Clayton uint32_t options, 51534ede34aSEugene Zelenko Stream &strm) 516dda4f7b5SGreg Clayton { 517dda4f7b5SGreg Clayton AddressRange range; 518b57e4a1bSJason Molenda StackFrame *frame = exe_ctx.GetFramePtr(); 519c14ee32dSGreg Clayton if (frame) 520dda4f7b5SGreg Clayton { 521c14ee32dSGreg Clayton SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol)); 522dda4f7b5SGreg Clayton if (sc.function) 523dda4f7b5SGreg Clayton { 524dda4f7b5SGreg Clayton range = sc.function->GetAddressRange(); 525dda4f7b5SGreg Clayton } 526e7612134SGreg Clayton else if (sc.symbol && sc.symbol->ValueIsAddress()) 527dda4f7b5SGreg Clayton { 528358cf1eaSGreg Clayton range.GetBaseAddress() = sc.symbol->GetAddressRef(); 529e7612134SGreg Clayton range.SetByteSize (sc.symbol->GetByteSize()); 530dda4f7b5SGreg Clayton } 531dda4f7b5SGreg Clayton else 532dda4f7b5SGreg Clayton { 533c14ee32dSGreg Clayton range.GetBaseAddress() = frame->GetFrameCodeAddress(); 534dda4f7b5SGreg Clayton } 535dda4f7b5SGreg Clayton 536dda4f7b5SGreg Clayton if (range.GetBaseAddress().IsValid() && range.GetByteSize() == 0) 537dda4f7b5SGreg Clayton range.SetByteSize (DEFAULT_DISASM_BYTE_SIZE); 538dda4f7b5SGreg Clayton } 539dda4f7b5SGreg Clayton 5401080edbcSGreg Clayton return Disassemble (debugger, 5411080edbcSGreg Clayton arch, 5421080edbcSGreg Clayton plugin_name, 5430f063ba6SJim Ingham flavor, 5441080edbcSGreg Clayton exe_ctx, 5451080edbcSGreg Clayton range, 5461080edbcSGreg Clayton num_instructions, 5471080edbcSGreg Clayton num_mixed_context_lines, 5481da6f9d7SGreg Clayton options, 5491080edbcSGreg Clayton strm); 550dda4f7b5SGreg Clayton } 551dda4f7b5SGreg Clayton 552357132ebSGreg Clayton Instruction::Instruction(const Address &address, AddressClass addr_class) : 5531080edbcSGreg Clayton m_address (address), 554357132ebSGreg Clayton m_address_class (addr_class), 555a97aa92aSSean Callanan m_opcode(), 556a97aa92aSSean Callanan m_calculated_strings(false) 5570ae96273SGreg Clayton { 55830fdc8d8SChris Lattner } 55930fdc8d8SChris Lattner 56034ede34aSEugene Zelenko Instruction::~Instruction() = default; 56130fdc8d8SChris Lattner 562357132ebSGreg Clayton AddressClass 563357132ebSGreg Clayton Instruction::GetAddressClass () 564357132ebSGreg Clayton { 565357132ebSGreg Clayton if (m_address_class == eAddressClassInvalid) 566357132ebSGreg Clayton m_address_class = m_address.GetAddressClass(); 567357132ebSGreg Clayton return m_address_class; 568357132ebSGreg Clayton } 56930fdc8d8SChris Lattner 570ba812f42SGreg Clayton void 571ba812f42SGreg Clayton Instruction::Dump (lldb_private::Stream *s, 572ba812f42SGreg Clayton uint32_t max_opcode_byte_size, 573ba812f42SGreg Clayton bool show_address, 574ba812f42SGreg Clayton bool show_bytes, 575aff1b357SJason Molenda const ExecutionContext* exe_ctx, 576aff1b357SJason Molenda const SymbolContext *sym_ctx, 577aff1b357SJason Molenda const SymbolContext *prev_sym_ctx, 578c980fa92SJason Molenda const FormatEntity::Entry *disassembly_addr_format, 579c980fa92SJason Molenda size_t max_address_text_size) 580ba812f42SGreg Clayton { 5817a37c1ecSJason Molenda size_t opcode_column_width = 7; 582ba812f42SGreg Clayton const size_t operand_column_width = 25; 583ba812f42SGreg Clayton 584ba812f42SGreg Clayton CalculateMnemonicOperandsAndCommentIfNeeded (exe_ctx); 585ba812f42SGreg Clayton 586ba812f42SGreg Clayton StreamString ss; 587ba812f42SGreg Clayton 588ba812f42SGreg Clayton if (show_address) 589ba812f42SGreg Clayton { 590554f68d3SGreg Clayton Debugger::FormatDisassemblerAddress (disassembly_addr_format, sym_ctx, prev_sym_ctx, exe_ctx, &m_address, ss); 591c980fa92SJason Molenda ss.FillLastLineToColumn (max_address_text_size, ' '); 592ba812f42SGreg Clayton } 593ba812f42SGreg Clayton 594ba812f42SGreg Clayton if (show_bytes) 595ba812f42SGreg Clayton { 596ba812f42SGreg Clayton if (m_opcode.GetType() == Opcode::eTypeBytes) 597ba812f42SGreg Clayton { 598ba812f42SGreg Clayton // x86_64 and i386 are the only ones that use bytes right now so 599ba812f42SGreg Clayton // pad out the byte dump to be able to always show 15 bytes (3 chars each) 600ba812f42SGreg Clayton // plus a space 601ba812f42SGreg Clayton if (max_opcode_byte_size > 0) 602ba812f42SGreg Clayton m_opcode.Dump (&ss, max_opcode_byte_size * 3 + 1); 603ba812f42SGreg Clayton else 604ba812f42SGreg Clayton m_opcode.Dump (&ss, 15 * 3 + 1); 605ba812f42SGreg Clayton } 606ba812f42SGreg Clayton else 607ba812f42SGreg Clayton { 608d616c97aSEd Maste // Else, we have ARM or MIPS which can show up to a uint32_t 609d616c97aSEd Maste // 0x00000000 (10 spaces) plus two for padding... 610ba812f42SGreg Clayton if (max_opcode_byte_size > 0) 611ba812f42SGreg Clayton m_opcode.Dump (&ss, max_opcode_byte_size * 3 + 1); 612ba812f42SGreg Clayton else 613ba812f42SGreg Clayton m_opcode.Dump (&ss, 12); 614ba812f42SGreg Clayton } 615ba812f42SGreg Clayton } 616ba812f42SGreg Clayton 617aff1b357SJason Molenda const size_t opcode_pos = ss.GetSizeOfLastLine(); 618ba812f42SGreg Clayton 6197a37c1ecSJason Molenda // The default opcode size of 7 characters is plenty for most architectures 6207a37c1ecSJason Molenda // but some like arm can pull out the occasional vqrshrun.s16. We won't get 6217a37c1ecSJason Molenda // consistent column spacing in these cases, unfortunately. 6227a37c1ecSJason Molenda if (m_opcode_name.length() >= opcode_column_width) 6237a37c1ecSJason Molenda { 6247a37c1ecSJason Molenda opcode_column_width = m_opcode_name.length() + 1; 6257a37c1ecSJason Molenda } 6267a37c1ecSJason Molenda 627ba812f42SGreg Clayton ss.PutCString (m_opcode_name.c_str()); 628ba812f42SGreg Clayton ss.FillLastLineToColumn (opcode_pos + opcode_column_width, ' '); 6290f063ba6SJim Ingham ss.PutCString (m_mnemonics.c_str()); 630ba812f42SGreg Clayton 631ba812f42SGreg Clayton if (!m_comment.empty()) 632ba812f42SGreg Clayton { 633ba812f42SGreg Clayton ss.FillLastLineToColumn (opcode_pos + opcode_column_width + operand_column_width, ' '); 634ba812f42SGreg Clayton ss.PutCString (" ; "); 635ba812f42SGreg Clayton ss.PutCString (m_comment.c_str()); 636ba812f42SGreg Clayton } 637ba812f42SGreg Clayton s->Write (ss.GetData(), ss.GetSize()); 638ba812f42SGreg Clayton } 639ba812f42SGreg Clayton 6407c9dd3ceSCaroline Tice bool 6417c9dd3ceSCaroline Tice Instruction::DumpEmulation (const ArchSpec &arch) 6427c9dd3ceSCaroline Tice { 64334ede34aSEugene Zelenko std::unique_ptr<EmulateInstruction> insn_emulator_ap(EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr)); 64434ede34aSEugene Zelenko if (insn_emulator_ap) 6457c9dd3ceSCaroline Tice { 64634ede34aSEugene Zelenko insn_emulator_ap->SetInstruction(GetOpcode(), GetAddress(), nullptr); 6472ed751bdSGreg Clayton return insn_emulator_ap->EvaluateInstruction (0); 6487c9dd3ceSCaroline Tice } 6497c9dd3ceSCaroline Tice 6507c9dd3ceSCaroline Tice return false; 6517c9dd3ceSCaroline Tice } 6527c9dd3ceSCaroline Tice 6537f3daedaSBhushan D. Attarde bool 6547f3daedaSBhushan D. Attarde Instruction::HasDelaySlot () 6557f3daedaSBhushan D. Attarde { 6567f3daedaSBhushan D. Attarde // Default is false. 6577f3daedaSBhushan D. Attarde return false; 6587f3daedaSBhushan D. Attarde } 6597f3daedaSBhushan D. Attarde 660de2fb9cfSCaroline Tice OptionValueSP 661de2fb9cfSCaroline Tice Instruction::ReadArray (FILE *in_file, Stream *out_stream, OptionValue::Type data_type) 662de2fb9cfSCaroline Tice { 663de2fb9cfSCaroline Tice bool done = false; 664de2fb9cfSCaroline Tice char buffer[1024]; 665de2fb9cfSCaroline Tice 666de2fb9cfSCaroline Tice OptionValueSP option_value_sp (new OptionValueArray (1u << data_type)); 667de2fb9cfSCaroline Tice 668de2fb9cfSCaroline Tice int idx = 0; 669de2fb9cfSCaroline Tice while (!done) 670de2fb9cfSCaroline Tice { 671de2fb9cfSCaroline Tice if (!fgets (buffer, 1023, in_file)) 672de2fb9cfSCaroline Tice { 673762f7135SGreg Clayton out_stream->Printf ("Instruction::ReadArray: Error reading file (fgets).\n"); 674de2fb9cfSCaroline Tice option_value_sp.reset (); 675de2fb9cfSCaroline Tice return option_value_sp; 676de2fb9cfSCaroline Tice } 677de2fb9cfSCaroline Tice 678de2fb9cfSCaroline Tice std::string line (buffer); 679de2fb9cfSCaroline Tice 680c7bece56SGreg Clayton size_t len = line.size(); 681de2fb9cfSCaroline Tice if (line[len-1] == '\n') 682de2fb9cfSCaroline Tice { 683de2fb9cfSCaroline Tice line[len-1] = '\0'; 684de2fb9cfSCaroline Tice line.resize (len-1); 685de2fb9cfSCaroline Tice } 686de2fb9cfSCaroline Tice 687de2fb9cfSCaroline Tice if ((line.size() == 1) && line[0] == ']') 688de2fb9cfSCaroline Tice { 689de2fb9cfSCaroline Tice done = true; 690de2fb9cfSCaroline Tice line.clear(); 691de2fb9cfSCaroline Tice } 692de2fb9cfSCaroline Tice 69334ede34aSEugene Zelenko if (!line.empty()) 694de2fb9cfSCaroline Tice { 695de2fb9cfSCaroline Tice std::string value; 696bc43cab5SGreg Clayton static RegularExpression g_reg_exp ("^[ \t]*([^ \t]+)[ \t]*$"); 697bc43cab5SGreg Clayton RegularExpression::Match regex_match(1); 698bc43cab5SGreg Clayton bool reg_exp_success = g_reg_exp.Execute (line.c_str(), ®ex_match); 699de2fb9cfSCaroline Tice if (reg_exp_success) 700bc43cab5SGreg Clayton regex_match.GetMatchAtIndex (line.c_str(), 1, value); 701de2fb9cfSCaroline Tice else 702de2fb9cfSCaroline Tice value = line; 703de2fb9cfSCaroline Tice 704de2fb9cfSCaroline Tice OptionValueSP data_value_sp; 705de2fb9cfSCaroline Tice switch (data_type) 706de2fb9cfSCaroline Tice { 707de2fb9cfSCaroline Tice case OptionValue::eTypeUInt64: 708de2fb9cfSCaroline Tice data_value_sp.reset (new OptionValueUInt64 (0, 0)); 709c95f7e2aSPavel Labath data_value_sp->SetValueFromString (value); 710de2fb9cfSCaroline Tice break; 711de2fb9cfSCaroline Tice // Other types can be added later as needed. 712de2fb9cfSCaroline Tice default: 713de2fb9cfSCaroline Tice data_value_sp.reset (new OptionValueString (value.c_str(), "")); 714de2fb9cfSCaroline Tice break; 715de2fb9cfSCaroline Tice } 716de2fb9cfSCaroline Tice 71784c39663SGreg Clayton option_value_sp->GetAsArray()->InsertValue (idx, data_value_sp); 718de2fb9cfSCaroline Tice ++idx; 719de2fb9cfSCaroline Tice } 720de2fb9cfSCaroline Tice } 721de2fb9cfSCaroline Tice 722de2fb9cfSCaroline Tice return option_value_sp; 723de2fb9cfSCaroline Tice } 724de2fb9cfSCaroline Tice 725de2fb9cfSCaroline Tice OptionValueSP 726de2fb9cfSCaroline Tice Instruction::ReadDictionary (FILE *in_file, Stream *out_stream) 727de2fb9cfSCaroline Tice { 728de2fb9cfSCaroline Tice bool done = false; 729de2fb9cfSCaroline Tice char buffer[1024]; 730de2fb9cfSCaroline Tice 731de2fb9cfSCaroline Tice OptionValueSP option_value_sp (new OptionValueDictionary()); 732de2fb9cfSCaroline Tice static ConstString encoding_key ("data_encoding"); 733de2fb9cfSCaroline Tice OptionValue::Type data_type = OptionValue::eTypeInvalid; 734de2fb9cfSCaroline Tice 735de2fb9cfSCaroline Tice 736de2fb9cfSCaroline Tice while (!done) 737de2fb9cfSCaroline Tice { 738de2fb9cfSCaroline Tice // Read the next line in the file 739de2fb9cfSCaroline Tice if (!fgets (buffer, 1023, in_file)) 740de2fb9cfSCaroline Tice { 741de2fb9cfSCaroline Tice out_stream->Printf ("Instruction::ReadDictionary: Error reading file (fgets).\n"); 742de2fb9cfSCaroline Tice option_value_sp.reset (); 743de2fb9cfSCaroline Tice return option_value_sp; 744de2fb9cfSCaroline Tice } 745de2fb9cfSCaroline Tice 746de2fb9cfSCaroline Tice // Check to see if the line contains the end-of-dictionary marker ("}") 747de2fb9cfSCaroline Tice std::string line (buffer); 748de2fb9cfSCaroline Tice 749c7bece56SGreg Clayton size_t len = line.size(); 750de2fb9cfSCaroline Tice if (line[len-1] == '\n') 751de2fb9cfSCaroline Tice { 752de2fb9cfSCaroline Tice line[len-1] = '\0'; 753de2fb9cfSCaroline Tice line.resize (len-1); 754de2fb9cfSCaroline Tice } 755de2fb9cfSCaroline Tice 756de2fb9cfSCaroline Tice if ((line.size() == 1) && (line[0] == '}')) 757de2fb9cfSCaroline Tice { 758de2fb9cfSCaroline Tice done = true; 759de2fb9cfSCaroline Tice line.clear(); 760de2fb9cfSCaroline Tice } 761de2fb9cfSCaroline Tice 762de2fb9cfSCaroline Tice // Try to find a key-value pair in the current line and add it to the dictionary. 76334ede34aSEugene Zelenko if (!line.empty()) 764de2fb9cfSCaroline Tice { 765bc43cab5SGreg Clayton static RegularExpression g_reg_exp ("^[ \t]*([a-zA-Z_][a-zA-Z0-9_]*)[ \t]*=[ \t]*(.*)[ \t]*$"); 766bc43cab5SGreg Clayton RegularExpression::Match regex_match(2); 767bc43cab5SGreg Clayton 768bc43cab5SGreg Clayton bool reg_exp_success = g_reg_exp.Execute (line.c_str(), ®ex_match); 769de2fb9cfSCaroline Tice std::string key; 770de2fb9cfSCaroline Tice std::string value; 771de2fb9cfSCaroline Tice if (reg_exp_success) 772de2fb9cfSCaroline Tice { 773bc43cab5SGreg Clayton regex_match.GetMatchAtIndex (line.c_str(), 1, key); 774bc43cab5SGreg Clayton regex_match.GetMatchAtIndex (line.c_str(), 2, value); 775de2fb9cfSCaroline Tice } 776de2fb9cfSCaroline Tice else 777de2fb9cfSCaroline Tice { 778de2fb9cfSCaroline Tice out_stream->Printf ("Instruction::ReadDictionary: Failure executing regular expression.\n"); 779de2fb9cfSCaroline Tice option_value_sp.reset(); 780de2fb9cfSCaroline Tice return option_value_sp; 781de2fb9cfSCaroline Tice } 782de2fb9cfSCaroline Tice 783de2fb9cfSCaroline Tice ConstString const_key (key.c_str()); 784de2fb9cfSCaroline Tice // Check value to see if it's the start of an array or dictionary. 785de2fb9cfSCaroline Tice 786de2fb9cfSCaroline Tice lldb::OptionValueSP value_sp; 787de2fb9cfSCaroline Tice assert (value.empty() == false); 788de2fb9cfSCaroline Tice assert (key.empty() == false); 789de2fb9cfSCaroline Tice 790de2fb9cfSCaroline Tice if (value[0] == '{') 791de2fb9cfSCaroline Tice { 792de2fb9cfSCaroline Tice assert (value.size() == 1); 793de2fb9cfSCaroline Tice // value is a dictionary 794de2fb9cfSCaroline Tice value_sp = ReadDictionary (in_file, out_stream); 79534ede34aSEugene Zelenko if (!value_sp) 796de2fb9cfSCaroline Tice { 797de2fb9cfSCaroline Tice option_value_sp.reset (); 798de2fb9cfSCaroline Tice return option_value_sp; 799de2fb9cfSCaroline Tice } 800de2fb9cfSCaroline Tice } 801de2fb9cfSCaroline Tice else if (value[0] == '[') 802de2fb9cfSCaroline Tice { 803de2fb9cfSCaroline Tice assert (value.size() == 1); 804de2fb9cfSCaroline Tice // value is an array 805de2fb9cfSCaroline Tice value_sp = ReadArray (in_file, out_stream, data_type); 80634ede34aSEugene Zelenko if (!value_sp) 807de2fb9cfSCaroline Tice { 808de2fb9cfSCaroline Tice option_value_sp.reset (); 809de2fb9cfSCaroline Tice return option_value_sp; 810de2fb9cfSCaroline Tice } 811de2fb9cfSCaroline Tice // We've used the data_type to read an array; re-set the type to Invalid 812de2fb9cfSCaroline Tice data_type = OptionValue::eTypeInvalid; 813de2fb9cfSCaroline Tice } 814de2fb9cfSCaroline Tice else if ((value[0] == '0') && (value[1] == 'x')) 815de2fb9cfSCaroline Tice { 816de2fb9cfSCaroline Tice value_sp.reset (new OptionValueUInt64 (0, 0)); 817c95f7e2aSPavel Labath value_sp->SetValueFromString (value); 818de2fb9cfSCaroline Tice } 819de2fb9cfSCaroline Tice else 820de2fb9cfSCaroline Tice { 821c7bece56SGreg Clayton size_t len = value.size(); 822de2fb9cfSCaroline Tice if ((value[0] == '"') && (value[len-1] == '"')) 823de2fb9cfSCaroline Tice value = value.substr (1, len-2); 824de2fb9cfSCaroline Tice value_sp.reset (new OptionValueString (value.c_str(), "")); 825de2fb9cfSCaroline Tice } 826de2fb9cfSCaroline Tice 827de2fb9cfSCaroline Tice if (const_key == encoding_key) 828de2fb9cfSCaroline Tice { 829de2fb9cfSCaroline Tice // A 'data_encoding=..." is NOT a normal key-value pair; it is meta-data indicating the 830de2fb9cfSCaroline Tice // data type of an upcoming array (usually the next bit of data to be read in). 831de2fb9cfSCaroline Tice if (strcmp (value.c_str(), "uint32_t") == 0) 832de2fb9cfSCaroline Tice data_type = OptionValue::eTypeUInt64; 833de2fb9cfSCaroline Tice } 834de2fb9cfSCaroline Tice else 83584c39663SGreg Clayton option_value_sp->GetAsDictionary()->SetValueForKey (const_key, value_sp, false); 836de2fb9cfSCaroline Tice } 837de2fb9cfSCaroline Tice } 838de2fb9cfSCaroline Tice 839de2fb9cfSCaroline Tice return option_value_sp; 840de2fb9cfSCaroline Tice } 841de2fb9cfSCaroline Tice 8427c9dd3ceSCaroline Tice bool 8433ac6711aSCaroline Tice Instruction::TestEmulation (Stream *out_stream, const char *file_name) 8443ac6711aSCaroline Tice { 8453ac6711aSCaroline Tice if (!out_stream) 8463ac6711aSCaroline Tice return false; 8473ac6711aSCaroline Tice 8483ac6711aSCaroline Tice if (!file_name) 8493ac6711aSCaroline Tice { 850ea80ba8bSJohnny Chen out_stream->Printf ("Instruction::TestEmulation: Missing file_name."); 8513ac6711aSCaroline Tice return false; 8523ac6711aSCaroline Tice } 853*190fadcdSZachary Turner FILE *test_file = FileSystem::Fopen(file_name, "r"); 8543ac6711aSCaroline Tice if (!test_file) 8553ac6711aSCaroline Tice { 856ea80ba8bSJohnny Chen out_stream->Printf ("Instruction::TestEmulation: Attempt to open test file failed."); 8573ac6711aSCaroline Tice return false; 8583ac6711aSCaroline Tice } 8593ac6711aSCaroline Tice 8603ac6711aSCaroline Tice char buffer[256]; 861de2fb9cfSCaroline Tice if (!fgets (buffer, 255, test_file)) 8623ac6711aSCaroline Tice { 863de2fb9cfSCaroline Tice out_stream->Printf ("Instruction::TestEmulation: Error reading first line of test file.\n"); 8643ac6711aSCaroline Tice fclose (test_file); 8653ac6711aSCaroline Tice return false; 8663ac6711aSCaroline Tice } 8673ac6711aSCaroline Tice 868de2fb9cfSCaroline Tice if (strncmp (buffer, "InstructionEmulationState={", 27) != 0) 869de2fb9cfSCaroline Tice { 870de2fb9cfSCaroline Tice out_stream->Printf ("Instructin::TestEmulation: Test file does not contain emulation state dictionary\n"); 871de2fb9cfSCaroline Tice fclose (test_file); 872de2fb9cfSCaroline Tice return false; 873de2fb9cfSCaroline Tice } 874de2fb9cfSCaroline Tice 875de2fb9cfSCaroline Tice // Read all the test information from the test file into an OptionValueDictionary. 876de2fb9cfSCaroline Tice 877de2fb9cfSCaroline Tice OptionValueSP data_dictionary_sp (ReadDictionary (test_file, out_stream)); 87834ede34aSEugene Zelenko if (!data_dictionary_sp) 879de2fb9cfSCaroline Tice { 880de2fb9cfSCaroline Tice out_stream->Printf ("Instruction::TestEmulation: Error reading Dictionary Object.\n"); 881de2fb9cfSCaroline Tice fclose (test_file); 882de2fb9cfSCaroline Tice return false; 883de2fb9cfSCaroline Tice } 884de2fb9cfSCaroline Tice 885de2fb9cfSCaroline Tice fclose (test_file); 886de2fb9cfSCaroline Tice 88784c39663SGreg Clayton OptionValueDictionary *data_dictionary = data_dictionary_sp->GetAsDictionary(); 888de2fb9cfSCaroline Tice static ConstString description_key ("assembly_string"); 889de2fb9cfSCaroline Tice static ConstString triple_key ("triple"); 890de2fb9cfSCaroline Tice 891de2fb9cfSCaroline Tice OptionValueSP value_sp = data_dictionary->GetValueForKey (description_key); 892de2fb9cfSCaroline Tice 89334ede34aSEugene Zelenko if (!value_sp) 894de2fb9cfSCaroline Tice { 895de2fb9cfSCaroline Tice out_stream->Printf ("Instruction::TestEmulation: Test file does not contain description string.\n"); 896de2fb9cfSCaroline Tice return false; 897de2fb9cfSCaroline Tice } 898de2fb9cfSCaroline Tice 899de2fb9cfSCaroline Tice SetDescription (value_sp->GetStringValue()); 900de2fb9cfSCaroline Tice 901de2fb9cfSCaroline Tice value_sp = data_dictionary->GetValueForKey (triple_key); 90234ede34aSEugene Zelenko if (!value_sp) 903de2fb9cfSCaroline Tice { 904de2fb9cfSCaroline Tice out_stream->Printf ("Instruction::TestEmulation: Test file does not contain triple.\n"); 905de2fb9cfSCaroline Tice return false; 906de2fb9cfSCaroline Tice } 907de2fb9cfSCaroline Tice 908de2fb9cfSCaroline Tice ArchSpec arch; 909de2fb9cfSCaroline Tice arch.SetTriple (llvm::Triple (value_sp->GetStringValue())); 9103ac6711aSCaroline Tice 9113ac6711aSCaroline Tice bool success = false; 91234ede34aSEugene Zelenko std::unique_ptr<EmulateInstruction> insn_emulator_ap(EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr)); 91334ede34aSEugene Zelenko if (insn_emulator_ap) 914de2fb9cfSCaroline Tice success = insn_emulator_ap->TestEmulation (out_stream, arch, data_dictionary); 9153ac6711aSCaroline Tice 9163ac6711aSCaroline Tice if (success) 917ea80ba8bSJohnny Chen out_stream->Printf ("Emulation test succeeded."); 9183ac6711aSCaroline Tice else 919ea80ba8bSJohnny Chen out_stream->Printf ("Emulation test failed."); 9203ac6711aSCaroline Tice 9213ac6711aSCaroline Tice return success; 9223ac6711aSCaroline Tice } 9233ac6711aSCaroline Tice 9243ac6711aSCaroline Tice bool 9257c9dd3ceSCaroline Tice Instruction::Emulate (const ArchSpec &arch, 9262ed751bdSGreg Clayton uint32_t evaluate_options, 9277c9dd3ceSCaroline Tice void *baton, 9287349bd90SGreg Clayton EmulateInstruction::ReadMemoryCallback read_mem_callback, 9297349bd90SGreg Clayton EmulateInstruction::WriteMemoryCallback write_mem_callback, 9307349bd90SGreg Clayton EmulateInstruction::ReadRegisterCallback read_reg_callback, 9317349bd90SGreg Clayton EmulateInstruction::WriteRegisterCallback write_reg_callback) 9327c9dd3ceSCaroline Tice { 93334ede34aSEugene Zelenko std::unique_ptr<EmulateInstruction> insn_emulator_ap(EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr)); 93434ede34aSEugene Zelenko if (insn_emulator_ap) 9357c9dd3ceSCaroline Tice { 9367c9dd3ceSCaroline Tice insn_emulator_ap->SetBaton(baton); 9377c9dd3ceSCaroline Tice insn_emulator_ap->SetCallbacks(read_mem_callback, write_mem_callback, read_reg_callback, write_reg_callback); 93834ede34aSEugene Zelenko insn_emulator_ap->SetInstruction(GetOpcode(), GetAddress(), nullptr); 9392ed751bdSGreg Clayton return insn_emulator_ap->EvaluateInstruction(evaluate_options); 9407c9dd3ceSCaroline Tice } 9417c9dd3ceSCaroline Tice 9427c9dd3ceSCaroline Tice return false; 9437c9dd3ceSCaroline Tice } 9447c9dd3ceSCaroline Tice 945ba812f42SGreg Clayton uint32_t 946ba812f42SGreg Clayton Instruction::GetData (DataExtractor &data) 947ba812f42SGreg Clayton { 948cd4ae1abSSean Callanan return m_opcode.GetData(data); 949ba812f42SGreg Clayton } 950ba812f42SGreg Clayton 9511d273166SGreg Clayton InstructionList::InstructionList() : 95230fdc8d8SChris Lattner m_instructions() 95330fdc8d8SChris Lattner { 95430fdc8d8SChris Lattner } 95530fdc8d8SChris Lattner 95634ede34aSEugene Zelenko InstructionList::~InstructionList() = default; 95730fdc8d8SChris Lattner 95830fdc8d8SChris Lattner size_t 9591d273166SGreg Clayton InstructionList::GetSize() const 96030fdc8d8SChris Lattner { 96130fdc8d8SChris Lattner return m_instructions.size(); 96230fdc8d8SChris Lattner } 96330fdc8d8SChris Lattner 964357132ebSGreg Clayton uint32_t 965357132ebSGreg Clayton InstructionList::GetMaxOpcocdeByteSize () const 966357132ebSGreg Clayton { 967357132ebSGreg Clayton uint32_t max_inst_size = 0; 968357132ebSGreg Clayton collection::const_iterator pos, end; 969357132ebSGreg Clayton for (pos = m_instructions.begin(), end = m_instructions.end(); 970357132ebSGreg Clayton pos != end; 971357132ebSGreg Clayton ++pos) 972357132ebSGreg Clayton { 973357132ebSGreg Clayton uint32_t inst_size = (*pos)->GetOpcode().GetByteSize(); 974357132ebSGreg Clayton if (max_inst_size < inst_size) 975357132ebSGreg Clayton max_inst_size = inst_size; 976357132ebSGreg Clayton } 977357132ebSGreg Clayton return max_inst_size; 978357132ebSGreg Clayton } 979357132ebSGreg Clayton 9801d273166SGreg Clayton InstructionSP 981c7bece56SGreg Clayton InstructionList::GetInstructionAtIndex (size_t idx) const 98230fdc8d8SChris Lattner { 9831d273166SGreg Clayton InstructionSP inst_sp; 98430fdc8d8SChris Lattner if (idx < m_instructions.size()) 9851d273166SGreg Clayton inst_sp = m_instructions[idx]; 9861d273166SGreg Clayton return inst_sp; 98730fdc8d8SChris Lattner } 98830fdc8d8SChris Lattner 98930fdc8d8SChris Lattner void 9905009f9d5SGreg Clayton InstructionList::Dump (Stream *s, 9915009f9d5SGreg Clayton bool show_address, 9925009f9d5SGreg Clayton bool show_bytes, 9935009f9d5SGreg Clayton const ExecutionContext* exe_ctx) 9945009f9d5SGreg Clayton { 9955009f9d5SGreg Clayton const uint32_t max_opcode_byte_size = GetMaxOpcocdeByteSize(); 9965009f9d5SGreg Clayton collection::const_iterator pos, begin, end; 997554f68d3SGreg Clayton 99834ede34aSEugene Zelenko const FormatEntity::Entry *disassembly_format = nullptr; 999554f68d3SGreg Clayton FormatEntity::Entry format; 1000554f68d3SGreg Clayton if (exe_ctx && exe_ctx->HasTargetScope()) 1001aff1b357SJason Molenda { 1002554f68d3SGreg Clayton disassembly_format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat (); 1003aff1b357SJason Molenda } 1004554f68d3SGreg Clayton else 1005554f68d3SGreg Clayton { 1006554f68d3SGreg Clayton FormatEntity::Parse("${addr}: ", format); 1007554f68d3SGreg Clayton disassembly_format = &format; 1008554f68d3SGreg Clayton } 1009554f68d3SGreg Clayton 10105009f9d5SGreg Clayton for (begin = m_instructions.begin(), end = m_instructions.end(), pos = begin; 10115009f9d5SGreg Clayton pos != end; 10125009f9d5SGreg Clayton ++pos) 10135009f9d5SGreg Clayton { 10145009f9d5SGreg Clayton if (pos != begin) 10155009f9d5SGreg Clayton s->EOL(); 101634ede34aSEugene Zelenko (*pos)->Dump(s, max_opcode_byte_size, show_address, show_bytes, exe_ctx, nullptr, nullptr, disassembly_format, 0); 10175009f9d5SGreg Clayton } 10185009f9d5SGreg Clayton } 10195009f9d5SGreg Clayton 10205009f9d5SGreg Clayton void 10211d273166SGreg Clayton InstructionList::Clear() 102230fdc8d8SChris Lattner { 102330fdc8d8SChris Lattner m_instructions.clear(); 102430fdc8d8SChris Lattner } 102530fdc8d8SChris Lattner 102630fdc8d8SChris Lattner void 10271d273166SGreg Clayton InstructionList::Append (lldb::InstructionSP &inst_sp) 102830fdc8d8SChris Lattner { 102930fdc8d8SChris Lattner if (inst_sp) 103030fdc8d8SChris Lattner m_instructions.push_back(inst_sp); 103130fdc8d8SChris Lattner } 103230fdc8d8SChris Lattner 1033564d8bc2SJim Ingham uint32_t 1034e76e7e93STed Woodward InstructionList::GetIndexOfNextBranchInstruction(uint32_t start, Target &target) const 1035564d8bc2SJim Ingham { 1036564d8bc2SJim Ingham size_t num_instructions = m_instructions.size(); 1037564d8bc2SJim Ingham 1038190636bcSJim Ingham uint32_t next_branch = UINT32_MAX; 1039e76e7e93STed Woodward size_t i; 1040e76e7e93STed Woodward for (i = start; i < num_instructions; i++) 1041564d8bc2SJim Ingham { 1042564d8bc2SJim Ingham if (m_instructions[i]->DoesBranch()) 1043564d8bc2SJim Ingham { 1044564d8bc2SJim Ingham next_branch = i; 1045564d8bc2SJim Ingham break; 1046564d8bc2SJim Ingham } 1047564d8bc2SJim Ingham } 1048e76e7e93STed Woodward 1049e76e7e93STed Woodward // Hexagon needs the first instruction of the packet with the branch. 1050e76e7e93STed Woodward // Go backwards until we find an instruction marked end-of-packet, or 1051e76e7e93STed Woodward // until we hit start. 1052e76e7e93STed Woodward if (target.GetArchitecture().GetTriple().getArch() == llvm::Triple::hexagon) 1053e76e7e93STed Woodward { 1054e76e7e93STed Woodward // If we didn't find a branch, find the last packet start. 1055190636bcSJim Ingham if (next_branch == UINT32_MAX) 1056e76e7e93STed Woodward { 1057e76e7e93STed Woodward i = num_instructions - 1; 1058e76e7e93STed Woodward } 1059e76e7e93STed Woodward 1060e76e7e93STed Woodward while (i > start) 1061e76e7e93STed Woodward { 1062e76e7e93STed Woodward --i; 1063e76e7e93STed Woodward 1064e76e7e93STed Woodward Error error; 1065e76e7e93STed Woodward uint32_t inst_bytes; 1066e76e7e93STed Woodward bool prefer_file_cache = false; // Read from process if process is running 1067e76e7e93STed Woodward lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; 1068e76e7e93STed Woodward target.ReadMemory(m_instructions[i]->GetAddress(), 1069e76e7e93STed Woodward prefer_file_cache, 1070e76e7e93STed Woodward &inst_bytes, 1071e76e7e93STed Woodward sizeof(inst_bytes), 1072e76e7e93STed Woodward error, 1073e76e7e93STed Woodward &load_addr); 1074e76e7e93STed Woodward // If we have an error reading memory, return start 1075e76e7e93STed Woodward if (!error.Success()) 1076e76e7e93STed Woodward return start; 1077e76e7e93STed Woodward // check if this is the last instruction in a packet 1078e76e7e93STed Woodward // bits 15:14 will be 11b or 00b for a duplex 1079e76e7e93STed Woodward if (((inst_bytes & 0xC000) == 0xC000) || 1080e76e7e93STed Woodward ((inst_bytes & 0xC000) == 0x0000)) 1081e76e7e93STed Woodward { 1082e76e7e93STed Woodward // instruction after this should be the start of next packet 1083e76e7e93STed Woodward next_branch = i + 1; 1084e76e7e93STed Woodward break; 1085e76e7e93STed Woodward } 1086e76e7e93STed Woodward } 1087e76e7e93STed Woodward 1088190636bcSJim Ingham if (next_branch == UINT32_MAX) 1089e76e7e93STed Woodward { 1090e76e7e93STed Woodward // We couldn't find the previous packet, so return start 1091e76e7e93STed Woodward next_branch = start; 1092e76e7e93STed Woodward } 1093e76e7e93STed Woodward } 1094564d8bc2SJim Ingham return next_branch; 1095564d8bc2SJim Ingham } 1096564d8bc2SJim Ingham 1097564d8bc2SJim Ingham uint32_t 109844d93782SGreg Clayton InstructionList::GetIndexOfInstructionAtAddress (const Address &address) 1099564d8bc2SJim Ingham { 1100c7bece56SGreg Clayton size_t num_instructions = m_instructions.size(); 1101190636bcSJim Ingham uint32_t index = UINT32_MAX; 1102c7bece56SGreg Clayton for (size_t i = 0; i < num_instructions; i++) 1103564d8bc2SJim Ingham { 1104564d8bc2SJim Ingham if (m_instructions[i]->GetAddress() == address) 1105564d8bc2SJim Ingham { 1106564d8bc2SJim Ingham index = i; 1107564d8bc2SJim Ingham break; 1108564d8bc2SJim Ingham } 1109564d8bc2SJim Ingham } 1110564d8bc2SJim Ingham return index; 1111564d8bc2SJim Ingham } 111230fdc8d8SChris Lattner 111344d93782SGreg Clayton uint32_t 111444d93782SGreg Clayton InstructionList::GetIndexOfInstructionAtLoadAddress (lldb::addr_t load_addr, Target &target) 111544d93782SGreg Clayton { 111644d93782SGreg Clayton Address address; 111744d93782SGreg Clayton address.SetLoadAddress(load_addr, &target); 111844d93782SGreg Clayton return GetIndexOfInstructionAtAddress(address); 111944d93782SGreg Clayton } 112044d93782SGreg Clayton 112130fdc8d8SChris Lattner size_t 11223faf47c4SGreg Clayton Disassembler::ParseInstructions (const ExecutionContext *exe_ctx, 112357f0630cSGreg Clayton const AddressRange &range, 11243faf47c4SGreg Clayton Stream *error_strm_ptr, 11253faf47c4SGreg Clayton bool prefer_file_cache) 112630fdc8d8SChris Lattner { 1127c14ee32dSGreg Clayton if (exe_ctx) 1128c14ee32dSGreg Clayton { 1129c14ee32dSGreg Clayton Target *target = exe_ctx->GetTargetPtr(); 1130dda4f7b5SGreg Clayton const addr_t byte_size = range.GetByteSize(); 113134ede34aSEugene Zelenko if (target == nullptr || byte_size == 0 || !range.GetBaseAddress().IsValid()) 113230fdc8d8SChris Lattner return 0; 113330fdc8d8SChris Lattner 1134dda4f7b5SGreg Clayton DataBufferHeap *heap_buffer = new DataBufferHeap (byte_size, '\0'); 1135dda4f7b5SGreg Clayton DataBufferSP data_sp(heap_buffer); 113630fdc8d8SChris Lattner 113730fdc8d8SChris Lattner Error error; 11383faf47c4SGreg Clayton lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; 1139357132ebSGreg Clayton const size_t bytes_read = target->ReadMemory (range.GetBaseAddress(), 1140357132ebSGreg Clayton prefer_file_cache, 1141357132ebSGreg Clayton heap_buffer->GetBytes(), 1142357132ebSGreg Clayton heap_buffer->GetByteSize(), 11433faf47c4SGreg Clayton error, 11443faf47c4SGreg Clayton &load_addr); 1145dda4f7b5SGreg Clayton 1146dda4f7b5SGreg Clayton if (bytes_read > 0) 114730fdc8d8SChris Lattner { 1148dda4f7b5SGreg Clayton if (bytes_read != heap_buffer->GetByteSize()) 1149dda4f7b5SGreg Clayton heap_buffer->SetByteSize (bytes_read); 1150357132ebSGreg Clayton DataExtractor data (data_sp, 1151357132ebSGreg Clayton m_arch.GetByteOrder(), 1152357132ebSGreg Clayton m_arch.GetAddressByteSize()); 11533faf47c4SGreg Clayton const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS; 1154190636bcSJim Ingham return DecodeInstructions(range.GetBaseAddress(), data, 0, UINT32_MAX, false, 115534ede34aSEugene Zelenko data_from_file); 115630fdc8d8SChris Lattner } 115757f0630cSGreg Clayton else if (error_strm_ptr) 115857f0630cSGreg Clayton { 115957f0630cSGreg Clayton const char *error_cstr = error.AsCString(); 116057f0630cSGreg Clayton if (error_cstr) 116157f0630cSGreg Clayton { 116257f0630cSGreg Clayton error_strm_ptr->Printf("error: %s\n", error_cstr); 116357f0630cSGreg Clayton } 116457f0630cSGreg Clayton } 116557f0630cSGreg Clayton } 116657f0630cSGreg Clayton else if (error_strm_ptr) 116757f0630cSGreg Clayton { 116857f0630cSGreg Clayton error_strm_ptr->PutCString("error: invalid execution context\n"); 1169c14ee32dSGreg Clayton } 117030fdc8d8SChris Lattner return 0; 117130fdc8d8SChris Lattner } 117230fdc8d8SChris Lattner 117337023b06SJim Ingham size_t 11743faf47c4SGreg Clayton Disassembler::ParseInstructions (const ExecutionContext *exe_ctx, 117537023b06SJim Ingham const Address &start, 11763faf47c4SGreg Clayton uint32_t num_instructions, 11773faf47c4SGreg Clayton bool prefer_file_cache) 117837023b06SJim Ingham { 1179357132ebSGreg Clayton m_instruction_list.Clear(); 118037023b06SJim Ingham 118134ede34aSEugene Zelenko if (exe_ctx == nullptr || num_instructions == 0 || !start.IsValid()) 118237023b06SJim Ingham return 0; 118337023b06SJim Ingham 1184c14ee32dSGreg Clayton Target *target = exe_ctx->GetTargetPtr(); 1185357132ebSGreg Clayton // Calculate the max buffer size we will need in order to disassemble 1186357132ebSGreg Clayton const addr_t byte_size = num_instructions * m_arch.GetMaximumOpcodeByteSize(); 118737023b06SJim Ingham 118834ede34aSEugene Zelenko if (target == nullptr || byte_size == 0) 118937023b06SJim Ingham return 0; 119037023b06SJim Ingham 119137023b06SJim Ingham DataBufferHeap *heap_buffer = new DataBufferHeap (byte_size, '\0'); 119237023b06SJim Ingham DataBufferSP data_sp (heap_buffer); 119337023b06SJim Ingham 119437023b06SJim Ingham Error error; 11953faf47c4SGreg Clayton lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; 1196357132ebSGreg Clayton const size_t bytes_read = target->ReadMemory (start, 1197357132ebSGreg Clayton prefer_file_cache, 1198357132ebSGreg Clayton heap_buffer->GetBytes(), 1199357132ebSGreg Clayton byte_size, 12003faf47c4SGreg Clayton error, 12013faf47c4SGreg Clayton &load_addr); 12023faf47c4SGreg Clayton 12033faf47c4SGreg Clayton const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS; 120437023b06SJim Ingham 120537023b06SJim Ingham if (bytes_read == 0) 1206357132ebSGreg Clayton return 0; 1207357132ebSGreg Clayton DataExtractor data (data_sp, 1208357132ebSGreg Clayton m_arch.GetByteOrder(), 1209357132ebSGreg Clayton m_arch.GetAddressByteSize()); 121037023b06SJim Ingham 1211357132ebSGreg Clayton const bool append_instructions = true; 1212357132ebSGreg Clayton DecodeInstructions (start, 1213357132ebSGreg Clayton data, 1214357132ebSGreg Clayton 0, 1215357132ebSGreg Clayton num_instructions, 12163faf47c4SGreg Clayton append_instructions, 12173faf47c4SGreg Clayton data_from_file); 121837023b06SJim Ingham 121937023b06SJim Ingham return m_instruction_list.GetSize(); 122037023b06SJim Ingham } 122137023b06SJim Ingham 122230fdc8d8SChris Lattner //---------------------------------------------------------------------- 122330fdc8d8SChris Lattner // Disassembler copy constructor 122430fdc8d8SChris Lattner //---------------------------------------------------------------------- 12250f063ba6SJim Ingham Disassembler::Disassembler(const ArchSpec& arch, const char *flavor) : 122630fdc8d8SChris Lattner m_arch (arch), 122730fdc8d8SChris Lattner m_instruction_list(), 12280f063ba6SJim Ingham m_base_addr(LLDB_INVALID_ADDRESS), 12290f063ba6SJim Ingham m_flavor () 123030fdc8d8SChris Lattner { 123134ede34aSEugene Zelenko if (flavor == nullptr) 12320f063ba6SJim Ingham m_flavor.assign("default"); 12330f063ba6SJim Ingham else 12340f063ba6SJim Ingham m_flavor.assign(flavor); 123575452e8cSJason Molenda 123675452e8cSJason Molenda // If this is an arm variant that can only include thumb (T16, T32) 123775452e8cSJason Molenda // instructions, force the arch triple to be "thumbv.." instead of 123875452e8cSJason Molenda // "armv..." 12396d9fe8c1SJason Molenda if ((arch.GetTriple().getArch() == llvm::Triple::arm || arch.GetTriple().getArch() == llvm::Triple::thumb) 124075452e8cSJason Molenda && (arch.GetCore() == ArchSpec::Core::eCore_arm_armv7m 124175452e8cSJason Molenda || arch.GetCore() == ArchSpec::Core::eCore_arm_armv7em 124275452e8cSJason Molenda || arch.GetCore() == ArchSpec::Core::eCore_arm_armv6m)) 124375452e8cSJason Molenda { 124475452e8cSJason Molenda std::string thumb_arch_name (arch.GetTriple().getArchName().str()); 124575452e8cSJason Molenda // Replace "arm" with "thumb" so we get all thumb variants correct 124675452e8cSJason Molenda if (thumb_arch_name.size() > 3) 124775452e8cSJason Molenda { 124875452e8cSJason Molenda thumb_arch_name.erase(0, 3); 124975452e8cSJason Molenda thumb_arch_name.insert(0, "thumb"); 125075452e8cSJason Molenda } 125175452e8cSJason Molenda m_arch.SetTriple (thumb_arch_name.c_str()); 125275452e8cSJason Molenda } 125330fdc8d8SChris Lattner } 125430fdc8d8SChris Lattner 125534ede34aSEugene Zelenko Disassembler::~Disassembler() = default; 125630fdc8d8SChris Lattner 12571d273166SGreg Clayton InstructionList & 125830fdc8d8SChris Lattner Disassembler::GetInstructionList () 125930fdc8d8SChris Lattner { 126030fdc8d8SChris Lattner return m_instruction_list; 126130fdc8d8SChris Lattner } 126230fdc8d8SChris Lattner 12631d273166SGreg Clayton const InstructionList & 126430fdc8d8SChris Lattner Disassembler::GetInstructionList () const 126530fdc8d8SChris Lattner { 126630fdc8d8SChris Lattner return m_instruction_list; 126730fdc8d8SChris Lattner } 12683ac6711aSCaroline Tice 12693ac6711aSCaroline Tice //---------------------------------------------------------------------- 12703ac6711aSCaroline Tice // Class PseudoInstruction 12713ac6711aSCaroline Tice //---------------------------------------------------------------------- 127234ede34aSEugene Zelenko 12733ac6711aSCaroline Tice PseudoInstruction::PseudoInstruction () : 12743ac6711aSCaroline Tice Instruction (Address(), eAddressClassUnknown), 12753ac6711aSCaroline Tice m_description () 12763ac6711aSCaroline Tice { 12773ac6711aSCaroline Tice } 12783ac6711aSCaroline Tice 127934ede34aSEugene Zelenko PseudoInstruction::~PseudoInstruction() = default; 12803ac6711aSCaroline Tice 12813ac6711aSCaroline Tice bool 128232ce20c5SJim Ingham PseudoInstruction::DoesBranch () 12833ac6711aSCaroline Tice { 12843ac6711aSCaroline Tice // This is NOT a valid question for a pseudo instruction. 12853ac6711aSCaroline Tice return false; 12863ac6711aSCaroline Tice } 12873ac6711aSCaroline Tice 12887f3daedaSBhushan D. Attarde bool 12897f3daedaSBhushan D. Attarde PseudoInstruction::HasDelaySlot () 12907f3daedaSBhushan D. Attarde { 12917f3daedaSBhushan D. Attarde // This is NOT a valid question for a pseudo instruction. 12927f3daedaSBhushan D. Attarde return false; 12937f3daedaSBhushan D. Attarde } 12947f3daedaSBhushan D. Attarde 12953ac6711aSCaroline Tice size_t 12963ac6711aSCaroline Tice PseudoInstruction::Decode (const lldb_private::Disassembler &disassembler, 12973ac6711aSCaroline Tice const lldb_private::DataExtractor &data, 1298c7bece56SGreg Clayton lldb::offset_t data_offset) 12993ac6711aSCaroline Tice { 13003ac6711aSCaroline Tice return m_opcode.GetByteSize(); 13013ac6711aSCaroline Tice } 13023ac6711aSCaroline Tice 13033ac6711aSCaroline Tice void 13043ac6711aSCaroline Tice PseudoInstruction::SetOpcode (size_t opcode_size, void *opcode_data) 13053ac6711aSCaroline Tice { 13063ac6711aSCaroline Tice if (!opcode_data) 13073ac6711aSCaroline Tice return; 13083ac6711aSCaroline Tice 13093ac6711aSCaroline Tice switch (opcode_size) 13103ac6711aSCaroline Tice { 13113ac6711aSCaroline Tice case 8: 13123ac6711aSCaroline Tice { 13133ac6711aSCaroline Tice uint8_t value8 = *((uint8_t *) opcode_data); 131490359963SEd Maste m_opcode.SetOpcode8 (value8, eByteOrderInvalid); 13153ac6711aSCaroline Tice break; 13163ac6711aSCaroline Tice } 13173ac6711aSCaroline Tice case 16: 13183ac6711aSCaroline Tice { 13193ac6711aSCaroline Tice uint16_t value16 = *((uint16_t *) opcode_data); 132090359963SEd Maste m_opcode.SetOpcode16 (value16, eByteOrderInvalid); 13213ac6711aSCaroline Tice break; 13223ac6711aSCaroline Tice } 13233ac6711aSCaroline Tice case 32: 13243ac6711aSCaroline Tice { 13253ac6711aSCaroline Tice uint32_t value32 = *((uint32_t *) opcode_data); 132690359963SEd Maste m_opcode.SetOpcode32 (value32, eByteOrderInvalid); 13273ac6711aSCaroline Tice break; 13283ac6711aSCaroline Tice } 13293ac6711aSCaroline Tice case 64: 13303ac6711aSCaroline Tice { 13313ac6711aSCaroline Tice uint64_t value64 = *((uint64_t *) opcode_data); 133290359963SEd Maste m_opcode.SetOpcode64 (value64, eByteOrderInvalid); 13333ac6711aSCaroline Tice break; 13343ac6711aSCaroline Tice } 13353ac6711aSCaroline Tice default: 13363ac6711aSCaroline Tice break; 13373ac6711aSCaroline Tice } 13383ac6711aSCaroline Tice } 13393ac6711aSCaroline Tice 13403ac6711aSCaroline Tice void 13413ac6711aSCaroline Tice PseudoInstruction::SetDescription (const char *description) 13423ac6711aSCaroline Tice { 13433ac6711aSCaroline Tice if (description && strlen (description) > 0) 13443ac6711aSCaroline Tice m_description = description; 13453ac6711aSCaroline Tice } 1346