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