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