aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/tools/lldb/source/Commands/CommandObjectFrame.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Commands/CommandObjectFrame.cpp')
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectFrame.cpp1134
1 files changed, 0 insertions, 1134 deletions
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectFrame.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectFrame.cpp
deleted file mode 100644
index ab6a07952f19..000000000000
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectFrame.cpp
+++ /dev/null
@@ -1,1134 +0,0 @@
-//===-- CommandObjectFrame.cpp ----------------------------------*- C++ -*-===//
-//
-// 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 "CommandObjectFrame.h"
-#include "lldb/Core/Debugger.h"
-#include "lldb/Core/Module.h"
-#include "lldb/Core/StreamFile.h"
-#include "lldb/Core/Value.h"
-#include "lldb/Core/ValueObject.h"
-#include "lldb/Core/ValueObjectVariable.h"
-#include "lldb/DataFormatters/DataVisualization.h"
-#include "lldb/DataFormatters/ValueObjectPrinter.h"
-#include "lldb/Host/Host.h"
-#include "lldb/Host/OptionParser.h"
-#include "lldb/Host/StringConvert.h"
-#include "lldb/Interpreter/CommandInterpreter.h"
-#include "lldb/Interpreter/CommandReturnObject.h"
-#include "lldb/Interpreter/OptionGroupFormat.h"
-#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
-#include "lldb/Interpreter/OptionGroupVariable.h"
-#include "lldb/Interpreter/Options.h"
-#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Symbol/CompilerType.h"
-#include "lldb/Symbol/Function.h"
-#include "lldb/Symbol/ObjectFile.h"
-#include "lldb/Symbol/SymbolContext.h"
-#include "lldb/Symbol/Type.h"
-#include "lldb/Symbol/Variable.h"
-#include "lldb/Symbol/VariableList.h"
-#include "lldb/Target/Process.h"
-#include "lldb/Target/StackFrame.h"
-#include "lldb/Target/StackFrameRecognizer.h"
-#include "lldb/Target/StopInfo.h"
-#include "lldb/Target/Target.h"
-#include "lldb/Target/Thread.h"
-#include "lldb/Utility/Args.h"
-#include "lldb/Utility/LLDBAssert.h"
-#include "lldb/Utility/StreamString.h"
-#include "lldb/Utility/Timer.h"
-
-#include <memory>
-#include <string>
-
-using namespace lldb;
-using namespace lldb_private;
-
-#pragma mark CommandObjectFrameDiagnose
-
-// CommandObjectFrameInfo
-
-// CommandObjectFrameDiagnose
-
-static constexpr OptionDefinition g_frame_diag_options[] = {
- // clang-format off
- { LLDB_OPT_SET_1, false, "register", 'r', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeRegisterName, "A register to diagnose." },
- { LLDB_OPT_SET_1, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddress, "An address to diagnose." },
- { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOffset, "An optional offset. Requires --register." }
- // clang-format on
-};
-
-class CommandObjectFrameDiagnose : public CommandObjectParsed {
-public:
- class CommandOptions : public Options {
- public:
- CommandOptions() : Options() { OptionParsingStarting(nullptr); }
-
- ~CommandOptions() override = default;
-
- Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
- ExecutionContext *execution_context) override {
- Status error;
- const int short_option = m_getopt_table[option_idx].val;
- switch (short_option) {
- case 'r':
- reg = ConstString(option_arg);
- break;
-
- case 'a': {
- address.emplace();
- if (option_arg.getAsInteger(0, *address)) {
- address.reset();
- error.SetErrorStringWithFormat("invalid address argument '%s'",
- option_arg.str().c_str());
- }
- } break;
-
- case 'o': {
- offset.emplace();
- if (option_arg.getAsInteger(0, *offset)) {
- offset.reset();
- error.SetErrorStringWithFormat("invalid offset argument '%s'",
- option_arg.str().c_str());
- }
- } break;
-
- default:
- error.SetErrorStringWithFormat("invalid short option character '%c'",
- short_option);
- break;
- }
-
- return error;
- }
-
- void OptionParsingStarting(ExecutionContext *execution_context) override {
- address.reset();
- reg.reset();
- offset.reset();
- }
-
- llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
- return llvm::makeArrayRef(g_frame_diag_options);
- }
-
- // Options.
- llvm::Optional<lldb::addr_t> address;
- llvm::Optional<ConstString> reg;
- llvm::Optional<int64_t> offset;
- };
-
- CommandObjectFrameDiagnose(CommandInterpreter &interpreter)
- : CommandObjectParsed(interpreter, "frame diagnose",
- "Try to determine what path path the current stop "
- "location used to get to a register or address",
- nullptr,
- eCommandRequiresThread | eCommandTryTargetAPILock |
- eCommandProcessMustBeLaunched |
- eCommandProcessMustBePaused),
- m_options() {
- CommandArgumentEntry arg;
- CommandArgumentData index_arg;
-
- // Define the first (and only) variant of this arg.
- index_arg.arg_type = eArgTypeFrameIndex;
- index_arg.arg_repetition = eArgRepeatOptional;
-
- // There is only one variant this argument could be; put it into the
- // argument entry.
- arg.push_back(index_arg);
-
- // Push the data for the first argument into the m_arguments vector.
- m_arguments.push_back(arg);
- }
-
- ~CommandObjectFrameDiagnose() override = default;
-
- Options *GetOptions() override { return &m_options; }
-
-protected:
- bool DoExecute(Args &command, CommandReturnObject &result) override {
- Thread *thread = m_exe_ctx.GetThreadPtr();
- StackFrameSP frame_sp = thread->GetSelectedFrame();
-
- ValueObjectSP valobj_sp;
-
- if (m_options.address.hasValue()) {
- if (m_options.reg.hasValue() || m_options.offset.hasValue()) {
- result.AppendError(
- "`frame diagnose --address` is incompatible with other arguments.");
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
- valobj_sp = frame_sp->GuessValueForAddress(m_options.address.getValue());
- } else if (m_options.reg.hasValue()) {
- valobj_sp = frame_sp->GuessValueForRegisterAndOffset(
- m_options.reg.getValue(), m_options.offset.getValueOr(0));
- } else {
- StopInfoSP stop_info_sp = thread->GetStopInfo();
- if (!stop_info_sp) {
- result.AppendError("No arguments provided, and no stop info.");
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- valobj_sp = StopInfo::GetCrashingDereference(stop_info_sp);
- }
-
- if (!valobj_sp) {
- result.AppendError("No diagnosis available.");
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
-
- DumpValueObjectOptions::DeclPrintingHelper helper = [&valobj_sp](
- ConstString type, ConstString var, const DumpValueObjectOptions &opts,
- Stream &stream) -> bool {
- const ValueObject::GetExpressionPathFormat format = ValueObject::
- GetExpressionPathFormat::eGetExpressionPathFormatHonorPointers;
- const bool qualify_cxx_base_classes = false;
- valobj_sp->GetExpressionPath(stream, qualify_cxx_base_classes, format);
- stream.PutCString(" =");
- return true;
- };
-
- DumpValueObjectOptions options;
- options.SetDeclPrintingHelper(helper);
- ValueObjectPrinter printer(valobj_sp.get(), &result.GetOutputStream(),
- options);
- printer.PrintValueObject();
-
- return true;
- }
-
-protected:
- CommandOptions m_options;
-};
-
-#pragma mark CommandObjectFrameInfo
-
-// CommandObjectFrameInfo
-
-class CommandObjectFrameInfo : public CommandObjectParsed {
-public:
- CommandObjectFrameInfo(CommandInterpreter &interpreter)
- : CommandObjectParsed(
- interpreter, "frame info", "List information about the current "
- "stack frame in the current thread.",
- "frame info",
- eCommandRequiresFrame | eCommandTryTargetAPILock |
- eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {}
-
- ~CommandObjectFrameInfo() override = default;
-
-protected:
- bool DoExecute(Args &command, CommandReturnObject &result) override {
- m_exe_ctx.GetFrameRef().DumpUsingSettingsFormat(&result.GetOutputStream());
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return result.Succeeded();
- }
-};
-
-#pragma mark CommandObjectFrameSelect
-
-// CommandObjectFrameSelect
-
-static OptionDefinition g_frame_select_options[] = {
- // clang-format off
- { LLDB_OPT_SET_1, false, "relative", 'r', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOffset, "A relative frame index offset from the current frame index." },
- // clang-format on
-};
-
-class CommandObjectFrameSelect : public CommandObjectParsed {
-public:
- class CommandOptions : public Options {
- public:
- CommandOptions() : Options() { OptionParsingStarting(nullptr); }
-
- ~CommandOptions() override = default;
-
- Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
- ExecutionContext *execution_context) override {
- Status error;
- const int short_option = m_getopt_table[option_idx].val;
- switch (short_option) {
- case 'r':
- if (option_arg.getAsInteger(0, relative_frame_offset)) {
- relative_frame_offset = INT32_MIN;
- error.SetErrorStringWithFormat("invalid frame offset argument '%s'",
- option_arg.str().c_str());
- }
- break;
-
- default:
- error.SetErrorStringWithFormat("invalid short option character '%c'",
- short_option);
- break;
- }
-
- return error;
- }
-
- void OptionParsingStarting(ExecutionContext *execution_context) override {
- relative_frame_offset = INT32_MIN;
- }
-
- llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
- return llvm::makeArrayRef(g_frame_select_options);
- }
-
- int32_t relative_frame_offset;
- };
-
- CommandObjectFrameSelect(CommandInterpreter &interpreter)
- : CommandObjectParsed(
- interpreter, "frame select", "Select the current stack frame by "
- "index from within the current thread "
- "(see 'thread backtrace'.)",
- nullptr,
- eCommandRequiresThread | eCommandTryTargetAPILock |
- eCommandProcessMustBeLaunched | eCommandProcessMustBePaused),
- m_options() {
- CommandArgumentEntry arg;
- CommandArgumentData index_arg;
-
- // Define the first (and only) variant of this arg.
- index_arg.arg_type = eArgTypeFrameIndex;
- index_arg.arg_repetition = eArgRepeatOptional;
-
- // There is only one variant this argument could be; put it into the
- // argument entry.
- arg.push_back(index_arg);
-
- // Push the data for the first argument into the m_arguments vector.
- m_arguments.push_back(arg);
- }
-
- ~CommandObjectFrameSelect() override = default;
-
- Options *GetOptions() override { return &m_options; }
-
-protected:
- bool DoExecute(Args &command, CommandReturnObject &result) override {
- // No need to check "thread" for validity as eCommandRequiresThread ensures
- // it is valid
- Thread *thread = m_exe_ctx.GetThreadPtr();
-
- uint32_t frame_idx = UINT32_MAX;
- if (m_options.relative_frame_offset != INT32_MIN) {
- // The one and only argument is a signed relative frame index
- frame_idx = thread->GetSelectedFrameIndex();
- if (frame_idx == UINT32_MAX)
- frame_idx = 0;
-
- if (m_options.relative_frame_offset < 0) {
- if (static_cast<int32_t>(frame_idx) >= -m_options.relative_frame_offset)
- frame_idx += m_options.relative_frame_offset;
- else {
- if (frame_idx == 0) {
- // If you are already at the bottom of the stack, then just warn
- // and don't reset the frame.
- result.AppendError("Already at the bottom of the stack.");
- result.SetStatus(eReturnStatusFailed);
- return false;
- } else
- frame_idx = 0;
- }
- } else if (m_options.relative_frame_offset > 0) {
- // I don't want "up 20" where "20" takes you past the top of the stack
- // to produce
- // an error, but rather to just go to the top. So I have to count the
- // stack here...
- const uint32_t num_frames = thread->GetStackFrameCount();
- if (static_cast<int32_t>(num_frames - frame_idx) >
- m_options.relative_frame_offset)
- frame_idx += m_options.relative_frame_offset;
- else {
- if (frame_idx == num_frames - 1) {
- // If we are already at the top of the stack, just warn and don't
- // reset the frame.
- result.AppendError("Already at the top of the stack.");
- result.SetStatus(eReturnStatusFailed);
- return false;
- } else
- frame_idx = num_frames - 1;
- }
- }
- } else {
- if (command.GetArgumentCount() > 1) {
- result.AppendErrorWithFormat(
- "too many arguments; expected frame-index, saw '%s'.\n",
- command[0].c_str());
- m_options.GenerateOptionUsage(
- result.GetErrorStream(), this,
- GetCommandInterpreter().GetDebugger().GetTerminalWidth());
- return false;
- }
-
- if (command.GetArgumentCount() == 1) {
- if (command[0].ref.getAsInteger(0, frame_idx)) {
- result.AppendErrorWithFormat("invalid frame index argument '%s'.",
- command[0].c_str());
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
- } else if (command.GetArgumentCount() == 0) {
- frame_idx = thread->GetSelectedFrameIndex();
- if (frame_idx == UINT32_MAX) {
- frame_idx = 0;
- }
- }
- }
-
- bool success = thread->SetSelectedFrameByIndexNoisily(
- frame_idx, result.GetOutputStream());
- if (success) {
- m_exe_ctx.SetFrameSP(thread->GetSelectedFrame());
- result.SetStatus(eReturnStatusSuccessFinishResult);
- } else {
- result.AppendErrorWithFormat("Frame index (%u) out of range.\n",
- frame_idx);
- result.SetStatus(eReturnStatusFailed);
- }
-
- return result.Succeeded();
- }
-
-protected:
- CommandOptions m_options;
-};
-
-#pragma mark CommandObjectFrameVariable
-// List images with associated information
-class CommandObjectFrameVariable : public CommandObjectParsed {
-public:
- CommandObjectFrameVariable(CommandInterpreter &interpreter)
- : CommandObjectParsed(
- interpreter, "frame variable",
- "Show variables for the current stack frame. Defaults to all "
- "arguments and local variables in scope. Names of argument, "
- "local, file static and file global variables can be specified. "
- "Children of aggregate variables can be specified such as "
- "'var->child.x'. The -> and [] operators in 'frame variable' do "
- "not invoke operator overloads if they exist, but directly access "
- "the specified element. If you want to trigger operator overloads "
- "use the expression command to print the variable instead."
- "\nIt is worth noting that except for overloaded "
- "operators, when printing local variables 'expr local_var' and "
- "'frame var local_var' produce the same "
- "results. However, 'frame variable' is more efficient, since it "
- "uses debug information and memory reads directly, rather than "
- "parsing and evaluating an expression, which may even involve "
- "JITing and running code in the target program.",
- nullptr, eCommandRequiresFrame | eCommandTryTargetAPILock |
- eCommandProcessMustBeLaunched |
- eCommandProcessMustBePaused | eCommandRequiresProcess),
- m_option_group(),
- m_option_variable(
- true), // Include the frame specific options by passing "true"
- m_option_format(eFormatDefault),
- m_varobj_options() {
- CommandArgumentEntry arg;
- CommandArgumentData var_name_arg;
-
- // Define the first (and only) variant of this arg.
- var_name_arg.arg_type = eArgTypeVarName;
- var_name_arg.arg_repetition = eArgRepeatStar;
-
- // There is only one variant this argument could be; put it into the
- // argument entry.
- arg.push_back(var_name_arg);
-
- // Push the data for the first argument into the m_arguments vector.
- m_arguments.push_back(arg);
-
- m_option_group.Append(&m_option_variable, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
- m_option_group.Append(&m_option_format,
- OptionGroupFormat::OPTION_GROUP_FORMAT |
- OptionGroupFormat::OPTION_GROUP_GDB_FMT,
- LLDB_OPT_SET_1);
- m_option_group.Append(&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
- m_option_group.Finalize();
- }
-
- ~CommandObjectFrameVariable() override = default;
-
- Options *GetOptions() override { return &m_option_group; }
-
- int HandleArgumentCompletion(
- CompletionRequest &request,
- OptionElementVector &opt_element_vector) override {
- // Arguments are the standard source file completer.
- CommandCompletions::InvokeCommonCompletionCallbacks(
- GetCommandInterpreter(), CommandCompletions::eVariablePathCompletion,
- request, nullptr);
- return request.GetNumberOfMatches();
- }
-
-protected:
- llvm::StringRef GetScopeString(VariableSP var_sp) {
- if (!var_sp)
- return llvm::StringRef::withNullAsEmpty(nullptr);
-
- switch (var_sp->GetScope()) {
- case eValueTypeVariableGlobal:
- return "GLOBAL: ";
- case eValueTypeVariableStatic:
- return "STATIC: ";
- case eValueTypeVariableArgument:
- return "ARG: ";
- case eValueTypeVariableLocal:
- return "LOCAL: ";
- case eValueTypeVariableThreadLocal:
- return "THREAD: ";
- default:
- break;
- }
-
- return llvm::StringRef::withNullAsEmpty(nullptr);
- }
-
- bool DoExecute(Args &command, CommandReturnObject &result) override {
- // No need to check "frame" for validity as eCommandRequiresFrame ensures
- // it is valid
- StackFrame *frame = m_exe_ctx.GetFramePtr();
-
- Stream &s = result.GetOutputStream();
-
- // Be careful about the stack frame, if any summary formatter runs code, it
- // might clear the StackFrameList for the thread. So hold onto a shared
- // pointer to the frame so it stays alive.
-
- VariableList *variable_list =
- frame->GetVariableList(m_option_variable.show_globals);
-
- VariableSP var_sp;
- ValueObjectSP valobj_sp;
-
- TypeSummaryImplSP summary_format_sp;
- if (!m_option_variable.summary.IsCurrentValueEmpty())
- DataVisualization::NamedSummaryFormats::GetSummaryFormat(
- ConstString(m_option_variable.summary.GetCurrentValue()),
- summary_format_sp);
- else if (!m_option_variable.summary_string.IsCurrentValueEmpty())
- summary_format_sp = std::make_shared<StringSummaryFormat>(
- TypeSummaryImpl::Flags(),
- m_option_variable.summary_string.GetCurrentValue());
-
- DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(
- eLanguageRuntimeDescriptionDisplayVerbosityFull, eFormatDefault,
- summary_format_sp));
-
- const SymbolContext &sym_ctx =
- frame->GetSymbolContext(eSymbolContextFunction);
- if (sym_ctx.function && sym_ctx.function->IsTopLevelFunction())
- m_option_variable.show_globals = true;
-
- if (variable_list) {
- const Format format = m_option_format.GetFormat();
- options.SetFormat(format);
-
- if (!command.empty()) {
- VariableList regex_var_list;
-
- // If we have any args to the variable command, we will make variable
- // objects from them...
- for (auto &entry : command) {
- if (m_option_variable.use_regex) {
- const size_t regex_start_index = regex_var_list.GetSize();
- llvm::StringRef name_str = entry.ref;
- RegularExpression regex(name_str);
- if (regex.Compile(name_str)) {
- size_t num_matches = 0;
- const size_t num_new_regex_vars =
- variable_list->AppendVariablesIfUnique(regex, regex_var_list,
- num_matches);
- if (num_new_regex_vars > 0) {
- for (size_t regex_idx = regex_start_index,
- end_index = regex_var_list.GetSize();
- regex_idx < end_index; ++regex_idx) {
- var_sp = regex_var_list.GetVariableAtIndex(regex_idx);
- if (var_sp) {
- valobj_sp = frame->GetValueObjectForFrameVariable(
- var_sp, m_varobj_options.use_dynamic);
- if (valobj_sp) {
- std::string scope_string;
- if (m_option_variable.show_scope)
- scope_string = GetScopeString(var_sp).str();
-
- if (!scope_string.empty())
- s.PutCString(scope_string);
-
- if (m_option_variable.show_decl &&
- var_sp->GetDeclaration().GetFile()) {
- bool show_fullpaths = false;
- bool show_module = true;
- if (var_sp->DumpDeclaration(&s, show_fullpaths,
- show_module))
- s.PutCString(": ");
- }
- valobj_sp->Dump(result.GetOutputStream(), options);
- }
- }
- }
- } else if (num_matches == 0) {
- result.GetErrorStream().Printf("error: no variables matched "
- "the regular expression '%s'.\n",
- entry.c_str());
- }
- } else {
- char regex_error[1024];
- if (regex.GetErrorAsCString(regex_error, sizeof(regex_error)))
- result.GetErrorStream().Printf("error: %s\n", regex_error);
- else
- result.GetErrorStream().Printf(
- "error: unknown regex error when compiling '%s'\n",
- entry.c_str());
- }
- } else // No regex, either exact variable names or variable
- // expressions.
- {
- Status error;
- uint32_t expr_path_options =
- StackFrame::eExpressionPathOptionCheckPtrVsMember |
- StackFrame::eExpressionPathOptionsAllowDirectIVarAccess |
- StackFrame::eExpressionPathOptionsInspectAnonymousUnions;
- lldb::VariableSP var_sp;
- valobj_sp = frame->GetValueForVariableExpressionPath(
- entry.ref, m_varobj_options.use_dynamic, expr_path_options,
- var_sp, error);
- if (valobj_sp) {
- std::string scope_string;
- if (m_option_variable.show_scope)
- scope_string = GetScopeString(var_sp).str();
-
- if (!scope_string.empty())
- s.PutCString(scope_string);
- if (m_option_variable.show_decl && var_sp &&
- var_sp->GetDeclaration().GetFile()) {
- var_sp->GetDeclaration().DumpStopContext(&s, false);
- s.PutCString(": ");
- }
-
- options.SetFormat(format);
- options.SetVariableFormatDisplayLanguage(
- valobj_sp->GetPreferredDisplayLanguage());
-
- Stream &output_stream = result.GetOutputStream();
- options.SetRootValueObjectName(
- valobj_sp->GetParent() ? entry.c_str() : nullptr);
- valobj_sp->Dump(output_stream, options);
- } else {
- const char *error_cstr = error.AsCString(nullptr);
- if (error_cstr)
- result.GetErrorStream().Printf("error: %s\n", error_cstr);
- else
- result.GetErrorStream().Printf("error: unable to find any "
- "variable expression path that "
- "matches '%s'.\n",
- entry.c_str());
- }
- }
- }
- } else // No command arg specified. Use variable_list, instead.
- {
- const size_t num_variables = variable_list->GetSize();
- if (num_variables > 0) {
- for (size_t i = 0; i < num_variables; i++) {
- var_sp = variable_list->GetVariableAtIndex(i);
- switch (var_sp->GetScope()) {
- case eValueTypeVariableGlobal:
- if (!m_option_variable.show_globals)
- continue;
- break;
- case eValueTypeVariableStatic:
- if (!m_option_variable.show_globals)
- continue;
- break;
- case eValueTypeVariableArgument:
- if (!m_option_variable.show_args)
- continue;
- break;
- case eValueTypeVariableLocal:
- if (!m_option_variable.show_locals)
- continue;
- break;
- default:
- continue;
- break;
- }
- std::string scope_string;
- if (m_option_variable.show_scope)
- scope_string = GetScopeString(var_sp).str();
-
- // Use the variable object code to make sure we are using the same
- // APIs as the public API will be using...
- valobj_sp = frame->GetValueObjectForFrameVariable(
- var_sp, m_varobj_options.use_dynamic);
- if (valobj_sp) {
- // When dumping all variables, don't print any variables that are
- // not in scope to avoid extra unneeded output
- if (valobj_sp->IsInScope()) {
- if (!valobj_sp->GetTargetSP()
- ->GetDisplayRuntimeSupportValues() &&
- valobj_sp->IsRuntimeSupportValue())
- continue;
-
- if (!scope_string.empty())
- s.PutCString(scope_string);
-
- if (m_option_variable.show_decl &&
- var_sp->GetDeclaration().GetFile()) {
- var_sp->GetDeclaration().DumpStopContext(&s, false);
- s.PutCString(": ");
- }
-
- options.SetFormat(format);
- options.SetVariableFormatDisplayLanguage(
- valobj_sp->GetPreferredDisplayLanguage());
- options.SetRootValueObjectName(
- var_sp ? var_sp->GetName().AsCString() : nullptr);
- valobj_sp->Dump(result.GetOutputStream(), options);
- }
- }
- }
- }
- }
- result.SetStatus(eReturnStatusSuccessFinishResult);
- }
-
- if (m_option_variable.show_recognized_args) {
- auto recognized_frame = frame->GetRecognizedFrame();
- if (recognized_frame) {
- ValueObjectListSP recognized_arg_list =
- recognized_frame->GetRecognizedArguments();
- if (recognized_arg_list) {
- for (auto &rec_value_sp : recognized_arg_list->GetObjects()) {
- options.SetFormat(m_option_format.GetFormat());
- options.SetVariableFormatDisplayLanguage(
- rec_value_sp->GetPreferredDisplayLanguage());
- options.SetRootValueObjectName(rec_value_sp->GetName().AsCString());
- rec_value_sp->Dump(result.GetOutputStream(), options);
- }
- }
- }
- }
-
- if (m_interpreter.TruncationWarningNecessary()) {
- result.GetOutputStream().Printf(m_interpreter.TruncationWarningText(),
- m_cmd_name.c_str());
- m_interpreter.TruncationWarningGiven();
- }
-
- // Increment statistics.
- bool res = result.Succeeded();
- Target *target = GetSelectedOrDummyTarget();
- if (res)
- target->IncrementStats(StatisticKind::FrameVarSuccess);
- else
- target->IncrementStats(StatisticKind::FrameVarFailure);
- return res;
- }
-
-protected:
- OptionGroupOptions m_option_group;
- OptionGroupVariable m_option_variable;
- OptionGroupFormat m_option_format;
- OptionGroupValueObjectDisplay m_varobj_options;
-};
-
-#pragma mark CommandObjectFrameRecognizer
-
-static OptionDefinition g_frame_recognizer_add_options[] = {
- // clang-format off
- { LLDB_OPT_SET_ALL, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Name of the module or shared library that this recognizer applies to." },
- { LLDB_OPT_SET_ALL, false, "function", 'n', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeName, "Name of the function that this recognizer applies to." },
- { LLDB_OPT_SET_2, false, "python-class", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonClass, "Give the name of a Python class to use for this frame recognizer." },
- { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Function name and module name are actually regular expressions." }
- // clang-format on
-};
-
-class CommandObjectFrameRecognizerAdd : public CommandObjectParsed {
-private:
- class CommandOptions : public Options {
- public:
- CommandOptions() : Options() {}
- ~CommandOptions() override = default;
-
- Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
- ExecutionContext *execution_context) override {
- Status error;
- const int short_option = m_getopt_table[option_idx].val;
-
- switch (short_option) {
- case 'l':
- m_class_name = std::string(option_arg);
- break;
- case 's':
- m_module = std::string(option_arg);
- break;
- case 'n':
- m_function = std::string(option_arg);
- break;
- case 'x':
- m_regex = true;
- break;
- default:
- error.SetErrorStringWithFormat("unrecognized option '%c'",
- short_option);
- break;
- }
-
- return error;
- }
-
- void OptionParsingStarting(ExecutionContext *execution_context) override {
- m_module = "";
- m_function = "";
- m_class_name = "";
- m_regex = false;
- }
-
- llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
- return llvm::makeArrayRef(g_frame_recognizer_add_options);
- }
-
- // Instance variables to hold the values for command options.
- std::string m_class_name;
- std::string m_module;
- std::string m_function;
- bool m_regex;
- };
-
- CommandOptions m_options;
-
- Options *GetOptions() override { return &m_options; }
-
-protected:
- bool DoExecute(Args &command, CommandReturnObject &result) override;
-
-public:
- CommandObjectFrameRecognizerAdd(CommandInterpreter &interpreter)
- : CommandObjectParsed(interpreter, "frame recognizer add",
- "Add a new frame recognizer.", nullptr),
- m_options() {
- SetHelpLong(R"(
-Frame recognizers allow for retrieving information about special frames based on
-ABI, arguments or other special properties of that frame, even without source
-code or debug info. Currently, one use case is to extract function arguments
-that would otherwise be unaccesible, or augment existing arguments.
-
-Adding a custom frame recognizer is possible by implementing a Python class
-and using the 'frame recognizer add' command. The Python class should have a
-'get_recognized_arguments' method and it will receive an argument of type
-lldb.SBFrame representing the current frame that we are trying to recognize.
-The method should return a (possibly empty) list of lldb.SBValue objects that
-represent the recognized arguments.
-
-An example of a recognizer that retrieves the file descriptor values from libc
-functions 'read', 'write' and 'close' follows:
-
- class LibcFdRecognizer(object):
- def get_recognized_arguments(self, frame):
- if frame.name in ["read", "write", "close"]:
- fd = frame.EvaluateExpression("$arg1").unsigned
- value = lldb.target.CreateValueFromExpression("fd", "(int)%d" % fd)
- return [value]
- return []
-
-The file containing this implementation can be imported via 'command script
-import' and then we can register this recognizer with 'frame recognizer add'.
-It's important to restrict the recognizer to the libc library (which is
-libsystem_kernel.dylib on macOS) to avoid matching functions with the same name
-in other modules:
-
-(lldb) command script import .../fd_recognizer.py
-(lldb) frame recognizer add -l fd_recognizer.LibcFdRecognizer -n read -s libsystem_kernel.dylib
-
-When the program is stopped at the beginning of the 'read' function in libc, we
-can view the recognizer arguments in 'frame variable':
-
-(lldb) b read
-(lldb) r
-Process 1234 stopped
-* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.3
- frame #0: 0x00007fff06013ca0 libsystem_kernel.dylib`read
-(lldb) frame variable
-(int) fd = 3
-
- )");
- }
- ~CommandObjectFrameRecognizerAdd() override = default;
-};
-
-bool CommandObjectFrameRecognizerAdd::DoExecute(Args &command,
- CommandReturnObject &result) {
-#ifndef LLDB_DISABLE_PYTHON
- if (m_options.m_class_name.empty()) {
- result.AppendErrorWithFormat(
- "%s needs a Python class name (-l argument).\n", m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- if (m_options.m_module.empty()) {
- result.AppendErrorWithFormat("%s needs a module name (-s argument).\n",
- m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- if (m_options.m_function.empty()) {
- result.AppendErrorWithFormat("%s needs a function name (-n argument).\n",
- m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
-
- if (interpreter &&
- !interpreter->CheckObjectExists(m_options.m_class_name.c_str())) {
- result.AppendWarning(
- "The provided class does not exist - please define it "
- "before attempting to use this frame recognizer");
- }
-
- StackFrameRecognizerSP recognizer_sp =
- StackFrameRecognizerSP(new ScriptedStackFrameRecognizer(
- interpreter, m_options.m_class_name.c_str()));
- if (m_options.m_regex) {
- auto module =
- RegularExpressionSP(new RegularExpression(m_options.m_module));
- auto func =
- RegularExpressionSP(new RegularExpression(m_options.m_function));
- StackFrameRecognizerManager::AddRecognizer(recognizer_sp, module, func);
- } else {
- auto module = ConstString(m_options.m_module);
- auto func = ConstString(m_options.m_function);
- StackFrameRecognizerManager::AddRecognizer(recognizer_sp, module, func);
- }
-#endif
-
- result.SetStatus(eReturnStatusSuccessFinishNoResult);
- return result.Succeeded();
-}
-
-class CommandObjectFrameRecognizerClear : public CommandObjectParsed {
-public:
- CommandObjectFrameRecognizerClear(CommandInterpreter &interpreter)
- : CommandObjectParsed(interpreter, "frame recognizer clear",
- "Delete all frame recognizers.", nullptr) {}
-
- ~CommandObjectFrameRecognizerClear() override = default;
-
-protected:
- bool DoExecute(Args &command, CommandReturnObject &result) override {
- StackFrameRecognizerManager::RemoveAllRecognizers();
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return result.Succeeded();
- }
-};
-
-class CommandObjectFrameRecognizerDelete : public CommandObjectParsed {
- public:
- CommandObjectFrameRecognizerDelete(CommandInterpreter &interpreter)
- : CommandObjectParsed(interpreter, "frame recognizer delete",
- "Delete an existing frame recognizer.", nullptr) {}
-
- ~CommandObjectFrameRecognizerDelete() override = default;
-
- protected:
- bool DoExecute(Args &command, CommandReturnObject &result) override {
- if (command.GetArgumentCount() == 0) {
- if (!m_interpreter.Confirm(
- "About to delete all frame recognizers, do you want to do that?",
- true)) {
- result.AppendMessage("Operation cancelled...");
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- StackFrameRecognizerManager::RemoveAllRecognizers();
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return result.Succeeded();
- }
-
- if (command.GetArgumentCount() != 1) {
- result.AppendErrorWithFormat("'%s' takes zero or one arguments.\n",
- m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- uint32_t recognizer_id =
- StringConvert::ToUInt32(command.GetArgumentAtIndex(0), 0, 0);
-
- StackFrameRecognizerManager::RemoveRecognizerWithID(recognizer_id);
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return result.Succeeded();
- }
-};
-
-class CommandObjectFrameRecognizerList : public CommandObjectParsed {
- public:
- CommandObjectFrameRecognizerList(CommandInterpreter &interpreter)
- : CommandObjectParsed(interpreter, "frame recognizer list",
- "Show a list of active frame recognizers.",
- nullptr) {}
-
- ~CommandObjectFrameRecognizerList() override = default;
-
- protected:
- bool DoExecute(Args &command, CommandReturnObject &result) override {
- bool any_printed = false;
- StackFrameRecognizerManager::ForEach(
- [&result, &any_printed](uint32_t recognizer_id, std::string name,
- std::string function, std::string symbol,
- bool regexp) {
- if (name == "") name = "(internal)";
- result.GetOutputStream().Printf(
- "%d: %s, module %s, function %s%s\n", recognizer_id, name.c_str(),
- function.c_str(), symbol.c_str(), regexp ? " (regexp)" : "");
- any_printed = true;
- });
-
- if (any_printed)
- result.SetStatus(eReturnStatusSuccessFinishResult);
- else {
- result.GetOutputStream().PutCString("no matching results found.\n");
- result.SetStatus(eReturnStatusSuccessFinishNoResult);
- }
- return result.Succeeded();
- }
-};
-
-class CommandObjectFrameRecognizerInfo : public CommandObjectParsed {
- public:
- CommandObjectFrameRecognizerInfo(CommandInterpreter &interpreter)
- : CommandObjectParsed(
- interpreter, "frame recognizer info",
- "Show which frame recognizer is applied a stack frame (if any).",
- nullptr) {
- CommandArgumentEntry arg;
- CommandArgumentData index_arg;
-
- // Define the first (and only) variant of this arg.
- index_arg.arg_type = eArgTypeFrameIndex;
- index_arg.arg_repetition = eArgRepeatPlain;
-
- // There is only one variant this argument could be; put it into the
- // argument entry.
- arg.push_back(index_arg);
-
- // Push the data for the first argument into the m_arguments vector.
- m_arguments.push_back(arg);
- }
-
- ~CommandObjectFrameRecognizerInfo() override = default;
-
- protected:
- bool DoExecute(Args &command, CommandReturnObject &result) override {
- Process *process = m_exe_ctx.GetProcessPtr();
- if (process == nullptr) {
- result.AppendError("no process");
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
- Thread *thread = m_exe_ctx.GetThreadPtr();
- if (thread == nullptr) {
- result.AppendError("no thread");
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
- if (command.GetArgumentCount() != 1) {
- result.AppendErrorWithFormat(
- "'%s' takes exactly one frame index argument.\n", m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- uint32_t frame_index =
- StringConvert::ToUInt32(command.GetArgumentAtIndex(0), 0, 0);
- StackFrameSP frame_sp = thread->GetStackFrameAtIndex(frame_index);
- if (!frame_sp) {
- result.AppendErrorWithFormat("no frame with index %u", frame_index);
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- auto recognizer =
- StackFrameRecognizerManager::GetRecognizerForFrame(frame_sp);
-
- Stream &output_stream = result.GetOutputStream();
- output_stream.Printf("frame %d ", frame_index);
- if (recognizer) {
- output_stream << "is recognized by ";
- output_stream << recognizer->GetName();
- } else {
- output_stream << "not recognized by any recognizer";
- }
- output_stream.EOL();
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return result.Succeeded();
- }
-};
-
-class CommandObjectFrameRecognizer : public CommandObjectMultiword {
- public:
- CommandObjectFrameRecognizer(CommandInterpreter &interpreter)
- : CommandObjectMultiword(
- interpreter, "frame recognizer",
- "Commands for editing and viewing frame recognizers.",
- "frame recognizer [<sub-command-options>] ") {
- LoadSubCommand(
- "add",
- CommandObjectSP(new CommandObjectFrameRecognizerAdd(interpreter)));
- LoadSubCommand(
- "clear",
- CommandObjectSP(new CommandObjectFrameRecognizerClear(interpreter)));
- LoadSubCommand(
- "delete",
- CommandObjectSP(new CommandObjectFrameRecognizerDelete(interpreter)));
- LoadSubCommand(
- "list",
- CommandObjectSP(new CommandObjectFrameRecognizerList(interpreter)));
- LoadSubCommand(
- "info",
- CommandObjectSP(new CommandObjectFrameRecognizerInfo(interpreter)));
- }
-
- ~CommandObjectFrameRecognizer() override = default;
-};
-
-#pragma mark CommandObjectMultiwordFrame
-
-// CommandObjectMultiwordFrame
-
-CommandObjectMultiwordFrame::CommandObjectMultiwordFrame(
- CommandInterpreter &interpreter)
- : CommandObjectMultiword(interpreter, "frame", "Commands for selecting and "
- "examing the current "
- "thread's stack frames.",
- "frame <subcommand> [<subcommand-options>]") {
- LoadSubCommand("diagnose",
- CommandObjectSP(new CommandObjectFrameDiagnose(interpreter)));
- LoadSubCommand("info",
- CommandObjectSP(new CommandObjectFrameInfo(interpreter)));
- LoadSubCommand("select",
- CommandObjectSP(new CommandObjectFrameSelect(interpreter)));
- LoadSubCommand("variable",
- CommandObjectSP(new CommandObjectFrameVariable(interpreter)));
-#ifndef LLDB_DISABLE_PYTHON
- LoadSubCommand(
- "recognizer",
- CommandObjectSP(new CommandObjectFrameRecognizer(interpreter)));
-#endif
-}
-
-CommandObjectMultiwordFrame::~CommandObjectMultiwordFrame() = default;