From 14f1b3e8826ce43b978db93a62d1166055db5394 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Mon, 2 Jan 2017 19:26:05 +0000 Subject: Vendor import of lldb trunk r290819: https://llvm.org/svn/llvm-project/lldb/trunk@290819 --- source/Commands/CommandObjectDisassemble.cpp | 1026 ++++++++++++-------------- 1 file changed, 488 insertions(+), 538 deletions(-) (limited to 'source/Commands/CommandObjectDisassemble.cpp') diff --git a/source/Commands/CommandObjectDisassemble.cpp b/source/Commands/CommandObjectDisassemble.cpp index 07a847aaebae..fa3a1440ffc0 100644 --- a/source/Commands/CommandObjectDisassemble.cpp +++ b/source/Commands/CommandObjectDisassemble.cpp @@ -29,585 +29,535 @@ #include "lldb/Target/Target.h" #define DEFAULT_DISASM_BYTE_SIZE 32 -#define DEFAULT_DISASM_NUM_INS 4 +#define DEFAULT_DISASM_NUM_INS 4 using namespace lldb; using namespace lldb_private; -CommandObjectDisassemble::CommandOptions::CommandOptions (CommandInterpreter &interpreter) : - Options(interpreter), - num_lines_context(0), - num_instructions (0), - func_name(), - current_function (false), - start_addr(), - end_addr (), - at_pc (false), - frame_line (false), - plugin_name (), - flavor_string(), - arch(), - some_location_specified (false), - symbol_containing_addr () -{ - OptionParsingStarting(); +static OptionDefinition g_disassemble_options[] = { + // clang-format off + { LLDB_OPT_SET_ALL, false, "bytes", 'b', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show opcode bytes when disassembling." }, + { LLDB_OPT_SET_ALL, false, "context", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNumLines, "Number of context lines of source to show." }, + { LLDB_OPT_SET_ALL, false, "mixed", 'm', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable mixed source and assembly display." }, + { LLDB_OPT_SET_ALL, false, "raw", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Print raw disassembly with no symbol information." }, + { LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePlugin, "Name of the disassembler plugin you want to use." }, + { LLDB_OPT_SET_ALL, false, "flavor", 'F', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeDisassemblyFlavor, "Name of the disassembly flavor you want to use. " + "Currently the only valid options are default, and for Intel " + "architectures, att and intel." }, + { LLDB_OPT_SET_ALL, false, "arch", 'A', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeArchitecture, "Specify the architecture to use from cross disassembly." }, + { LLDB_OPT_SET_1 | + LLDB_OPT_SET_2, true, "start-address", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Address at which to start disassembling." }, + { LLDB_OPT_SET_1, false, "end-address", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Address at which to end disassembling." }, + { LLDB_OPT_SET_2 | + LLDB_OPT_SET_3 | + LLDB_OPT_SET_4 | + LLDB_OPT_SET_5, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNumLines, "Number of instructions to display." }, + { LLDB_OPT_SET_3, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Disassemble entire contents of the given function name." }, + { LLDB_OPT_SET_4, false, "frame", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Disassemble from the start of the current frame's function." }, + { LLDB_OPT_SET_5, false, "pc", 'p', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Disassemble around the current pc." }, + { 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." }, + { LLDB_OPT_SET_7, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Disassemble function containing this address." }, + // clang-format on +}; + +CommandObjectDisassemble::CommandOptions::CommandOptions() + : Options(), num_lines_context(0), num_instructions(0), func_name(), + current_function(false), start_addr(), end_addr(), at_pc(false), + frame_line(false), plugin_name(), flavor_string(), arch(), + some_location_specified(false), symbol_containing_addr() { + OptionParsingStarting(nullptr); } CommandObjectDisassemble::CommandOptions::~CommandOptions() = default; -Error -CommandObjectDisassemble::CommandOptions::SetOptionValue (uint32_t option_idx, const char *option_arg) -{ - Error error; - - const int short_option = m_getopt_table[option_idx].val; - - bool success; - - switch (short_option) - { - case 'm': - show_mixed = true; - break; - - case 'C': - num_lines_context = StringConvert::ToUInt32(option_arg, 0, 0, &success); - if (!success) - error.SetErrorStringWithFormat ("invalid num context lines string: \"%s\"", option_arg); - break; - - case 'c': - num_instructions = StringConvert::ToUInt32(option_arg, 0, 0, &success); - if (!success) - error.SetErrorStringWithFormat ("invalid num of instructions string: \"%s\"", option_arg); - break; - - case 'b': - show_bytes = true; - break; - - case 's': - { - ExecutionContext exe_ctx (m_interpreter.GetExecutionContext()); - start_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error); - if (start_addr != LLDB_INVALID_ADDRESS) - some_location_specified = true; - } - break; - case 'e': - { - ExecutionContext exe_ctx (m_interpreter.GetExecutionContext()); - end_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error); - if (end_addr != LLDB_INVALID_ADDRESS) - some_location_specified = true; - } - break; - - case 'n': - func_name.assign (option_arg); - some_location_specified = true; - break; - - case 'p': - at_pc = true; - some_location_specified = true; - break; - - case 'l': - frame_line = true; - // Disassemble the current source line kind of implies showing mixed - // source code context. - show_mixed = true; - some_location_specified = true; - break; - - case 'P': - plugin_name.assign (option_arg); - break; - - case 'F': - { - Target *target = m_interpreter.GetExecutionContext().GetTargetPtr(); - if (target->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86 - || target->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86_64) - { - flavor_string.assign (option_arg); - } - else - error.SetErrorStringWithFormat("Disassembler flavors are currently only supported for x86 and x86_64 targets."); - break; - } - - case 'r': - raw = true; - break; - - case 'f': - current_function = true; - some_location_specified = true; - break; - - case 'A': - if (!arch.SetTriple (option_arg, m_interpreter.GetPlatform (true).get())) - arch.SetTriple (option_arg); - break; - - case 'a': - { - ExecutionContext exe_ctx (m_interpreter.GetExecutionContext()); - symbol_containing_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error); - if (symbol_containing_addr != LLDB_INVALID_ADDRESS) - { - some_location_specified = true; - } - } - break; +Error CommandObjectDisassemble::CommandOptions::SetOptionValue( + uint32_t option_idx, llvm::StringRef option_arg, + ExecutionContext *execution_context) { + Error error; + + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 'm': + show_mixed = true; + break; + + case 'C': + if (option_arg.getAsInteger(0, num_lines_context)) + error.SetErrorStringWithFormat("invalid num context lines string: \"%s\"", + option_arg.str().c_str()); + break; + + case 'c': + if (option_arg.getAsInteger(0, num_instructions)) + error.SetErrorStringWithFormat( + "invalid num of instructions string: \"%s\"", + option_arg.str().c_str()); + break; + + case 'b': + show_bytes = true; + break; + + case 's': { + start_addr = Args::StringToAddress(execution_context, option_arg, + LLDB_INVALID_ADDRESS, &error); + if (start_addr != LLDB_INVALID_ADDRESS) + some_location_specified = true; + } break; + case 'e': { + end_addr = Args::StringToAddress(execution_context, option_arg, + LLDB_INVALID_ADDRESS, &error); + if (end_addr != LLDB_INVALID_ADDRESS) + some_location_specified = true; + } break; + + case 'n': + func_name.assign(option_arg); + some_location_specified = true; + break; + + case 'p': + at_pc = true; + some_location_specified = true; + break; + + case 'l': + frame_line = true; + // Disassemble the current source line kind of implies showing mixed + // source code context. + show_mixed = true; + some_location_specified = true; + break; + + case 'P': + plugin_name.assign(option_arg); + break; + + case 'F': { + TargetSP target_sp = + execution_context ? execution_context->GetTargetSP() : TargetSP(); + if (target_sp && (target_sp->GetArchitecture().GetTriple().getArch() == + llvm::Triple::x86 || + target_sp->GetArchitecture().GetTriple().getArch() == + llvm::Triple::x86_64)) { + flavor_string.assign(option_arg); + } else + error.SetErrorStringWithFormat("Disassembler flavors are currently only " + "supported for x86 and x86_64 targets."); + break; + } + + case 'r': + raw = true; + break; + + case 'f': + current_function = true; + some_location_specified = true; + break; + + case 'A': + if (execution_context) { + auto target_sp = + execution_context ? execution_context->GetTargetSP() : TargetSP(); + auto platform_sp = target_sp ? target_sp->GetPlatform() : PlatformSP(); + if (!arch.SetTriple(option_arg, platform_sp.get())) + arch.SetTriple(option_arg); + } + break; - default: - error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); - break; + case 'a': { + symbol_containing_addr = Args::StringToAddress( + execution_context, option_arg, LLDB_INVALID_ADDRESS, &error); + if (symbol_containing_addr != LLDB_INVALID_ADDRESS) { + some_location_specified = true; } + } break; - return error; -} + default: + error.SetErrorStringWithFormat("unrecognized short option '%c'", + short_option); + break; + } -void -CommandObjectDisassemble::CommandOptions::OptionParsingStarting () -{ - show_mixed = false; - show_bytes = false; - num_lines_context = 0; - num_instructions = 0; - func_name.clear(); - current_function = false; - at_pc = false; - frame_line = false; - start_addr = LLDB_INVALID_ADDRESS; - end_addr = LLDB_INVALID_ADDRESS; - symbol_containing_addr = LLDB_INVALID_ADDRESS; - raw = false; - plugin_name.clear(); - - Target *target = m_interpreter.GetExecutionContext().GetTargetPtr(); - - // This is a hack till we get the ability to specify features based on architecture. For now GetDisassemblyFlavor - // is really only valid for x86 (and for the llvm assembler plugin, but I'm papering over that since that is the - // only disassembler plugin we have... - if (target) - { - if (target->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86 - || target->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86_64) - { - flavor_string.assign(target->GetDisassemblyFlavor()); - } - else - flavor_string.assign ("default"); - - } - else - flavor_string.assign("default"); - - arch.Clear(); - some_location_specified = false; + return error; } -Error -CommandObjectDisassemble::CommandOptions::OptionParsingFinished () -{ - if (!some_location_specified) - current_function = true; - return Error(); +void CommandObjectDisassemble::CommandOptions::OptionParsingStarting( + ExecutionContext *execution_context) { + show_mixed = false; + show_bytes = false; + num_lines_context = 0; + num_instructions = 0; + func_name.clear(); + current_function = false; + at_pc = false; + frame_line = false; + start_addr = LLDB_INVALID_ADDRESS; + end_addr = LLDB_INVALID_ADDRESS; + symbol_containing_addr = LLDB_INVALID_ADDRESS; + raw = false; + plugin_name.clear(); + + Target *target = + execution_context ? execution_context->GetTargetPtr() : nullptr; + + // This is a hack till we get the ability to specify features based on + // architecture. For now GetDisassemblyFlavor + // is really only valid for x86 (and for the llvm assembler plugin, but I'm + // papering over that since that is the + // only disassembler plugin we have... + if (target) { + if (target->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86 || + target->GetArchitecture().GetTriple().getArch() == + llvm::Triple::x86_64) { + flavor_string.assign(target->GetDisassemblyFlavor()); + } else + flavor_string.assign("default"); + + } else + flavor_string.assign("default"); + + arch.Clear(); + some_location_specified = false; } -const OptionDefinition* -CommandObjectDisassemble::CommandOptions::GetDefinitions () -{ - return g_option_table; +Error CommandObjectDisassemble::CommandOptions::OptionParsingFinished( + ExecutionContext *execution_context) { + if (!some_location_specified) + current_function = true; + return Error(); } -OptionDefinition -CommandObjectDisassemble::CommandOptions::g_option_table[] = -{ -{ LLDB_OPT_SET_ALL, false, "bytes" , 'b', OptionParser::eNoArgument , nullptr, nullptr, 0, eArgTypeNone, "Show opcode bytes when disassembling."}, -{ LLDB_OPT_SET_ALL, false, "context" , 'C', OptionParser::eRequiredArgument , nullptr, nullptr, 0, eArgTypeNumLines, "Number of context lines of source to show."}, -{ LLDB_OPT_SET_ALL, false, "mixed" , 'm', OptionParser::eNoArgument , nullptr, nullptr, 0, eArgTypeNone, "Enable mixed source and assembly display."}, -{ LLDB_OPT_SET_ALL, false, "raw" , 'r', OptionParser::eNoArgument , nullptr, nullptr, 0, eArgTypeNone, "Print raw disassembly with no symbol information."}, -{ LLDB_OPT_SET_ALL, false, "plugin" , 'P', OptionParser::eRequiredArgument , nullptr, nullptr, 0, eArgTypePlugin, "Name of the disassembler plugin you want to use."}, -{ LLDB_OPT_SET_ALL, false, "flavor" , 'F', OptionParser::eRequiredArgument , nullptr, nullptr, 0, eArgTypeDisassemblyFlavor, "Name of the disassembly flavor you want to use. " - "Currently the only valid options are default, and for Intel" - " architectures, att and intel."}, -{ LLDB_OPT_SET_ALL, false, "arch" , 'A', OptionParser::eRequiredArgument , nullptr, nullptr, 0, eArgTypeArchitecture,"Specify the architecture to use from cross disassembly."}, -{ LLDB_OPT_SET_1 | - LLDB_OPT_SET_2 , true , "start-address", 's', OptionParser::eRequiredArgument , nullptr, nullptr, 0, eArgTypeAddressOrExpression,"Address at which to start disassembling."}, -{ LLDB_OPT_SET_1 , false, "end-address" , 'e', OptionParser::eRequiredArgument , nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Address at which to end disassembling."}, -{ LLDB_OPT_SET_2 | - LLDB_OPT_SET_3 | - LLDB_OPT_SET_4 | - LLDB_OPT_SET_5 , false, "count" , 'c', OptionParser::eRequiredArgument , nullptr, nullptr, 0, eArgTypeNumLines, "Number of instructions to display."}, -{ LLDB_OPT_SET_3 , false, "name" , 'n', OptionParser::eRequiredArgument , nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, - "Disassemble entire contents of the given function name."}, -{ LLDB_OPT_SET_4 , false, "frame" , 'f', OptionParser::eNoArgument , nullptr, nullptr, 0, eArgTypeNone, "Disassemble from the start of the current frame's function."}, -{ LLDB_OPT_SET_5 , false, "pc" , 'p', OptionParser::eNoArgument , nullptr, nullptr, 0, eArgTypeNone, "Disassemble around the current pc."}, -{ 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."}, -{ LLDB_OPT_SET_7 , false, "address" , 'a', OptionParser::eRequiredArgument , nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Disassemble function containing this address."}, -{ 0 , false, nullptr , 0, 0 , nullptr, nullptr, 0, eArgTypeNone, nullptr } -}; +llvm::ArrayRef +CommandObjectDisassemble::CommandOptions::GetDefinitions() { + return llvm::makeArrayRef(g_disassemble_options); +} //------------------------------------------------------------------------- // CommandObjectDisassemble //------------------------------------------------------------------------- -CommandObjectDisassemble::CommandObjectDisassemble(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "disassemble", "Disassemble specified instructions in the current target. " - "Defaults to the current function for the current thread and " - "stack frame.", - "disassemble []"), - m_options(interpreter) -{ -} +CommandObjectDisassemble::CommandObjectDisassemble( + CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "disassemble", + "Disassemble specified instructions in the current target. " + "Defaults to the current function for the current thread and " + "stack frame.", + "disassemble []"), + m_options() {} CommandObjectDisassemble::~CommandObjectDisassemble() = default; -bool -CommandObjectDisassemble::DoExecute (Args& command, CommandReturnObject &result) -{ - Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); - if (target == nullptr) - { - result.AppendError ("invalid target, create a debug target using the 'target create' command"); - result.SetStatus (eReturnStatusFailed); - return false; +bool CommandObjectDisassemble::DoExecute(Args &command, + CommandReturnObject &result) { + Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + if (target == nullptr) { + result.AppendError("invalid target, create a debug target using the " + "'target create' command"); + result.SetStatus(eReturnStatusFailed); + return false; + } + if (!m_options.arch.IsValid()) + m_options.arch = target->GetArchitecture(); + + if (!m_options.arch.IsValid()) { + result.AppendError( + "use the --arch option or set the target architecture to disassemble"); + result.SetStatus(eReturnStatusFailed); + return false; + } + + const char *plugin_name = m_options.GetPluginName(); + const char *flavor_string = m_options.GetFlavorString(); + + DisassemblerSP disassembler = + Disassembler::FindPlugin(m_options.arch, flavor_string, plugin_name); + + if (!disassembler) { + if (plugin_name) { + result.AppendErrorWithFormat( + "Unable to find Disassembler plug-in named '%s' that supports the " + "'%s' architecture.\n", + plugin_name, m_options.arch.GetArchitectureName()); + } else + result.AppendErrorWithFormat( + "Unable to find Disassembler plug-in for the '%s' architecture.\n", + m_options.arch.GetArchitectureName()); + result.SetStatus(eReturnStatusFailed); + return false; + } else if (flavor_string != nullptr && + !disassembler->FlavorValidForArchSpec(m_options.arch, + flavor_string)) + result.AppendWarningWithFormat( + "invalid disassembler flavor \"%s\", using default.\n", flavor_string); + + result.SetStatus(eReturnStatusSuccessFinishResult); + + if (!command.empty()) { + result.AppendErrorWithFormat( + "\"disassemble\" arguments are specified as options.\n"); + const int terminal_width = + GetCommandInterpreter().GetDebugger().GetTerminalWidth(); + GetOptions()->GenerateOptionUsage(result.GetErrorStream(), this, + terminal_width); + result.SetStatus(eReturnStatusFailed); + return false; + } + + if (m_options.show_mixed && m_options.num_lines_context == 0) + m_options.num_lines_context = 2; + + // Always show the PC in the disassembly + uint32_t options = Disassembler::eOptionMarkPCAddress; + + // Mark the source line for the current PC only if we are doing mixed source + // and assembly + if (m_options.show_mixed) + options |= Disassembler::eOptionMarkPCSourceLine; + + if (m_options.show_bytes) + options |= Disassembler::eOptionShowBytes; + + if (m_options.raw) + options |= Disassembler::eOptionRawOuput; + + if (!m_options.func_name.empty()) { + ConstString name(m_options.func_name.c_str()); + + if (Disassembler::Disassemble( + m_interpreter.GetDebugger(), m_options.arch, plugin_name, + flavor_string, m_exe_ctx, name, + nullptr, // Module * + m_options.num_instructions, m_options.show_mixed, + m_options.show_mixed ? m_options.num_lines_context : 0, options, + result.GetOutputStream())) { + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendErrorWithFormat("Unable to find symbol with name '%s'.\n", + name.GetCString()); + result.SetStatus(eReturnStatusFailed); } - if (!m_options.arch.IsValid()) - m_options.arch = target->GetArchitecture(); - - if (!m_options.arch.IsValid()) - { - result.AppendError ("use the --arch option or set the target architecture to disassemble"); - result.SetStatus (eReturnStatusFailed); + } else { + std::vector ranges; + AddressRange range; + StackFrame *frame = m_exe_ctx.GetFramePtr(); + if (m_options.frame_line) { + if (frame == nullptr) { + result.AppendError("Cannot disassemble around the current line without " + "a selected frame.\n"); + result.SetStatus(eReturnStatusFailed); return false; - } - - const char *plugin_name = m_options.GetPluginName (); - const char *flavor_string = m_options.GetFlavorString(); - - DisassemblerSP disassembler = Disassembler::FindPlugin(m_options.arch, flavor_string, plugin_name); - - if (!disassembler) - { - if (plugin_name) - { - result.AppendErrorWithFormat ("Unable to find Disassembler plug-in named '%s' that supports the '%s' architecture.\n", - plugin_name, - m_options.arch.GetArchitectureName()); - } - else - result.AppendErrorWithFormat ("Unable to find Disassembler plug-in for the '%s' architecture.\n", - m_options.arch.GetArchitectureName()); - result.SetStatus (eReturnStatusFailed); + } + LineEntry pc_line_entry( + frame->GetSymbolContext(eSymbolContextLineEntry).line_entry); + if (pc_line_entry.IsValid()) { + range = pc_line_entry.range; + } else { + m_options.at_pc = + true; // No line entry, so just disassemble around the current pc + m_options.show_mixed = false; + } + } else if (m_options.current_function) { + if (frame == nullptr) { + result.AppendError("Cannot disassemble around the current function " + "without a selected frame.\n"); + result.SetStatus(eReturnStatusFailed); return false; + } + Symbol *symbol = frame->GetSymbolContext(eSymbolContextSymbol).symbol; + if (symbol) { + range.GetBaseAddress() = symbol->GetAddress(); + range.SetByteSize(symbol->GetByteSize()); + } } - else if (flavor_string != nullptr && !disassembler->FlavorValidForArchSpec(m_options.arch, flavor_string)) - result.AppendWarningWithFormat("invalid disassembler flavor \"%s\", using default.\n", flavor_string); - result.SetStatus (eReturnStatusSuccessFinishResult); - - if (command.GetArgumentCount() != 0) - { - result.AppendErrorWithFormat ("\"disassemble\" arguments are specified as options.\n"); - GetOptions()->GenerateOptionUsage (result.GetErrorStream(), this); - result.SetStatus (eReturnStatusFailed); - return false; - } - - if (m_options.show_mixed && m_options.num_lines_context == 0) - m_options.num_lines_context = 1; - - // Always show the PC in the disassembly - uint32_t options = Disassembler::eOptionMarkPCAddress; - - // Mark the source line for the current PC only if we are doing mixed source and assembly - if (m_options.show_mixed) - options |= Disassembler::eOptionMarkPCSourceLine; - - if (m_options.show_bytes) - options |= Disassembler::eOptionShowBytes; - - if (m_options.raw) - options |= Disassembler::eOptionRawOuput; - - if (!m_options.func_name.empty()) - { - ConstString name(m_options.func_name.c_str()); - - if (Disassembler::Disassemble(m_interpreter.GetDebugger(), - m_options.arch, - plugin_name, - flavor_string, - m_exe_ctx, - name, - nullptr, // Module * - m_options.num_instructions, - m_options.show_mixed ? m_options.num_lines_context : 0, - options, - result.GetOutputStream())) - { - result.SetStatus (eReturnStatusSuccessFinishResult); + // Did the "m_options.frame_line" find a valid range already? If so + // skip the rest... + if (range.GetByteSize() == 0) { + if (m_options.at_pc) { + if (frame == nullptr) { + result.AppendError("Cannot disassemble around the current PC without " + "a selected frame.\n"); + result.SetStatus(eReturnStatusFailed); + return false; } - else - { - result.AppendErrorWithFormat ("Unable to find symbol with name '%s'.\n", name.GetCString()); - result.SetStatus (eReturnStatusFailed); + range.GetBaseAddress() = frame->GetFrameCodeAddress(); + if (m_options.num_instructions == 0) { + // Disassembling at the PC always disassembles some number of + // instructions (not the whole function). + m_options.num_instructions = DEFAULT_DISASM_NUM_INS; } - } - else - { - std::vector ranges; - AddressRange range; - StackFrame *frame = m_exe_ctx.GetFramePtr(); - if (m_options.frame_line) - { - if (frame == nullptr) - { - result.AppendError ("Cannot disassemble around the current line without a selected frame.\n"); - result.SetStatus (eReturnStatusFailed); - return false; - } - LineEntry pc_line_entry (frame->GetSymbolContext(eSymbolContextLineEntry).line_entry); - if (pc_line_entry.IsValid()) - { - range = pc_line_entry.range; + ranges.push_back(range); + } else { + range.GetBaseAddress().SetOffset(m_options.start_addr); + if (range.GetBaseAddress().IsValid()) { + if (m_options.end_addr != LLDB_INVALID_ADDRESS) { + if (m_options.end_addr <= m_options.start_addr) { + result.AppendErrorWithFormat( + "End address before start address.\n"); + result.SetStatus(eReturnStatusFailed); + return false; } - else - { - m_options.at_pc = true; // No line entry, so just disassemble around the current pc - m_options.show_mixed = false; - } - } - else if (m_options.current_function) - { - if (frame == nullptr) - { - result.AppendError ("Cannot disassemble around the current function without a selected frame.\n"); - result.SetStatus (eReturnStatusFailed); - return false; - } - Symbol *symbol = frame->GetSymbolContext(eSymbolContextSymbol).symbol; - if (symbol) - { - range.GetBaseAddress() = symbol->GetAddress(); - range.SetByteSize(symbol->GetByteSize()); - } - } - - // Did the "m_options.frame_line" find a valid range already? If so - // skip the rest... - if (range.GetByteSize() == 0) - { - if (m_options.at_pc) - { - if (frame == nullptr) - { - result.AppendError ("Cannot disassemble around the current PC without a selected frame.\n"); - result.SetStatus (eReturnStatusFailed); - return false; + range.SetByteSize(m_options.end_addr - m_options.start_addr); + } + ranges.push_back(range); + } else { + if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS && + target) { + if (!target->GetSectionLoadList().IsEmpty()) { + bool failed = false; + Address symbol_containing_address; + if (target->GetSectionLoadList().ResolveLoadAddress( + m_options.symbol_containing_addr, + symbol_containing_address)) { + ModuleSP module_sp(symbol_containing_address.GetModule()); + SymbolContext sc; + bool resolve_tail_call_address = true; // PC can be one past the + // address range of the + // function. + module_sp->ResolveSymbolContextForAddress( + symbol_containing_address, eSymbolContextEverything, sc, + resolve_tail_call_address); + if (sc.function || sc.symbol) { + sc.GetAddressRange(eSymbolContextFunction | + eSymbolContextSymbol, + 0, false, range); + } else { + failed = true; } - range.GetBaseAddress() = frame->GetFrameCodeAddress(); - if (m_options.num_instructions == 0) - { - // Disassembling at the PC always disassembles some number of instructions (not the whole function). - m_options.num_instructions = DEFAULT_DISASM_NUM_INS; - } - ranges.push_back(range); - } - else - { - range.GetBaseAddress().SetOffset (m_options.start_addr); - if (range.GetBaseAddress().IsValid()) - { - if (m_options.end_addr != LLDB_INVALID_ADDRESS) - { - if (m_options.end_addr <= m_options.start_addr) - { - result.AppendErrorWithFormat ("End address before start address.\n"); - result.SetStatus (eReturnStatusFailed); - return false; - } - range.SetByteSize (m_options.end_addr - m_options.start_addr); - } + } else { + failed = true; + } + if (failed) { + result.AppendErrorWithFormat( + "Could not find function bounds for address 0x%" PRIx64 + "\n", + m_options.symbol_containing_addr); + result.SetStatus(eReturnStatusFailed); + return false; + } + ranges.push_back(range); + } else { + for (lldb::ModuleSP module_sp : target->GetImages().Modules()) { + lldb::addr_t file_addr = m_options.symbol_containing_addr; + Address file_address; + if (module_sp->ResolveFileAddress(file_addr, file_address)) { + SymbolContext sc; + bool resolve_tail_call_address = true; // PC can be one past + // the address range of + // the function. + module_sp->ResolveSymbolContextForAddress( + file_address, eSymbolContextEverything, sc, + resolve_tail_call_address); + if (sc.function || sc.symbol) { + sc.GetAddressRange(eSymbolContextFunction | + eSymbolContextSymbol, + 0, false, range); ranges.push_back(range); + } } - else - { - if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS - && target) - { - if (!target->GetSectionLoadList().IsEmpty()) - { - bool failed = false; - Address symbol_containing_address; - if (target->GetSectionLoadList().ResolveLoadAddress (m_options.symbol_containing_addr, symbol_containing_address)) - { - ModuleSP module_sp (symbol_containing_address.GetModule()); - SymbolContext sc; - bool resolve_tail_call_address = true; // PC can be one past the address range of the function. - module_sp->ResolveSymbolContextForAddress (symbol_containing_address, eSymbolContextEverything, sc, - resolve_tail_call_address); - if (sc.function || sc.symbol) - { - sc.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, range); - } - else - { - failed = true; - } - } - else - { - failed = true; - } - if (failed) - { - result.AppendErrorWithFormat ("Could not find function bounds for address 0x%" PRIx64 "\n", m_options.symbol_containing_addr); - result.SetStatus (eReturnStatusFailed); - return false; - } - ranges.push_back(range); - } - else - { - for (lldb::ModuleSP module_sp : target->GetImages().Modules()) - { - lldb::addr_t file_addr = m_options.symbol_containing_addr; - Address file_address; - if (module_sp->ResolveFileAddress(file_addr, file_address)) - { - SymbolContext sc; - bool resolve_tail_call_address = true; // PC can be one past the address range of the function. - module_sp->ResolveSymbolContextForAddress (file_address, eSymbolContextEverything, sc, resolve_tail_call_address); - if (sc.function || sc.symbol) - { - sc.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, range); - ranges.push_back(range); - } - } - } - } - } - } + } } + } } - else - ranges.push_back(range); - - if (m_options.num_instructions != 0) - { - if (ranges.empty()) - { - // The default action is to disassemble the current frame function. - if (frame) - { - SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol)); - if (sc.function) - range.GetBaseAddress() = sc.function->GetAddressRange().GetBaseAddress(); - else if (sc.symbol && sc.symbol->ValueIsAddress()) - range.GetBaseAddress() = sc.symbol->GetAddress(); - else - range.GetBaseAddress() = frame->GetFrameCodeAddress(); - } - - if (!range.GetBaseAddress().IsValid()) - { - result.AppendError ("invalid frame"); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - - bool print_sc_header = ranges.size() > 1; - for (AddressRange cur_range : ranges) - { - if (Disassembler::Disassemble (m_interpreter.GetDebugger(), - m_options.arch, - plugin_name, - flavor_string, - m_exe_ctx, - cur_range.GetBaseAddress(), - m_options.num_instructions, - m_options.show_mixed ? m_options.num_lines_context : 0, - options, - result.GetOutputStream())) - { - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - if (m_options.start_addr != LLDB_INVALID_ADDRESS) - result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8" PRIx64 ".\n", m_options.start_addr); - else if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS) - result.AppendErrorWithFormat ("Failed to disassemble memory in function at 0x%8.8" PRIx64 ".\n", m_options.symbol_containing_addr); - result.SetStatus (eReturnStatusFailed); - } - } - if (print_sc_header) - result.AppendMessage("\n"); + } + } else + ranges.push_back(range); + + if (m_options.num_instructions != 0) { + if (ranges.empty()) { + // The default action is to disassemble the current frame function. + if (frame) { + SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction | + eSymbolContextSymbol)); + if (sc.function) + range.GetBaseAddress() = + sc.function->GetAddressRange().GetBaseAddress(); + else if (sc.symbol && sc.symbol->ValueIsAddress()) + range.GetBaseAddress() = sc.symbol->GetAddress(); + else + range.GetBaseAddress() = frame->GetFrameCodeAddress(); } - else - { - if (ranges.empty()) - { - // The default action is to disassemble the current frame function. - if (frame) - { - SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol)); - if (sc.function) - range = sc.function->GetAddressRange(); - else if (sc.symbol && sc.symbol->ValueIsAddress()) - { - range.GetBaseAddress() = sc.symbol->GetAddress(); - range.SetByteSize (sc.symbol->GetByteSize()); - } - else - range.GetBaseAddress() = frame->GetFrameCodeAddress(); - } - else - { - result.AppendError ("invalid frame"); - result.SetStatus (eReturnStatusFailed); - return false; - } - ranges.push_back(range); - } - - bool print_sc_header = ranges.size() > 1; - for (AddressRange cur_range : ranges) - { - if (cur_range.GetByteSize() == 0) - cur_range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE); - - if (Disassembler::Disassemble (m_interpreter.GetDebugger(), - m_options.arch, - plugin_name, - flavor_string, - m_exe_ctx, - cur_range, - m_options.num_instructions, - m_options.show_mixed ? m_options.num_lines_context : 0, - options, - result.GetOutputStream())) - { - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8" PRIx64 ".\n", m_options.start_addr); - result.SetStatus (eReturnStatusFailed); - } - if (print_sc_header) - result.AppendMessage("\n"); - } + + if (!range.GetBaseAddress().IsValid()) { + result.AppendError("invalid frame"); + result.SetStatus(eReturnStatusFailed); + return false; + } + } + + bool print_sc_header = ranges.size() > 1; + for (AddressRange cur_range : ranges) { + if (Disassembler::Disassemble( + m_interpreter.GetDebugger(), m_options.arch, plugin_name, + flavor_string, m_exe_ctx, cur_range.GetBaseAddress(), + m_options.num_instructions, m_options.show_mixed, + m_options.show_mixed ? m_options.num_lines_context : 0, options, + result.GetOutputStream())) { + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + if (m_options.start_addr != LLDB_INVALID_ADDRESS) + result.AppendErrorWithFormat( + "Failed to disassemble memory at 0x%8.8" PRIx64 ".\n", + m_options.start_addr); + else if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS) + result.AppendErrorWithFormat( + "Failed to disassemble memory in function at 0x%8.8" PRIx64 + ".\n", + m_options.symbol_containing_addr); + result.SetStatus(eReturnStatusFailed); + } + } + if (print_sc_header) + result.AppendMessage("\n"); + } else { + if (ranges.empty()) { + // The default action is to disassemble the current frame function. + if (frame) { + SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction | + eSymbolContextSymbol)); + if (sc.function) + range = sc.function->GetAddressRange(); + else if (sc.symbol && sc.symbol->ValueIsAddress()) { + range.GetBaseAddress() = sc.symbol->GetAddress(); + range.SetByteSize(sc.symbol->GetByteSize()); + } else + range.GetBaseAddress() = frame->GetFrameCodeAddress(); + } else { + result.AppendError("invalid frame"); + result.SetStatus(eReturnStatusFailed); + return false; + } + ranges.push_back(range); + } + + bool print_sc_header = ranges.size() > 1; + for (AddressRange cur_range : ranges) { + if (cur_range.GetByteSize() == 0) + cur_range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE); + + if (Disassembler::Disassemble( + m_interpreter.GetDebugger(), m_options.arch, plugin_name, + flavor_string, m_exe_ctx, cur_range, m_options.num_instructions, + m_options.show_mixed, + m_options.show_mixed ? m_options.num_lines_context : 0, options, + result.GetOutputStream())) { + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + result.AppendErrorWithFormat( + "Failed to disassemble memory at 0x%8.8" PRIx64 ".\n", + m_options.start_addr); + result.SetStatus(eReturnStatusFailed); } + if (print_sc_header) + result.AppendMessage("\n"); + } } + } - return result.Succeeded(); + return result.Succeeded(); } -- cgit v1.2.3