LLDB mainline
CommandObjectFrame.cpp
Go to the documentation of this file.
1//===-- CommandObjectFrame.cpp --------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
13#include "lldb/Host/Config.h"
30#include "lldb/Target/Target.h"
31#include "lldb/Target/Thread.h"
32#include "lldb/Utility/Args.h"
33
34#include <memory>
35#include <optional>
36#include <string>
37
38using namespace lldb;
39using namespace lldb_private;
40
41#pragma mark CommandObjectFrameDiagnose
42
43// CommandObjectFrameInfo
44
45// CommandObjectFrameDiagnose
46
47#define LLDB_OPTIONS_frame_diag
48#include "CommandOptions.inc"
49
51public:
52 class CommandOptions : public Options {
53 public:
55
56 ~CommandOptions() override = default;
57
58 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
59 ExecutionContext *execution_context) override {
61 const int short_option = m_getopt_table[option_idx].val;
62 switch (short_option) {
63 case 'r':
64 reg = ConstString(option_arg);
65 break;
66
67 case 'a': {
68 address.emplace();
69 if (option_arg.getAsInteger(0, *address)) {
70 address.reset();
71 error.SetErrorStringWithFormat("invalid address argument '%s'",
72 option_arg.str().c_str());
73 }
74 } break;
75
76 case 'o': {
77 offset.emplace();
78 if (option_arg.getAsInteger(0, *offset)) {
79 offset.reset();
80 error.SetErrorStringWithFormat("invalid offset argument '%s'",
81 option_arg.str().c_str());
82 }
83 } break;
84
85 default:
86 llvm_unreachable("Unimplemented option");
87 }
88
89 return error;
90 }
91
92 void OptionParsingStarting(ExecutionContext *execution_context) override {
93 address.reset();
94 reg.reset();
95 offset.reset();
96 }
97
98 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
99 return llvm::ArrayRef(g_frame_diag_options);
100 }
101
102 // Options.
103 std::optional<lldb::addr_t> address;
104 std::optional<ConstString> reg;
105 std::optional<int64_t> offset;
106 };
107
109 : CommandObjectParsed(interpreter, "frame diagnose",
110 "Try to determine what path the current stop "
111 "location used to get to a register or address",
112 nullptr,
113 eCommandRequiresThread | eCommandTryTargetAPILock |
114 eCommandProcessMustBeLaunched |
115 eCommandProcessMustBePaused) {
117 CommandArgumentData index_arg;
118
119 // Define the first (and only) variant of this arg.
120 index_arg.arg_type = eArgTypeFrameIndex;
122
123 // There is only one variant this argument could be; put it into the
124 // argument entry.
125 arg.push_back(index_arg);
126
127 // Push the data for the first argument into the m_arguments vector.
128 m_arguments.push_back(arg);
129 }
130
131 ~CommandObjectFrameDiagnose() override = default;
132
133 Options *GetOptions() override { return &m_options; }
134
135protected:
136 bool DoExecute(Args &command, CommandReturnObject &result) override {
137 Thread *thread = m_exe_ctx.GetThreadPtr();
138 StackFrameSP frame_sp = thread->GetSelectedFrame();
139
140 ValueObjectSP valobj_sp;
141
142 if (m_options.address) {
143 if (m_options.reg || m_options.offset) {
144 result.AppendError(
145 "`frame diagnose --address` is incompatible with other arguments.");
146 return false;
147 }
148 valobj_sp = frame_sp->GuessValueForAddress(*m_options.address);
149 } else if (m_options.reg) {
150 valobj_sp = frame_sp->GuessValueForRegisterAndOffset(
151 *m_options.reg, m_options.offset.value_or(0));
152 } else {
153 StopInfoSP stop_info_sp = thread->GetStopInfo();
154 if (!stop_info_sp) {
155 result.AppendError("No arguments provided, and no stop info.");
156 return false;
157 }
158
159 valobj_sp = StopInfo::GetCrashingDereference(stop_info_sp);
160 }
161
162 if (!valobj_sp) {
163 result.AppendError("No diagnosis available.");
164 return false;
165 }
166
168 [&valobj_sp](ConstString type, ConstString var,
169 const DumpValueObjectOptions &opts,
170 Stream &stream) -> bool {
171 const ValueObject::GetExpressionPathFormat format = ValueObject::
172 GetExpressionPathFormat::eGetExpressionPathFormatHonorPointers;
173 valobj_sp->GetExpressionPath(stream, format);
174 stream.PutCString(" =");
175 return true;
176 };
177
179 options.SetDeclPrintingHelper(helper);
180 ValueObjectPrinter printer(valobj_sp.get(), &result.GetOutputStream(),
181 options);
182 printer.PrintValueObject();
183
184 return true;
185 }
186
188};
189
190#pragma mark CommandObjectFrameInfo
191
192// CommandObjectFrameInfo
193
195public:
197 : CommandObjectParsed(interpreter, "frame info",
198 "List information about the current "
199 "stack frame in the current thread.",
200 "frame info",
201 eCommandRequiresFrame | eCommandTryTargetAPILock |
202 eCommandProcessMustBeLaunched |
203 eCommandProcessMustBePaused) {}
204
205 ~CommandObjectFrameInfo() override = default;
206
207protected:
208 bool DoExecute(Args &command, CommandReturnObject &result) override {
211 return result.Succeeded();
212 }
213};
214
215#pragma mark CommandObjectFrameSelect
216
217// CommandObjectFrameSelect
218
219#define LLDB_OPTIONS_frame_select
220#include "CommandOptions.inc"
221
223public:
224 class CommandOptions : public Options {
225 public:
227
228 ~CommandOptions() override = default;
229
230 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
231 ExecutionContext *execution_context) override {
233 const int short_option = m_getopt_table[option_idx].val;
234 switch (short_option) {
235 case 'r': {
236 int32_t offset = 0;
237 if (option_arg.getAsInteger(0, offset) || offset == INT32_MIN) {
238 error.SetErrorStringWithFormat("invalid frame offset argument '%s'",
239 option_arg.str().c_str());
240 } else
241 relative_frame_offset = offset;
242 break;
243 }
244
245 default:
246 llvm_unreachable("Unimplemented option");
247 }
248
249 return error;
250 }
251
252 void OptionParsingStarting(ExecutionContext *execution_context) override {
253 relative_frame_offset.reset();
254 }
255
256 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
257 return llvm::ArrayRef(g_frame_select_options);
258 }
259
260 std::optional<int32_t> relative_frame_offset;
261 };
262
264 : CommandObjectParsed(interpreter, "frame select",
265 "Select the current stack frame by "
266 "index from within the current thread "
267 "(see 'thread backtrace'.)",
268 nullptr,
269 eCommandRequiresThread | eCommandTryTargetAPILock |
270 eCommandProcessMustBeLaunched |
271 eCommandProcessMustBePaused) {
273 CommandArgumentData index_arg;
274
275 // Define the first (and only) variant of this arg.
276 index_arg.arg_type = eArgTypeFrameIndex;
278
279 // There is only one variant this argument could be; put it into the
280 // argument entry.
281 arg.push_back(index_arg);
282
283 // Push the data for the first argument into the m_arguments vector.
284 m_arguments.push_back(arg);
285 }
286
287 ~CommandObjectFrameSelect() override = default;
288
289 void
291 OptionElementVector &opt_element_vector) override {
292 if (request.GetCursorIndex() != 0)
293 return;
294
297 request, nullptr);
298 }
299
300 Options *GetOptions() override { return &m_options; }
301
302protected:
303 bool DoExecute(Args &command, CommandReturnObject &result) override {
304 // No need to check "thread" for validity as eCommandRequiresThread ensures
305 // it is valid
306 Thread *thread = m_exe_ctx.GetThreadPtr();
307
308 uint32_t frame_idx = UINT32_MAX;
310 // The one and only argument is a signed relative frame index
311 frame_idx = thread->GetSelectedFrameIndex();
312 if (frame_idx == UINT32_MAX)
313 frame_idx = 0;
314
316 if (static_cast<int32_t>(frame_idx) >=
318 frame_idx += *m_options.relative_frame_offset;
319 else {
320 if (frame_idx == 0) {
321 // If you are already at the bottom of the stack, then just warn
322 // and don't reset the frame.
323 result.AppendError("Already at the bottom of the stack.");
324 return false;
325 } else
326 frame_idx = 0;
327 }
328 } else if (*m_options.relative_frame_offset > 0) {
329 // I don't want "up 20" where "20" takes you past the top of the stack
330 // to produce
331 // an error, but rather to just go to the top. So I have to count the
332 // stack here...
333 const uint32_t num_frames = thread->GetStackFrameCount();
334 if (static_cast<int32_t>(num_frames - frame_idx) >
336 frame_idx += *m_options.relative_frame_offset;
337 else {
338 if (frame_idx == num_frames - 1) {
339 // If we are already at the top of the stack, just warn and don't
340 // reset the frame.
341 result.AppendError("Already at the top of the stack.");
342 return false;
343 } else
344 frame_idx = num_frames - 1;
345 }
346 }
347 } else {
348 if (command.GetArgumentCount() > 1) {
350 "too many arguments; expected frame-index, saw '%s'.\n",
351 command[0].c_str());
353 result.GetErrorStream(), *this,
354 GetCommandInterpreter().GetDebugger().GetTerminalWidth());
355 return false;
356 }
357
358 if (command.GetArgumentCount() == 1) {
359 if (command[0].ref().getAsInteger(0, frame_idx)) {
360 result.AppendErrorWithFormat("invalid frame index argument '%s'.",
361 command[0].c_str());
362 return false;
363 }
364 } else if (command.GetArgumentCount() == 0) {
365 frame_idx = thread->GetSelectedFrameIndex();
366 if (frame_idx == UINT32_MAX) {
367 frame_idx = 0;
368 }
369 }
370 }
371
372 bool success = thread->SetSelectedFrameByIndexNoisily(
373 frame_idx, result.GetOutputStream());
374 if (success) {
377 } else {
378 result.AppendErrorWithFormat("Frame index (%u) out of range.\n",
379 frame_idx);
380 }
381
382 return result.Succeeded();
383 }
384
386};
387
388#pragma mark CommandObjectFrameVariable
389// List images with associated information
391public:
394 interpreter, "frame variable",
395 "Show variables for the current stack frame. Defaults to all "
396 "arguments and local variables in scope. Names of argument, "
397 "local, file static and file global variables can be specified.",
398 nullptr,
399 eCommandRequiresFrame | eCommandTryTargetAPILock |
400 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused |
401 eCommandRequiresProcess),
403 true), // Include the frame specific options by passing "true"
405 SetHelpLong(R"(
406Children of aggregate variables can be specified such as 'var->child.x'. In
407'frame variable', the operators -> and [] do not invoke operator overloads if
408they exist, but directly access the specified element. If you want to trigger
409operator overloads use the expression command to print the variable instead.
410
411It is worth noting that except for overloaded operators, when printing local
412variables 'expr local_var' and 'frame var local_var' produce the same results.
413However, 'frame variable' is more efficient, since it uses debug information and
414memory reads directly, rather than parsing and evaluating an expression, which
415may even involve JITing and running code in the target program.)");
416
418 CommandArgumentData var_name_arg;
419
420 // Define the first (and only) variant of this arg.
421 var_name_arg.arg_type = eArgTypeVarName;
422 var_name_arg.arg_repetition = eArgRepeatStar;
423
424 // There is only one variant this argument could be; put it into the
425 // argument entry.
426 arg.push_back(var_name_arg);
427
428 // Push the data for the first argument into the m_arguments vector.
429 m_arguments.push_back(arg);
430
438 }
439
440 ~CommandObjectFrameVariable() override = default;
441
442 Options *GetOptions() override { return &m_option_group; }
443
444 void
446 OptionElementVector &opt_element_vector) override {
447 // Arguments are the standard source file completer.
450 request, nullptr);
451 }
452
453protected:
454 llvm::StringRef GetScopeString(VariableSP var_sp) {
455 if (!var_sp)
456 return llvm::StringRef();
457
458 switch (var_sp->GetScope()) {
460 return "GLOBAL: ";
462 return "STATIC: ";
464 return "ARG: ";
466 return "LOCAL: ";
468 return "THREAD: ";
469 default:
470 break;
471 }
472
473 return llvm::StringRef();
474 }
475
476 bool DoExecute(Args &command, CommandReturnObject &result) override {
477 // No need to check "frame" for validity as eCommandRequiresFrame ensures
478 // it is valid
480
481 Stream &s = result.GetOutputStream();
482
483 // Be careful about the stack frame, if any summary formatter runs code, it
484 // might clear the StackFrameList for the thread. So hold onto a shared
485 // pointer to the frame so it stays alive.
486
488 VariableList *variable_list =
490
491 if (error.Fail() && (!variable_list || variable_list->GetSize() == 0)) {
492 result.AppendError(error.AsCString());
493
494 }
495 VariableSP var_sp;
496 ValueObjectSP valobj_sp;
497
498 TypeSummaryImplSP summary_format_sp;
502 summary_format_sp);
504 summary_format_sp = std::make_shared<StringSummaryFormat>(
507
510 summary_format_sp));
511
512 const SymbolContext &sym_ctx =
513 frame->GetSymbolContext(eSymbolContextFunction);
514 if (sym_ctx.function && sym_ctx.function->IsTopLevelFunction())
516
517 if (variable_list) {
518 const Format format = m_option_format.GetFormat();
519 options.SetFormat(format);
520
521 if (!command.empty()) {
522 VariableList regex_var_list;
523
524 // If we have any args to the variable command, we will make variable
525 // objects from them...
526 for (auto &entry : command) {
528 const size_t regex_start_index = regex_var_list.GetSize();
529 llvm::StringRef name_str = entry.ref();
530 RegularExpression regex(name_str);
531 if (regex.IsValid()) {
532 size_t num_matches = 0;
533 const size_t num_new_regex_vars =
534 variable_list->AppendVariablesIfUnique(regex, regex_var_list,
535 num_matches);
536 if (num_new_regex_vars > 0) {
537 for (size_t regex_idx = regex_start_index,
538 end_index = regex_var_list.GetSize();
539 regex_idx < end_index; ++regex_idx) {
540 var_sp = regex_var_list.GetVariableAtIndex(regex_idx);
541 if (var_sp) {
542 valobj_sp = frame->GetValueObjectForFrameVariable(
544 if (valobj_sp) {
545 std::string scope_string;
547 scope_string = GetScopeString(var_sp).str();
548
549 if (!scope_string.empty())
550 s.PutCString(scope_string);
551
553 var_sp->GetDeclaration().GetFile()) {
554 bool show_fullpaths = false;
555 bool show_module = true;
556 if (var_sp->DumpDeclaration(&s, show_fullpaths,
557 show_module))
558 s.PutCString(": ");
559 }
560 valobj_sp->Dump(result.GetOutputStream(), options);
561 }
562 }
563 }
564 } else if (num_matches == 0) {
566 "no variables matched the regular expression '%s'.",
567 entry.c_str());
568 }
569 } else {
570 if (llvm::Error err = regex.GetError())
571 result.AppendError(llvm::toString(std::move(err)));
572 else
574 "unknown regex error when compiling '%s'", entry.c_str());
575 }
576 } else // No regex, either exact variable names or variable
577 // expressions.
578 {
580 uint32_t expr_path_options =
584 lldb::VariableSP var_sp;
585 valobj_sp = frame->GetValueForVariableExpressionPath(
586 entry.ref(), m_varobj_options.use_dynamic, expr_path_options,
587 var_sp, error);
588 if (valobj_sp) {
589 std::string scope_string;
591 scope_string = GetScopeString(var_sp).str();
592
593 if (!scope_string.empty())
594 s.PutCString(scope_string);
595 if (m_option_variable.show_decl && var_sp &&
596 var_sp->GetDeclaration().GetFile()) {
597 var_sp->GetDeclaration().DumpStopContext(&s, false);
598 s.PutCString(": ");
599 }
600
601 options.SetFormat(format);
603 valobj_sp->GetPreferredDisplayLanguage());
604
605 Stream &output_stream = result.GetOutputStream();
607 valobj_sp->GetParent() ? entry.c_str() : nullptr);
608 valobj_sp->Dump(output_stream, options);
609 } else {
610 if (auto error_cstr = error.AsCString(nullptr))
611 result.AppendError(error_cstr);
612 else
614 "unable to find any variable expression path that matches "
615 "'%s'.",
616 entry.c_str());
617 }
618 }
619 }
620 } else // No command arg specified. Use variable_list, instead.
621 {
622 const size_t num_variables = variable_list->GetSize();
623 if (num_variables > 0) {
624 for (size_t i = 0; i < num_variables; i++) {
625 var_sp = variable_list->GetVariableAtIndex(i);
626 switch (var_sp->GetScope()) {
629 continue;
630 break;
633 continue;
634 break;
637 continue;
638 break;
641 continue;
642 break;
643 default:
644 continue;
645 break;
646 }
647 std::string scope_string;
649 scope_string = GetScopeString(var_sp).str();
650
651 // Use the variable object code to make sure we are using the same
652 // APIs as the public API will be using...
653 valobj_sp = frame->GetValueObjectForFrameVariable(
655 if (valobj_sp) {
656 // When dumping all variables, don't print any variables that are
657 // not in scope to avoid extra unneeded output
658 if (valobj_sp->IsInScope()) {
659 if (!valobj_sp->GetTargetSP()
660 ->GetDisplayRuntimeSupportValues() &&
661 valobj_sp->IsRuntimeSupportValue())
662 continue;
663
664 if (!scope_string.empty())
665 s.PutCString(scope_string);
666
668 var_sp->GetDeclaration().GetFile()) {
669 var_sp->GetDeclaration().DumpStopContext(&s, false);
670 s.PutCString(": ");
671 }
672
673 options.SetFormat(format);
675 valobj_sp->GetPreferredDisplayLanguage());
677 var_sp ? var_sp->GetName().AsCString() : nullptr);
678 valobj_sp->Dump(result.GetOutputStream(), options);
679 }
680 }
681 }
682 }
683 }
684 if (result.GetStatus() != eReturnStatusFailed)
686 }
687
689 auto recognized_frame = frame->GetRecognizedFrame();
690 if (recognized_frame) {
691 ValueObjectListSP recognized_arg_list =
692 recognized_frame->GetRecognizedArguments();
693 if (recognized_arg_list) {
694 for (auto &rec_value_sp : recognized_arg_list->GetObjects()) {
697 rec_value_sp->GetPreferredDisplayLanguage());
698 options.SetRootValueObjectName(rec_value_sp->GetName().AsCString());
699 rec_value_sp->Dump(result.GetOutputStream(), options);
700 }
701 }
702 }
703 }
704
706 m_cmd_name);
707
708 // Increment statistics.
709 bool res = result.Succeeded();
711 if (res)
712 target_stats.GetFrameVariableStats().NotifySuccess();
713 else
714 target_stats.GetFrameVariableStats().NotifyFailure();
715 return res;
716 }
717
722};
723
724#pragma mark CommandObjectFrameRecognizer
725
726#define LLDB_OPTIONS_frame_recognizer_add
727#include "CommandOptions.inc"
728
730private:
731 class CommandOptions : public Options {
732 public:
733 CommandOptions() = default;
734 ~CommandOptions() override = default;
735
736 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
737 ExecutionContext *execution_context) override {
739 const int short_option = m_getopt_table[option_idx].val;
740
741 switch (short_option) {
742 case 'f': {
743 bool value, success;
744 value = OptionArgParser::ToBoolean(option_arg, true, &success);
745 if (success) {
747 } else {
748 error.SetErrorStringWithFormat(
749 "invalid boolean value '%s' passed for -f option",
750 option_arg.str().c_str());
751 }
752 } break;
753 case 'l':
754 m_class_name = std::string(option_arg);
755 break;
756 case 's':
757 m_module = std::string(option_arg);
758 break;
759 case 'n':
760 m_symbols.push_back(std::string(option_arg));
761 break;
762 case 'x':
763 m_regex = true;
764 break;
765 default:
766 llvm_unreachable("Unimplemented option");
767 }
768
769 return error;
770 }
771
772 void OptionParsingStarting(ExecutionContext *execution_context) override {
773 m_module = "";
774 m_symbols.clear();
775 m_class_name = "";
776 m_regex = false;
778 }
779
780 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
781 return llvm::ArrayRef(g_frame_recognizer_add_options);
782 }
783
784 // Instance variables to hold the values for command options.
785 std::string m_class_name;
786 std::string m_module;
787 std::vector<std::string> m_symbols;
790 };
791
793
794 Options *GetOptions() override { return &m_options; }
795
796protected:
797 bool DoExecute(Args &command, CommandReturnObject &result) override;
798
799public:
801 : CommandObjectParsed(interpreter, "frame recognizer add",
802 "Add a new frame recognizer.", nullptr) {
803 SetHelpLong(R"(
804Frame recognizers allow for retrieving information about special frames based on
805ABI, arguments or other special properties of that frame, even without source
806code or debug info. Currently, one use case is to extract function arguments
807that would otherwise be unaccesible, or augment existing arguments.
808
809Adding a custom frame recognizer is possible by implementing a Python class
810and using the 'frame recognizer add' command. The Python class should have a
811'get_recognized_arguments' method and it will receive an argument of type
812lldb.SBFrame representing the current frame that we are trying to recognize.
813The method should return a (possibly empty) list of lldb.SBValue objects that
814represent the recognized arguments.
815
816An example of a recognizer that retrieves the file descriptor values from libc
817functions 'read', 'write' and 'close' follows:
818
819 class LibcFdRecognizer(object):
820 def get_recognized_arguments(self, frame):
821 if frame.name in ["read", "write", "close"]:
822 fd = frame.EvaluateExpression("$arg1").unsigned
823 target = frame.thread.process.target
824 value = target.CreateValueFromExpression("fd", "(int)%d" % fd)
825 return [value]
826 return []
827
828The file containing this implementation can be imported via 'command script
829import' and then we can register this recognizer with 'frame recognizer add'.
830It's important to restrict the recognizer to the libc library (which is
831libsystem_kernel.dylib on macOS) to avoid matching functions with the same name
832in other modules:
833
834(lldb) command script import .../fd_recognizer.py
835(lldb) frame recognizer add -l fd_recognizer.LibcFdRecognizer -n read -s libsystem_kernel.dylib
836
837When the program is stopped at the beginning of the 'read' function in libc, we
838can view the recognizer arguments in 'frame variable':
839
840(lldb) b read
841(lldb) r
842Process 1234 stopped
843* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.3
844 frame #0: 0x00007fff06013ca0 libsystem_kernel.dylib`read
845(lldb) frame variable
846(int) fd = 3
847
848 )");
849 }
851};
852
854 CommandReturnObject &result) {
855#if LLDB_ENABLE_PYTHON
856 if (m_options.m_class_name.empty()) {
858 "%s needs a Python class name (-l argument).\n", m_cmd_name.c_str());
859 return false;
860 }
861
862 if (m_options.m_module.empty()) {
863 result.AppendErrorWithFormat("%s needs a module name (-s argument).\n",
864 m_cmd_name.c_str());
865 return false;
866 }
867
868 if (m_options.m_symbols.empty()) {
870 "%s needs at least one symbol name (-n argument).\n",
871 m_cmd_name.c_str());
872 return false;
873 }
874
875 if (m_options.m_regex && m_options.m_symbols.size() > 1) {
877 "%s needs only one symbol regular expression (-n argument).\n",
878 m_cmd_name.c_str());
879 return false;
880 }
881
883
884 if (interpreter &&
885 !interpreter->CheckObjectExists(m_options.m_class_name.c_str())) {
886 result.AppendWarning("The provided class does not exist - please define it "
887 "before attempting to use this frame recognizer");
888 }
889
890 StackFrameRecognizerSP recognizer_sp =
891 StackFrameRecognizerSP(new ScriptedStackFrameRecognizer(
892 interpreter, m_options.m_class_name.c_str()));
893 if (m_options.m_regex) {
894 auto module =
895 RegularExpressionSP(new RegularExpression(m_options.m_module));
896 auto func =
897 RegularExpressionSP(new RegularExpression(m_options.m_symbols.front()));
899 recognizer_sp, module, func, m_options.m_first_instruction_only);
900 } else {
901 auto module = ConstString(m_options.m_module);
902 std::vector<ConstString> symbols(m_options.m_symbols.begin(),
903 m_options.m_symbols.end());
905 recognizer_sp, module, symbols, m_options.m_first_instruction_only);
906 }
907#endif
908
910 return result.Succeeded();
911}
912
914public:
916 : CommandObjectParsed(interpreter, "frame recognizer clear",
917 "Delete all frame recognizers.", nullptr) {}
918
920
921protected:
922 bool DoExecute(Args &command, CommandReturnObject &result) override {
927 return result.Succeeded();
928 }
929};
930
932public:
934 : CommandObjectParsed(interpreter, "frame recognizer delete",
935 "Delete an existing frame recognizer by id.",
936 nullptr) {
938 m_arguments.push_back({thread_arg});
939 }
940
942
943 void
945 OptionElementVector &opt_element_vector) override {
946 if (request.GetCursorIndex() != 0)
947 return;
948
950 [&request](uint32_t rid, std::string rname, std::string module,
951 llvm::ArrayRef<lldb_private::ConstString> symbols,
952 bool regexp) {
953 StreamString strm;
954 if (rname.empty())
955 rname = "(internal)";
956
957 strm << rname;
958 if (!module.empty())
959 strm << ", module " << module;
960 if (!symbols.empty())
961 for (auto &symbol : symbols)
962 strm << ", symbol " << symbol;
963 if (regexp)
964 strm << " (regexp)";
965
966 request.TryCompleteCurrentArg(std::to_string(rid), strm.GetString());
967 });
968 }
969
970protected:
971 bool DoExecute(Args &command, CommandReturnObject &result) override {
972 if (command.GetArgumentCount() == 0) {
974 "About to delete all frame recognizers, do you want to do that?",
975 true)) {
976 result.AppendMessage("Operation cancelled...");
977 return false;
978 }
979
984 return result.Succeeded();
985 }
986
987 if (command.GetArgumentCount() != 1) {
988 result.AppendErrorWithFormat("'%s' takes zero or one arguments.\n",
989 m_cmd_name.c_str());
990 return false;
991 }
992
993 uint32_t recognizer_id;
994 if (!llvm::to_integer(command.GetArgumentAtIndex(0), recognizer_id)) {
995 result.AppendErrorWithFormat("'%s' is not a valid recognizer id.\n",
996 command.GetArgumentAtIndex(0));
997 return false;
998 }
999
1001 .GetFrameRecognizerManager()
1002 .RemoveRecognizerWithID(recognizer_id)) {
1003 result.AppendErrorWithFormat("'%s' is not a valid recognizer id.\n",
1004 command.GetArgumentAtIndex(0));
1005 return false;
1006 }
1008 return result.Succeeded();
1009 }
1010};
1011
1013public:
1015 : CommandObjectParsed(interpreter, "frame recognizer list",
1016 "Show a list of active frame recognizers.",
1017 nullptr) {}
1018
1020
1021protected:
1022 bool DoExecute(Args &command, CommandReturnObject &result) override {
1023 bool any_printed = false;
1025 [&result, &any_printed](
1026 uint32_t recognizer_id, std::string name, std::string module,
1027 llvm::ArrayRef<ConstString> symbols, bool regexp) {
1028 Stream &stream = result.GetOutputStream();
1029
1030 if (name.empty())
1031 name = "(internal)";
1032
1033 stream << std::to_string(recognizer_id) << ": " << name;
1034 if (!module.empty())
1035 stream << ", module " << module;
1036 if (!symbols.empty())
1037 for (auto &symbol : symbols)
1038 stream << ", symbol " << symbol;
1039 if (regexp)
1040 stream << " (regexp)";
1041
1042 stream.EOL();
1043 stream.Flush();
1044
1045 any_printed = true;
1046 });
1047
1048 if (any_printed)
1050 else {
1051 result.GetOutputStream().PutCString("no matching results found.\n");
1053 }
1054 return result.Succeeded();
1055 }
1056};
1057
1059public:
1062 interpreter, "frame recognizer info",
1063 "Show which frame recognizer is applied a stack frame (if any).",
1064 nullptr) {
1066 CommandArgumentData index_arg;
1067
1068 // Define the first (and only) variant of this arg.
1069 index_arg.arg_type = eArgTypeFrameIndex;
1070 index_arg.arg_repetition = eArgRepeatPlain;
1071
1072 // There is only one variant this argument could be; put it into the
1073 // argument entry.
1074 arg.push_back(index_arg);
1075
1076 // Push the data for the first argument into the m_arguments vector.
1077 m_arguments.push_back(arg);
1078 }
1079
1081
1082protected:
1083 bool DoExecute(Args &command, CommandReturnObject &result) override {
1084 const char *frame_index_str = command.GetArgumentAtIndex(0);
1085 uint32_t frame_index;
1086 if (!llvm::to_integer(frame_index_str, frame_index)) {
1087 result.AppendErrorWithFormat("'%s' is not a valid frame index.",
1088 frame_index_str);
1089 return false;
1090 }
1091
1092 Process *process = m_exe_ctx.GetProcessPtr();
1093 if (process == nullptr) {
1094 result.AppendError("no process");
1095 return false;
1096 }
1097 Thread *thread = m_exe_ctx.GetThreadPtr();
1098 if (thread == nullptr) {
1099 result.AppendError("no thread");
1100 return false;
1101 }
1102 if (command.GetArgumentCount() != 1) {
1103 result.AppendErrorWithFormat(
1104 "'%s' takes exactly one frame index argument.\n", m_cmd_name.c_str());
1105 return false;
1106 }
1107
1108 StackFrameSP frame_sp = thread->GetStackFrameAtIndex(frame_index);
1109 if (!frame_sp) {
1110 result.AppendErrorWithFormat("no frame with index %u", frame_index);
1111 return false;
1112 }
1113
1114 auto recognizer = GetSelectedOrDummyTarget()
1116 .GetRecognizerForFrame(frame_sp);
1117
1118 Stream &output_stream = result.GetOutputStream();
1119 output_stream.Printf("frame %d ", frame_index);
1120 if (recognizer) {
1121 output_stream << "is recognized by ";
1122 output_stream << recognizer->GetName();
1123 } else {
1124 output_stream << "not recognized by any recognizer";
1125 }
1126 output_stream.EOL();
1128 return result.Succeeded();
1129 }
1130};
1131
1133public:
1136 interpreter, "frame recognizer",
1137 "Commands for editing and viewing frame recognizers.",
1138 "frame recognizer [<sub-command-options>] ") {
1139 LoadSubCommand("add", CommandObjectSP(new CommandObjectFrameRecognizerAdd(
1140 interpreter)));
1142 "clear",
1143 CommandObjectSP(new CommandObjectFrameRecognizerClear(interpreter)));
1145 "delete",
1146 CommandObjectSP(new CommandObjectFrameRecognizerDelete(interpreter)));
1147 LoadSubCommand("list", CommandObjectSP(new CommandObjectFrameRecognizerList(
1148 interpreter)));
1149 LoadSubCommand("info", CommandObjectSP(new CommandObjectFrameRecognizerInfo(
1150 interpreter)));
1151 }
1152
1153 ~CommandObjectFrameRecognizer() override = default;
1154};
1155
1156#pragma mark CommandObjectMultiwordFrame
1157
1158// CommandObjectMultiwordFrame
1159
1161 CommandInterpreter &interpreter)
1162 : CommandObjectMultiword(interpreter, "frame",
1163 "Commands for selecting and "
1164 "examing the current "
1165 "thread's stack frames.",
1166 "frame <subcommand> [<subcommand-options>]") {
1167 LoadSubCommand("diagnose",
1168 CommandObjectSP(new CommandObjectFrameDiagnose(interpreter)));
1169 LoadSubCommand("info",
1170 CommandObjectSP(new CommandObjectFrameInfo(interpreter)));
1171 LoadSubCommand("select",
1172 CommandObjectSP(new CommandObjectFrameSelect(interpreter)));
1173 LoadSubCommand("variable",
1174 CommandObjectSP(new CommandObjectFrameVariable(interpreter)));
1175#if LLDB_ENABLE_PYTHON
1176 LoadSubCommand("recognizer", CommandObjectSP(new CommandObjectFrameRecognizer(
1177 interpreter)));
1178#endif
1179}
1180
static llvm::raw_ostream & error(Stream &strm)
void OptionParsingStarting(ExecutionContext *execution_context) override
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
~CommandObjectFrameDiagnose() override=default
CommandObjectFrameDiagnose(CommandInterpreter &interpreter)
Options * GetOptions() override
bool DoExecute(Args &command, CommandReturnObject &result) override
CommandObjectFrameInfo(CommandInterpreter &interpreter)
bool DoExecute(Args &command, CommandReturnObject &result) override
~CommandObjectFrameInfo() override=default
void OptionParsingStarting(ExecutionContext *execution_context) override
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
CommandObjectFrameRecognizerAdd(CommandInterpreter &interpreter)
bool DoExecute(Args &command, CommandReturnObject &result) override
~CommandObjectFrameRecognizerAdd() override=default
CommandObjectFrameRecognizerClear(CommandInterpreter &interpreter)
~CommandObjectFrameRecognizerClear() override=default
bool DoExecute(Args &command, CommandReturnObject &result) override
bool DoExecute(Args &command, CommandReturnObject &result) override
~CommandObjectFrameRecognizerDelete() override=default
void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override
The input array contains a parsed version of the line.
CommandObjectFrameRecognizerDelete(CommandInterpreter &interpreter)
CommandObjectFrameRecognizerInfo(CommandInterpreter &interpreter)
~CommandObjectFrameRecognizerInfo() override=default
bool DoExecute(Args &command, CommandReturnObject &result) override
bool DoExecute(Args &command, CommandReturnObject &result) override
CommandObjectFrameRecognizerList(CommandInterpreter &interpreter)
~CommandObjectFrameRecognizerList() override=default
~CommandObjectFrameRecognizer() override=default
CommandObjectFrameRecognizer(CommandInterpreter &interpreter)
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
void OptionParsingStarting(ExecutionContext *execution_context) override
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
bool DoExecute(Args &command, CommandReturnObject &result) override
~CommandObjectFrameSelect() override=default
CommandObjectFrameSelect(CommandInterpreter &interpreter)
Options * GetOptions() override
void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override
The input array contains a parsed version of the line.
Options * GetOptions() override
OptionGroupVariable m_option_variable
void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override
The input array contains a parsed version of the line.
OptionGroupValueObjectDisplay m_varobj_options
bool DoExecute(Args &command, CommandReturnObject &result) override
llvm::StringRef GetScopeString(VariableSP var_sp)
~CommandObjectFrameVariable() override=default
CommandObjectFrameVariable(CommandInterpreter &interpreter)
A command line argument class.
Definition: Args.h:33
size_t GetArgumentCount() const
Gets the number of arguments left in this command object.
Definition: Args.h:116
const char * GetArgumentAtIndex(size_t idx) const
Gets the NULL terminated C string argument pointer for the argument at index idx.
Definition: Args.cpp:264
bool empty() const
Definition: Args.h:118
static bool InvokeCommonCompletionCallbacks(CommandInterpreter &interpreter, uint32_t completion_mask, lldb_private::CompletionRequest &request, SearchFilter *searcher)
bool Confirm(llvm::StringRef message, bool default_answer)
void PrintWarningsIfNecessary(Stream &s, const std::string &cmd_name)
CommandObjectMultiwordFrame(CommandInterpreter &interpreter)
bool LoadSubCommand(llvm::StringRef cmd_name, const lldb::CommandObjectSP &command_obj) override
std::vector< CommandArgumentData > CommandArgumentEntry
virtual void SetHelpLong(llvm::StringRef str)
ExecutionContext m_exe_ctx
std::vector< CommandArgumentEntry > m_arguments
CommandInterpreter & GetCommandInterpreter()
CommandInterpreter & m_interpreter
Target & GetSelectedOrDummyTarget(bool prefer_dummy=false)
void AppendMessage(llvm::StringRef in_string)
void void AppendError(llvm::StringRef in_string)
void SetStatus(lldb::ReturnStatus status)
void AppendErrorWithFormat(const char *format,...) __attribute__((format(printf
lldb::ReturnStatus GetStatus() const
void void AppendWarning(llvm::StringRef in_string)
"lldb/Utility/ArgCompletionRequest.h"
void TryCompleteCurrentArg(llvm::StringRef completion, llvm::StringRef description="")
Adds a possible completion string if the completion would complete the current argument.
A uniqued constant string class.
Definition: ConstString.h:39
static bool GetSummaryFormat(ConstString type, lldb::TypeSummaryImplSP &entry)
ScriptInterpreter * GetScriptInterpreter(bool can_create=true, std::optional< lldb::ScriptLanguage > language={})
Definition: Debugger.cpp:1560
DumpValueObjectOptions & SetVariableFormatDisplayLanguage(lldb::LanguageType lang=lldb::eLanguageTypeUnknown)
std::function< bool(ConstString, ConstString, const DumpValueObjectOptions &, Stream &)> DeclPrintingHelper
DumpValueObjectOptions & SetDeclPrintingHelper(DeclPrintingHelper helper)
DumpValueObjectOptions & SetRootValueObjectName(const char *name=nullptr)
DumpValueObjectOptions & SetFormat(lldb::Format format=lldb::eFormatDefault)
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
void SetFrameSP(const lldb::StackFrameSP &frame_sp)
Set accessor to set only the frame shared pointer.
StackFrame * GetFramePtr() const
Returns a pointer to the frame object.
StackFrame & GetFrameRef() const
Returns a reference to the thread object.
Process * GetProcessPtr() const
Returns a pointer to the process object.
Thread * GetThreadPtr() const
Returns a pointer to the thread object.
bool IsTopLevelFunction()
Get whether this function represents a 'top-level' function.
Definition: Function.cpp:477
static const uint32_t OPTION_GROUP_GDB_FMT
static const uint32_t OPTION_GROUP_FORMAT
void Append(OptionGroup *group)
Append options from a OptionGroup class.
Definition: Options.cpp:755
DumpValueObjectOptions GetAsDumpOptions(LanguageRuntimeDescriptionDisplayVerbosity lang_descr_verbosity=eLanguageRuntimeDescriptionDisplayVerbosityFull, lldb::Format format=lldb::eFormatDefault, lldb::TypeSummaryImplSP summary_sp=lldb::TypeSummaryImplSP())
const char * GetCurrentValue() const
A command line option parsing protocol class.
Definition: Options.h:58
void GenerateOptionUsage(Stream &strm, CommandObject &cmd, uint32_t screen_width)
Definition: Options.cpp:395
std::vector< Option > m_getopt_table
Definition: Options.h:198
A plug-in interface definition class for debugging a process.
Definition: Process.h:343
bool IsValid() const
Test if this object contains a valid regular expression.
llvm::Error GetError() const
Return an error if the regular expression failed to compile.
virtual bool CheckObjectExists(const char *name)
Python implementation for frame recognizers.
lldb::StackFrameRecognizerSP GetRecognizerForFrame(lldb::StackFrameSP frame)
void AddRecognizer(lldb::StackFrameRecognizerSP recognizer, ConstString module, llvm::ArrayRef< ConstString > symbols, bool first_instruction_only=true)
void ForEach(std::function< void(uint32_t recognizer_id, std::string recognizer_name, std::string module, llvm::ArrayRef< ConstString > symbols, bool regexp)> const &callback)
This base class provides an interface to stack frames.
Definition: StackFrame.h:41
@ eExpressionPathOptionsInspectAnonymousUnions
Definition: StackFrame.h:49
@ eExpressionPathOptionsAllowDirectIVarAccess
Definition: StackFrame.h:48
VariableList * GetVariableList(bool get_file_globals, Status *error_ptr)
Retrieve the list of variables that are in scope at this StackFrame's pc.
Definition: StackFrame.cpp:424
void DumpUsingSettingsFormat(Stream *strm, bool show_unique=false, const char *frame_marker=nullptr)
Print a description for this frame using the frame-format formatter settings.
lldb::ValueObjectSP GetValueForVariableExpressionPath(llvm::StringRef var_expr, lldb::DynamicValueType use_dynamic, uint32_t options, lldb::VariableSP &var_sp, Status &error)
Create a ValueObject for a variable name / pathname, possibly including simple dereference/child sele...
Definition: StackFrame.cpp:508
lldb::ValueObjectSP GetValueObjectForFrameVariable(const lldb::VariableSP &variable_sp, lldb::DynamicValueType use_dynamic)
Create a ValueObject for a given Variable in this StackFrame.
const SymbolContext & GetSymbolContext(lldb::SymbolContextItem resolve_scope)
Provide a SymbolContext for this StackFrame's current pc value.
Definition: StackFrame.cpp:300
lldb::RecognizedStackFrameSP GetRecognizedFrame()
An error handling class.
Definition: Status.h:44
static lldb::ValueObjectSP GetCrashingDereference(lldb::StopInfoSP &stop_info_sp, lldb::addr_t *crashing_address=nullptr)
Definition: StopInfo.cpp:1442
llvm::StringRef GetString() const
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:107
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition: Stream.cpp:63
virtual void Flush()=0
Flush the stream.
size_t EOL()
Output and End of Line character to the stream.
Definition: Stream.cpp:128
Defines a symbol context baton that can be handed other debug core functions.
Definition: SymbolContext.h:33
Function * function
The Function for a given query.
A class that represents statistics for a since lldb_private::Target.
Definition: Statistics.h:134
StatsSuccessFail & GetFrameVariableStats()
Definition: Statistics.h:145
TargetStats & GetStatistics()
Definition: Target.h:1577
StackFrameRecognizerManager & GetFrameRecognizerManager()
Definition: Target.h:1429
virtual lldb::StackFrameSP GetStackFrameAtIndex(uint32_t idx)
Definition: Thread.h:399
uint32_t GetSelectedFrameIndex()
Definition: Thread.h:431
lldb::StackFrameSP GetSelectedFrame()
Definition: Thread.cpp:267
lldb::StopInfoSP GetStopInfo()
Definition: Thread.cpp:336
bool SetSelectedFrameByIndexNoisily(uint32_t frame_idx, Stream &output_stream)
Definition: Thread.cpp:296
virtual uint32_t GetStackFrameCount()
Definition: Thread.h:395
lldb::VariableSP GetVariableAtIndex(size_t idx) const
size_t AppendVariablesIfUnique(VariableList &var_list)
#define LLDB_OPT_SET_1
Definition: lldb-defines.h:102
#define LLDB_OPT_SET_ALL
Definition: lldb-defines.h:101
#define UINT32_MAX
Definition: lldb-defines.h:19
A class that represents a running process on the host machine.
Definition: SBAttachInfo.h:14
std::vector< OptionArgElement > OptionElementVector
Definition: Options.h:43
Definition: SBAddress.h:15
Format
Display format definitions.
@ eReturnStatusFailed
@ eReturnStatusSuccessFinishResult
@ eReturnStatusSuccessFinishNoResult
@ eArgTypeFrameIndex
@ eArgTypeRecognizerID
@ eValueTypeVariableGlobal
globals variable
@ eValueTypeVariableLocal
function local variables
@ eValueTypeVariableArgument
function argument variables
@ eValueTypeVariableStatic
static variable
@ eValueTypeVariableThreadLocal
thread local storage variable
Used to build individual command argument lists.
Definition: CommandObject.h:93
static bool ToBoolean(llvm::StringRef s, bool fail_value, bool *success_ptr)