180814287SRaphael Isemann //===-- CommandObjectDisassemble.cpp --------------------------------------===// 230fdc8d8SChris Lattner // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 630fdc8d8SChris Lattner // 730fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 830fdc8d8SChris Lattner 926cac3afSEugene Zelenko #include "CommandObjectDisassemble.h" 1030fdc8d8SChris Lattner #include "lldb/Core/AddressRange.h" 111f746071SGreg Clayton #include "lldb/Core/Disassembler.h" 12801237a2SJason Molenda #include "lldb/Core/Module.h" 133eb2b44dSZachary Turner #include "lldb/Host/OptionParser.h" 1430fdc8d8SChris Lattner #include "lldb/Interpreter/CommandInterpreter.h" 1530fdc8d8SChris Lattner #include "lldb/Interpreter/CommandReturnObject.h" 1647cbf4a0SPavel Labath #include "lldb/Interpreter/OptionArgParser.h" 1740af72e1SJim Ingham #include "lldb/Interpreter/Options.h" 181f746071SGreg Clayton #include "lldb/Symbol/Function.h" 1930fdc8d8SChris Lattner #include "lldb/Symbol/Symbol.h" 20d5944cd1SGreg Clayton #include "lldb/Target/SectionLoadList.h" 21b57e4a1bSJason Molenda #include "lldb/Target/StackFrame.h" 2230fdc8d8SChris Lattner #include "lldb/Target/Target.h" 2330fdc8d8SChris Lattner 248b845ac5SPavel Labath static constexpr unsigned default_disasm_byte_size = 32; 258b845ac5SPavel Labath static constexpr unsigned default_disasm_num_ins = 4; 2630fdc8d8SChris Lattner 2730fdc8d8SChris Lattner using namespace lldb; 2830fdc8d8SChris Lattner using namespace lldb_private; 2930fdc8d8SChris Lattner 30f1883637SRaphael Isemann #define LLDB_OPTIONS_disassemble 31f1883637SRaphael Isemann #include "CommandOptions.inc" 321f0f5b5bSZachary Turner 33abb0ed44SKazu Hirata CommandObjectDisassemble::CommandOptions::CommandOptions() { 34e1cfbc79STodd Fiala OptionParsingStarting(nullptr); 3530fdc8d8SChris Lattner } 3630fdc8d8SChris Lattner 3726cac3afSEugene Zelenko CommandObjectDisassemble::CommandOptions::~CommandOptions() = default; 3830fdc8d8SChris Lattner 3997206d57SZachary Turner Status CommandObjectDisassemble::CommandOptions::SetOptionValue( 40fe11483bSZachary Turner uint32_t option_idx, llvm::StringRef option_arg, 41b9c1b51eSKate Stone ExecutionContext *execution_context) { 4297206d57SZachary Turner Status error; 4330fdc8d8SChris Lattner 443bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 4530fdc8d8SChris Lattner 46b9c1b51eSKate Stone switch (short_option) { 4730fdc8d8SChris Lattner case 'm': 4830fdc8d8SChris Lattner show_mixed = true; 4930fdc8d8SChris Lattner break; 5030fdc8d8SChris Lattner 51357132ebSGreg Clayton case 'C': 52fe11483bSZachary Turner if (option_arg.getAsInteger(0, num_lines_context)) 53b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid num context lines string: \"%s\"", 54fe11483bSZachary Turner option_arg.str().c_str()); 5537023b06SJim Ingham break; 5637023b06SJim Ingham 5730fdc8d8SChris Lattner case 'c': 58fe11483bSZachary Turner if (option_arg.getAsInteger(0, num_instructions)) 59b9c1b51eSKate Stone error.SetErrorStringWithFormat( 60fe11483bSZachary Turner "invalid num of instructions string: \"%s\"", 61fe11483bSZachary Turner option_arg.str().c_str()); 6230fdc8d8SChris Lattner break; 6330fdc8d8SChris Lattner 6430fdc8d8SChris Lattner case 'b': 6530fdc8d8SChris Lattner show_bytes = true; 6630fdc8d8SChris Lattner break; 6730fdc8d8SChris Lattner 68b9c1b51eSKate Stone case 's': { 6947cbf4a0SPavel Labath start_addr = OptionArgParser::ToAddress(execution_context, option_arg, 70e1cfbc79STodd Fiala LLDB_INVALID_ADDRESS, &error); 71b9d5df58SGreg Clayton if (start_addr != LLDB_INVALID_ADDRESS) 723555b5d7SJim Ingham some_location_specified = true; 73b9c1b51eSKate Stone } break; 74b9c1b51eSKate Stone case 'e': { 7547cbf4a0SPavel Labath end_addr = OptionArgParser::ToAddress(execution_context, option_arg, 76e1cfbc79STodd Fiala LLDB_INVALID_ADDRESS, &error); 77b9d5df58SGreg Clayton if (end_addr != LLDB_INVALID_ADDRESS) 783555b5d7SJim Ingham some_location_specified = true; 79b9c1b51eSKate Stone } break; 8026cac3afSEugene Zelenko 8130fdc8d8SChris Lattner case 'n': 82adcd0268SBenjamin Kramer func_name.assign(std::string(option_arg)); 833555b5d7SJim Ingham some_location_specified = true; 8430fdc8d8SChris Lattner break; 8530fdc8d8SChris Lattner 8637023b06SJim Ingham case 'p': 8732e0a750SGreg Clayton at_pc = true; 883555b5d7SJim Ingham some_location_specified = true; 8932e0a750SGreg Clayton break; 9032e0a750SGreg Clayton 9132e0a750SGreg Clayton case 'l': 9232e0a750SGreg Clayton frame_line = true; 9305097246SAdrian Prantl // Disassemble the current source line kind of implies showing mixed source 9405097246SAdrian Prantl // code context. 9532e0a750SGreg Clayton show_mixed = true; 963555b5d7SJim Ingham some_location_specified = true; 9737023b06SJim Ingham break; 9837023b06SJim Ingham 991080edbcSGreg Clayton case 'P': 100adcd0268SBenjamin Kramer plugin_name.assign(std::string(option_arg)); 1011080edbcSGreg Clayton break; 1021080edbcSGreg Clayton 103b9c1b51eSKate Stone case 'F': { 104b9c1b51eSKate Stone TargetSP target_sp = 105b9c1b51eSKate Stone execution_context ? execution_context->GetTargetSP() : TargetSP(); 106b9c1b51eSKate Stone if (target_sp && (target_sp->GetArchitecture().GetTriple().getArch() == 107b9c1b51eSKate Stone llvm::Triple::x86 || 108b9c1b51eSKate Stone target_sp->GetArchitecture().GetTriple().getArch() == 109b9c1b51eSKate Stone llvm::Triple::x86_64)) { 110adcd0268SBenjamin Kramer flavor_string.assign(std::string(option_arg)); 111b9c1b51eSKate Stone } else 112b9c1b51eSKate Stone error.SetErrorStringWithFormat("Disassembler flavors are currently only " 113b9c1b51eSKate Stone "supported for x86 and x86_64 targets."); 1140f063ba6SJim Ingham break; 1150f063ba6SJim Ingham } 11626cac3afSEugene Zelenko 11730fdc8d8SChris Lattner case 'r': 11830fdc8d8SChris Lattner raw = true; 11930fdc8d8SChris Lattner break; 12030fdc8d8SChris Lattner 1218ceb8ba2SJohnny Chen case 'f': 1221fb2e7dfSGreg Clayton current_function = true; 1233555b5d7SJim Ingham some_location_specified = true; 1248ceb8ba2SJohnny Chen break; 1258ceb8ba2SJohnny Chen 126801237a2SJason Molenda case 'A': 127b9c1b51eSKate Stone if (execution_context) { 128be73fd6bSTatyana Krasnukha const auto &target_sp = execution_context->GetTargetSP(); 129be73fd6bSTatyana Krasnukha auto platform_ptr = target_sp ? target_sp->GetPlatform().get() : nullptr; 130be73fd6bSTatyana Krasnukha arch = Platform::GetAugmentedArchSpec(platform_ptr, option_arg); 131e1cfbc79STodd Fiala } 132357132ebSGreg Clayton break; 133357132ebSGreg Clayton 134b9c1b51eSKate Stone case 'a': { 13547cbf4a0SPavel Labath symbol_containing_addr = OptionArgParser::ToAddress( 136b9c1b51eSKate Stone execution_context, option_arg, LLDB_INVALID_ADDRESS, &error); 137b9c1b51eSKate Stone if (symbol_containing_addr != LLDB_INVALID_ADDRESS) { 138801237a2SJason Molenda some_location_specified = true; 139801237a2SJason Molenda } 140b9c1b51eSKate Stone } break; 141801237a2SJason Molenda 1428b845ac5SPavel Labath case '\x01': 1438b845ac5SPavel Labath force = true; 1448b845ac5SPavel Labath break; 1458b845ac5SPavel Labath 14630fdc8d8SChris Lattner default: 14736162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 14830fdc8d8SChris Lattner } 14930fdc8d8SChris Lattner 15030fdc8d8SChris Lattner return error; 15130fdc8d8SChris Lattner } 15230fdc8d8SChris Lattner 153b9c1b51eSKate Stone void CommandObjectDisassemble::CommandOptions::OptionParsingStarting( 154b9c1b51eSKate Stone ExecutionContext *execution_context) { 15530fdc8d8SChris Lattner show_mixed = false; 15630fdc8d8SChris Lattner show_bytes = false; 15730fdc8d8SChris Lattner num_lines_context = 0; 15837023b06SJim Ingham num_instructions = 0; 15932e0a750SGreg Clayton func_name.clear(); 1601fb2e7dfSGreg Clayton current_function = false; 16132e0a750SGreg Clayton at_pc = false; 16232e0a750SGreg Clayton frame_line = false; 16332e0a750SGreg Clayton start_addr = LLDB_INVALID_ADDRESS; 16432e0a750SGreg Clayton end_addr = LLDB_INVALID_ADDRESS; 165801237a2SJason Molenda symbol_containing_addr = LLDB_INVALID_ADDRESS; 166a68c1a21SSean Callanan raw = false; 16732e0a750SGreg Clayton plugin_name.clear(); 1680f063ba6SJim Ingham 169e1cfbc79STodd Fiala Target *target = 170e1cfbc79STodd Fiala execution_context ? execution_context->GetTargetPtr() : nullptr; 1710f063ba6SJim Ingham 172b9c1b51eSKate Stone // This is a hack till we get the ability to specify features based on 17305097246SAdrian Prantl // architecture. For now GetDisassemblyFlavor is really only valid for x86 17405097246SAdrian Prantl // (and for the llvm assembler plugin, but I'm papering over that since that 17505097246SAdrian Prantl // is the only disassembler plugin we have... 176b9c1b51eSKate Stone if (target) { 177b9c1b51eSKate Stone if (target->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86 || 178b9c1b51eSKate Stone target->GetArchitecture().GetTriple().getArch() == 179b9c1b51eSKate Stone llvm::Triple::x86_64) { 1800f063ba6SJim Ingham flavor_string.assign(target->GetDisassemblyFlavor()); 181b9c1b51eSKate Stone } else 1820f063ba6SJim Ingham flavor_string.assign("default"); 1830f063ba6SJim Ingham 184b9c1b51eSKate Stone } else 1850f063ba6SJim Ingham flavor_string.assign("default"); 1860f063ba6SJim Ingham 18732e0a750SGreg Clayton arch.Clear(); 1883555b5d7SJim Ingham some_location_specified = false; 1898b845ac5SPavel Labath force = false; 1903555b5d7SJim Ingham } 1913555b5d7SJim Ingham 19297206d57SZachary Turner Status CommandObjectDisassemble::CommandOptions::OptionParsingFinished( 193b9c1b51eSKate Stone ExecutionContext *execution_context) { 1943555b5d7SJim Ingham if (!some_location_specified) 1951fb2e7dfSGreg Clayton current_function = true; 19697206d57SZachary Turner return Status(); 19730fdc8d8SChris Lattner } 19830fdc8d8SChris Lattner 1991f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> 200b9c1b51eSKate Stone CommandObjectDisassemble::CommandOptions::GetDefinitions() { 20170602439SZachary Turner return llvm::makeArrayRef(g_disassemble_options); 20230fdc8d8SChris Lattner } 20330fdc8d8SChris Lattner 20430fdc8d8SChris Lattner // CommandObjectDisassemble 20530fdc8d8SChris Lattner 206b9c1b51eSKate Stone CommandObjectDisassemble::CommandObjectDisassemble( 207b9c1b51eSKate Stone CommandInterpreter &interpreter) 208b9c1b51eSKate Stone : CommandObjectParsed( 209b9c1b51eSKate Stone interpreter, "disassemble", 210b9c1b51eSKate Stone "Disassemble specified instructions in the current target. " 2117428a18cSKate Stone "Defaults to the current function for the current thread and " 2127428a18cSKate Stone "stack frame.", 21304a4c091SRaphael Isemann "disassemble [<cmd-options>]", eCommandRequiresTarget), 214b9c1b51eSKate Stone m_options() {} 21530fdc8d8SChris Lattner 21626cac3afSEugene Zelenko CommandObjectDisassemble::~CommandObjectDisassemble() = default; 21730fdc8d8SChris Lattner 2188b845ac5SPavel Labath llvm::Error CommandObjectDisassemble::CheckRangeSize(const AddressRange &range, 2198b845ac5SPavel Labath llvm::StringRef what) { 2208b845ac5SPavel Labath if (m_options.num_instructions > 0 || m_options.force || 221b889ef42SMed Ismail Bennani range.GetByteSize() < GetDebugger().GetStopDisassemblyMaxSize()) 2228b845ac5SPavel Labath return llvm::Error::success(); 2238b845ac5SPavel Labath StreamString msg; 2248b845ac5SPavel Labath msg << "Not disassembling " << what << " because it is very large "; 2258b845ac5SPavel Labath range.Dump(&msg, &GetSelectedTarget(), Address::DumpStyleLoadAddress, 2268b845ac5SPavel Labath Address::DumpStyleFileAddress); 2278b845ac5SPavel Labath msg << ". To disassemble specify an instruction count limit, start/stop " 2288b845ac5SPavel Labath "addresses or use the --force option."; 2298b845ac5SPavel Labath return llvm::createStringError(llvm::inconvertibleErrorCode(), 2308b845ac5SPavel Labath msg.GetString()); 2318b845ac5SPavel Labath } 2328b845ac5SPavel Labath 2331ca1e08eSPavel Labath llvm::Expected<std::vector<AddressRange>> 2341ca1e08eSPavel Labath CommandObjectDisassemble::GetContainingAddressRanges() { 2351ca1e08eSPavel Labath std::vector<AddressRange> ranges; 2361ca1e08eSPavel Labath const auto &get_range = [&](Address addr) { 2371ca1e08eSPavel Labath ModuleSP module_sp(addr.GetModule()); 2381ca1e08eSPavel Labath SymbolContext sc; 2391ca1e08eSPavel Labath bool resolve_tail_call_address = true; 2401ca1e08eSPavel Labath addr.GetModule()->ResolveSymbolContextForAddress( 2411ca1e08eSPavel Labath addr, eSymbolContextEverything, sc, resolve_tail_call_address); 2421ca1e08eSPavel Labath if (sc.function || sc.symbol) { 2431ca1e08eSPavel Labath AddressRange range; 2441ca1e08eSPavel Labath sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0, 2451ca1e08eSPavel Labath false, range); 2461ca1e08eSPavel Labath ranges.push_back(range); 2471ca1e08eSPavel Labath } 2481ca1e08eSPavel Labath }; 2491ca1e08eSPavel Labath 2501ca1e08eSPavel Labath Target &target = GetSelectedTarget(); 2511ca1e08eSPavel Labath if (!target.GetSectionLoadList().IsEmpty()) { 2521ca1e08eSPavel Labath Address symbol_containing_address; 2531ca1e08eSPavel Labath if (target.GetSectionLoadList().ResolveLoadAddress( 2541ca1e08eSPavel Labath m_options.symbol_containing_addr, symbol_containing_address)) { 2551ca1e08eSPavel Labath get_range(symbol_containing_address); 2561ca1e08eSPavel Labath } 2571ca1e08eSPavel Labath } else { 2581ca1e08eSPavel Labath for (lldb::ModuleSP module_sp : target.GetImages().Modules()) { 2591ca1e08eSPavel Labath Address file_address; 2601ca1e08eSPavel Labath if (module_sp->ResolveFileAddress(m_options.symbol_containing_addr, 2611ca1e08eSPavel Labath file_address)) { 2621ca1e08eSPavel Labath get_range(file_address); 2631ca1e08eSPavel Labath } 2641ca1e08eSPavel Labath } 2651ca1e08eSPavel Labath } 2661ca1e08eSPavel Labath 2671ca1e08eSPavel Labath if (ranges.empty()) { 2681ca1e08eSPavel Labath return llvm::createStringError( 2691ca1e08eSPavel Labath llvm::inconvertibleErrorCode(), 2701ca1e08eSPavel Labath "Could not find function bounds for address 0x%" PRIx64, 2711ca1e08eSPavel Labath m_options.symbol_containing_addr); 2721ca1e08eSPavel Labath } 2738b845ac5SPavel Labath 2748b845ac5SPavel Labath if (llvm::Error err = CheckRangeSize(ranges[0], "the function")) 2758b845ac5SPavel Labath return std::move(err); 2761ca1e08eSPavel Labath return ranges; 2771ca1e08eSPavel Labath } 2781ca1e08eSPavel Labath 2791ca1e08eSPavel Labath llvm::Expected<std::vector<AddressRange>> 2801ca1e08eSPavel Labath CommandObjectDisassemble::GetCurrentFunctionRanges() { 281*daba8236SJason Molenda Process *process = m_exe_ctx.GetProcessPtr(); 2821ca1e08eSPavel Labath StackFrame *frame = m_exe_ctx.GetFramePtr(); 2831ca1e08eSPavel Labath if (!frame) { 284*daba8236SJason Molenda if (process) { 285*daba8236SJason Molenda return llvm::createStringError( 286*daba8236SJason Molenda llvm::inconvertibleErrorCode(), 287*daba8236SJason Molenda "Cannot disassemble around the current " 288*daba8236SJason Molenda "function without the process being stopped.\n"); 289*daba8236SJason Molenda } else { 2901ca1e08eSPavel Labath return llvm::createStringError(llvm::inconvertibleErrorCode(), 2911ca1e08eSPavel Labath "Cannot disassemble around the current " 292*daba8236SJason Molenda "function without a selected frame: " 293*daba8236SJason Molenda "no currently running process.\n"); 294*daba8236SJason Molenda } 2951ca1e08eSPavel Labath } 2961ca1e08eSPavel Labath SymbolContext sc( 2971ca1e08eSPavel Labath frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol)); 2981ca1e08eSPavel Labath AddressRange range; 2991ca1e08eSPavel Labath if (sc.function) 3001ca1e08eSPavel Labath range = sc.function->GetAddressRange(); 3011ca1e08eSPavel Labath else if (sc.symbol && sc.symbol->ValueIsAddress()) { 3021ca1e08eSPavel Labath range = {sc.symbol->GetAddress(), sc.symbol->GetByteSize()}; 3031ca1e08eSPavel Labath } else 3048b845ac5SPavel Labath range = {frame->GetFrameCodeAddress(), default_disasm_byte_size}; 3051ca1e08eSPavel Labath 3068b845ac5SPavel Labath if (llvm::Error err = CheckRangeSize(range, "the current function")) 3078b845ac5SPavel Labath return std::move(err); 3081ca1e08eSPavel Labath return std::vector<AddressRange>{range}; 3091ca1e08eSPavel Labath } 3101ca1e08eSPavel Labath 3111ca1e08eSPavel Labath llvm::Expected<std::vector<AddressRange>> 3121ca1e08eSPavel Labath CommandObjectDisassemble::GetCurrentLineRanges() { 313*daba8236SJason Molenda Process *process = m_exe_ctx.GetProcessPtr(); 3141ca1e08eSPavel Labath StackFrame *frame = m_exe_ctx.GetFramePtr(); 3151ca1e08eSPavel Labath if (!frame) { 316*daba8236SJason Molenda if (process) { 317*daba8236SJason Molenda return llvm::createStringError( 318*daba8236SJason Molenda llvm::inconvertibleErrorCode(), 319*daba8236SJason Molenda "Cannot disassemble around the current " 320*daba8236SJason Molenda "function without the process being stopped.\n"); 321*daba8236SJason Molenda } else { 3221ca1e08eSPavel Labath return llvm::createStringError(llvm::inconvertibleErrorCode(), 3231ca1e08eSPavel Labath "Cannot disassemble around the current " 324*daba8236SJason Molenda "line without a selected frame: " 325*daba8236SJason Molenda "no currently running process.\n"); 326*daba8236SJason Molenda } 3271ca1e08eSPavel Labath } 3281ca1e08eSPavel Labath 3291ca1e08eSPavel Labath LineEntry pc_line_entry( 3301ca1e08eSPavel Labath frame->GetSymbolContext(eSymbolContextLineEntry).line_entry); 3311ca1e08eSPavel Labath if (pc_line_entry.IsValid()) 3321ca1e08eSPavel Labath return std::vector<AddressRange>{pc_line_entry.range}; 3331ca1e08eSPavel Labath 3341ca1e08eSPavel Labath // No line entry, so just disassemble around the current pc 3351ca1e08eSPavel Labath m_options.show_mixed = false; 3361ca1e08eSPavel Labath return GetPCRanges(); 3371ca1e08eSPavel Labath } 3381ca1e08eSPavel Labath 3391ca1e08eSPavel Labath llvm::Expected<std::vector<AddressRange>> 3408b845ac5SPavel Labath CommandObjectDisassemble::GetNameRanges(CommandReturnObject &result) { 3411ca1e08eSPavel Labath ConstString name(m_options.func_name.c_str()); 342c020be17SJonas Devlieghere 343c020be17SJonas Devlieghere ModuleFunctionSearchOptions function_options; 344c020be17SJonas Devlieghere function_options.include_symbols = true; 345c020be17SJonas Devlieghere function_options.include_inlines = true; 3461ca1e08eSPavel Labath 3471ca1e08eSPavel Labath // Find functions matching the given name. 3481ca1e08eSPavel Labath SymbolContextList sc_list; 349c020be17SJonas Devlieghere GetSelectedTarget().GetImages().FindFunctions(name, eFunctionNameTypeAuto, 350c020be17SJonas Devlieghere function_options, sc_list); 3511ca1e08eSPavel Labath 3521ca1e08eSPavel Labath std::vector<AddressRange> ranges; 3538b845ac5SPavel Labath llvm::Error range_errs = llvm::Error::success(); 3541ca1e08eSPavel Labath AddressRange range; 3551ca1e08eSPavel Labath const uint32_t scope = 3561ca1e08eSPavel Labath eSymbolContextBlock | eSymbolContextFunction | eSymbolContextSymbol; 3571ca1e08eSPavel Labath const bool use_inline_block_range = true; 3581ca1e08eSPavel Labath for (SymbolContext sc : sc_list.SymbolContexts()) { 3591ca1e08eSPavel Labath for (uint32_t range_idx = 0; 3601ca1e08eSPavel Labath sc.GetAddressRange(scope, range_idx, use_inline_block_range, range); 3611ca1e08eSPavel Labath ++range_idx) { 3628b845ac5SPavel Labath if (llvm::Error err = CheckRangeSize(range, "a range")) 3638b845ac5SPavel Labath range_errs = joinErrors(std::move(range_errs), std::move(err)); 3648b845ac5SPavel Labath else 3651ca1e08eSPavel Labath ranges.push_back(range); 3661ca1e08eSPavel Labath } 3671ca1e08eSPavel Labath } 3681ca1e08eSPavel Labath if (ranges.empty()) { 3698b845ac5SPavel Labath if (range_errs) 3708b845ac5SPavel Labath return std::move(range_errs); 3711ca1e08eSPavel Labath return llvm::createStringError(llvm::inconvertibleErrorCode(), 3721ca1e08eSPavel Labath "Unable to find symbol with name '%s'.\n", 3731ca1e08eSPavel Labath name.GetCString()); 3741ca1e08eSPavel Labath } 3758b845ac5SPavel Labath if (range_errs) 3768b845ac5SPavel Labath result.AppendWarning(toString(std::move(range_errs))); 3771ca1e08eSPavel Labath return ranges; 3781ca1e08eSPavel Labath } 3791ca1e08eSPavel Labath 3801ca1e08eSPavel Labath llvm::Expected<std::vector<AddressRange>> 3811ca1e08eSPavel Labath CommandObjectDisassemble::GetPCRanges() { 382*daba8236SJason Molenda Process *process = m_exe_ctx.GetProcessPtr(); 3831ca1e08eSPavel Labath StackFrame *frame = m_exe_ctx.GetFramePtr(); 3841ca1e08eSPavel Labath if (!frame) { 385*daba8236SJason Molenda if (process) { 386*daba8236SJason Molenda return llvm::createStringError( 387*daba8236SJason Molenda llvm::inconvertibleErrorCode(), 388*daba8236SJason Molenda "Cannot disassemble around the current " 389*daba8236SJason Molenda "function without the process being stopped.\n"); 390*daba8236SJason Molenda } else { 3911ca1e08eSPavel Labath return llvm::createStringError(llvm::inconvertibleErrorCode(), 3921ca1e08eSPavel Labath "Cannot disassemble around the current " 393*daba8236SJason Molenda "PC without a selected frame: " 394*daba8236SJason Molenda "no currently running process.\n"); 395*daba8236SJason Molenda } 3961ca1e08eSPavel Labath } 3971ca1e08eSPavel Labath 3981ca1e08eSPavel Labath if (m_options.num_instructions == 0) { 3991ca1e08eSPavel Labath // Disassembling at the PC always disassembles some number of 4001ca1e08eSPavel Labath // instructions (not the whole function). 4018b845ac5SPavel Labath m_options.num_instructions = default_disasm_num_ins; 4021ca1e08eSPavel Labath } 4031ca1e08eSPavel Labath return std::vector<AddressRange>{{frame->GetFrameCodeAddress(), 0}}; 4041ca1e08eSPavel Labath } 4051ca1e08eSPavel Labath 4061ca1e08eSPavel Labath llvm::Expected<std::vector<AddressRange>> 4071ca1e08eSPavel Labath CommandObjectDisassemble::GetStartEndAddressRanges() { 4081ca1e08eSPavel Labath addr_t size = 0; 4091ca1e08eSPavel Labath if (m_options.end_addr != LLDB_INVALID_ADDRESS) { 4101ca1e08eSPavel Labath if (m_options.end_addr <= m_options.start_addr) { 4111ca1e08eSPavel Labath return llvm::createStringError(llvm::inconvertibleErrorCode(), 4121ca1e08eSPavel Labath "End address before start address."); 4131ca1e08eSPavel Labath } 4141ca1e08eSPavel Labath size = m_options.end_addr - m_options.start_addr; 4151ca1e08eSPavel Labath } 4161ca1e08eSPavel Labath return std::vector<AddressRange>{{Address(m_options.start_addr), size}}; 4171ca1e08eSPavel Labath } 4181ca1e08eSPavel Labath 4191ca1e08eSPavel Labath llvm::Expected<std::vector<AddressRange>> 4208b845ac5SPavel Labath CommandObjectDisassemble::GetRangesForSelectedMode( 4218b845ac5SPavel Labath CommandReturnObject &result) { 4221ca1e08eSPavel Labath if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS) 4231ca1e08eSPavel Labath return CommandObjectDisassemble::GetContainingAddressRanges(); 4241ca1e08eSPavel Labath if (m_options.current_function) 4251ca1e08eSPavel Labath return CommandObjectDisassemble::GetCurrentFunctionRanges(); 4261ca1e08eSPavel Labath if (m_options.frame_line) 4271ca1e08eSPavel Labath return CommandObjectDisassemble::GetCurrentLineRanges(); 4281ca1e08eSPavel Labath if (!m_options.func_name.empty()) 4298b845ac5SPavel Labath return CommandObjectDisassemble::GetNameRanges(result); 4301ca1e08eSPavel Labath if (m_options.start_addr != LLDB_INVALID_ADDRESS) 4311ca1e08eSPavel Labath return CommandObjectDisassemble::GetStartEndAddressRanges(); 4321ca1e08eSPavel Labath return CommandObjectDisassemble::GetPCRanges(); 4331ca1e08eSPavel Labath } 4341ca1e08eSPavel Labath 435b9c1b51eSKate Stone bool CommandObjectDisassemble::DoExecute(Args &command, 436b9c1b51eSKate Stone CommandReturnObject &result) { 43704a4c091SRaphael Isemann Target *target = &GetSelectedTarget(); 43804a4c091SRaphael Isemann 43932e0a750SGreg Clayton if (!m_options.arch.IsValid()) 44032e0a750SGreg Clayton m_options.arch = target->GetArchitecture(); 44130fdc8d8SChris Lattner 442b9c1b51eSKate Stone if (!m_options.arch.IsValid()) { 443b9c1b51eSKate Stone result.AppendError( 444b9c1b51eSKate Stone "use the --arch option or set the target architecture to disassemble"); 44530fdc8d8SChris Lattner return false; 44630fdc8d8SChris Lattner } 44730fdc8d8SChris Lattner 4481080edbcSGreg Clayton const char *plugin_name = m_options.GetPluginName(); 4490f063ba6SJim Ingham const char *flavor_string = m_options.GetFlavorString(); 4500f063ba6SJim Ingham 451b9c1b51eSKate Stone DisassemblerSP disassembler = 452b9c1b51eSKate Stone Disassembler::FindPlugin(m_options.arch, flavor_string, plugin_name); 45330fdc8d8SChris Lattner 454b9c1b51eSKate Stone if (!disassembler) { 455b9c1b51eSKate Stone if (plugin_name) { 456b9c1b51eSKate Stone result.AppendErrorWithFormat( 457b9c1b51eSKate Stone "Unable to find Disassembler plug-in named '%s' that supports the " 458b9c1b51eSKate Stone "'%s' architecture.\n", 459b9c1b51eSKate Stone plugin_name, m_options.arch.GetArchitectureName()); 460b9c1b51eSKate Stone } else 461b9c1b51eSKate Stone result.AppendErrorWithFormat( 462b9c1b51eSKate Stone "Unable to find Disassembler plug-in for the '%s' architecture.\n", 46332e0a750SGreg Clayton m_options.arch.GetArchitectureName()); 46430fdc8d8SChris Lattner return false; 465a925974bSAdrian Prantl } else if (flavor_string != nullptr && !disassembler->FlavorValidForArchSpec( 466a925974bSAdrian Prantl m_options.arch, flavor_string)) 467b9c1b51eSKate Stone result.AppendWarningWithFormat( 468b9c1b51eSKate Stone "invalid disassembler flavor \"%s\", using default.\n", flavor_string); 46930fdc8d8SChris Lattner 47030fdc8d8SChris Lattner result.SetStatus(eReturnStatusSuccessFinishResult); 47130fdc8d8SChris Lattner 47211eb9c64SZachary Turner if (!command.empty()) { 473b9c1b51eSKate Stone result.AppendErrorWithFormat( 474b9c1b51eSKate Stone "\"disassemble\" arguments are specified as options.\n"); 475e1cfbc79STodd Fiala const int terminal_width = 476e1cfbc79STodd Fiala GetCommandInterpreter().GetDebugger().GetTerminalWidth(); 477e1cfbc79STodd Fiala GetOptions()->GenerateOptionUsage(result.GetErrorStream(), this, 478e1cfbc79STodd Fiala terminal_width); 4798651121cSJim Ingham return false; 4808651121cSJim Ingham } 4818651121cSJim Ingham 482dda4f7b5SGreg Clayton if (m_options.show_mixed && m_options.num_lines_context == 0) 4830b4c26b2SJason Molenda m_options.num_lines_context = 2; 484dda4f7b5SGreg Clayton 485b10d72f0SGreg Clayton // Always show the PC in the disassembly 486b10d72f0SGreg Clayton uint32_t options = Disassembler::eOptionMarkPCAddress; 4871da6f9d7SGreg Clayton 488b9c1b51eSKate Stone // Mark the source line for the current PC only if we are doing mixed source 489b9c1b51eSKate Stone // and assembly 490b10d72f0SGreg Clayton if (m_options.show_mixed) 491b10d72f0SGreg Clayton options |= Disassembler::eOptionMarkPCSourceLine; 4921da6f9d7SGreg Clayton 4931da6f9d7SGreg Clayton if (m_options.show_bytes) 4941da6f9d7SGreg Clayton options |= Disassembler::eOptionShowBytes; 4951da6f9d7SGreg Clayton 4961da6f9d7SGreg Clayton if (m_options.raw) 4971da6f9d7SGreg Clayton options |= Disassembler::eOptionRawOuput; 49837023b06SJim Ingham 4998b845ac5SPavel Labath llvm::Expected<std::vector<AddressRange>> ranges = 5008b845ac5SPavel Labath GetRangesForSelectedMode(result); 5011ca1e08eSPavel Labath if (!ranges) { 5021ca1e08eSPavel Labath result.AppendError(toString(ranges.takeError())); 503c6a38957SPavel Labath return result.Succeeded(); 504dda4f7b5SGreg Clayton } 50537023b06SJim Ingham 5061ca1e08eSPavel Labath bool print_sc_header = ranges->size() > 1; 5071ca1e08eSPavel Labath for (AddressRange cur_range : *ranges) { 508af3db4e9SPavel Labath Disassembler::Limit limit; 509af3db4e9SPavel Labath if (m_options.num_instructions == 0) { 510af3db4e9SPavel Labath limit = {Disassembler::Limit::Bytes, cur_range.GetByteSize()}; 511af3db4e9SPavel Labath if (limit.value == 0) 5128b845ac5SPavel Labath limit.value = default_disasm_byte_size; 5133245dd59SPavel Labath } else { 514af3db4e9SPavel Labath limit = {Disassembler::Limit::Instructions, m_options.num_instructions}; 5153245dd59SPavel Labath } 516af3db4e9SPavel Labath if (Disassembler::Disassemble( 517af3db4e9SPavel Labath GetDebugger(), m_options.arch, plugin_name, flavor_string, 518af3db4e9SPavel Labath m_exe_ctx, cur_range.GetBaseAddress(), limit, m_options.show_mixed, 519af3db4e9SPavel Labath m_options.show_mixed ? m_options.num_lines_context : 0, options, 520af3db4e9SPavel Labath result.GetOutputStream())) { 521dda4f7b5SGreg Clayton result.SetStatus(eReturnStatusSuccessFinishResult); 522b9c1b51eSKate Stone } else { 5233245dd59SPavel Labath if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS) { 5243245dd59SPavel Labath result.AppendErrorWithFormat( 5253245dd59SPavel Labath "Failed to disassemble memory in function at 0x%8.8" PRIx64 ".\n", 5263245dd59SPavel Labath m_options.symbol_containing_addr); 5273245dd59SPavel Labath } else { 528b9c1b51eSKate Stone result.AppendErrorWithFormat( 529b9c1b51eSKate Stone "Failed to disassemble memory at 0x%8.8" PRIx64 ".\n", 53005229752SPavel Labath cur_range.GetBaseAddress().GetLoadAddress(target)); 5313245dd59SPavel Labath } 53230fdc8d8SChris Lattner } 5332f2c876eSJim Ingham if (print_sc_header) 5348b845ac5SPavel Labath result.GetOutputStream() << "\n"; 5352f2c876eSJim Ingham } 53630fdc8d8SChris Lattner 53730fdc8d8SChris Lattner return result.Succeeded(); 53830fdc8d8SChris Lattner } 539