003 File Manager
Current Path:
/usr/src/contrib/llvm-project/lldb/source/Commands
usr
/
src
/
contrib
/
llvm-project
/
lldb
/
source
/
Commands
/
📁
..
📄
CommandCompletions.cpp
(21.8 KB)
📄
CommandObjectApropos.cpp
(3.61 KB)
📄
CommandObjectApropos.h
(904 B)
📄
CommandObjectBreakpoint.cpp
(81.05 KB)
📄
CommandObjectBreakpoint.h
(1.72 KB)
📄
CommandObjectBreakpointCommand.cpp
(25.81 KB)
📄
CommandObjectBreakpointCommand.h
(902 B)
📄
CommandObjectCommands.cpp
(63.2 KB)
📄
CommandObjectCommands.h
(877 B)
📄
CommandObjectDisassemble.cpp
(17.74 KB)
📄
CommandObjectDisassemble.h
(3.05 KB)
📄
CommandObjectExpression.cpp
(23.86 KB)
📄
CommandObjectExpression.h
(3.63 KB)
📄
CommandObjectFrame.cpp
(42.35 KB)
📄
CommandObjectFrame.h
(852 B)
📄
CommandObjectGUI.cpp
(1.79 KB)
📄
CommandObjectGUI.h
(870 B)
📄
CommandObjectHelp.cpp
(8.53 KB)
📄
CommandObjectHelp.h
(2.35 KB)
📄
CommandObjectLanguage.cpp
(933 B)
📄
CommandObjectLanguage.h
(883 B)
📄
CommandObjectLog.cpp
(17.02 KB)
📄
CommandObjectLog.h
(1004 B)
📄
CommandObjectMemory.cpp
(61.7 KB)
📄
CommandObjectMemory.h
(799 B)
📄
CommandObjectMultiword.cpp
(13.54 KB)
📄
CommandObjectPlatform.cpp
(61.17 KB)
📄
CommandObjectPlatform.h
(997 B)
📄
CommandObjectPlugin.cpp
(2.68 KB)
📄
CommandObjectPlugin.h
(799 B)
📄
CommandObjectProcess.cpp
(55.63 KB)
📄
CommandObjectProcess.h
(866 B)
📄
CommandObjectQuit.cpp
(3.81 KB)
📄
CommandObjectQuit.h
(930 B)
📄
CommandObjectRegister.cpp
(15.66 KB)
📄
CommandObjectRegister.h
(1.04 KB)
📄
CommandObjectReproducer.cpp
(17.86 KB)
📄
CommandObjectReproducer.h
(851 B)
📄
CommandObjectSettings.cpp
(38.87 KB)
📄
CommandObjectSettings.h
(873 B)
📄
CommandObjectSource.cpp
(47.71 KB)
📄
CommandObjectSource.h
(863 B)
📄
CommandObjectStats.cpp
(3.52 KB)
📄
CommandObjectStats.h
(791 B)
📄
CommandObjectTarget.cpp
(177.86 KB)
📄
CommandObjectTarget.h
(859 B)
📄
CommandObjectThread.cpp
(78.3 KB)
📄
CommandObjectThread.h
(826 B)
📄
CommandObjectType.cpp
(98.61 KB)
📄
CommandObjectType.h
(774 B)
📄
CommandObjectVersion.cpp
(1.18 KB)
📄
CommandObjectVersion.h
(898 B)
📄
CommandObjectWatchpoint.cpp
(40.55 KB)
📄
CommandObjectWatchpoint.h
(1.04 KB)
📄
CommandObjectWatchpointCommand.cpp
(23.68 KB)
📄
CommandObjectWatchpointCommand.h
(902 B)
📄
Options.td
(58.93 KB)
📄
OptionsBase.td
(7.3 KB)
Editing: CommandObjectDisassemble.cpp
//===-- CommandObjectDisassemble.cpp --------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "CommandObjectDisassemble.h" #include "lldb/Core/AddressRange.h" #include "lldb/Core/Disassembler.h" #include "lldb/Core/Module.h" #include "lldb/Host/OptionParser.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/OptionArgParser.h" #include "lldb/Interpreter/Options.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Target/SectionLoadList.h" #include "lldb/Target/StackFrame.h" #include "lldb/Target/Target.h" static constexpr unsigned default_disasm_byte_size = 32; static constexpr unsigned default_disasm_num_ins = 4; static constexpr unsigned large_function_threshold = 8000; using namespace lldb; using namespace lldb_private; #define LLDB_OPTIONS_disassemble #include "CommandOptions.inc" 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; Status CommandObjectDisassemble::CommandOptions::SetOptionValue( uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) { Status 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 = OptionArgParser::ToAddress(execution_context, option_arg, LLDB_INVALID_ADDRESS, &error); if (start_addr != LLDB_INVALID_ADDRESS) some_location_specified = true; } break; case 'e': { end_addr = OptionArgParser::ToAddress(execution_context, option_arg, LLDB_INVALID_ADDRESS, &error); if (end_addr != LLDB_INVALID_ADDRESS) some_location_specified = true; } break; case 'n': func_name.assign(std::string(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(std::string(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(std::string(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) { const auto &target_sp = execution_context->GetTargetSP(); auto platform_ptr = target_sp ? target_sp->GetPlatform().get() : nullptr; arch = Platform::GetAugmentedArchSpec(platform_ptr, option_arg); } break; case 'a': { symbol_containing_addr = OptionArgParser::ToAddress( execution_context, option_arg, LLDB_INVALID_ADDRESS, &error); if (symbol_containing_addr != LLDB_INVALID_ADDRESS) { some_location_specified = true; } } break; case '\x01': force = true; break; default: llvm_unreachable("Unimplemented option"); } 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; force = false; } Status CommandObjectDisassemble::CommandOptions::OptionParsingFinished( ExecutionContext *execution_context) { if (!some_location_specified) current_function = true; return Status(); } llvm::ArrayRef<OptionDefinition> 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 [<cmd-options>]", eCommandRequiresTarget), m_options() {} CommandObjectDisassemble::~CommandObjectDisassemble() = default; llvm::Error CommandObjectDisassemble::CheckRangeSize(const AddressRange &range, llvm::StringRef what) { if (m_options.num_instructions > 0 || m_options.force || range.GetByteSize() < large_function_threshold) return llvm::Error::success(); StreamString msg; msg << "Not disassembling " << what << " because it is very large "; range.Dump(&msg, &GetSelectedTarget(), Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress); msg << ". To disassemble specify an instruction count limit, start/stop " "addresses or use the --force option."; return llvm::createStringError(llvm::inconvertibleErrorCode(), msg.GetString()); } llvm::Expected<std::vector<AddressRange>> CommandObjectDisassemble::GetContainingAddressRanges() { std::vector<AddressRange> ranges; const auto &get_range = [&](Address addr) { ModuleSP module_sp(addr.GetModule()); SymbolContext sc; bool resolve_tail_call_address = true; addr.GetModule()->ResolveSymbolContextForAddress( addr, eSymbolContextEverything, sc, resolve_tail_call_address); if (sc.function || sc.symbol) { AddressRange range; sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0, false, range); ranges.push_back(range); } }; Target &target = GetSelectedTarget(); if (!target.GetSectionLoadList().IsEmpty()) { Address symbol_containing_address; if (target.GetSectionLoadList().ResolveLoadAddress( m_options.symbol_containing_addr, symbol_containing_address)) { get_range(symbol_containing_address); } } else { for (lldb::ModuleSP module_sp : target.GetImages().Modules()) { Address file_address; if (module_sp->ResolveFileAddress(m_options.symbol_containing_addr, file_address)) { get_range(file_address); } } } if (ranges.empty()) { return llvm::createStringError( llvm::inconvertibleErrorCode(), "Could not find function bounds for address 0x%" PRIx64, m_options.symbol_containing_addr); } if (llvm::Error err = CheckRangeSize(ranges[0], "the function")) return std::move(err); return ranges; } llvm::Expected<std::vector<AddressRange>> CommandObjectDisassemble::GetCurrentFunctionRanges() { StackFrame *frame = m_exe_ctx.GetFramePtr(); if (!frame) { return llvm::createStringError(llvm::inconvertibleErrorCode(), "Cannot disassemble around the current " "function without a selected frame.\n"); } SymbolContext sc( frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol)); AddressRange range; if (sc.function) range = sc.function->GetAddressRange(); else if (sc.symbol && sc.symbol->ValueIsAddress()) { range = {sc.symbol->GetAddress(), sc.symbol->GetByteSize()}; } else range = {frame->GetFrameCodeAddress(), default_disasm_byte_size}; if (llvm::Error err = CheckRangeSize(range, "the current function")) return std::move(err); return std::vector<AddressRange>{range}; } llvm::Expected<std::vector<AddressRange>> CommandObjectDisassemble::GetCurrentLineRanges() { StackFrame *frame = m_exe_ctx.GetFramePtr(); if (!frame) { return llvm::createStringError(llvm::inconvertibleErrorCode(), "Cannot disassemble around the current " "line without a selected frame.\n"); } LineEntry pc_line_entry( frame->GetSymbolContext(eSymbolContextLineEntry).line_entry); if (pc_line_entry.IsValid()) return std::vector<AddressRange>{pc_line_entry.range}; // No line entry, so just disassemble around the current pc m_options.show_mixed = false; return GetPCRanges(); } llvm::Expected<std::vector<AddressRange>> CommandObjectDisassemble::GetNameRanges(CommandReturnObject &result) { ConstString name(m_options.func_name.c_str()); const bool include_symbols = true; const bool include_inlines = true; // Find functions matching the given name. SymbolContextList sc_list; GetSelectedTarget().GetImages().FindFunctions( name, eFunctionNameTypeAuto, include_symbols, include_inlines, sc_list); std::vector<AddressRange> ranges; llvm::Error range_errs = llvm::Error::success(); AddressRange range; const uint32_t scope = eSymbolContextBlock | eSymbolContextFunction | eSymbolContextSymbol; const bool use_inline_block_range = true; for (SymbolContext sc : sc_list.SymbolContexts()) { for (uint32_t range_idx = 0; sc.GetAddressRange(scope, range_idx, use_inline_block_range, range); ++range_idx) { if (llvm::Error err = CheckRangeSize(range, "a range")) range_errs = joinErrors(std::move(range_errs), std::move(err)); else ranges.push_back(range); } } if (ranges.empty()) { if (range_errs) return std::move(range_errs); return llvm::createStringError(llvm::inconvertibleErrorCode(), "Unable to find symbol with name '%s'.\n", name.GetCString()); } if (range_errs) result.AppendWarning(toString(std::move(range_errs))); return ranges; } llvm::Expected<std::vector<AddressRange>> CommandObjectDisassemble::GetPCRanges() { StackFrame *frame = m_exe_ctx.GetFramePtr(); if (!frame) { return llvm::createStringError(llvm::inconvertibleErrorCode(), "Cannot disassemble around the current " "PC without a selected frame.\n"); } 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; } return std::vector<AddressRange>{{frame->GetFrameCodeAddress(), 0}}; } llvm::Expected<std::vector<AddressRange>> CommandObjectDisassemble::GetStartEndAddressRanges() { addr_t size = 0; if (m_options.end_addr != LLDB_INVALID_ADDRESS) { if (m_options.end_addr <= m_options.start_addr) { return llvm::createStringError(llvm::inconvertibleErrorCode(), "End address before start address."); } size = m_options.end_addr - m_options.start_addr; } return std::vector<AddressRange>{{Address(m_options.start_addr), size}}; } llvm::Expected<std::vector<AddressRange>> CommandObjectDisassemble::GetRangesForSelectedMode( CommandReturnObject &result) { if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS) return CommandObjectDisassemble::GetContainingAddressRanges(); if (m_options.current_function) return CommandObjectDisassemble::GetCurrentFunctionRanges(); if (m_options.frame_line) return CommandObjectDisassemble::GetCurrentLineRanges(); if (!m_options.func_name.empty()) return CommandObjectDisassemble::GetNameRanges(result); if (m_options.start_addr != LLDB_INVALID_ADDRESS) return CommandObjectDisassemble::GetStartEndAddressRanges(); return CommandObjectDisassemble::GetPCRanges(); } bool CommandObjectDisassemble::DoExecute(Args &command, CommandReturnObject &result) { Target *target = &GetSelectedTarget(); 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; llvm::Expected<std::vector<AddressRange>> ranges = GetRangesForSelectedMode(result); if (!ranges) { result.AppendError(toString(ranges.takeError())); result.SetStatus(eReturnStatusFailed); return result.Succeeded(); } bool print_sc_header = ranges->size() > 1; for (AddressRange cur_range : *ranges) { Disassembler::Limit limit; if (m_options.num_instructions == 0) { limit = {Disassembler::Limit::Bytes, cur_range.GetByteSize()}; if (limit.value == 0) limit.value = default_disasm_byte_size; } else { limit = {Disassembler::Limit::Instructions, m_options.num_instructions}; } if (Disassembler::Disassemble( GetDebugger(), m_options.arch, plugin_name, flavor_string, m_exe_ctx, cur_range.GetBaseAddress(), limit, m_options.show_mixed, m_options.show_mixed ? m_options.num_lines_context : 0, options, result.GetOutputStream())) { result.SetStatus(eReturnStatusSuccessFinishResult); } 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); } else { result.AppendErrorWithFormat( "Failed to disassemble memory at 0x%8.8" PRIx64 ".\n", cur_range.GetBaseAddress().GetLoadAddress(target)); } result.SetStatus(eReturnStatusFailed); } if (print_sc_header) result.GetOutputStream() << "\n"; } return result.Succeeded(); }
Upload File
Create Folder