xref: /freebsd-src/contrib/llvm-project/lldb/source/Commands/CommandObjectFrame.cpp (revision e9ac41698b2f322d55ccf9da50a3596edb2c1800)
1 //===-- CommandObjectFrame.cpp --------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 #include "CommandObjectFrame.h"
9 #include "lldb/Core/Debugger.h"
10 #include "lldb/Core/ValueObject.h"
11 #include "lldb/DataFormatters/DataVisualization.h"
12 #include "lldb/DataFormatters/ValueObjectPrinter.h"
13 #include "lldb/Host/Config.h"
14 #include "lldb/Host/OptionParser.h"
15 #include "lldb/Interpreter/CommandInterpreter.h"
16 #include "lldb/Interpreter/CommandOptionArgumentTable.h"
17 #include "lldb/Interpreter/CommandReturnObject.h"
18 #include "lldb/Interpreter/OptionArgParser.h"
19 #include "lldb/Interpreter/OptionGroupFormat.h"
20 #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
21 #include "lldb/Interpreter/OptionGroupVariable.h"
22 #include "lldb/Interpreter/Options.h"
23 #include "lldb/Symbol/Function.h"
24 #include "lldb/Symbol/SymbolContext.h"
25 #include "lldb/Symbol/Variable.h"
26 #include "lldb/Symbol/VariableList.h"
27 #include "lldb/Target/StackFrame.h"
28 #include "lldb/Target/StackFrameRecognizer.h"
29 #include "lldb/Target/StopInfo.h"
30 #include "lldb/Target/Target.h"
31 #include "lldb/Target/Thread.h"
32 #include "lldb/Utility/Args.h"
33 
34 #include <memory>
35 #include <optional>
36 #include <string>
37 
38 using namespace lldb;
39 using namespace lldb_private;
40 
41 #pragma mark CommandObjectFrameDiagnose
42 
43 // CommandObjectFrameInfo
44 
45 // CommandObjectFrameDiagnose
46 
47 #define LLDB_OPTIONS_frame_diag
48 #include "CommandOptions.inc"
49 
50 class CommandObjectFrameDiagnose : public CommandObjectParsed {
51 public:
52   class CommandOptions : public Options {
53   public:
54     CommandOptions() { OptionParsingStarting(nullptr); }
55 
56     ~CommandOptions() override = default;
57 
58     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
59                           ExecutionContext *execution_context) override {
60       Status error;
61       const int short_option = m_getopt_table[option_idx].val;
62       switch (short_option) {
63       case 'r':
64         reg = ConstString(option_arg);
65         break;
66 
67       case 'a': {
68         address.emplace();
69         if (option_arg.getAsInteger(0, *address)) {
70           address.reset();
71           error.SetErrorStringWithFormat("invalid address argument '%s'",
72                                          option_arg.str().c_str());
73         }
74       } break;
75 
76       case 'o': {
77         offset.emplace();
78         if (option_arg.getAsInteger(0, *offset)) {
79           offset.reset();
80           error.SetErrorStringWithFormat("invalid offset argument '%s'",
81                                          option_arg.str().c_str());
82         }
83       } break;
84 
85       default:
86         llvm_unreachable("Unimplemented option");
87       }
88 
89       return error;
90     }
91 
92     void OptionParsingStarting(ExecutionContext *execution_context) override {
93       address.reset();
94       reg.reset();
95       offset.reset();
96     }
97 
98     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
99       return llvm::ArrayRef(g_frame_diag_options);
100     }
101 
102     // Options.
103     std::optional<lldb::addr_t> address;
104     std::optional<ConstString> reg;
105     std::optional<int64_t> offset;
106   };
107 
108   CommandObjectFrameDiagnose(CommandInterpreter &interpreter)
109       : CommandObjectParsed(interpreter, "frame diagnose",
110                             "Try to determine what path the current stop "
111                             "location used to get to a register or address",
112                             nullptr,
113                             eCommandRequiresThread | eCommandTryTargetAPILock |
114                                 eCommandProcessMustBeLaunched |
115                                 eCommandProcessMustBePaused) {
116     CommandArgumentEntry arg;
117     CommandArgumentData index_arg;
118 
119     // Define the first (and only) variant of this arg.
120     index_arg.arg_type = eArgTypeFrameIndex;
121     index_arg.arg_repetition = eArgRepeatOptional;
122 
123     // There is only one variant this argument could be; put it into the
124     // argument entry.
125     arg.push_back(index_arg);
126 
127     // Push the data for the first argument into the m_arguments vector.
128     m_arguments.push_back(arg);
129   }
130 
131   ~CommandObjectFrameDiagnose() override = default;
132 
133   Options *GetOptions() override { return &m_options; }
134 
135 protected:
136   void DoExecute(Args &command, CommandReturnObject &result) override {
137     Thread *thread = m_exe_ctx.GetThreadPtr();
138     StackFrameSP frame_sp = thread->GetSelectedFrame(SelectMostRelevantFrame);
139 
140     ValueObjectSP valobj_sp;
141 
142     if (m_options.address) {
143       if (m_options.reg || m_options.offset) {
144         result.AppendError(
145             "`frame diagnose --address` is incompatible with other arguments.");
146         return;
147       }
148       valobj_sp = frame_sp->GuessValueForAddress(*m_options.address);
149     } else if (m_options.reg) {
150       valobj_sp = frame_sp->GuessValueForRegisterAndOffset(
151           *m_options.reg, m_options.offset.value_or(0));
152     } else {
153       StopInfoSP stop_info_sp = thread->GetStopInfo();
154       if (!stop_info_sp) {
155         result.AppendError("No arguments provided, and no stop info.");
156         return;
157       }
158 
159       valobj_sp = StopInfo::GetCrashingDereference(stop_info_sp);
160     }
161 
162     if (!valobj_sp) {
163       result.AppendError("No diagnosis available.");
164       return;
165     }
166 
167     DumpValueObjectOptions::DeclPrintingHelper helper =
168         [&valobj_sp](ConstString type, ConstString var,
169                      const DumpValueObjectOptions &opts,
170                      Stream &stream) -> bool {
171       const ValueObject::GetExpressionPathFormat format = ValueObject::
172           GetExpressionPathFormat::eGetExpressionPathFormatHonorPointers;
173       valobj_sp->GetExpressionPath(stream, format);
174       stream.PutCString(" =");
175       return true;
176     };
177 
178     DumpValueObjectOptions options;
179     options.SetDeclPrintingHelper(helper);
180     ValueObjectPrinter printer(valobj_sp.get(), &result.GetOutputStream(),
181                                options);
182     printer.PrintValueObject();
183   }
184 
185   CommandOptions m_options;
186 };
187 
188 #pragma mark CommandObjectFrameInfo
189 
190 // CommandObjectFrameInfo
191 
192 class CommandObjectFrameInfo : public CommandObjectParsed {
193 public:
194   CommandObjectFrameInfo(CommandInterpreter &interpreter)
195       : CommandObjectParsed(interpreter, "frame info",
196                             "List information about the current "
197                             "stack frame in the current thread.",
198                             "frame info",
199                             eCommandRequiresFrame | eCommandTryTargetAPILock |
200                                 eCommandProcessMustBeLaunched |
201                                 eCommandProcessMustBePaused) {}
202 
203   ~CommandObjectFrameInfo() override = default;
204 
205 protected:
206   void DoExecute(Args &command, CommandReturnObject &result) override {
207     m_exe_ctx.GetFrameRef().DumpUsingSettingsFormat(&result.GetOutputStream());
208     result.SetStatus(eReturnStatusSuccessFinishResult);
209   }
210 };
211 
212 #pragma mark CommandObjectFrameSelect
213 
214 // CommandObjectFrameSelect
215 
216 #define LLDB_OPTIONS_frame_select
217 #include "CommandOptions.inc"
218 
219 class CommandObjectFrameSelect : public CommandObjectParsed {
220 public:
221   class CommandOptions : public Options {
222   public:
223     CommandOptions() { OptionParsingStarting(nullptr); }
224 
225     ~CommandOptions() override = default;
226 
227     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
228                           ExecutionContext *execution_context) override {
229       Status error;
230       const int short_option = m_getopt_table[option_idx].val;
231       switch (short_option) {
232       case 'r': {
233         int32_t offset = 0;
234         if (option_arg.getAsInteger(0, offset) || offset == INT32_MIN) {
235           error.SetErrorStringWithFormat("invalid frame offset argument '%s'",
236                                          option_arg.str().c_str());
237         } else
238           relative_frame_offset = offset;
239         break;
240       }
241 
242       default:
243         llvm_unreachable("Unimplemented option");
244       }
245 
246       return error;
247     }
248 
249     void OptionParsingStarting(ExecutionContext *execution_context) override {
250       relative_frame_offset.reset();
251     }
252 
253     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
254       return llvm::ArrayRef(g_frame_select_options);
255     }
256 
257     std::optional<int32_t> relative_frame_offset;
258   };
259 
260   CommandObjectFrameSelect(CommandInterpreter &interpreter)
261       : CommandObjectParsed(interpreter, "frame select",
262                             "Select the current stack frame by "
263                             "index from within the current thread "
264                             "(see 'thread backtrace'.)",
265                             nullptr,
266                             eCommandRequiresThread | eCommandTryTargetAPILock |
267                                 eCommandProcessMustBeLaunched |
268                                 eCommandProcessMustBePaused) {
269     CommandArgumentEntry arg;
270     CommandArgumentData index_arg;
271 
272     // Define the first (and only) variant of this arg.
273     index_arg.arg_type = eArgTypeFrameIndex;
274     index_arg.arg_repetition = eArgRepeatOptional;
275 
276     // There is only one variant this argument could be; put it into the
277     // argument entry.
278     arg.push_back(index_arg);
279 
280     // Push the data for the first argument into the m_arguments vector.
281     m_arguments.push_back(arg);
282   }
283 
284   ~CommandObjectFrameSelect() override = default;
285 
286   void
287   HandleArgumentCompletion(CompletionRequest &request,
288                            OptionElementVector &opt_element_vector) override {
289     if (request.GetCursorIndex() != 0)
290       return;
291 
292     lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
293         GetCommandInterpreter(), lldb::eFrameIndexCompletion, request, nullptr);
294   }
295 
296   Options *GetOptions() override { return &m_options; }
297 
298 protected:
299   void DoExecute(Args &command, CommandReturnObject &result) override {
300     // No need to check "thread" for validity as eCommandRequiresThread ensures
301     // it is valid
302     Thread *thread = m_exe_ctx.GetThreadPtr();
303 
304     uint32_t frame_idx = UINT32_MAX;
305     if (m_options.relative_frame_offset) {
306       // The one and only argument is a signed relative frame index
307       frame_idx = thread->GetSelectedFrameIndex(SelectMostRelevantFrame);
308       if (frame_idx == UINT32_MAX)
309         frame_idx = 0;
310 
311       if (*m_options.relative_frame_offset < 0) {
312         if (static_cast<int32_t>(frame_idx) >=
313             -*m_options.relative_frame_offset)
314           frame_idx += *m_options.relative_frame_offset;
315         else {
316           if (frame_idx == 0) {
317             // If you are already at the bottom of the stack, then just warn
318             // and don't reset the frame.
319             result.AppendError("Already at the bottom of the stack.");
320             return;
321           } else
322             frame_idx = 0;
323         }
324       } else if (*m_options.relative_frame_offset > 0) {
325         // I don't want "up 20" where "20" takes you past the top of the stack
326         // to produce an error, but rather to just go to the top.  OTOH, start
327         // by seeing if the requested frame exists, in which case we can avoid
328         // counting the stack here...
329         const uint32_t frame_requested = frame_idx
330             + *m_options.relative_frame_offset;
331         StackFrameSP frame_sp = thread->GetStackFrameAtIndex(frame_requested);
332         if (frame_sp)
333           frame_idx = frame_requested;
334         else {
335           // The request went past the stack, so handle that case:
336           const uint32_t num_frames = thread->GetStackFrameCount();
337           if (static_cast<int32_t>(num_frames - frame_idx) >
338               *m_options.relative_frame_offset)
339           frame_idx += *m_options.relative_frame_offset;
340           else {
341             if (frame_idx == num_frames - 1) {
342               // If we are already at the top of the stack, just warn and don't
343               // reset the frame.
344               result.AppendError("Already at the top of the stack.");
345               return;
346             } else
347               frame_idx = num_frames - 1;
348           }
349         }
350       }
351     } else {
352       if (command.GetArgumentCount() > 1) {
353         result.AppendErrorWithFormat(
354             "too many arguments; expected frame-index, saw '%s'.\n",
355             command[0].c_str());
356         m_options.GenerateOptionUsage(
357             result.GetErrorStream(), *this,
358             GetCommandInterpreter().GetDebugger().GetTerminalWidth());
359         return;
360       }
361 
362       if (command.GetArgumentCount() == 1) {
363         if (command[0].ref().getAsInteger(0, frame_idx)) {
364           result.AppendErrorWithFormat("invalid frame index argument '%s'.",
365                                        command[0].c_str());
366           return;
367         }
368       } else if (command.GetArgumentCount() == 0) {
369         frame_idx = thread->GetSelectedFrameIndex(SelectMostRelevantFrame);
370         if (frame_idx == UINT32_MAX) {
371           frame_idx = 0;
372         }
373       }
374     }
375 
376     bool success = thread->SetSelectedFrameByIndexNoisily(
377         frame_idx, result.GetOutputStream());
378     if (success) {
379       m_exe_ctx.SetFrameSP(thread->GetSelectedFrame(SelectMostRelevantFrame));
380       result.SetStatus(eReturnStatusSuccessFinishResult);
381     } else {
382       result.AppendErrorWithFormat("Frame index (%u) out of range.\n",
383                                    frame_idx);
384     }
385   }
386 
387   CommandOptions m_options;
388 };
389 
390 #pragma mark CommandObjectFrameVariable
391 // List images with associated information
392 class CommandObjectFrameVariable : public CommandObjectParsed {
393 public:
394   CommandObjectFrameVariable(CommandInterpreter &interpreter)
395       : CommandObjectParsed(
396             interpreter, "frame variable",
397             "Show variables for the current stack frame. Defaults to all "
398             "arguments and local variables in scope. Names of argument, "
399             "local, file static and file global variables can be specified.",
400             nullptr,
401             eCommandRequiresFrame | eCommandTryTargetAPILock |
402                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused |
403                 eCommandRequiresProcess),
404         m_option_variable(
405             true), // Include the frame specific options by passing "true"
406         m_option_format(eFormatDefault) {
407     SetHelpLong(R"(
408 Children of aggregate variables can be specified such as 'var->child.x'.  In
409 'frame variable', the operators -> and [] do not invoke operator overloads if
410 they exist, but directly access the specified element.  If you want to trigger
411 operator overloads use the expression command to print the variable instead.
412 
413 It is worth noting that except for overloaded operators, when printing local
414 variables 'expr local_var' and 'frame var local_var' produce the same results.
415 However, 'frame variable' is more efficient, since it uses debug information and
416 memory reads directly, rather than parsing and evaluating an expression, which
417 may even involve JITing and running code in the target program.)");
418 
419     CommandArgumentEntry arg;
420     CommandArgumentData var_name_arg;
421 
422     // Define the first (and only) variant of this arg.
423     var_name_arg.arg_type = eArgTypeVarName;
424     var_name_arg.arg_repetition = eArgRepeatStar;
425 
426     // There is only one variant this argument could be; put it into the
427     // argument entry.
428     arg.push_back(var_name_arg);
429 
430     // Push the data for the first argument into the m_arguments vector.
431     m_arguments.push_back(arg);
432 
433     m_option_group.Append(&m_option_variable, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
434     m_option_group.Append(&m_option_format,
435                           OptionGroupFormat::OPTION_GROUP_FORMAT |
436                               OptionGroupFormat::OPTION_GROUP_GDB_FMT,
437                           LLDB_OPT_SET_1);
438     m_option_group.Append(&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
439     m_option_group.Finalize();
440   }
441 
442   ~CommandObjectFrameVariable() override = default;
443 
444   Options *GetOptions() override { return &m_option_group; }
445 
446   void
447   HandleArgumentCompletion(CompletionRequest &request,
448                            OptionElementVector &opt_element_vector) override {
449     // Arguments are the standard source file completer.
450     lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
451         GetCommandInterpreter(), lldb::eVariablePathCompletion, request,
452         nullptr);
453   }
454 
455 protected:
456   llvm::StringRef GetScopeString(VariableSP var_sp) {
457     if (!var_sp)
458       return llvm::StringRef();
459 
460     switch (var_sp->GetScope()) {
461     case eValueTypeVariableGlobal:
462       return "GLOBAL: ";
463     case eValueTypeVariableStatic:
464       return "STATIC: ";
465     case eValueTypeVariableArgument:
466       return "ARG: ";
467     case eValueTypeVariableLocal:
468       return "LOCAL: ";
469     case eValueTypeVariableThreadLocal:
470       return "THREAD: ";
471     default:
472       break;
473     }
474 
475     return llvm::StringRef();
476   }
477 
478   /// Returns true if `scope` matches any of the options in `m_option_variable`.
479   bool ScopeRequested(lldb::ValueType scope) {
480     switch (scope) {
481     case eValueTypeVariableGlobal:
482     case eValueTypeVariableStatic:
483       return m_option_variable.show_globals;
484     case eValueTypeVariableArgument:
485       return m_option_variable.show_args;
486     case eValueTypeVariableLocal:
487       return m_option_variable.show_locals;
488     case eValueTypeInvalid:
489     case eValueTypeRegister:
490     case eValueTypeRegisterSet:
491     case eValueTypeConstResult:
492     case eValueTypeVariableThreadLocal:
493     case eValueTypeVTable:
494     case eValueTypeVTableEntry:
495       return false;
496     }
497     llvm_unreachable("Unexpected scope value");
498   }
499 
500   /// Finds all the variables in `all_variables` whose name matches `regex`,
501   /// inserting them into `matches`. Variables already contained in `matches`
502   /// are not inserted again.
503   /// Nullopt is returned in case of no matches.
504   /// A sub-range of `matches` with all newly inserted variables is returned.
505   /// This may be empty if all matches were already contained in `matches`.
506   std::optional<llvm::ArrayRef<VariableSP>>
507   findUniqueRegexMatches(RegularExpression &regex,
508                          VariableList &matches,
509                          const VariableList &all_variables) {
510     bool any_matches = false;
511     const size_t previous_num_vars = matches.GetSize();
512 
513     for (const VariableSP &var : all_variables) {
514       if (!var->NameMatches(regex) || !ScopeRequested(var->GetScope()))
515         continue;
516       any_matches = true;
517       matches.AddVariableIfUnique(var);
518     }
519 
520     if (any_matches)
521       return matches.toArrayRef().drop_front(previous_num_vars);
522     return std::nullopt;
523   }
524 
525   void DoExecute(Args &command, CommandReturnObject &result) override {
526     // No need to check "frame" for validity as eCommandRequiresFrame ensures
527     // it is valid
528     StackFrame *frame = m_exe_ctx.GetFramePtr();
529 
530     Stream &s = result.GetOutputStream();
531 
532     // Using a regex should behave like looking for an exact name match: it
533     // also finds globals.
534     m_option_variable.show_globals |= m_option_variable.use_regex;
535 
536     // Be careful about the stack frame, if any summary formatter runs code, it
537     // might clear the StackFrameList for the thread.  So hold onto a shared
538     // pointer to the frame so it stays alive.
539 
540     Status error;
541     VariableList *variable_list =
542         frame->GetVariableList(m_option_variable.show_globals, &error);
543 
544     if (error.Fail() && (!variable_list || variable_list->GetSize() == 0)) {
545       result.AppendError(error.AsCString());
546 
547     }
548     ValueObjectSP valobj_sp;
549 
550     TypeSummaryImplSP summary_format_sp;
551     if (!m_option_variable.summary.IsCurrentValueEmpty())
552       DataVisualization::NamedSummaryFormats::GetSummaryFormat(
553           ConstString(m_option_variable.summary.GetCurrentValue()),
554           summary_format_sp);
555     else if (!m_option_variable.summary_string.IsCurrentValueEmpty())
556       summary_format_sp = std::make_shared<StringSummaryFormat>(
557           TypeSummaryImpl::Flags(),
558           m_option_variable.summary_string.GetCurrentValue());
559 
560     DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(
561         eLanguageRuntimeDescriptionDisplayVerbosityFull, eFormatDefault,
562         summary_format_sp));
563 
564     const SymbolContext &sym_ctx =
565         frame->GetSymbolContext(eSymbolContextFunction);
566     if (sym_ctx.function && sym_ctx.function->IsTopLevelFunction())
567       m_option_variable.show_globals = true;
568 
569     if (variable_list) {
570       const Format format = m_option_format.GetFormat();
571       options.SetFormat(format);
572 
573       if (!command.empty()) {
574         VariableList regex_var_list;
575 
576         // If we have any args to the variable command, we will make variable
577         // objects from them...
578         for (auto &entry : command) {
579           if (m_option_variable.use_regex) {
580             llvm::StringRef name_str = entry.ref();
581             RegularExpression regex(name_str);
582             if (regex.IsValid()) {
583               std::optional<llvm::ArrayRef<VariableSP>> results =
584                   findUniqueRegexMatches(regex, regex_var_list, *variable_list);
585               if (!results) {
586                 result.AppendErrorWithFormat(
587                     "no variables matched the regular expression '%s'.",
588                     entry.c_str());
589                 continue;
590               }
591               for (const VariableSP &var_sp : *results) {
592                 valobj_sp = frame->GetValueObjectForFrameVariable(
593                     var_sp, m_varobj_options.use_dynamic);
594                 if (valobj_sp) {
595                   std::string scope_string;
596                   if (m_option_variable.show_scope)
597                     scope_string = GetScopeString(var_sp).str();
598 
599                   if (!scope_string.empty())
600                     s.PutCString(scope_string);
601 
602                   if (m_option_variable.show_decl &&
603                       var_sp->GetDeclaration().GetFile()) {
604                     bool show_fullpaths = false;
605                     bool show_module = true;
606                     if (var_sp->DumpDeclaration(&s, show_fullpaths,
607                                                 show_module))
608                       s.PutCString(": ");
609                   }
610                   valobj_sp->Dump(result.GetOutputStream(), options);
611                 }
612               }
613             } else {
614               if (llvm::Error err = regex.GetError())
615                 result.AppendError(llvm::toString(std::move(err)));
616               else
617                 result.AppendErrorWithFormat(
618                     "unknown regex error when compiling '%s'", entry.c_str());
619             }
620           } else // No regex, either exact variable names or variable
621                  // expressions.
622           {
623             Status error;
624             uint32_t expr_path_options =
625                 StackFrame::eExpressionPathOptionCheckPtrVsMember |
626                 StackFrame::eExpressionPathOptionsAllowDirectIVarAccess |
627                 StackFrame::eExpressionPathOptionsInspectAnonymousUnions;
628             lldb::VariableSP var_sp;
629             valobj_sp = frame->GetValueForVariableExpressionPath(
630                 entry.ref(), m_varobj_options.use_dynamic, expr_path_options,
631                 var_sp, error);
632             if (valobj_sp) {
633               std::string scope_string;
634               if (m_option_variable.show_scope)
635                 scope_string = GetScopeString(var_sp).str();
636 
637               if (!scope_string.empty())
638                 s.PutCString(scope_string);
639               if (m_option_variable.show_decl && var_sp &&
640                   var_sp->GetDeclaration().GetFile()) {
641                 var_sp->GetDeclaration().DumpStopContext(&s, false);
642                 s.PutCString(": ");
643               }
644 
645               options.SetFormat(format);
646               options.SetVariableFormatDisplayLanguage(
647                   valobj_sp->GetPreferredDisplayLanguage());
648 
649               Stream &output_stream = result.GetOutputStream();
650               options.SetRootValueObjectName(
651                   valobj_sp->GetParent() ? entry.c_str() : nullptr);
652               valobj_sp->Dump(output_stream, options);
653             } else {
654               if (auto error_cstr = error.AsCString(nullptr))
655                 result.AppendError(error_cstr);
656               else
657                 result.AppendErrorWithFormat(
658                     "unable to find any variable expression path that matches "
659                     "'%s'.",
660                     entry.c_str());
661             }
662           }
663         }
664       } else // No command arg specified.  Use variable_list, instead.
665       {
666         const size_t num_variables = variable_list->GetSize();
667         if (num_variables > 0) {
668           for (size_t i = 0; i < num_variables; i++) {
669             VariableSP var_sp = variable_list->GetVariableAtIndex(i);
670             if (!ScopeRequested(var_sp->GetScope()))
671                 continue;
672             std::string scope_string;
673             if (m_option_variable.show_scope)
674               scope_string = GetScopeString(var_sp).str();
675 
676             // Use the variable object code to make sure we are using the same
677             // APIs as the public API will be using...
678             valobj_sp = frame->GetValueObjectForFrameVariable(
679                 var_sp, m_varobj_options.use_dynamic);
680             if (valobj_sp) {
681               // When dumping all variables, don't print any variables that are
682               // not in scope to avoid extra unneeded output
683               if (valobj_sp->IsInScope()) {
684                 if (!valobj_sp->GetTargetSP()
685                          ->GetDisplayRuntimeSupportValues() &&
686                     valobj_sp->IsRuntimeSupportValue())
687                   continue;
688 
689                 if (!scope_string.empty())
690                   s.PutCString(scope_string);
691 
692                 if (m_option_variable.show_decl &&
693                     var_sp->GetDeclaration().GetFile()) {
694                   var_sp->GetDeclaration().DumpStopContext(&s, false);
695                   s.PutCString(": ");
696                 }
697 
698                 options.SetFormat(format);
699                 options.SetVariableFormatDisplayLanguage(
700                     valobj_sp->GetPreferredDisplayLanguage());
701                 options.SetRootValueObjectName(
702                     var_sp ? var_sp->GetName().AsCString() : nullptr);
703                 valobj_sp->Dump(result.GetOutputStream(), options);
704               }
705             }
706           }
707         }
708       }
709       if (result.GetStatus() != eReturnStatusFailed)
710         result.SetStatus(eReturnStatusSuccessFinishResult);
711     }
712 
713     if (m_option_variable.show_recognized_args) {
714       auto recognized_frame = frame->GetRecognizedFrame();
715       if (recognized_frame) {
716         ValueObjectListSP recognized_arg_list =
717             recognized_frame->GetRecognizedArguments();
718         if (recognized_arg_list) {
719           for (auto &rec_value_sp : recognized_arg_list->GetObjects()) {
720             options.SetFormat(m_option_format.GetFormat());
721             options.SetVariableFormatDisplayLanguage(
722                 rec_value_sp->GetPreferredDisplayLanguage());
723             options.SetRootValueObjectName(rec_value_sp->GetName().AsCString());
724             rec_value_sp->Dump(result.GetOutputStream(), options);
725           }
726         }
727       }
728     }
729 
730     m_interpreter.PrintWarningsIfNecessary(result.GetOutputStream(),
731                                            m_cmd_name);
732 
733     // Increment statistics.
734     TargetStats &target_stats = GetSelectedOrDummyTarget().GetStatistics();
735     if (result.Succeeded())
736       target_stats.GetFrameVariableStats().NotifySuccess();
737     else
738       target_stats.GetFrameVariableStats().NotifyFailure();
739   }
740 
741   OptionGroupOptions m_option_group;
742   OptionGroupVariable m_option_variable;
743   OptionGroupFormat m_option_format;
744   OptionGroupValueObjectDisplay m_varobj_options;
745 };
746 
747 #pragma mark CommandObjectFrameRecognizer
748 
749 #define LLDB_OPTIONS_frame_recognizer_add
750 #include "CommandOptions.inc"
751 
752 class CommandObjectFrameRecognizerAdd : public CommandObjectParsed {
753 private:
754   class CommandOptions : public Options {
755   public:
756     CommandOptions() = default;
757     ~CommandOptions() override = default;
758 
759     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
760                           ExecutionContext *execution_context) override {
761       Status error;
762       const int short_option = m_getopt_table[option_idx].val;
763 
764       switch (short_option) {
765       case 'f': {
766         bool value, success;
767         value = OptionArgParser::ToBoolean(option_arg, true, &success);
768         if (success) {
769           m_first_instruction_only = value;
770         } else {
771           error.SetErrorStringWithFormat(
772               "invalid boolean value '%s' passed for -f option",
773               option_arg.str().c_str());
774         }
775       } break;
776       case 'l':
777         m_class_name = std::string(option_arg);
778         break;
779       case 's':
780         m_module = std::string(option_arg);
781         break;
782       case 'n':
783         m_symbols.push_back(std::string(option_arg));
784         break;
785       case 'x':
786         m_regex = true;
787         break;
788       default:
789         llvm_unreachable("Unimplemented option");
790       }
791 
792       return error;
793     }
794 
795     void OptionParsingStarting(ExecutionContext *execution_context) override {
796       m_module = "";
797       m_symbols.clear();
798       m_class_name = "";
799       m_regex = false;
800       m_first_instruction_only = true;
801     }
802 
803     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
804       return llvm::ArrayRef(g_frame_recognizer_add_options);
805     }
806 
807     // Instance variables to hold the values for command options.
808     std::string m_class_name;
809     std::string m_module;
810     std::vector<std::string> m_symbols;
811     bool m_regex;
812     bool m_first_instruction_only;
813   };
814 
815   CommandOptions m_options;
816 
817   Options *GetOptions() override { return &m_options; }
818 
819 protected:
820   void DoExecute(Args &command, CommandReturnObject &result) override;
821 
822 public:
823   CommandObjectFrameRecognizerAdd(CommandInterpreter &interpreter)
824       : CommandObjectParsed(interpreter, "frame recognizer add",
825                             "Add a new frame recognizer.", nullptr) {
826     SetHelpLong(R"(
827 Frame recognizers allow for retrieving information about special frames based on
828 ABI, arguments or other special properties of that frame, even without source
829 code or debug info. Currently, one use case is to extract function arguments
830 that would otherwise be unaccesible, or augment existing arguments.
831 
832 Adding a custom frame recognizer is possible by implementing a Python class
833 and using the 'frame recognizer add' command. The Python class should have a
834 'get_recognized_arguments' method and it will receive an argument of type
835 lldb.SBFrame representing the current frame that we are trying to recognize.
836 The method should return a (possibly empty) list of lldb.SBValue objects that
837 represent the recognized arguments.
838 
839 An example of a recognizer that retrieves the file descriptor values from libc
840 functions 'read', 'write' and 'close' follows:
841 
842   class LibcFdRecognizer(object):
843     def get_recognized_arguments(self, frame):
844       if frame.name in ["read", "write", "close"]:
845         fd = frame.EvaluateExpression("$arg1").unsigned
846         target = frame.thread.process.target
847         value = target.CreateValueFromExpression("fd", "(int)%d" % fd)
848         return [value]
849       return []
850 
851 The file containing this implementation can be imported via 'command script
852 import' and then we can register this recognizer with 'frame recognizer add'.
853 It's important to restrict the recognizer to the libc library (which is
854 libsystem_kernel.dylib on macOS) to avoid matching functions with the same name
855 in other modules:
856 
857 (lldb) command script import .../fd_recognizer.py
858 (lldb) frame recognizer add -l fd_recognizer.LibcFdRecognizer -n read -s libsystem_kernel.dylib
859 
860 When the program is stopped at the beginning of the 'read' function in libc, we
861 can view the recognizer arguments in 'frame variable':
862 
863 (lldb) b read
864 (lldb) r
865 Process 1234 stopped
866 * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.3
867     frame #0: 0x00007fff06013ca0 libsystem_kernel.dylib`read
868 (lldb) frame variable
869 (int) fd = 3
870 
871     )");
872   }
873   ~CommandObjectFrameRecognizerAdd() override = default;
874 };
875 
876 void CommandObjectFrameRecognizerAdd::DoExecute(Args &command,
877                                                 CommandReturnObject &result) {
878 #if LLDB_ENABLE_PYTHON
879   if (m_options.m_class_name.empty()) {
880     result.AppendErrorWithFormat(
881         "%s needs a Python class name (-l argument).\n", m_cmd_name.c_str());
882     return;
883   }
884 
885   if (m_options.m_module.empty()) {
886     result.AppendErrorWithFormat("%s needs a module name (-s argument).\n",
887                                  m_cmd_name.c_str());
888     return;
889   }
890 
891   if (m_options.m_symbols.empty()) {
892     result.AppendErrorWithFormat(
893         "%s needs at least one symbol name (-n argument).\n",
894         m_cmd_name.c_str());
895     return;
896   }
897 
898   if (m_options.m_regex && m_options.m_symbols.size() > 1) {
899     result.AppendErrorWithFormat(
900         "%s needs only one symbol regular expression (-n argument).\n",
901         m_cmd_name.c_str());
902     return;
903   }
904 
905   ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
906 
907   if (interpreter &&
908       !interpreter->CheckObjectExists(m_options.m_class_name.c_str())) {
909     result.AppendWarning("The provided class does not exist - please define it "
910                          "before attempting to use this frame recognizer");
911   }
912 
913   StackFrameRecognizerSP recognizer_sp =
914       StackFrameRecognizerSP(new ScriptedStackFrameRecognizer(
915           interpreter, m_options.m_class_name.c_str()));
916   if (m_options.m_regex) {
917     auto module =
918         RegularExpressionSP(new RegularExpression(m_options.m_module));
919     auto func =
920         RegularExpressionSP(new RegularExpression(m_options.m_symbols.front()));
921     GetSelectedOrDummyTarget().GetFrameRecognizerManager().AddRecognizer(
922         recognizer_sp, module, func, m_options.m_first_instruction_only);
923   } else {
924     auto module = ConstString(m_options.m_module);
925     std::vector<ConstString> symbols(m_options.m_symbols.begin(),
926                                      m_options.m_symbols.end());
927     GetSelectedOrDummyTarget().GetFrameRecognizerManager().AddRecognizer(
928         recognizer_sp, module, symbols, m_options.m_first_instruction_only);
929   }
930 #endif
931 
932   result.SetStatus(eReturnStatusSuccessFinishNoResult);
933 }
934 
935 class CommandObjectFrameRecognizerClear : public CommandObjectParsed {
936 public:
937   CommandObjectFrameRecognizerClear(CommandInterpreter &interpreter)
938       : CommandObjectParsed(interpreter, "frame recognizer clear",
939                             "Delete all frame recognizers.", nullptr) {}
940 
941   ~CommandObjectFrameRecognizerClear() override = default;
942 
943 protected:
944   void DoExecute(Args &command, CommandReturnObject &result) override {
945     GetSelectedOrDummyTarget()
946         .GetFrameRecognizerManager()
947         .RemoveAllRecognizers();
948     result.SetStatus(eReturnStatusSuccessFinishResult);
949   }
950 };
951 
952 class CommandObjectFrameRecognizerDelete : public CommandObjectParsed {
953 public:
954   CommandObjectFrameRecognizerDelete(CommandInterpreter &interpreter)
955       : CommandObjectParsed(interpreter, "frame recognizer delete",
956                             "Delete an existing frame recognizer by id.",
957                             nullptr) {
958     CommandArgumentData thread_arg{eArgTypeRecognizerID, eArgRepeatPlain};
959     m_arguments.push_back({thread_arg});
960   }
961 
962   ~CommandObjectFrameRecognizerDelete() override = default;
963 
964   void
965   HandleArgumentCompletion(CompletionRequest &request,
966                            OptionElementVector &opt_element_vector) override {
967     if (request.GetCursorIndex() != 0)
968       return;
969 
970     GetSelectedOrDummyTarget().GetFrameRecognizerManager().ForEach(
971         [&request](uint32_t rid, std::string rname, std::string module,
972                    llvm::ArrayRef<lldb_private::ConstString> symbols,
973                    bool regexp) {
974           StreamString strm;
975           if (rname.empty())
976             rname = "(internal)";
977 
978           strm << rname;
979           if (!module.empty())
980             strm << ", module " << module;
981           if (!symbols.empty())
982             for (auto &symbol : symbols)
983               strm << ", symbol " << symbol;
984           if (regexp)
985             strm << " (regexp)";
986 
987           request.TryCompleteCurrentArg(std::to_string(rid), strm.GetString());
988         });
989   }
990 
991 protected:
992   void DoExecute(Args &command, CommandReturnObject &result) override {
993     if (command.GetArgumentCount() == 0) {
994       if (!m_interpreter.Confirm(
995               "About to delete all frame recognizers, do you want to do that?",
996               true)) {
997         result.AppendMessage("Operation cancelled...");
998         return;
999       }
1000 
1001       GetSelectedOrDummyTarget()
1002           .GetFrameRecognizerManager()
1003           .RemoveAllRecognizers();
1004       result.SetStatus(eReturnStatusSuccessFinishResult);
1005       return;
1006     }
1007 
1008     if (command.GetArgumentCount() != 1) {
1009       result.AppendErrorWithFormat("'%s' takes zero or one arguments.\n",
1010                                    m_cmd_name.c_str());
1011       return;
1012     }
1013 
1014     uint32_t recognizer_id;
1015     if (!llvm::to_integer(command.GetArgumentAtIndex(0), recognizer_id)) {
1016       result.AppendErrorWithFormat("'%s' is not a valid recognizer id.\n",
1017                                    command.GetArgumentAtIndex(0));
1018       return;
1019     }
1020 
1021     if (!GetSelectedOrDummyTarget()
1022              .GetFrameRecognizerManager()
1023              .RemoveRecognizerWithID(recognizer_id)) {
1024       result.AppendErrorWithFormat("'%s' is not a valid recognizer id.\n",
1025                                    command.GetArgumentAtIndex(0));
1026       return;
1027     }
1028     result.SetStatus(eReturnStatusSuccessFinishResult);
1029   }
1030 };
1031 
1032 class CommandObjectFrameRecognizerList : public CommandObjectParsed {
1033 public:
1034   CommandObjectFrameRecognizerList(CommandInterpreter &interpreter)
1035       : CommandObjectParsed(interpreter, "frame recognizer list",
1036                             "Show a list of active frame recognizers.",
1037                             nullptr) {}
1038 
1039   ~CommandObjectFrameRecognizerList() override = default;
1040 
1041 protected:
1042   void DoExecute(Args &command, CommandReturnObject &result) override {
1043     bool any_printed = false;
1044     GetSelectedOrDummyTarget().GetFrameRecognizerManager().ForEach(
1045         [&result, &any_printed](
1046             uint32_t recognizer_id, std::string name, std::string module,
1047             llvm::ArrayRef<ConstString> symbols, bool regexp) {
1048           Stream &stream = result.GetOutputStream();
1049 
1050           if (name.empty())
1051             name = "(internal)";
1052 
1053           stream << std::to_string(recognizer_id) << ": " << name;
1054           if (!module.empty())
1055             stream << ", module " << module;
1056           if (!symbols.empty())
1057             for (auto &symbol : symbols)
1058               stream << ", symbol " << symbol;
1059           if (regexp)
1060             stream << " (regexp)";
1061 
1062           stream.EOL();
1063           stream.Flush();
1064 
1065           any_printed = true;
1066         });
1067 
1068     if (any_printed)
1069       result.SetStatus(eReturnStatusSuccessFinishResult);
1070     else {
1071       result.GetOutputStream().PutCString("no matching results found.\n");
1072       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1073     }
1074   }
1075 };
1076 
1077 class CommandObjectFrameRecognizerInfo : public CommandObjectParsed {
1078 public:
1079   CommandObjectFrameRecognizerInfo(CommandInterpreter &interpreter)
1080       : CommandObjectParsed(
1081             interpreter, "frame recognizer info",
1082             "Show which frame recognizer is applied a stack frame (if any).",
1083             nullptr) {
1084     CommandArgumentEntry arg;
1085     CommandArgumentData index_arg;
1086 
1087     // Define the first (and only) variant of this arg.
1088     index_arg.arg_type = eArgTypeFrameIndex;
1089     index_arg.arg_repetition = eArgRepeatPlain;
1090 
1091     // There is only one variant this argument could be; put it into the
1092     // argument entry.
1093     arg.push_back(index_arg);
1094 
1095     // Push the data for the first argument into the m_arguments vector.
1096     m_arguments.push_back(arg);
1097   }
1098 
1099   ~CommandObjectFrameRecognizerInfo() override = default;
1100 
1101 protected:
1102   void DoExecute(Args &command, CommandReturnObject &result) override {
1103     const char *frame_index_str = command.GetArgumentAtIndex(0);
1104     uint32_t frame_index;
1105     if (!llvm::to_integer(frame_index_str, frame_index)) {
1106       result.AppendErrorWithFormat("'%s' is not a valid frame index.",
1107                                    frame_index_str);
1108       return;
1109     }
1110 
1111     Process *process = m_exe_ctx.GetProcessPtr();
1112     if (process == nullptr) {
1113       result.AppendError("no process");
1114       return;
1115     }
1116     Thread *thread = m_exe_ctx.GetThreadPtr();
1117     if (thread == nullptr) {
1118       result.AppendError("no thread");
1119       return;
1120     }
1121     if (command.GetArgumentCount() != 1) {
1122       result.AppendErrorWithFormat(
1123           "'%s' takes exactly one frame index argument.\n", m_cmd_name.c_str());
1124       return;
1125     }
1126 
1127     StackFrameSP frame_sp = thread->GetStackFrameAtIndex(frame_index);
1128     if (!frame_sp) {
1129       result.AppendErrorWithFormat("no frame with index %u", frame_index);
1130       return;
1131     }
1132 
1133     auto recognizer = GetSelectedOrDummyTarget()
1134                           .GetFrameRecognizerManager()
1135                           .GetRecognizerForFrame(frame_sp);
1136 
1137     Stream &output_stream = result.GetOutputStream();
1138     output_stream.Printf("frame %d ", frame_index);
1139     if (recognizer) {
1140       output_stream << "is recognized by ";
1141       output_stream << recognizer->GetName();
1142     } else {
1143       output_stream << "not recognized by any recognizer";
1144     }
1145     output_stream.EOL();
1146     result.SetStatus(eReturnStatusSuccessFinishResult);
1147   }
1148 };
1149 
1150 class CommandObjectFrameRecognizer : public CommandObjectMultiword {
1151 public:
1152   CommandObjectFrameRecognizer(CommandInterpreter &interpreter)
1153       : CommandObjectMultiword(
1154             interpreter, "frame recognizer",
1155             "Commands for editing and viewing frame recognizers.",
1156             "frame recognizer [<sub-command-options>] ") {
1157     LoadSubCommand("add", CommandObjectSP(new CommandObjectFrameRecognizerAdd(
1158                               interpreter)));
1159     LoadSubCommand(
1160         "clear",
1161         CommandObjectSP(new CommandObjectFrameRecognizerClear(interpreter)));
1162     LoadSubCommand(
1163         "delete",
1164         CommandObjectSP(new CommandObjectFrameRecognizerDelete(interpreter)));
1165     LoadSubCommand("list", CommandObjectSP(new CommandObjectFrameRecognizerList(
1166                                interpreter)));
1167     LoadSubCommand("info", CommandObjectSP(new CommandObjectFrameRecognizerInfo(
1168                                interpreter)));
1169   }
1170 
1171   ~CommandObjectFrameRecognizer() override = default;
1172 };
1173 
1174 #pragma mark CommandObjectMultiwordFrame
1175 
1176 // CommandObjectMultiwordFrame
1177 
1178 CommandObjectMultiwordFrame::CommandObjectMultiwordFrame(
1179     CommandInterpreter &interpreter)
1180     : CommandObjectMultiword(interpreter, "frame",
1181                              "Commands for selecting and "
1182                              "examing the current "
1183                              "thread's stack frames.",
1184                              "frame <subcommand> [<subcommand-options>]") {
1185   LoadSubCommand("diagnose",
1186                  CommandObjectSP(new CommandObjectFrameDiagnose(interpreter)));
1187   LoadSubCommand("info",
1188                  CommandObjectSP(new CommandObjectFrameInfo(interpreter)));
1189   LoadSubCommand("select",
1190                  CommandObjectSP(new CommandObjectFrameSelect(interpreter)));
1191   LoadSubCommand("variable",
1192                  CommandObjectSP(new CommandObjectFrameVariable(interpreter)));
1193 #if LLDB_ENABLE_PYTHON
1194   LoadSubCommand("recognizer", CommandObjectSP(new CommandObjectFrameRecognizer(
1195                                    interpreter)));
1196 #endif
1197 }
1198 
1199 CommandObjectMultiwordFrame::~CommandObjectMultiwordFrame() = default;
1200