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 }
118
119 ~CommandObjectFrameDiagnose() override = default;
120
121 Options *GetOptions() override { return &m_options; }
122
123protected:
124 void DoExecute(Args &command, CommandReturnObject &result) override {
125 Thread *thread = m_exe_ctx.GetThreadPtr();
127
128 ValueObjectSP valobj_sp;
129
130 if (m_options.address) {
131 if (m_options.reg || m_options.offset) {
132 result.AppendError(
133 "`frame diagnose --address` is incompatible with other arguments.");
134 return;
135 }
136 valobj_sp = frame_sp->GuessValueForAddress(*m_options.address);
137 } else if (m_options.reg) {
138 valobj_sp = frame_sp->GuessValueForRegisterAndOffset(
139 *m_options.reg, m_options.offset.value_or(0));
140 } else {
141 StopInfoSP stop_info_sp = thread->GetStopInfo();
142 if (!stop_info_sp) {
143 result.AppendError("No arguments provided, and no stop info.");
144 return;
145 }
146
147 valobj_sp = StopInfo::GetCrashingDereference(stop_info_sp);
148 }
149
150 if (!valobj_sp) {
151 result.AppendError("No diagnosis available.");
152 return;
153 }
154
156 [&valobj_sp](ConstString type, ConstString var,
157 const DumpValueObjectOptions &opts,
158 Stream &stream) -> bool {
159 const ValueObject::GetExpressionPathFormat format = ValueObject::
160 GetExpressionPathFormat::eGetExpressionPathFormatHonorPointers;
161 valobj_sp->GetExpressionPath(stream, format);
162 stream.PutCString(" =");
163 return true;
164 };
165
167 options.SetDeclPrintingHelper(helper);
168 // We've already handled the case where the value object sp is null, so
169 // this is just to make sure future changes don't skip that:
170 assert(valobj_sp.get() && "Must have a valid ValueObject to print");
171 ValueObjectPrinter printer(*valobj_sp, &result.GetOutputStream(),
172 options);
173 if (llvm::Error error = printer.PrintValueObject())
174 result.AppendError(toString(std::move(error)));
175 }
176
178};
179
180#pragma mark CommandObjectFrameInfo
181
182// CommandObjectFrameInfo
183
185public:
187 : CommandObjectParsed(interpreter, "frame info",
188 "List information about the current "
189 "stack frame in the current thread.",
190 "frame info",
191 eCommandRequiresFrame | eCommandTryTargetAPILock |
192 eCommandProcessMustBeLaunched |
193 eCommandProcessMustBePaused) {}
194
195 ~CommandObjectFrameInfo() override = default;
196
197protected:
198 void DoExecute(Args &command, CommandReturnObject &result) override {
201 }
202};
203
204#pragma mark CommandObjectFrameSelect
205
206// CommandObjectFrameSelect
207
208#define LLDB_OPTIONS_frame_select
209#include "CommandOptions.inc"
210
212public:
213 class CommandOptions : public Options {
214 public:
216
217 ~CommandOptions() override = default;
218
219 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
220 ExecutionContext *execution_context) override {
222 const int short_option = m_getopt_table[option_idx].val;
223 switch (short_option) {
224 case 'r': {
225 int32_t offset = 0;
226 if (option_arg.getAsInteger(0, offset) || offset == INT32_MIN) {
227 error.SetErrorStringWithFormat("invalid frame offset argument '%s'",
228 option_arg.str().c_str());
229 } else
230 relative_frame_offset = offset;
231 break;
232 }
233
234 default:
235 llvm_unreachable("Unimplemented option");
236 }
237
238 return error;
239 }
240
241 void OptionParsingStarting(ExecutionContext *execution_context) override {
242 relative_frame_offset.reset();
243 }
244
245 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
246 return llvm::ArrayRef(g_frame_select_options);
247 }
248
249 std::optional<int32_t> relative_frame_offset;
250 };
251
253 : CommandObjectParsed(interpreter, "frame select",
254 "Select the current stack frame by "
255 "index from within the current thread "
256 "(see 'thread backtrace'.)",
257 nullptr,
258 eCommandRequiresThread | eCommandTryTargetAPILock |
259 eCommandProcessMustBeLaunched |
260 eCommandProcessMustBePaused) {
262 }
263
264 ~CommandObjectFrameSelect() override = default;
265
266 Options *GetOptions() override { return &m_options; }
267
268protected:
269 void DoExecute(Args &command, CommandReturnObject &result) override {
270 // No need to check "thread" for validity as eCommandRequiresThread ensures
271 // it is valid
272 Thread *thread = m_exe_ctx.GetThreadPtr();
273
274 uint32_t frame_idx = UINT32_MAX;
276 // The one and only argument is a signed relative frame index
278 if (frame_idx == UINT32_MAX)
279 frame_idx = 0;
280
282 if (static_cast<int32_t>(frame_idx) >=
284 frame_idx += *m_options.relative_frame_offset;
285 else {
286 if (frame_idx == 0) {
287 // If you are already at the bottom of the stack, then just warn
288 // and don't reset the frame.
289 result.AppendError("Already at the bottom of the stack.");
290 return;
291 } else
292 frame_idx = 0;
293 }
294 } else if (*m_options.relative_frame_offset > 0) {
295 // I don't want "up 20" where "20" takes you past the top of the stack
296 // to produce an error, but rather to just go to the top. OTOH, start
297 // by seeing if the requested frame exists, in which case we can avoid
298 // counting the stack here...
299 const uint32_t frame_requested = frame_idx
301 StackFrameSP frame_sp = thread->GetStackFrameAtIndex(frame_requested);
302 if (frame_sp)
303 frame_idx = frame_requested;
304 else {
305 // The request went past the stack, so handle that case:
306 const uint32_t num_frames = thread->GetStackFrameCount();
307 if (static_cast<int32_t>(num_frames - frame_idx) >
309 frame_idx += *m_options.relative_frame_offset;
310 else {
311 if (frame_idx == num_frames - 1) {
312 // If we are already at the top of the stack, just warn and don't
313 // reset the frame.
314 result.AppendError("Already at the top of the stack.");
315 return;
316 } else
317 frame_idx = num_frames - 1;
318 }
319 }
320 }
321 } else {
322 if (command.GetArgumentCount() > 1) {
324 "too many arguments; expected frame-index, saw '%s'.\n",
325 command[0].c_str());
327 result.GetErrorStream(), *this,
328 GetCommandInterpreter().GetDebugger().GetTerminalWidth());
329 return;
330 }
331
332 if (command.GetArgumentCount() == 1) {
333 if (command[0].ref().getAsInteger(0, frame_idx)) {
334 result.AppendErrorWithFormat("invalid frame index argument '%s'.",
335 command[0].c_str());
336 return;
337 }
338 } else if (command.GetArgumentCount() == 0) {
340 if (frame_idx == UINT32_MAX) {
341 frame_idx = 0;
342 }
343 }
344 }
345
346 bool success = thread->SetSelectedFrameByIndexNoisily(
347 frame_idx, result.GetOutputStream());
348 if (success) {
351 } else {
352 result.AppendErrorWithFormat("Frame index (%u) out of range.\n",
353 frame_idx);
354 }
355 }
356
358};
359
360#pragma mark CommandObjectFrameVariable
361// List images with associated information
363public:
366 interpreter, "frame variable",
367 "Show variables for the current stack frame. Defaults to all "
368 "arguments and local variables in scope. Names of argument, "
369 "local, file static and file global variables can be specified.",
370 nullptr,
371 eCommandRequiresFrame | eCommandTryTargetAPILock |
372 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused |
373 eCommandRequiresProcess),
375 true), // Include the frame specific options by passing "true"
377 SetHelpLong(R"(
378Children of aggregate variables can be specified such as 'var->child.x'. In
379'frame variable', the operators -> and [] do not invoke operator overloads if
380they exist, but directly access the specified element. If you want to trigger
381operator overloads use the expression command to print the variable instead.
382
383It is worth noting that except for overloaded operators, when printing local
384variables 'expr local_var' and 'frame var local_var' produce the same results.
385However, 'frame variable' is more efficient, since it uses debug information and
386memory reads directly, rather than parsing and evaluating an expression, which
387may even involve JITing and running code in the target program.)");
388
390
398 }
399
400 ~CommandObjectFrameVariable() override = default;
401
402 Options *GetOptions() override { return &m_option_group; }
403
404protected:
405 llvm::StringRef GetScopeString(VariableSP var_sp) {
406 if (!var_sp)
407 return llvm::StringRef();
408
409 switch (var_sp->GetScope()) {
411 return "GLOBAL: ";
413 return "STATIC: ";
415 return "ARG: ";
417 return "LOCAL: ";
419 return "THREAD: ";
420 default:
421 break;
422 }
423
424 return llvm::StringRef();
425 }
426
427 /// Returns true if `scope` matches any of the options in `m_option_variable`.
429 switch (scope) {
442 case eValueTypeVTable:
444 return false;
445 }
446 llvm_unreachable("Unexpected scope value");
447 }
448
449 /// Finds all the variables in `all_variables` whose name matches `regex`,
450 /// inserting them into `matches`. Variables already contained in `matches`
451 /// are not inserted again.
452 /// Nullopt is returned in case of no matches.
453 /// A sub-range of `matches` with all newly inserted variables is returned.
454 /// This may be empty if all matches were already contained in `matches`.
455 std::optional<llvm::ArrayRef<VariableSP>>
457 VariableList &matches,
458 const VariableList &all_variables) {
459 bool any_matches = false;
460 const size_t previous_num_vars = matches.GetSize();
461
462 for (const VariableSP &var : all_variables) {
463 if (!var->NameMatches(regex) || !ScopeRequested(var->GetScope()))
464 continue;
465 any_matches = true;
466 matches.AddVariableIfUnique(var);
467 }
468
469 if (any_matches)
470 return matches.toArrayRef().drop_front(previous_num_vars);
471 return std::nullopt;
472 }
473
474 void DoExecute(Args &command, CommandReturnObject &result) override {
475 // No need to check "frame" for validity as eCommandRequiresFrame ensures
476 // it is valid
478
479 Stream &s = result.GetOutputStream();
480
481 // Using a regex should behave like looking for an exact name match: it
482 // also finds globals.
484
485 // Be careful about the stack frame, if any summary formatter runs code, it
486 // might clear the StackFrameList for the thread. So hold onto a shared
487 // pointer to the frame so it stays alive.
488
490 VariableList *variable_list =
492
493 if (error.Fail() && (!variable_list || variable_list->GetSize() == 0)) {
494 result.AppendError(error.AsCString());
495
496 }
497 ValueObjectSP valobj_sp;
498
499 TypeSummaryImplSP summary_format_sp;
503 summary_format_sp);
505 summary_format_sp = std::make_shared<StringSummaryFormat>(
508
511 summary_format_sp));
512
513 const SymbolContext &sym_ctx =
514 frame->GetSymbolContext(eSymbolContextFunction);
515 if (sym_ctx.function && sym_ctx.function->IsTopLevelFunction())
517
518 if (variable_list) {
519 const Format format = m_option_format.GetFormat();
520 options.SetFormat(format);
521
522 if (!command.empty()) {
523 VariableList regex_var_list;
524
525 // If we have any args to the variable command, we will make variable
526 // objects from them...
527 for (auto &entry : command) {
529 llvm::StringRef name_str = entry.ref();
530 RegularExpression regex(name_str);
531 if (regex.IsValid()) {
532 std::optional<llvm::ArrayRef<VariableSP>> results =
533 findUniqueRegexMatches(regex, regex_var_list, *variable_list);
534 if (!results) {
536 "no variables matched the regular expression '%s'.",
537 entry.c_str());
538 continue;
539 }
540 for (const VariableSP &var_sp : *results) {
541 valobj_sp = frame->GetValueObjectForFrameVariable(
543 if (valobj_sp) {
544 std::string scope_string;
546 scope_string = GetScopeString(var_sp).str();
547
548 if (!scope_string.empty())
549 s.PutCString(scope_string);
550
552 var_sp->GetDeclaration().GetFile()) {
553 bool show_fullpaths = false;
554 bool show_module = true;
555 if (var_sp->DumpDeclaration(&s, show_fullpaths,
556 show_module))
557 s.PutCString(": ");
558 }
559 auto &strm = result.GetOutputStream();
560 if (llvm::Error error = valobj_sp->Dump(strm, options))
561 result.AppendError(toString(std::move(error)));
562 }
563 }
564 } else {
565 if (llvm::Error err = regex.GetError())
566 result.AppendError(llvm::toString(std::move(err)));
567 else
569 "unknown regex error when compiling '%s'", entry.c_str());
570 }
571 } else // No regex, either exact variable names or variable
572 // expressions.
573 {
575 uint32_t expr_path_options =
579 lldb::VariableSP var_sp;
580 valobj_sp = frame->GetValueForVariableExpressionPath(
581 entry.ref(), m_varobj_options.use_dynamic, expr_path_options,
582 var_sp, error);
583 if (valobj_sp) {
584 std::string scope_string;
586 scope_string = GetScopeString(var_sp).str();
587
588 if (!scope_string.empty())
589 s.PutCString(scope_string);
590 if (m_option_variable.show_decl && var_sp &&
591 var_sp->GetDeclaration().GetFile()) {
592 var_sp->GetDeclaration().DumpStopContext(&s, false);
593 s.PutCString(": ");
594 }
595
596 options.SetFormat(format);
598 valobj_sp->GetPreferredDisplayLanguage());
599
600 Stream &output_stream = result.GetOutputStream();
602 valobj_sp->GetParent() ? entry.c_str() : nullptr);
603 if (llvm::Error error = valobj_sp->Dump(output_stream, options))
604 result.AppendError(toString(std::move(error)));
605 } else {
606 if (auto error_cstr = error.AsCString(nullptr))
607 result.AppendError(error_cstr);
608 else
610 "unable to find any variable expression path that matches "
611 "'%s'.",
612 entry.c_str());
613 }
614 }
615 }
616 } else // No command arg specified. Use variable_list, instead.
617 {
618 const size_t num_variables = variable_list->GetSize();
619 if (num_variables > 0) {
620 for (size_t i = 0; i < num_variables; i++) {
621 VariableSP var_sp = variable_list->GetVariableAtIndex(i);
622 if (!ScopeRequested(var_sp->GetScope()))
623 continue;
624 std::string scope_string;
626 scope_string = GetScopeString(var_sp).str();
627
628 // Use the variable object code to make sure we are using the same
629 // APIs as the public API will be using...
630 valobj_sp = frame->GetValueObjectForFrameVariable(
632 if (valobj_sp) {
633 // When dumping all variables, don't print any variables that are
634 // not in scope to avoid extra unneeded output
635 if (valobj_sp->IsInScope()) {
636 if (!valobj_sp->GetTargetSP()
637 ->GetDisplayRuntimeSupportValues() &&
638 valobj_sp->IsRuntimeSupportValue())
639 continue;
640
641 if (!scope_string.empty())
642 s.PutCString(scope_string);
643
645 var_sp->GetDeclaration().GetFile()) {
646 var_sp->GetDeclaration().DumpStopContext(&s, false);
647 s.PutCString(": ");
648 }
649
650 options.SetFormat(format);
652 valobj_sp->GetPreferredDisplayLanguage());
654 var_sp ? var_sp->GetName().AsCString() : nullptr);
655 if (llvm::Error error =
656 valobj_sp->Dump(result.GetOutputStream(), options))
657 result.AppendError(toString(std::move(error)));
658 }
659 }
660 }
661 }
662 }
663 if (result.GetStatus() != eReturnStatusFailed)
665 }
666
668 auto recognized_frame = frame->GetRecognizedFrame();
669 if (recognized_frame) {
670 ValueObjectListSP recognized_arg_list =
671 recognized_frame->GetRecognizedArguments();
672 if (recognized_arg_list) {
673 for (auto &rec_value_sp : recognized_arg_list->GetObjects()) {
676 rec_value_sp->GetPreferredDisplayLanguage());
677 options.SetRootValueObjectName(rec_value_sp->GetName().AsCString());
678 if (llvm::Error error =
679 rec_value_sp->Dump(result.GetOutputStream(), options))
680 result.AppendError(toString(std::move(error)));
681 }
682 }
683 }
684 }
685
687 m_cmd_name);
688
689 // Increment statistics.
691 if (result.Succeeded())
692 target_stats.GetFrameVariableStats().NotifySuccess();
693 else
694 target_stats.GetFrameVariableStats().NotifyFailure();
695 }
696
701};
702
703#pragma mark CommandObjectFrameRecognizer
704
705#define LLDB_OPTIONS_frame_recognizer_add
706#include "CommandOptions.inc"
707
709private:
710 class CommandOptions : public Options {
711 public:
712 CommandOptions() = default;
713 ~CommandOptions() override = default;
714
715 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
716 ExecutionContext *execution_context) override {
718 const int short_option = m_getopt_table[option_idx].val;
719
720 switch (short_option) {
721 case 'f': {
722 bool value, success;
723 value = OptionArgParser::ToBoolean(option_arg, true, &success);
724 if (success) {
726 } else {
727 error.SetErrorStringWithFormat(
728 "invalid boolean value '%s' passed for -f option",
729 option_arg.str().c_str());
730 }
731 } break;
732 case 'l':
733 m_class_name = std::string(option_arg);
734 break;
735 case 's':
736 m_module = std::string(option_arg);
737 break;
738 case 'n':
739 m_symbols.push_back(std::string(option_arg));
740 break;
741 case 'x':
742 m_regex = true;
743 break;
744 default:
745 llvm_unreachable("Unimplemented option");
746 }
747
748 return error;
749 }
750
751 void OptionParsingStarting(ExecutionContext *execution_context) override {
752 m_module = "";
753 m_symbols.clear();
754 m_class_name = "";
755 m_regex = false;
757 }
758
759 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
760 return llvm::ArrayRef(g_frame_recognizer_add_options);
761 }
762
763 // Instance variables to hold the values for command options.
764 std::string m_class_name;
765 std::string m_module;
766 std::vector<std::string> m_symbols;
769 };
770
772
773 Options *GetOptions() override { return &m_options; }
774
775protected:
776 void DoExecute(Args &command, CommandReturnObject &result) override;
777
778public:
780 : CommandObjectParsed(interpreter, "frame recognizer add",
781 "Add a new frame recognizer.", nullptr) {
782 SetHelpLong(R"(
783Frame recognizers allow for retrieving information about special frames based on
784ABI, arguments or other special properties of that frame, even without source
785code or debug info. Currently, one use case is to extract function arguments
786that would otherwise be unaccesible, or augment existing arguments.
787
788Adding a custom frame recognizer is possible by implementing a Python class
789and using the 'frame recognizer add' command. The Python class should have a
790'get_recognized_arguments' method and it will receive an argument of type
791lldb.SBFrame representing the current frame that we are trying to recognize.
792The method should return a (possibly empty) list of lldb.SBValue objects that
793represent the recognized arguments.
794
795An example of a recognizer that retrieves the file descriptor values from libc
796functions 'read', 'write' and 'close' follows:
797
798 class LibcFdRecognizer(object):
799 def get_recognized_arguments(self, frame):
800 if frame.name in ["read", "write", "close"]:
801 fd = frame.EvaluateExpression("$arg1").unsigned
802 target = frame.thread.process.target
803 value = target.CreateValueFromExpression("fd", "(int)%d" % fd)
804 return [value]
805 return []
806
807The file containing this implementation can be imported via 'command script
808import' and then we can register this recognizer with 'frame recognizer add'.
809It's important to restrict the recognizer to the libc library (which is
810libsystem_kernel.dylib on macOS) to avoid matching functions with the same name
811in other modules:
812
813(lldb) command script import .../fd_recognizer.py
814(lldb) frame recognizer add -l fd_recognizer.LibcFdRecognizer -n read -s libsystem_kernel.dylib
815
816When the program is stopped at the beginning of the 'read' function in libc, we
817can view the recognizer arguments in 'frame variable':
818
819(lldb) b read
820(lldb) r
821Process 1234 stopped
822* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.3
823 frame #0: 0x00007fff06013ca0 libsystem_kernel.dylib`read
824(lldb) frame variable
825(int) fd = 3
826
827 )");
828 }
830};
831
833 CommandReturnObject &result) {
834#if LLDB_ENABLE_PYTHON
835 if (m_options.m_class_name.empty()) {
837 "%s needs a Python class name (-l argument).\n", m_cmd_name.c_str());
838 return;
839 }
840
841 if (m_options.m_module.empty()) {
842 result.AppendErrorWithFormat("%s needs a module name (-s argument).\n",
843 m_cmd_name.c_str());
844 return;
845 }
846
847 if (m_options.m_symbols.empty()) {
849 "%s needs at least one symbol name (-n argument).\n",
850 m_cmd_name.c_str());
851 return;
852 }
853
854 if (m_options.m_regex && m_options.m_symbols.size() > 1) {
856 "%s needs only one symbol regular expression (-n argument).\n",
857 m_cmd_name.c_str());
858 return;
859 }
860
862
863 if (interpreter &&
864 !interpreter->CheckObjectExists(m_options.m_class_name.c_str())) {
865 result.AppendWarning("The provided class does not exist - please define it "
866 "before attempting to use this frame recognizer");
867 }
868
869 StackFrameRecognizerSP recognizer_sp =
871 interpreter, m_options.m_class_name.c_str()));
872 if (m_options.m_regex) {
873 auto module =
875 auto func =
878 recognizer_sp, module, func, m_options.m_first_instruction_only);
879 } else {
880 auto module = ConstString(m_options.m_module);
881 std::vector<ConstString> symbols(m_options.m_symbols.begin(),
882 m_options.m_symbols.end());
884 recognizer_sp, module, symbols, m_options.m_first_instruction_only);
885 }
886#endif
887
889}
890
892public:
894 : CommandObjectParsed(interpreter, "frame recognizer clear",
895 "Delete all frame recognizers.", nullptr) {}
896
898
899protected:
900 void DoExecute(Args &command, CommandReturnObject &result) override {
905 }
906};
907
909public:
911 : CommandObjectParsed(interpreter, "frame recognizer delete",
912 "Delete an existing frame recognizer by id.",
913 nullptr) {
915 }
916
918
919 void
921 OptionElementVector &opt_element_vector) override {
922 if (request.GetCursorIndex() != 0)
923 return;
924
926 [&request](uint32_t rid, std::string rname, std::string module,
927 llvm::ArrayRef<lldb_private::ConstString> symbols,
928 bool regexp) {
929 StreamString strm;
930 if (rname.empty())
931 rname = "(internal)";
932
933 strm << rname;
934 if (!module.empty())
935 strm << ", module " << module;
936 if (!symbols.empty())
937 for (auto &symbol : symbols)
938 strm << ", symbol " << symbol;
939 if (regexp)
940 strm << " (regexp)";
941
942 request.TryCompleteCurrentArg(std::to_string(rid), strm.GetString());
943 });
944 }
945
946protected:
947 void DoExecute(Args &command, CommandReturnObject &result) override {
948 if (command.GetArgumentCount() == 0) {
950 "About to delete all frame recognizers, do you want to do that?",
951 true)) {
952 result.AppendMessage("Operation cancelled...");
953 return;
954 }
955
960 return;
961 }
962
963 if (command.GetArgumentCount() != 1) {
964 result.AppendErrorWithFormat("'%s' takes zero or one arguments.\n",
965 m_cmd_name.c_str());
966 return;
967 }
968
969 uint32_t recognizer_id;
970 if (!llvm::to_integer(command.GetArgumentAtIndex(0), recognizer_id)) {
971 result.AppendErrorWithFormat("'%s' is not a valid recognizer id.\n",
972 command.GetArgumentAtIndex(0));
973 return;
974 }
975
977 .GetFrameRecognizerManager()
978 .RemoveRecognizerWithID(recognizer_id)) {
979 result.AppendErrorWithFormat("'%s' is not a valid recognizer id.\n",
980 command.GetArgumentAtIndex(0));
981 return;
982 }
984 }
985};
986
988public:
990 : CommandObjectParsed(interpreter, "frame recognizer list",
991 "Show a list of active frame recognizers.",
992 nullptr) {}
993
995
996protected:
997 void DoExecute(Args &command, CommandReturnObject &result) override {
998 bool any_printed = false;
1000 [&result, &any_printed](
1001 uint32_t recognizer_id, std::string name, std::string module,
1002 llvm::ArrayRef<ConstString> symbols, bool regexp) {
1003 Stream &stream = result.GetOutputStream();
1004
1005 if (name.empty())
1006 name = "(internal)";
1007
1008 stream << std::to_string(recognizer_id) << ": " << name;
1009 if (!module.empty())
1010 stream << ", module " << module;
1011 if (!symbols.empty())
1012 for (auto &symbol : symbols)
1013 stream << ", symbol " << symbol;
1014 if (regexp)
1015 stream << " (regexp)";
1016
1017 stream.EOL();
1018 stream.Flush();
1019
1020 any_printed = true;
1021 });
1022
1023 if (any_printed)
1025 else {
1026 result.GetOutputStream().PutCString("no matching results found.\n");
1028 }
1029 }
1030};
1031
1033public:
1036 interpreter, "frame recognizer info",
1037 "Show which frame recognizer is applied a stack frame (if any).",
1038 nullptr) {
1040 }
1041
1043
1044protected:
1045 void DoExecute(Args &command, CommandReturnObject &result) override {
1046 const char *frame_index_str = command.GetArgumentAtIndex(0);
1047 uint32_t frame_index;
1048 if (!llvm::to_integer(frame_index_str, frame_index)) {
1049 result.AppendErrorWithFormat("'%s' is not a valid frame index.",
1050 frame_index_str);
1051 return;
1052 }
1053
1054 Process *process = m_exe_ctx.GetProcessPtr();
1055 if (process == nullptr) {
1056 result.AppendError("no process");
1057 return;
1058 }
1059 Thread *thread = m_exe_ctx.GetThreadPtr();
1060 if (thread == nullptr) {
1061 result.AppendError("no thread");
1062 return;
1063 }
1064 if (command.GetArgumentCount() != 1) {
1065 result.AppendErrorWithFormat(
1066 "'%s' takes exactly one frame index argument.\n", m_cmd_name.c_str());
1067 return;
1068 }
1069
1070 StackFrameSP frame_sp = thread->GetStackFrameAtIndex(frame_index);
1071 if (!frame_sp) {
1072 result.AppendErrorWithFormat("no frame with index %u", frame_index);
1073 return;
1074 }
1075
1076 auto recognizer = GetSelectedOrDummyTarget()
1078 .GetRecognizerForFrame(frame_sp);
1079
1080 Stream &output_stream = result.GetOutputStream();
1081 output_stream.Printf("frame %d ", frame_index);
1082 if (recognizer) {
1083 output_stream << "is recognized by ";
1084 output_stream << recognizer->GetName();
1085 } else {
1086 output_stream << "not recognized by any recognizer";
1087 }
1088 output_stream.EOL();
1090 }
1091};
1092
1094public:
1097 interpreter, "frame recognizer",
1098 "Commands for editing and viewing frame recognizers.",
1099 "frame recognizer [<sub-command-options>] ") {
1101 interpreter)));
1103 "clear",
1106 "delete",
1109 interpreter)));
1111 interpreter)));
1112 }
1113
1114 ~CommandObjectFrameRecognizer() override = default;
1115};
1116
1117#pragma mark CommandObjectMultiwordFrame
1118
1119// CommandObjectMultiwordFrame
1120
1122 CommandInterpreter &interpreter)
1123 : CommandObjectMultiword(interpreter, "frame",
1124 "Commands for selecting and "
1125 "examing the current "
1126 "thread's stack frames.",
1127 "frame <subcommand> [<subcommand-options>]") {
1128 LoadSubCommand("diagnose",
1130 LoadSubCommand("info",
1131 CommandObjectSP(new CommandObjectFrameInfo(interpreter)));
1132 LoadSubCommand("select",
1133 CommandObjectSP(new CommandObjectFrameSelect(interpreter)));
1134 LoadSubCommand("variable",
1136#if LLDB_ENABLE_PYTHON
1138 interpreter)));
1139#endif
1140}
1141
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
void DoExecute(Args &command, CommandReturnObject &result) override
CommandObjectFrameInfo(CommandInterpreter &interpreter)
void 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)
void DoExecute(Args &command, CommandReturnObject &result) override
~CommandObjectFrameRecognizerAdd() override=default
CommandObjectFrameRecognizerClear(CommandInterpreter &interpreter)
~CommandObjectFrameRecognizerClear() override=default
void DoExecute(Args &command, CommandReturnObject &result) override
~CommandObjectFrameRecognizerDelete() override=default
void DoExecute(Args &command, CommandReturnObject &result) override
void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override
The default version handles argument definitions that have only one argument type,...
CommandObjectFrameRecognizerDelete(CommandInterpreter &interpreter)
CommandObjectFrameRecognizerInfo(CommandInterpreter &interpreter)
~CommandObjectFrameRecognizerInfo() override=default
void DoExecute(Args &command, CommandReturnObject &result) override
CommandObjectFrameRecognizerList(CommandInterpreter &interpreter)
~CommandObjectFrameRecognizerList() override=default
void DoExecute(Args &command, CommandReturnObject &result) override
~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
~CommandObjectFrameSelect() override=default
CommandObjectFrameSelect(CommandInterpreter &interpreter)
Options * GetOptions() override
void DoExecute(Args &command, CommandReturnObject &result) override
Options * GetOptions() override
OptionGroupVariable m_option_variable
OptionGroupValueObjectDisplay m_varobj_options
bool ScopeRequested(lldb::ValueType scope)
Returns true if scope matches any of the options in m_option_variable.
llvm::StringRef GetScopeString(VariableSP var_sp)
std::optional< llvm::ArrayRef< VariableSP > > findUniqueRegexMatches(RegularExpression &regex, VariableList &matches, const VariableList &all_variables)
Finds all the variables in all_variables whose name matches regex, inserting them into matches.
~CommandObjectFrameVariable() override=default
CommandObjectFrameVariable(CommandInterpreter &interpreter)
void DoExecute(Args &command, CommandReturnObject &result) override
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:263
bool empty() const
Definition: Args.h:118
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
virtual void SetHelpLong(llvm::StringRef str)
void AddSimpleArgumentList(lldb::CommandArgumentType arg_type, ArgumentRepetitionType repetition_type=eArgRepeatPlain)
ExecutionContext m_exe_ctx
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:40
static bool GetSummaryFormat(ConstString type, lldb::TypeSummaryImplSP &entry)
ScriptInterpreter * GetScriptInterpreter(bool can_create=true, std::optional< lldb::ScriptLanguage > language={})
Definition: Debugger.cpp:1684
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:512
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:341
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 ForEach(std::function< void(uint32_t recognizer_id, std::string recognizer_name, std::string module, llvm::ArrayRef< ConstString > symbols, bool regexp)> const &callback)
void AddRecognizer(lldb::StackFrameRecognizerSP recognizer, ConstString module, llvm::ArrayRef< ConstString > symbols, bool first_instruction_only=true)
This base class provides an interface to stack frames.
Definition: StackFrame.h:43
@ eExpressionPathOptionsInspectAnonymousUnions
Definition: StackFrame.h:51
@ eExpressionPathOptionsAllowDirectIVarAccess
Definition: StackFrame.h:50
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:1456
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:134
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition: Stream.cpp:65
virtual void Flush()=0
Flush the stream.
size_t EOL()
Output and End of Line character to the stream.
Definition: Stream.cpp:155
Defines a symbol context baton that can be handed other debug core functions.
Definition: SymbolContext.h:34
Function * function
The Function for a given query.
A class that represents statistics for a since lldb_private::Target.
Definition: Statistics.h:178
StatsSuccessFail & GetFrameVariableStats()
Definition: Statistics.h:190
TargetStats & GetStatistics()
Definition: Target.h:1618
StackFrameRecognizerManager & GetFrameRecognizerManager()
Definition: Target.h:1468
virtual lldb::StackFrameSP GetStackFrameAtIndex(uint32_t idx)
Definition: Thread.h:406
lldb::StackFrameSP GetSelectedFrame(SelectMostRelevant select_most_relevant)
Definition: Thread.cpp:265
uint32_t GetSelectedFrameIndex(SelectMostRelevant select_most_relevant)
Definition: Thread.h:442
lldb::StopInfoSP GetStopInfo()
Definition: Thread.cpp:341
bool SetSelectedFrameByIndexNoisily(uint32_t frame_idx, Stream &output_stream)
Definition: Thread.cpp:294
virtual uint32_t GetStackFrameCount()
GetStackFrameCount can be expensive.
Definition: Thread.h:402
bool AddVariableIfUnique(const lldb::VariableSP &var_sp)
lldb::VariableSP GetVariableAtIndex(size_t idx) const
llvm::ArrayRef< lldb::VariableSP > toArrayRef()
Definition: VariableList.h:78
#define LLDB_OPT_SET_1
Definition: lldb-defines.h:111
#define LLDB_OPT_SET_ALL
Definition: lldb-defines.h:110
#define UINT32_MAX
Definition: lldb-defines.h:19
@ SelectMostRelevantFrame
A class that represents a running process on the host machine.
std::vector< OptionArgElement > OptionElementVector
Definition: Options.h:43
const char * toString(AppleArm64ExceptionClass EC)
Definition: SBAddress.h:15
std::shared_ptr< lldb_private::StackFrame > StackFrameSP
Definition: lldb-forward.h:418
std::shared_ptr< lldb_private::TypeSummaryImpl > TypeSummaryImplSP
Definition: lldb-forward.h:469
std::shared_ptr< lldb_private::CommandObject > CommandObjectSP
Definition: lldb-forward.h:329
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
Definition: lldb-forward.h:478
Format
Display format definitions.
std::shared_ptr< lldb_private::RegularExpression > RegularExpressionSP
Definition: lldb-forward.h:393
std::shared_ptr< lldb_private::ValueObjectList > ValueObjectListSP
Definition: lldb-forward.h:482
@ eReturnStatusFailed
@ eReturnStatusSuccessFinishResult
@ eReturnStatusSuccessFinishNoResult
@ eArgTypeFrameIndex
@ eArgTypeRecognizerID
std::shared_ptr< lldb_private::Variable > VariableSP
Definition: lldb-forward.h:480
std::shared_ptr< lldb_private::StackFrameRecognizer > StackFrameRecognizerSP
Definition: lldb-forward.h:422
std::shared_ptr< lldb_private::StopInfo > StopInfoSP
Definition: lldb-forward.h:425
@ eValueTypeVTableEntry
function pointer in virtual function table
@ eValueTypeVTable
virtual function table
@ eValueTypeInvalid
@ eValueTypeVariableGlobal
globals variable
@ eValueTypeConstResult
constant result variables
@ eValueTypeVariableLocal
function local variables
@ eValueTypeVariableArgument
function argument variables
@ eValueTypeRegister
stack frame register value
@ eValueTypeVariableStatic
static variable
@ eValueTypeRegisterSet
A collection of stack frame register values.
@ eValueTypeVariableThreadLocal
thread local storage variable
static bool ToBoolean(llvm::StringRef s, bool fail_value, bool *success_ptr)