130fdc8d8SChris Lattner //===-- CommandObjectDisassemble.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 // C Includes 1130fdc8d8SChris Lattner // C++ Includes 1230fdc8d8SChris Lattner // Other libraries and framework includes 1330fdc8d8SChris Lattner // Project includes 1426cac3afSEugene Zelenko #include "CommandObjectDisassemble.h" 1530fdc8d8SChris Lattner #include "lldb/Core/AddressRange.h" 161f746071SGreg Clayton #include "lldb/Core/Disassembler.h" 17801237a2SJason Molenda #include "lldb/Core/Module.h" 181f746071SGreg Clayton #include "lldb/Core/SourceManager.h" 195275aaa0SVince Harron #include "lldb/Host/StringConvert.h" 2030fdc8d8SChris Lattner #include "lldb/Interpreter/CommandCompletions.h" 2130fdc8d8SChris Lattner #include "lldb/Interpreter/CommandInterpreter.h" 2230fdc8d8SChris Lattner #include "lldb/Interpreter/CommandReturnObject.h" 2340af72e1SJim Ingham #include "lldb/Interpreter/Options.h" 241f746071SGreg Clayton #include "lldb/Symbol/Function.h" 2530fdc8d8SChris Lattner #include "lldb/Symbol/Symbol.h" 2630fdc8d8SChris Lattner #include "lldb/Target/Process.h" 27d5944cd1SGreg Clayton #include "lldb/Target/SectionLoadList.h" 28b57e4a1bSJason Molenda #include "lldb/Target/StackFrame.h" 2930fdc8d8SChris Lattner #include "lldb/Target/Target.h" 3030fdc8d8SChris Lattner 3130fdc8d8SChris Lattner #define DEFAULT_DISASM_BYTE_SIZE 32 3237023b06SJim Ingham #define DEFAULT_DISASM_NUM_INS 4 3330fdc8d8SChris Lattner 3430fdc8d8SChris Lattner using namespace lldb; 3530fdc8d8SChris Lattner using namespace lldb_private; 3630fdc8d8SChris Lattner 37*e1cfbc79STodd Fiala CommandObjectDisassemble::CommandOptions::CommandOptions() : 38*e1cfbc79STodd Fiala Options(), 3937023b06SJim Ingham num_lines_context(0), 4037023b06SJim Ingham num_instructions (0), 4132e0a750SGreg Clayton func_name(), 421fb2e7dfSGreg Clayton current_function (false), 4332e0a750SGreg Clayton start_addr(), 4432e0a750SGreg Clayton end_addr (), 4532e0a750SGreg Clayton at_pc (false), 4632e0a750SGreg Clayton frame_line (false), 4732e0a750SGreg Clayton plugin_name (), 480f063ba6SJim Ingham flavor_string(), 493555b5d7SJim Ingham arch(), 50801237a2SJason Molenda some_location_specified (false), 51801237a2SJason Molenda symbol_containing_addr () 5230fdc8d8SChris Lattner { 53*e1cfbc79STodd Fiala OptionParsingStarting(nullptr); 5430fdc8d8SChris Lattner } 5530fdc8d8SChris Lattner 5626cac3afSEugene Zelenko CommandObjectDisassemble::CommandOptions::~CommandOptions() = default; 5730fdc8d8SChris Lattner 5830fdc8d8SChris Lattner Error 59*e1cfbc79STodd Fiala CommandObjectDisassemble::CommandOptions::SetOptionValue(uint32_t option_idx, 60*e1cfbc79STodd Fiala const char *option_arg, 61*e1cfbc79STodd Fiala ExecutionContext *execution_context) 6230fdc8d8SChris Lattner { 6330fdc8d8SChris Lattner Error error; 6430fdc8d8SChris Lattner 653bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 6630fdc8d8SChris Lattner 6737023b06SJim Ingham bool success; 6837023b06SJim Ingham 6930fdc8d8SChris Lattner switch (short_option) 7030fdc8d8SChris Lattner { 7130fdc8d8SChris Lattner case 'm': 7230fdc8d8SChris Lattner show_mixed = true; 7330fdc8d8SChris Lattner break; 7430fdc8d8SChris Lattner 75357132ebSGreg Clayton case 'C': 765275aaa0SVince Harron num_lines_context = StringConvert::ToUInt32(option_arg, 0, 0, &success); 7737023b06SJim Ingham if (!success) 7886edbf41SGreg Clayton error.SetErrorStringWithFormat ("invalid num context lines string: \"%s\"", option_arg); 7937023b06SJim Ingham break; 8037023b06SJim Ingham 8130fdc8d8SChris Lattner case 'c': 825275aaa0SVince Harron num_instructions = StringConvert::ToUInt32(option_arg, 0, 0, &success); 8337023b06SJim Ingham if (!success) 8486edbf41SGreg Clayton error.SetErrorStringWithFormat ("invalid num of instructions string: \"%s\"", option_arg); 8530fdc8d8SChris Lattner break; 8630fdc8d8SChris Lattner 8730fdc8d8SChris Lattner case 'b': 8830fdc8d8SChris Lattner show_bytes = true; 8930fdc8d8SChris Lattner break; 9030fdc8d8SChris Lattner 918651121cSJim Ingham case 's': 92b9d5df58SGreg Clayton { 93*e1cfbc79STodd Fiala start_addr = Args::StringToAddress(execution_context, option_arg, 94*e1cfbc79STodd Fiala LLDB_INVALID_ADDRESS, &error); 95b9d5df58SGreg Clayton if (start_addr != LLDB_INVALID_ADDRESS) 963555b5d7SJim Ingham some_location_specified = true; 97b9d5df58SGreg Clayton } 988651121cSJim Ingham break; 998651121cSJim Ingham case 'e': 100b9d5df58SGreg Clayton { 101*e1cfbc79STodd Fiala end_addr = Args::StringToAddress(execution_context, option_arg, 102*e1cfbc79STodd Fiala LLDB_INVALID_ADDRESS, &error); 103b9d5df58SGreg Clayton if (end_addr != LLDB_INVALID_ADDRESS) 1043555b5d7SJim Ingham some_location_specified = true; 105b9d5df58SGreg Clayton } 106b9d5df58SGreg Clayton break; 10726cac3afSEugene Zelenko 10830fdc8d8SChris Lattner case 'n': 10932e0a750SGreg Clayton func_name.assign (option_arg); 1103555b5d7SJim Ingham some_location_specified = true; 11130fdc8d8SChris Lattner break; 11230fdc8d8SChris Lattner 11337023b06SJim Ingham case 'p': 11432e0a750SGreg Clayton at_pc = true; 1153555b5d7SJim Ingham some_location_specified = true; 11632e0a750SGreg Clayton break; 11732e0a750SGreg Clayton 11832e0a750SGreg Clayton case 'l': 11932e0a750SGreg Clayton frame_line = true; 12032e0a750SGreg Clayton // Disassemble the current source line kind of implies showing mixed 12132e0a750SGreg Clayton // source code context. 12232e0a750SGreg Clayton show_mixed = true; 1233555b5d7SJim Ingham some_location_specified = true; 12437023b06SJim Ingham break; 12537023b06SJim Ingham 1261080edbcSGreg Clayton case 'P': 12732e0a750SGreg Clayton plugin_name.assign (option_arg); 1281080edbcSGreg Clayton break; 1291080edbcSGreg Clayton 1300f063ba6SJim Ingham case 'F': 1310f063ba6SJim Ingham { 132*e1cfbc79STodd Fiala TargetSP target_sp = execution_context ? 133*e1cfbc79STodd Fiala execution_context->GetTargetSP() : TargetSP(); 134*e1cfbc79STodd Fiala if (target_sp && 135*e1cfbc79STodd Fiala (target_sp->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86 136*e1cfbc79STodd Fiala || target_sp->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86_64)) 1370f063ba6SJim Ingham { 1380f063ba6SJim Ingham flavor_string.assign (option_arg); 1390f063ba6SJim Ingham } 1400f063ba6SJim Ingham else 1410f063ba6SJim Ingham error.SetErrorStringWithFormat("Disassembler flavors are currently only supported for x86 and x86_64 targets."); 1420f063ba6SJim Ingham break; 1430f063ba6SJim Ingham } 14426cac3afSEugene Zelenko 14530fdc8d8SChris Lattner case 'r': 14630fdc8d8SChris Lattner raw = true; 14730fdc8d8SChris Lattner break; 14830fdc8d8SChris Lattner 1498ceb8ba2SJohnny Chen case 'f': 1501fb2e7dfSGreg Clayton current_function = true; 1513555b5d7SJim Ingham some_location_specified = true; 1528ceb8ba2SJohnny Chen break; 1538ceb8ba2SJohnny Chen 154801237a2SJason Molenda case 'A': 155*e1cfbc79STodd Fiala if (execution_context) 156*e1cfbc79STodd Fiala { 157*e1cfbc79STodd Fiala auto target_sp = execution_context ? 158*e1cfbc79STodd Fiala execution_context->GetTargetSP() : TargetSP(); 159*e1cfbc79STodd Fiala auto platform_sp = 160*e1cfbc79STodd Fiala target_sp ? target_sp->GetPlatform() : PlatformSP(); 161*e1cfbc79STodd Fiala if (!arch.SetTriple (option_arg, platform_sp.get())) 16270512317SGreg Clayton arch.SetTriple (option_arg); 163*e1cfbc79STodd Fiala } 164357132ebSGreg Clayton break; 165357132ebSGreg Clayton 166801237a2SJason Molenda case 'a': 167801237a2SJason Molenda { 168*e1cfbc79STodd Fiala symbol_containing_addr = 169*e1cfbc79STodd Fiala Args::StringToAddress(execution_context,option_arg, 170*e1cfbc79STodd Fiala LLDB_INVALID_ADDRESS, &error); 171801237a2SJason Molenda if (symbol_containing_addr != LLDB_INVALID_ADDRESS) 172801237a2SJason Molenda { 173801237a2SJason Molenda some_location_specified = true; 174801237a2SJason Molenda } 175801237a2SJason Molenda } 176801237a2SJason Molenda break; 177801237a2SJason Molenda 17830fdc8d8SChris Lattner default: 17986edbf41SGreg Clayton error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); 18030fdc8d8SChris Lattner break; 18130fdc8d8SChris Lattner } 18230fdc8d8SChris Lattner 18330fdc8d8SChris Lattner return error; 18430fdc8d8SChris Lattner } 18530fdc8d8SChris Lattner 18630fdc8d8SChris Lattner void 187*e1cfbc79STodd Fiala CommandObjectDisassemble::CommandOptions::OptionParsingStarting( 188*e1cfbc79STodd Fiala ExecutionContext *execution_context) 18930fdc8d8SChris Lattner { 19030fdc8d8SChris Lattner show_mixed = false; 19130fdc8d8SChris Lattner show_bytes = false; 19230fdc8d8SChris Lattner num_lines_context = 0; 19337023b06SJim Ingham num_instructions = 0; 19432e0a750SGreg Clayton func_name.clear(); 1951fb2e7dfSGreg Clayton current_function = false; 19632e0a750SGreg Clayton at_pc = false; 19732e0a750SGreg Clayton frame_line = false; 19832e0a750SGreg Clayton start_addr = LLDB_INVALID_ADDRESS; 19932e0a750SGreg Clayton end_addr = LLDB_INVALID_ADDRESS; 200801237a2SJason Molenda symbol_containing_addr = LLDB_INVALID_ADDRESS; 201a68c1a21SSean Callanan raw = false; 20232e0a750SGreg Clayton plugin_name.clear(); 2030f063ba6SJim Ingham 204*e1cfbc79STodd Fiala Target *target = 205*e1cfbc79STodd Fiala execution_context ? execution_context->GetTargetPtr() : nullptr; 2060f063ba6SJim Ingham 2070f063ba6SJim Ingham // This is a hack till we get the ability to specify features based on architecture. For now GetDisassemblyFlavor 2080f063ba6SJim Ingham // is really only valid for x86 (and for the llvm assembler plugin, but I'm papering over that since that is the 2090f063ba6SJim Ingham // only disassembler plugin we have... 2100f063ba6SJim Ingham if (target) 2110f063ba6SJim Ingham { 2120f063ba6SJim Ingham if (target->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86 2130f063ba6SJim Ingham || target->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86_64) 2140f063ba6SJim Ingham { 2150f063ba6SJim Ingham flavor_string.assign(target->GetDisassemblyFlavor()); 2160f063ba6SJim Ingham } 2170f063ba6SJim Ingham else 2180f063ba6SJim Ingham flavor_string.assign ("default"); 2190f063ba6SJim Ingham 2200f063ba6SJim Ingham } 2210f063ba6SJim Ingham else 2220f063ba6SJim Ingham flavor_string.assign("default"); 2230f063ba6SJim Ingham 22432e0a750SGreg Clayton arch.Clear(); 2253555b5d7SJim Ingham some_location_specified = false; 2263555b5d7SJim Ingham } 2273555b5d7SJim Ingham 2283555b5d7SJim Ingham Error 229*e1cfbc79STodd Fiala CommandObjectDisassemble::CommandOptions::OptionParsingFinished( 230*e1cfbc79STodd Fiala ExecutionContext *execution_context) 2313555b5d7SJim Ingham { 2323555b5d7SJim Ingham if (!some_location_specified) 2331fb2e7dfSGreg Clayton current_function = true; 2343555b5d7SJim Ingham return Error(); 23530fdc8d8SChris Lattner } 23630fdc8d8SChris Lattner 237e0d378b3SGreg Clayton const OptionDefinition* 23830fdc8d8SChris Lattner CommandObjectDisassemble::CommandOptions::GetDefinitions () 23930fdc8d8SChris Lattner { 24030fdc8d8SChris Lattner return g_option_table; 24130fdc8d8SChris Lattner } 24230fdc8d8SChris Lattner 243e0d378b3SGreg Clayton OptionDefinition 24430fdc8d8SChris Lattner CommandObjectDisassemble::CommandOptions::g_option_table[] = 24530fdc8d8SChris Lattner { 24626cac3afSEugene Zelenko { LLDB_OPT_SET_ALL, false, "bytes" , 'b', OptionParser::eNoArgument , nullptr, nullptr, 0, eArgTypeNone, "Show opcode bytes when disassembling."}, 24726cac3afSEugene Zelenko { LLDB_OPT_SET_ALL, false, "context" , 'C', OptionParser::eRequiredArgument , nullptr, nullptr, 0, eArgTypeNumLines, "Number of context lines of source to show."}, 24826cac3afSEugene Zelenko { LLDB_OPT_SET_ALL, false, "mixed" , 'm', OptionParser::eNoArgument , nullptr, nullptr, 0, eArgTypeNone, "Enable mixed source and assembly display."}, 24926cac3afSEugene Zelenko { LLDB_OPT_SET_ALL, false, "raw" , 'r', OptionParser::eNoArgument , nullptr, nullptr, 0, eArgTypeNone, "Print raw disassembly with no symbol information."}, 25026cac3afSEugene Zelenko { LLDB_OPT_SET_ALL, false, "plugin" , 'P', OptionParser::eRequiredArgument , nullptr, nullptr, 0, eArgTypePlugin, "Name of the disassembler plugin you want to use."}, 25126cac3afSEugene Zelenko { LLDB_OPT_SET_ALL, false, "flavor" , 'F', OptionParser::eRequiredArgument , nullptr, nullptr, 0, eArgTypeDisassemblyFlavor, "Name of the disassembly flavor you want to use. " 2520f063ba6SJim Ingham "Currently the only valid options are default, and for Intel" 2530f063ba6SJim Ingham " architectures, att and intel."}, 25426cac3afSEugene Zelenko { LLDB_OPT_SET_ALL, false, "arch" , 'A', OptionParser::eRequiredArgument , nullptr, nullptr, 0, eArgTypeArchitecture,"Specify the architecture to use from cross disassembly."}, 255357132ebSGreg Clayton { LLDB_OPT_SET_1 | 25626cac3afSEugene Zelenko LLDB_OPT_SET_2 , true , "start-address", 's', OptionParser::eRequiredArgument , nullptr, nullptr, 0, eArgTypeAddressOrExpression,"Address at which to start disassembling."}, 25726cac3afSEugene Zelenko { LLDB_OPT_SET_1 , false, "end-address" , 'e', OptionParser::eRequiredArgument , nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Address at which to end disassembling."}, 258357132ebSGreg Clayton { LLDB_OPT_SET_2 | 259357132ebSGreg Clayton LLDB_OPT_SET_3 | 260357132ebSGreg Clayton LLDB_OPT_SET_4 | 26126cac3afSEugene Zelenko LLDB_OPT_SET_5 , false, "count" , 'c', OptionParser::eRequiredArgument , nullptr, nullptr, 0, eArgTypeNumLines, "Number of instructions to display."}, 26226cac3afSEugene Zelenko { LLDB_OPT_SET_3 , false, "name" , 'n', OptionParser::eRequiredArgument , nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, 2631fb2e7dfSGreg Clayton "Disassemble entire contents of the given function name."}, 26426cac3afSEugene Zelenko { LLDB_OPT_SET_4 , false, "frame" , 'f', OptionParser::eNoArgument , nullptr, nullptr, 0, eArgTypeNone, "Disassemble from the start of the current frame's function."}, 26526cac3afSEugene Zelenko { LLDB_OPT_SET_5 , false, "pc" , 'p', OptionParser::eNoArgument , nullptr, nullptr, 0, eArgTypeNone, "Disassemble around the current pc."}, 26626cac3afSEugene Zelenko { LLDB_OPT_SET_6 , false, "line" , 'l', OptionParser::eNoArgument , nullptr, nullptr, 0, eArgTypeNone, "Disassemble the current frame's current source line instructions if there is debug line table information, else disassemble around the pc."}, 26726cac3afSEugene Zelenko { LLDB_OPT_SET_7 , false, "address" , 'a', OptionParser::eRequiredArgument , nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Disassemble function containing this address."}, 26826cac3afSEugene Zelenko { 0 , false, nullptr , 0, 0 , nullptr, nullptr, 0, eArgTypeNone, nullptr } 26930fdc8d8SChris Lattner }; 27030fdc8d8SChris Lattner 27130fdc8d8SChris Lattner //------------------------------------------------------------------------- 27230fdc8d8SChris Lattner // CommandObjectDisassemble 27330fdc8d8SChris Lattner //------------------------------------------------------------------------- 27430fdc8d8SChris Lattner 2757428a18cSKate Stone CommandObjectDisassemble::CommandObjectDisassemble(CommandInterpreter &interpreter) 2767428a18cSKate Stone : CommandObjectParsed(interpreter, "disassemble", "Disassemble specified instructions in the current target. " 2777428a18cSKate Stone "Defaults to the current function for the current thread and " 2787428a18cSKate Stone "stack frame.", 279eb0103f2SGreg Clayton "disassemble [<cmd-options>]"), 280*e1cfbc79STodd Fiala m_options() 28130fdc8d8SChris Lattner { 28230fdc8d8SChris Lattner } 28330fdc8d8SChris Lattner 28426cac3afSEugene Zelenko CommandObjectDisassemble::~CommandObjectDisassemble() = default; 28530fdc8d8SChris Lattner 28630fdc8d8SChris Lattner bool 2875a988416SJim Ingham CommandObjectDisassemble::DoExecute (Args& command, CommandReturnObject &result) 28830fdc8d8SChris Lattner { 289a7015092SGreg Clayton Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 29026cac3afSEugene Zelenko if (target == nullptr) 29130fdc8d8SChris Lattner { 292effe5c95SGreg Clayton result.AppendError ("invalid target, create a debug target using the 'target create' command"); 29330fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 29430fdc8d8SChris Lattner return false; 29530fdc8d8SChris Lattner } 29632e0a750SGreg Clayton if (!m_options.arch.IsValid()) 29732e0a750SGreg Clayton m_options.arch = target->GetArchitecture(); 29830fdc8d8SChris Lattner 29932e0a750SGreg Clayton if (!m_options.arch.IsValid()) 30030fdc8d8SChris Lattner { 301125adcf0SJason Molenda result.AppendError ("use the --arch option or set the target architecture to disassemble"); 30230fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 30330fdc8d8SChris Lattner return false; 30430fdc8d8SChris Lattner } 30530fdc8d8SChris Lattner 3061080edbcSGreg Clayton const char *plugin_name = m_options.GetPluginName (); 3070f063ba6SJim Ingham const char *flavor_string = m_options.GetFlavorString(); 3080f063ba6SJim Ingham 3090f063ba6SJim Ingham DisassemblerSP disassembler = Disassembler::FindPlugin(m_options.arch, flavor_string, plugin_name); 31030fdc8d8SChris Lattner 3119a028519SSean Callanan if (!disassembler) 31230fdc8d8SChris Lattner { 3131080edbcSGreg Clayton if (plugin_name) 3140f063ba6SJim Ingham { 315357132ebSGreg Clayton result.AppendErrorWithFormat ("Unable to find Disassembler plug-in named '%s' that supports the '%s' architecture.\n", 316357132ebSGreg Clayton plugin_name, 31732e0a750SGreg Clayton m_options.arch.GetArchitectureName()); 3180f063ba6SJim Ingham } 3191080edbcSGreg Clayton else 320357132ebSGreg Clayton result.AppendErrorWithFormat ("Unable to find Disassembler plug-in for the '%s' architecture.\n", 32132e0a750SGreg Clayton m_options.arch.GetArchitectureName()); 32230fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 32330fdc8d8SChris Lattner return false; 32430fdc8d8SChris Lattner } 32526cac3afSEugene Zelenko else if (flavor_string != nullptr && !disassembler->FlavorValidForArchSpec(m_options.arch, flavor_string)) 3260f063ba6SJim Ingham result.AppendWarningWithFormat("invalid disassembler flavor \"%s\", using default.\n", flavor_string); 32730fdc8d8SChris Lattner 32830fdc8d8SChris Lattner result.SetStatus (eReturnStatusSuccessFinishResult); 32930fdc8d8SChris Lattner 330dda4f7b5SGreg Clayton if (command.GetArgumentCount() != 0) 33130fdc8d8SChris Lattner { 332a7015092SGreg Clayton result.AppendErrorWithFormat ("\"disassemble\" arguments are specified as options.\n"); 333*e1cfbc79STodd Fiala const int terminal_width = 334*e1cfbc79STodd Fiala GetCommandInterpreter().GetDebugger().GetTerminalWidth(); 335*e1cfbc79STodd Fiala GetOptions()->GenerateOptionUsage(result.GetErrorStream(), this, 336*e1cfbc79STodd Fiala terminal_width); 3378651121cSJim Ingham result.SetStatus (eReturnStatusFailed); 3388651121cSJim Ingham return false; 3398651121cSJim Ingham } 3408651121cSJim Ingham 341dda4f7b5SGreg Clayton if (m_options.show_mixed && m_options.num_lines_context == 0) 3426dbd3983SGreg Clayton m_options.num_lines_context = 1; 343dda4f7b5SGreg Clayton 344b10d72f0SGreg Clayton // Always show the PC in the disassembly 345b10d72f0SGreg Clayton uint32_t options = Disassembler::eOptionMarkPCAddress; 3461da6f9d7SGreg Clayton 347b10d72f0SGreg Clayton // Mark the source line for the current PC only if we are doing mixed source and assembly 348b10d72f0SGreg Clayton if (m_options.show_mixed) 349b10d72f0SGreg Clayton options |= Disassembler::eOptionMarkPCSourceLine; 3501da6f9d7SGreg Clayton 3511da6f9d7SGreg Clayton if (m_options.show_bytes) 3521da6f9d7SGreg Clayton options |= Disassembler::eOptionShowBytes; 3531da6f9d7SGreg Clayton 3541da6f9d7SGreg Clayton if (m_options.raw) 3551da6f9d7SGreg Clayton options |= Disassembler::eOptionRawOuput; 35637023b06SJim Ingham 35732e0a750SGreg Clayton if (!m_options.func_name.empty()) 358dda4f7b5SGreg Clayton { 35932e0a750SGreg Clayton ConstString name(m_options.func_name.c_str()); 360dda4f7b5SGreg Clayton 361a7015092SGreg Clayton if (Disassembler::Disassemble(m_interpreter.GetDebugger(), 36232e0a750SGreg Clayton m_options.arch, 3631080edbcSGreg Clayton plugin_name, 3640f063ba6SJim Ingham flavor_string, 365f9fc609fSGreg Clayton m_exe_ctx, 366dda4f7b5SGreg Clayton name, 36726cac3afSEugene Zelenko nullptr, // Module * 36837023b06SJim Ingham m_options.num_instructions, 369dda4f7b5SGreg Clayton m_options.show_mixed ? m_options.num_lines_context : 0, 3701da6f9d7SGreg Clayton options, 371dda4f7b5SGreg Clayton result.GetOutputStream())) 372dda4f7b5SGreg Clayton { 373dda4f7b5SGreg Clayton result.SetStatus (eReturnStatusSuccessFinishResult); 374dda4f7b5SGreg Clayton } 375dda4f7b5SGreg Clayton else 376dda4f7b5SGreg Clayton { 377dda4f7b5SGreg Clayton result.AppendErrorWithFormat ("Unable to find symbol with name '%s'.\n", name.GetCString()); 378dda4f7b5SGreg Clayton result.SetStatus (eReturnStatusFailed); 379dda4f7b5SGreg Clayton } 380dda4f7b5SGreg Clayton } 381dda4f7b5SGreg Clayton else 382dda4f7b5SGreg Clayton { 3832f2c876eSJim Ingham std::vector<AddressRange> ranges; 38432e0a750SGreg Clayton AddressRange range; 385b57e4a1bSJason Molenda StackFrame *frame = m_exe_ctx.GetFramePtr(); 38632e0a750SGreg Clayton if (m_options.frame_line) 38732e0a750SGreg Clayton { 38826cac3afSEugene Zelenko if (frame == nullptr) 3893555b5d7SJim Ingham { 3903555b5d7SJim Ingham result.AppendError ("Cannot disassemble around the current line without a selected frame.\n"); 3913555b5d7SJim Ingham result.SetStatus (eReturnStatusFailed); 3923555b5d7SJim Ingham return false; 3933555b5d7SJim Ingham } 394c14ee32dSGreg Clayton LineEntry pc_line_entry (frame->GetSymbolContext(eSymbolContextLineEntry).line_entry); 39532e0a750SGreg Clayton if (pc_line_entry.IsValid()) 39632e0a750SGreg Clayton { 39732e0a750SGreg Clayton range = pc_line_entry.range; 39832e0a750SGreg Clayton } 39932e0a750SGreg Clayton else 40032e0a750SGreg Clayton { 40132e0a750SGreg Clayton m_options.at_pc = true; // No line entry, so just disassemble around the current pc 40232e0a750SGreg Clayton m_options.show_mixed = false; 40332e0a750SGreg Clayton } 40432e0a750SGreg Clayton } 4051fb2e7dfSGreg Clayton else if (m_options.current_function) 4063555b5d7SJim Ingham { 40726cac3afSEugene Zelenko if (frame == nullptr) 4083555b5d7SJim Ingham { 4093555b5d7SJim Ingham result.AppendError ("Cannot disassemble around the current function without a selected frame.\n"); 4103555b5d7SJim Ingham result.SetStatus (eReturnStatusFailed); 4113555b5d7SJim Ingham return false; 4123555b5d7SJim Ingham } 413c14ee32dSGreg Clayton Symbol *symbol = frame->GetSymbolContext(eSymbolContextSymbol).symbol; 4143555b5d7SJim Ingham if (symbol) 415e7612134SGreg Clayton { 416e7612134SGreg Clayton range.GetBaseAddress() = symbol->GetAddress(); 417e7612134SGreg Clayton range.SetByteSize(symbol->GetByteSize()); 418e7612134SGreg Clayton } 4193555b5d7SJim Ingham } 42037023b06SJim Ingham 42132e0a750SGreg Clayton // Did the "m_options.frame_line" find a valid range already? If so 42232e0a750SGreg Clayton // skip the rest... 42332e0a750SGreg Clayton if (range.GetByteSize() == 0) 42432e0a750SGreg Clayton { 42532e0a750SGreg Clayton if (m_options.at_pc) 4268651121cSJim Ingham { 42726cac3afSEugene Zelenko if (frame == nullptr) 42837023b06SJim Ingham { 42937023b06SJim Ingham result.AppendError ("Cannot disassemble around the current PC without a selected frame.\n"); 43037023b06SJim Ingham result.SetStatus (eReturnStatusFailed); 43137023b06SJim Ingham return false; 43237023b06SJim Ingham } 433c14ee32dSGreg Clayton range.GetBaseAddress() = frame->GetFrameCodeAddress(); 43437023b06SJim Ingham if (m_options.num_instructions == 0) 43537023b06SJim Ingham { 43637023b06SJim Ingham // Disassembling at the PC always disassembles some number of instructions (not the whole function). 43737023b06SJim Ingham m_options.num_instructions = DEFAULT_DISASM_NUM_INS; 43837023b06SJim Ingham } 4392f2c876eSJim Ingham ranges.push_back(range); 44037023b06SJim Ingham } 44137023b06SJim Ingham else 44237023b06SJim Ingham { 44332e0a750SGreg Clayton range.GetBaseAddress().SetOffset (m_options.start_addr); 44432e0a750SGreg Clayton if (range.GetBaseAddress().IsValid()) 44537023b06SJim Ingham { 44632e0a750SGreg Clayton if (m_options.end_addr != LLDB_INVALID_ADDRESS) 4478651121cSJim Ingham { 44832e0a750SGreg Clayton if (m_options.end_addr <= m_options.start_addr) 4498651121cSJim Ingham { 4508651121cSJim Ingham result.AppendErrorWithFormat ("End address before start address.\n"); 4518651121cSJim Ingham result.SetStatus (eReturnStatusFailed); 4528651121cSJim Ingham return false; 4538651121cSJim Ingham } 45432e0a750SGreg Clayton range.SetByteSize (m_options.end_addr - m_options.start_addr); 45532e0a750SGreg Clayton } 4562f4693aaSJim Ingham ranges.push_back(range); 45737023b06SJim Ingham } 458801237a2SJason Molenda else 459801237a2SJason Molenda { 460801237a2SJason Molenda if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS 4612f2c876eSJim Ingham && target) 4622f2c876eSJim Ingham { 4632f2c876eSJim Ingham if (!target->GetSectionLoadList().IsEmpty()) 464801237a2SJason Molenda { 465801237a2SJason Molenda bool failed = false; 466801237a2SJason Molenda Address symbol_containing_address; 467801237a2SJason Molenda if (target->GetSectionLoadList().ResolveLoadAddress (m_options.symbol_containing_addr, symbol_containing_address)) 468801237a2SJason Molenda { 469801237a2SJason Molenda ModuleSP module_sp (symbol_containing_address.GetModule()); 470801237a2SJason Molenda SymbolContext sc; 47135729bb1SAshok Thirumurthi bool resolve_tail_call_address = true; // PC can be one past the address range of the function. 47235729bb1SAshok Thirumurthi module_sp->ResolveSymbolContextForAddress (symbol_containing_address, eSymbolContextEverything, sc, 47335729bb1SAshok Thirumurthi resolve_tail_call_address); 474801237a2SJason Molenda if (sc.function || sc.symbol) 475801237a2SJason Molenda { 476801237a2SJason Molenda sc.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, range); 477801237a2SJason Molenda } 478801237a2SJason Molenda else 479801237a2SJason Molenda { 480801237a2SJason Molenda failed = true; 481801237a2SJason Molenda } 482801237a2SJason Molenda } 483801237a2SJason Molenda else 484801237a2SJason Molenda { 485801237a2SJason Molenda failed = true; 486801237a2SJason Molenda } 487801237a2SJason Molenda if (failed) 488801237a2SJason Molenda { 489801237a2SJason Molenda result.AppendErrorWithFormat ("Could not find function bounds for address 0x%" PRIx64 "\n", m_options.symbol_containing_addr); 490801237a2SJason Molenda result.SetStatus (eReturnStatusFailed); 491801237a2SJason Molenda return false; 492801237a2SJason Molenda } 4932f2c876eSJim Ingham ranges.push_back(range); 494801237a2SJason Molenda } 4952f2c876eSJim Ingham else 4962f2c876eSJim Ingham { 4972f2c876eSJim Ingham for (lldb::ModuleSP module_sp : target->GetImages().Modules()) 4982f2c876eSJim Ingham { 4992f2c876eSJim Ingham lldb::addr_t file_addr = m_options.symbol_containing_addr; 5002f2c876eSJim Ingham Address file_address; 5012f2c876eSJim Ingham if (module_sp->ResolveFileAddress(file_addr, file_address)) 5022f2c876eSJim Ingham { 5032f2c876eSJim Ingham SymbolContext sc; 5042f2c876eSJim Ingham bool resolve_tail_call_address = true; // PC can be one past the address range of the function. 5052f2c876eSJim Ingham module_sp->ResolveSymbolContextForAddress (file_address, eSymbolContextEverything, sc, resolve_tail_call_address); 5062f2c876eSJim Ingham if (sc.function || sc.symbol) 5072f2c876eSJim Ingham { 5082f2c876eSJim Ingham sc.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, range); 5092f2c876eSJim Ingham ranges.push_back(range); 510801237a2SJason Molenda } 51137023b06SJim Ingham } 51237023b06SJim Ingham } 5132f2c876eSJim Ingham } 5142f2c876eSJim Ingham } 5152f2c876eSJim Ingham } 5162f2c876eSJim Ingham } 5172f2c876eSJim Ingham } 5182f2c876eSJim Ingham else 5192f2c876eSJim Ingham ranges.push_back(range); 5202f2c876eSJim Ingham 52137023b06SJim Ingham if (m_options.num_instructions != 0) 52237023b06SJim Ingham { 52326cac3afSEugene Zelenko if (ranges.empty()) 52437023b06SJim Ingham { 52537023b06SJim Ingham // The default action is to disassemble the current frame function. 526c14ee32dSGreg Clayton if (frame) 52737023b06SJim Ingham { 528c14ee32dSGreg Clayton SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol)); 52937023b06SJim Ingham if (sc.function) 53032e0a750SGreg Clayton range.GetBaseAddress() = sc.function->GetAddressRange().GetBaseAddress(); 531e7612134SGreg Clayton else if (sc.symbol && sc.symbol->ValueIsAddress()) 532e7612134SGreg Clayton range.GetBaseAddress() = sc.symbol->GetAddress(); 53337023b06SJim Ingham else 534c14ee32dSGreg Clayton range.GetBaseAddress() = frame->GetFrameCodeAddress(); 53537023b06SJim Ingham } 53637023b06SJim Ingham 53732e0a750SGreg Clayton if (!range.GetBaseAddress().IsValid()) 53837023b06SJim Ingham { 53937023b06SJim Ingham result.AppendError ("invalid frame"); 54037023b06SJim Ingham result.SetStatus (eReturnStatusFailed); 54137023b06SJim Ingham return false; 54237023b06SJim Ingham } 54337023b06SJim Ingham } 54437023b06SJim Ingham 5452f2c876eSJim Ingham bool print_sc_header = ranges.size() > 1; 5462f2c876eSJim Ingham for (AddressRange cur_range : ranges) 5472f2c876eSJim Ingham { 54837023b06SJim Ingham if (Disassembler::Disassemble (m_interpreter.GetDebugger(), 54932e0a750SGreg Clayton m_options.arch, 5501080edbcSGreg Clayton plugin_name, 5510f063ba6SJim Ingham flavor_string, 552f9fc609fSGreg Clayton m_exe_ctx, 5532f2c876eSJim Ingham cur_range.GetBaseAddress(), 55437023b06SJim Ingham m_options.num_instructions, 55537023b06SJim Ingham m_options.show_mixed ? m_options.num_lines_context : 0, 5561da6f9d7SGreg Clayton options, 55737023b06SJim Ingham result.GetOutputStream())) 55837023b06SJim Ingham { 55937023b06SJim Ingham result.SetStatus (eReturnStatusSuccessFinishResult); 5608651121cSJim Ingham } 5618651121cSJim Ingham else 56237023b06SJim Ingham { 5632f2c876eSJim Ingham if (m_options.start_addr != LLDB_INVALID_ADDRESS) 564d01b2953SDaniel Malea result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8" PRIx64 ".\n", m_options.start_addr); 5652f2c876eSJim Ingham else if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS) 5662f2c876eSJim Ingham result.AppendErrorWithFormat ("Failed to disassemble memory in function at 0x%8.8" PRIx64 ".\n", m_options.symbol_containing_addr); 56737023b06SJim Ingham result.SetStatus (eReturnStatusFailed); 56837023b06SJim Ingham } 56937023b06SJim Ingham } 5702f2c876eSJim Ingham if (print_sc_header) 5712f2c876eSJim Ingham result.AppendMessage("\n"); 5722f2c876eSJim Ingham } 57337023b06SJim Ingham else 57437023b06SJim Ingham { 57526cac3afSEugene Zelenko if (ranges.empty()) 57630fdc8d8SChris Lattner { 5778ceb8ba2SJohnny Chen // The default action is to disassemble the current frame function. 578c14ee32dSGreg Clayton if (frame) 57930fdc8d8SChris Lattner { 580c14ee32dSGreg Clayton SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol)); 58130fdc8d8SChris Lattner if (sc.function) 582dda4f7b5SGreg Clayton range = sc.function->GetAddressRange(); 583e7612134SGreg Clayton else if (sc.symbol && sc.symbol->ValueIsAddress()) 584e7612134SGreg Clayton { 585e7612134SGreg Clayton range.GetBaseAddress() = sc.symbol->GetAddress(); 586e7612134SGreg Clayton range.SetByteSize (sc.symbol->GetByteSize()); 587e7612134SGreg Clayton } 58830fdc8d8SChris Lattner else 589c14ee32dSGreg Clayton range.GetBaseAddress() = frame->GetFrameCodeAddress(); 59030fdc8d8SChris Lattner } 59130fdc8d8SChris Lattner else 59230fdc8d8SChris Lattner { 59330fdc8d8SChris Lattner result.AppendError ("invalid frame"); 59430fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 59530fdc8d8SChris Lattner return false; 59630fdc8d8SChris Lattner } 5972f2c876eSJim Ingham ranges.push_back(range); 59830fdc8d8SChris Lattner } 5992f2c876eSJim Ingham 6002f2c876eSJim Ingham bool print_sc_header = ranges.size() > 1; 6012f2c876eSJim Ingham for (AddressRange cur_range : ranges) 6022f2c876eSJim Ingham { 6032f2c876eSJim Ingham if (cur_range.GetByteSize() == 0) 6042f2c876eSJim Ingham cur_range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE); 60530fdc8d8SChris Lattner 606a7015092SGreg Clayton if (Disassembler::Disassemble (m_interpreter.GetDebugger(), 60732e0a750SGreg Clayton m_options.arch, 6081080edbcSGreg Clayton plugin_name, 6090f063ba6SJim Ingham flavor_string, 610f9fc609fSGreg Clayton m_exe_ctx, 6112f2c876eSJim Ingham cur_range, 61237023b06SJim Ingham m_options.num_instructions, 613dda4f7b5SGreg Clayton m_options.show_mixed ? m_options.num_lines_context : 0, 6141da6f9d7SGreg Clayton options, 615dda4f7b5SGreg Clayton result.GetOutputStream())) 61630fdc8d8SChris Lattner { 617dda4f7b5SGreg Clayton result.SetStatus (eReturnStatusSuccessFinishResult); 61830fdc8d8SChris Lattner } 61930fdc8d8SChris Lattner else 62030fdc8d8SChris Lattner { 621d01b2953SDaniel Malea result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8" PRIx64 ".\n", m_options.start_addr); 62230fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 62330fdc8d8SChris Lattner } 6242f2c876eSJim Ingham if (print_sc_header) 6252f2c876eSJim Ingham result.AppendMessage("\n"); 6262f2c876eSJim Ingham } 62730fdc8d8SChris Lattner } 62837023b06SJim Ingham } 62930fdc8d8SChris Lattner 63030fdc8d8SChris Lattner return result.Succeeded(); 63130fdc8d8SChris Lattner } 632