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