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