1 //===-- CommandObjectFrame.cpp ----------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
14 // Other libraries and framework includes
16 #include "CommandObjectFrame.h"
17 #include "lldb/Core/Debugger.h"
18 #include "lldb/Core/Module.h"
19 #include "lldb/Core/StreamFile.h"
20 #include "lldb/Core/Value.h"
21 #include "lldb/Core/ValueObject.h"
22 #include "lldb/Core/ValueObjectVariable.h"
23 #include "lldb/DataFormatters/DataVisualization.h"
24 #include "lldb/DataFormatters/ValueObjectPrinter.h"
25 #include "lldb/Host/Host.h"
26 #include "lldb/Host/OptionParser.h"
27 #include "lldb/Interpreter/Args.h"
28 #include "lldb/Interpreter/CommandInterpreter.h"
29 #include "lldb/Interpreter/CommandReturnObject.h"
30 #include "lldb/Interpreter/OptionGroupFormat.h"
31 #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
32 #include "lldb/Interpreter/OptionGroupVariable.h"
33 #include "lldb/Interpreter/Options.h"
34 #include "lldb/Symbol/ClangASTContext.h"
35 #include "lldb/Symbol/CompilerType.h"
36 #include "lldb/Symbol/Function.h"
37 #include "lldb/Symbol/ObjectFile.h"
38 #include "lldb/Symbol/SymbolContext.h"
39 #include "lldb/Symbol/Type.h"
40 #include "lldb/Symbol/Variable.h"
41 #include "lldb/Symbol/VariableList.h"
42 #include "lldb/Target/Process.h"
43 #include "lldb/Target/StackFrame.h"
44 #include "lldb/Target/StopInfo.h"
45 #include "lldb/Target/Target.h"
46 #include "lldb/Target/Thread.h"
47 #include "lldb/Utility/LLDBAssert.h"
48 #include "lldb/Utility/StreamString.h"
49 #include "lldb/Utility/Timer.h"
52 using namespace lldb_private;
54 #pragma mark CommandObjectFrameDiagnose
56 //-------------------------------------------------------------------------
57 // CommandObjectFrameInfo
58 //-------------------------------------------------------------------------
60 //-------------------------------------------------------------------------
61 // CommandObjectFrameDiagnose
62 //-------------------------------------------------------------------------
64 static OptionDefinition g_frame_diag_options[] = {
66 { LLDB_OPT_SET_1, false, "register", 'r', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeRegisterName, "A register to diagnose." },
67 { LLDB_OPT_SET_1, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddress, "An address to diagnose." },
68 { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOffset, "An optional offset. Requires --register." }
72 class CommandObjectFrameDiagnose : public CommandObjectParsed {
74 class CommandOptions : public Options {
76 CommandOptions() : Options() { OptionParsingStarting(nullptr); }
78 ~CommandOptions() override = default;
80 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
81 ExecutionContext *execution_context) override {
83 const int short_option = m_getopt_table[option_idx].val;
84 switch (short_option) {
86 reg = ConstString(option_arg);
91 if (option_arg.getAsInteger(0, *address)) {
93 error.SetErrorStringWithFormat("invalid address argument '%s'",
94 option_arg.str().c_str());
100 if (option_arg.getAsInteger(0, *offset)) {
102 error.SetErrorStringWithFormat("invalid offset argument '%s'",
103 option_arg.str().c_str());
108 error.SetErrorStringWithFormat("invalid short option character '%c'",
116 void OptionParsingStarting(ExecutionContext *execution_context) override {
122 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
123 return llvm::makeArrayRef(g_frame_diag_options);
127 llvm::Optional<lldb::addr_t> address;
128 llvm::Optional<ConstString> reg;
129 llvm::Optional<int64_t> offset;
132 CommandObjectFrameDiagnose(CommandInterpreter &interpreter)
133 : CommandObjectParsed(interpreter, "frame diagnose",
134 "Try to determine what path path the current stop "
135 "location used to get to a register or address",
137 eCommandRequiresThread | eCommandTryTargetAPILock |
138 eCommandProcessMustBeLaunched |
139 eCommandProcessMustBePaused),
141 CommandArgumentEntry arg;
142 CommandArgumentData index_arg;
144 // Define the first (and only) variant of this arg.
145 index_arg.arg_type = eArgTypeFrameIndex;
146 index_arg.arg_repetition = eArgRepeatOptional;
148 // There is only one variant this argument could be; put it into the
150 arg.push_back(index_arg);
152 // Push the data for the first argument into the m_arguments vector.
153 m_arguments.push_back(arg);
156 ~CommandObjectFrameDiagnose() override = default;
158 Options *GetOptions() override { return &m_options; }
161 bool DoExecute(Args &command, CommandReturnObject &result) override {
162 Thread *thread = m_exe_ctx.GetThreadPtr();
163 StackFrameSP frame_sp = thread->GetSelectedFrame();
165 ValueObjectSP valobj_sp;
167 if (m_options.address.hasValue()) {
168 if (m_options.reg.hasValue() || m_options.offset.hasValue()) {
170 "`frame diagnose --address` is incompatible with other arguments.");
171 result.SetStatus(eReturnStatusFailed);
174 valobj_sp = frame_sp->GuessValueForAddress(m_options.address.getValue());
175 } else if (m_options.reg.hasValue()) {
176 valobj_sp = frame_sp->GuessValueForRegisterAndOffset(
177 m_options.reg.getValue(), m_options.offset.getValueOr(0));
179 StopInfoSP stop_info_sp = thread->GetStopInfo();
181 result.AppendError("No arguments provided, and no stop info.");
182 result.SetStatus(eReturnStatusFailed);
186 valobj_sp = StopInfo::GetCrashingDereference(stop_info_sp);
190 result.AppendError("No diagnosis available.");
191 result.SetStatus(eReturnStatusFailed);
196 DumpValueObjectOptions::DeclPrintingHelper helper = [&valobj_sp](
197 ConstString type, ConstString var, const DumpValueObjectOptions &opts,
198 Stream &stream) -> bool {
199 const ValueObject::GetExpressionPathFormat format = ValueObject::
200 GetExpressionPathFormat::eGetExpressionPathFormatHonorPointers;
201 const bool qualify_cxx_base_classes = false;
202 valobj_sp->GetExpressionPath(stream, qualify_cxx_base_classes, format);
203 stream.PutCString(" =");
207 DumpValueObjectOptions options;
208 options.SetDeclPrintingHelper(helper);
209 ValueObjectPrinter printer(valobj_sp.get(), &result.GetOutputStream(),
211 printer.PrintValueObject();
217 CommandOptions m_options;
220 #pragma mark CommandObjectFrameInfo
222 //-------------------------------------------------------------------------
223 // CommandObjectFrameInfo
224 //-------------------------------------------------------------------------
226 class CommandObjectFrameInfo : public CommandObjectParsed {
228 CommandObjectFrameInfo(CommandInterpreter &interpreter)
229 : CommandObjectParsed(
230 interpreter, "frame info", "List information about the current "
231 "stack frame in the current thread.",
233 eCommandRequiresFrame | eCommandTryTargetAPILock |
234 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {}
236 ~CommandObjectFrameInfo() override = default;
239 bool DoExecute(Args &command, CommandReturnObject &result) override {
240 m_exe_ctx.GetFrameRef().DumpUsingSettingsFormat(&result.GetOutputStream());
241 result.SetStatus(eReturnStatusSuccessFinishResult);
242 return result.Succeeded();
246 #pragma mark CommandObjectFrameSelect
248 //-------------------------------------------------------------------------
249 // CommandObjectFrameSelect
250 //-------------------------------------------------------------------------
252 static OptionDefinition g_frame_select_options[] = {
254 { LLDB_OPT_SET_1, false, "relative", 'r', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOffset, "A relative frame index offset from the current frame index." },
258 class CommandObjectFrameSelect : public CommandObjectParsed {
260 class CommandOptions : public Options {
262 CommandOptions() : Options() { OptionParsingStarting(nullptr); }
264 ~CommandOptions() override = default;
266 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
267 ExecutionContext *execution_context) override {
269 const int short_option = m_getopt_table[option_idx].val;
270 switch (short_option) {
272 if (option_arg.getAsInteger(0, relative_frame_offset)) {
273 relative_frame_offset = INT32_MIN;
274 error.SetErrorStringWithFormat("invalid frame offset argument '%s'",
275 option_arg.str().c_str());
280 error.SetErrorStringWithFormat("invalid short option character '%c'",
288 void OptionParsingStarting(ExecutionContext *execution_context) override {
289 relative_frame_offset = INT32_MIN;
292 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
293 return llvm::makeArrayRef(g_frame_select_options);
296 int32_t relative_frame_offset;
299 CommandObjectFrameSelect(CommandInterpreter &interpreter)
300 : CommandObjectParsed(
301 interpreter, "frame select", "Select the current stack frame by "
302 "index from within the current thread "
303 "(see 'thread backtrace'.)",
305 eCommandRequiresThread | eCommandTryTargetAPILock |
306 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused),
308 CommandArgumentEntry arg;
309 CommandArgumentData index_arg;
311 // Define the first (and only) variant of this arg.
312 index_arg.arg_type = eArgTypeFrameIndex;
313 index_arg.arg_repetition = eArgRepeatOptional;
315 // There is only one variant this argument could be; put it into the
317 arg.push_back(index_arg);
319 // Push the data for the first argument into the m_arguments vector.
320 m_arguments.push_back(arg);
323 ~CommandObjectFrameSelect() override = default;
325 Options *GetOptions() override { return &m_options; }
328 bool DoExecute(Args &command, CommandReturnObject &result) override {
329 // No need to check "thread" for validity as eCommandRequiresThread ensures
331 Thread *thread = m_exe_ctx.GetThreadPtr();
333 uint32_t frame_idx = UINT32_MAX;
334 if (m_options.relative_frame_offset != INT32_MIN) {
335 // The one and only argument is a signed relative frame index
336 frame_idx = thread->GetSelectedFrameIndex();
337 if (frame_idx == UINT32_MAX)
340 if (m_options.relative_frame_offset < 0) {
341 if (static_cast<int32_t>(frame_idx) >= -m_options.relative_frame_offset)
342 frame_idx += m_options.relative_frame_offset;
344 if (frame_idx == 0) {
345 // If you are already at the bottom of the stack, then just warn and
346 // don't reset the frame.
347 result.AppendError("Already at the bottom of the stack.");
348 result.SetStatus(eReturnStatusFailed);
353 } else if (m_options.relative_frame_offset > 0) {
354 // I don't want "up 20" where "20" takes you past the top of the stack
356 // an error, but rather to just go to the top. So I have to count the
358 const uint32_t num_frames = thread->GetStackFrameCount();
359 if (static_cast<int32_t>(num_frames - frame_idx) >
360 m_options.relative_frame_offset)
361 frame_idx += m_options.relative_frame_offset;
363 if (frame_idx == num_frames - 1) {
364 // If we are already at the top of the stack, just warn and don't
366 result.AppendError("Already at the top of the stack.");
367 result.SetStatus(eReturnStatusFailed);
370 frame_idx = num_frames - 1;
374 if (command.GetArgumentCount() > 1) {
375 result.AppendErrorWithFormat(
376 "too many arguments; expected frame-index, saw '%s'.\n",
378 m_options.GenerateOptionUsage(
379 result.GetErrorStream(), this,
380 GetCommandInterpreter().GetDebugger().GetTerminalWidth());
384 if (command.GetArgumentCount() == 1) {
385 if (command[0].ref.getAsInteger(0, frame_idx)) {
386 result.AppendErrorWithFormat("invalid frame index argument '%s'.",
388 result.SetStatus(eReturnStatusFailed);
391 } else if (command.GetArgumentCount() == 0) {
392 frame_idx = thread->GetSelectedFrameIndex();
393 if (frame_idx == UINT32_MAX) {
399 bool success = thread->SetSelectedFrameByIndexNoisily(
400 frame_idx, result.GetOutputStream());
402 m_exe_ctx.SetFrameSP(thread->GetSelectedFrame());
403 result.SetStatus(eReturnStatusSuccessFinishResult);
405 result.AppendErrorWithFormat("Frame index (%u) out of range.\n",
407 result.SetStatus(eReturnStatusFailed);
410 return result.Succeeded();
414 CommandOptions m_options;
417 #pragma mark CommandObjectFrameVariable
418 //----------------------------------------------------------------------
419 // List images with associated information
420 //----------------------------------------------------------------------
421 class CommandObjectFrameVariable : public CommandObjectParsed {
423 CommandObjectFrameVariable(CommandInterpreter &interpreter)
424 : CommandObjectParsed(
425 interpreter, "frame variable",
426 "Show variables for the current stack frame. Defaults to all "
427 "arguments and local variables in scope. Names of argument, "
428 "local, file static and file global variables can be specified. "
429 "Children of aggregate variables can be specified such as "
431 nullptr, eCommandRequiresFrame | eCommandTryTargetAPILock |
432 eCommandProcessMustBeLaunched |
433 eCommandProcessMustBePaused | eCommandRequiresProcess),
436 true), // Include the frame specific options by passing "true"
437 m_option_format(eFormatDefault),
439 CommandArgumentEntry arg;
440 CommandArgumentData var_name_arg;
442 // Define the first (and only) variant of this arg.
443 var_name_arg.arg_type = eArgTypeVarName;
444 var_name_arg.arg_repetition = eArgRepeatStar;
446 // There is only one variant this argument could be; put it into the
448 arg.push_back(var_name_arg);
450 // Push the data for the first argument into the m_arguments vector.
451 m_arguments.push_back(arg);
453 m_option_group.Append(&m_option_variable, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
454 m_option_group.Append(&m_option_format,
455 OptionGroupFormat::OPTION_GROUP_FORMAT |
456 OptionGroupFormat::OPTION_GROUP_GDB_FMT,
458 m_option_group.Append(&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
459 m_option_group.Finalize();
462 ~CommandObjectFrameVariable() override = default;
464 Options *GetOptions() override { return &m_option_group; }
466 int HandleArgumentCompletion(Args &input, int &cursor_index,
467 int &cursor_char_position,
468 OptionElementVector &opt_element_vector,
469 int match_start_point, int max_return_elements,
471 StringList &matches) override {
472 // Arguments are the standard source file completer.
473 auto completion_str = input[cursor_index].ref;
474 completion_str = completion_str.take_front(cursor_char_position);
476 CommandCompletions::InvokeCommonCompletionCallbacks(
477 GetCommandInterpreter(), CommandCompletions::eVariablePathCompletion,
478 completion_str, match_start_point, max_return_elements, nullptr,
479 word_complete, matches);
480 return matches.GetSize();
484 llvm::StringRef GetScopeString(VariableSP var_sp) {
486 return llvm::StringRef::withNullAsEmpty(nullptr);
488 switch (var_sp->GetScope()) {
489 case eValueTypeVariableGlobal:
491 case eValueTypeVariableStatic:
493 case eValueTypeVariableArgument:
495 case eValueTypeVariableLocal:
497 case eValueTypeVariableThreadLocal:
503 return llvm::StringRef::withNullAsEmpty(nullptr);
506 bool DoExecute(Args &command, CommandReturnObject &result) override {
507 // No need to check "frame" for validity as eCommandRequiresFrame ensures it
509 StackFrame *frame = m_exe_ctx.GetFramePtr();
511 Stream &s = result.GetOutputStream();
513 // Be careful about the stack frame, if any summary formatter runs code, it
514 // might clear the StackFrameList
515 // for the thread. So hold onto a shared pointer to the frame so it stays
518 VariableList *variable_list =
519 frame->GetVariableList(m_option_variable.show_globals);
522 ValueObjectSP valobj_sp;
524 TypeSummaryImplSP summary_format_sp;
525 if (!m_option_variable.summary.IsCurrentValueEmpty())
526 DataVisualization::NamedSummaryFormats::GetSummaryFormat(
527 ConstString(m_option_variable.summary.GetCurrentValue()),
529 else if (!m_option_variable.summary_string.IsCurrentValueEmpty())
530 summary_format_sp.reset(new StringSummaryFormat(
531 TypeSummaryImpl::Flags(),
532 m_option_variable.summary_string.GetCurrentValue()));
534 DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(
535 eLanguageRuntimeDescriptionDisplayVerbosityFull, eFormatDefault,
538 const SymbolContext &sym_ctx =
539 frame->GetSymbolContext(eSymbolContextFunction);
540 if (sym_ctx.function && sym_ctx.function->IsTopLevelFunction())
541 m_option_variable.show_globals = true;
544 const Format format = m_option_format.GetFormat();
545 options.SetFormat(format);
547 if (!command.empty()) {
548 VariableList regex_var_list;
550 // If we have any args to the variable command, we will make
551 // variable objects from them...
552 for (auto &entry : command) {
553 if (m_option_variable.use_regex) {
554 const size_t regex_start_index = regex_var_list.GetSize();
555 llvm::StringRef name_str = entry.ref;
556 RegularExpression regex(name_str);
557 if (regex.Compile(name_str)) {
558 size_t num_matches = 0;
559 const size_t num_new_regex_vars =
560 variable_list->AppendVariablesIfUnique(regex, regex_var_list,
562 if (num_new_regex_vars > 0) {
563 for (size_t regex_idx = regex_start_index,
564 end_index = regex_var_list.GetSize();
565 regex_idx < end_index; ++regex_idx) {
566 var_sp = regex_var_list.GetVariableAtIndex(regex_idx);
568 valobj_sp = frame->GetValueObjectForFrameVariable(
569 var_sp, m_varobj_options.use_dynamic);
571 std::string scope_string;
572 if (m_option_variable.show_scope)
573 scope_string = GetScopeString(var_sp).str();
575 if (!scope_string.empty())
576 s.PutCString(scope_string);
578 if (m_option_variable.show_decl &&
579 var_sp->GetDeclaration().GetFile()) {
580 bool show_fullpaths = false;
581 bool show_module = true;
582 if (var_sp->DumpDeclaration(&s, show_fullpaths,
586 valobj_sp->Dump(result.GetOutputStream(), options);
590 } else if (num_matches == 0) {
591 result.GetErrorStream().Printf("error: no variables matched "
592 "the regular expression '%s'.\n",
596 char regex_error[1024];
597 if (regex.GetErrorAsCString(regex_error, sizeof(regex_error)))
598 result.GetErrorStream().Printf("error: %s\n", regex_error);
600 result.GetErrorStream().Printf(
601 "error: unknown regex error when compiling '%s'\n",
604 } else // No regex, either exact variable names or variable
608 uint32_t expr_path_options =
609 StackFrame::eExpressionPathOptionCheckPtrVsMember |
610 StackFrame::eExpressionPathOptionsAllowDirectIVarAccess |
611 StackFrame::eExpressionPathOptionsInspectAnonymousUnions;
612 lldb::VariableSP var_sp;
613 valobj_sp = frame->GetValueForVariableExpressionPath(
614 entry.ref, m_varobj_options.use_dynamic, expr_path_options,
617 std::string scope_string;
618 if (m_option_variable.show_scope)
619 scope_string = GetScopeString(var_sp).str();
621 if (!scope_string.empty())
622 s.PutCString(scope_string);
624 // if (format != eFormatDefault)
625 // valobj_sp->SetFormat (format);
626 if (m_option_variable.show_decl && var_sp &&
627 var_sp->GetDeclaration().GetFile()) {
628 var_sp->GetDeclaration().DumpStopContext(&s, false);
632 options.SetFormat(format);
633 options.SetVariableFormatDisplayLanguage(
634 valobj_sp->GetPreferredDisplayLanguage());
636 Stream &output_stream = result.GetOutputStream();
637 options.SetRootValueObjectName(
638 valobj_sp->GetParent() ? entry.c_str() : nullptr);
639 valobj_sp->Dump(output_stream, options);
641 const char *error_cstr = error.AsCString(nullptr);
643 result.GetErrorStream().Printf("error: %s\n", error_cstr);
645 result.GetErrorStream().Printf("error: unable to find any "
646 "variable expression path that "
652 } else // No command arg specified. Use variable_list, instead.
654 const size_t num_variables = variable_list->GetSize();
655 if (num_variables > 0) {
656 for (size_t i = 0; i < num_variables; i++) {
657 var_sp = variable_list->GetVariableAtIndex(i);
658 switch (var_sp->GetScope()) {
659 case eValueTypeVariableGlobal:
660 if (!m_option_variable.show_globals)
663 case eValueTypeVariableStatic:
664 if (!m_option_variable.show_globals)
667 case eValueTypeVariableArgument:
668 if (!m_option_variable.show_args)
671 case eValueTypeVariableLocal:
672 if (!m_option_variable.show_locals)
679 std::string scope_string;
680 if (m_option_variable.show_scope)
681 scope_string = GetScopeString(var_sp).str();
683 // Use the variable object code to make sure we are
684 // using the same APIs as the public API will be
686 valobj_sp = frame->GetValueObjectForFrameVariable(
687 var_sp, m_varobj_options.use_dynamic);
689 // When dumping all variables, don't print any variables
690 // that are not in scope to avoid extra unneeded output
691 if (valobj_sp->IsInScope()) {
692 if (!valobj_sp->GetTargetSP()
693 ->GetDisplayRuntimeSupportValues() &&
694 valobj_sp->IsRuntimeSupportValue())
697 if (!scope_string.empty())
698 s.PutCString(scope_string);
700 if (m_option_variable.show_decl &&
701 var_sp->GetDeclaration().GetFile()) {
702 var_sp->GetDeclaration().DumpStopContext(&s, false);
706 options.SetFormat(format);
707 options.SetVariableFormatDisplayLanguage(
708 valobj_sp->GetPreferredDisplayLanguage());
709 options.SetRootValueObjectName(
710 var_sp ? var_sp->GetName().AsCString() : nullptr);
711 valobj_sp->Dump(result.GetOutputStream(), options);
717 result.SetStatus(eReturnStatusSuccessFinishResult);
720 if (m_interpreter.TruncationWarningNecessary()) {
721 result.GetOutputStream().Printf(m_interpreter.TruncationWarningText(),
723 m_interpreter.TruncationWarningGiven();
726 return result.Succeeded();
730 OptionGroupOptions m_option_group;
731 OptionGroupVariable m_option_variable;
732 OptionGroupFormat m_option_format;
733 OptionGroupValueObjectDisplay m_varobj_options;
736 #pragma mark CommandObjectMultiwordFrame
738 //-------------------------------------------------------------------------
739 // CommandObjectMultiwordFrame
740 //-------------------------------------------------------------------------
742 CommandObjectMultiwordFrame::CommandObjectMultiwordFrame(
743 CommandInterpreter &interpreter)
744 : CommandObjectMultiword(interpreter, "frame", "Commands for selecting and "
745 "examing the current "
746 "thread's stack frames.",
747 "frame <subcommand> [<subcommand-options>]") {
748 LoadSubCommand("diagnose",
749 CommandObjectSP(new CommandObjectFrameDiagnose(interpreter)));
750 LoadSubCommand("info",
751 CommandObjectSP(new CommandObjectFrameInfo(interpreter)));
752 LoadSubCommand("select",
753 CommandObjectSP(new CommandObjectFrameSelect(interpreter)));
754 LoadSubCommand("variable",
755 CommandObjectSP(new CommandObjectFrameVariable(interpreter)));
758 CommandObjectMultiwordFrame::~CommandObjectMultiwordFrame() = default;