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