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