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//===----------------------------------------------------------------------===//
12#include "lldb/Host/Config.h"
29#include "lldb/Target/Target.h"
30#include "lldb/Target/Thread.h"
31#include "lldb/Utility/Args.h"
35
36#include <memory>
37#include <optional>
38#include <string>
39
40using namespace lldb;
41using namespace lldb_private;
42
43#pragma mark CommandObjectFrameDiagnose
44
45// CommandObjectFrameInfo
46
47// CommandObjectFrameDiagnose
48
49#define LLDB_OPTIONS_frame_diag
50#include "CommandOptions.inc"
51
53public:
54 class CommandOptions : public Options {
55 public:
57
58 ~CommandOptions() override = default;
59
60 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
61 ExecutionContext *execution_context) override {
63 const int short_option = m_getopt_table[option_idx].val;
64 switch (short_option) {
65 case 'r':
66 reg = ConstString(option_arg);
67 break;
68
69 case 'a': {
70 address.emplace();
71 if (option_arg.getAsInteger(0, *address)) {
72 address.reset();
74 "invalid address argument '%s'", option_arg.str().c_str());
75 }
76 } break;
77
78 case 'o': {
79 offset.emplace();
80 if (option_arg.getAsInteger(0, *offset)) {
81 offset.reset();
83 "invalid offset argument '%s'", option_arg.str().c_str());
84 }
85 } break;
86
87 default:
88 llvm_unreachable("Unimplemented option");
89 }
90
91 return error;
92 }
93
94 void OptionParsingStarting(ExecutionContext *execution_context) override {
95 address.reset();
96 reg.reset();
97 offset.reset();
98 }
99
100 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
101 return llvm::ArrayRef(g_frame_diag_options);
102 }
103
104 // Options.
105 std::optional<lldb::addr_t> address;
106 std::optional<ConstString> reg;
107 std::optional<int64_t> offset;
108 };
109
111 : CommandObjectParsed(interpreter, "frame diagnose",
112 "Try to determine what path the current stop "
113 "location used to get to a register or address",
114 nullptr,
115 eCommandRequiresThread | eCommandTryTargetAPILock |
116 eCommandProcessMustBeLaunched |
117 eCommandProcessMustBePaused) {
119 }
120
121 ~CommandObjectFrameDiagnose() override = default;
122
123 Options *GetOptions() override { return &m_options; }
124
125protected:
126 void DoExecute(Args &command, CommandReturnObject &result) override {
127 Thread *thread = m_exe_ctx.GetThreadPtr();
128 StackFrameSP frame_sp = thread->GetSelectedFrame(SelectMostRelevantFrame);
129
130 ValueObjectSP valobj_sp;
131
132 if (m_options.address) {
133 if (m_options.reg || m_options.offset) {
134 result.AppendError(
135 "`frame diagnose --address` is incompatible with other arguments.");
136 return;
137 }
138 valobj_sp = frame_sp->GuessValueForAddress(*m_options.address);
139 } else if (m_options.reg) {
140 valobj_sp = frame_sp->GuessValueForRegisterAndOffset(
141 *m_options.reg, m_options.offset.value_or(0));
142 } else {
143 StopInfoSP stop_info_sp = thread->GetStopInfo();
144 if (!stop_info_sp) {
145 result.AppendError("no arguments provided, and no stop info");
146 return;
147 }
148
149 valobj_sp = StopInfo::GetCrashingDereference(stop_info_sp);
150 }
151
152 if (!valobj_sp) {
153 result.AppendError("no diagnosis available");
154 return;
155 }
156
157 result.GetValueObjectList().Append(valobj_sp);
159 [&valobj_sp](ConstString type, ConstString var,
160 const DumpValueObjectOptions &opts,
161 Stream &stream) -> bool {
162 const ValueObject::GetExpressionPathFormat format = ValueObject::
163 GetExpressionPathFormat::eGetExpressionPathFormatHonorPointers;
164 valobj_sp->GetExpressionPath(stream, format);
165 stream.PutCString(" =");
166 return true;
167 };
168
170 options.SetDeclPrintingHelper(helper);
171 // We've already handled the case where the value object sp is null, so
172 // this is just to make sure future changes don't skip that:
173 assert(valobj_sp.get() && "Must have a valid ValueObject to print");
174 ValueObjectPrinter printer(*valobj_sp, &result.GetOutputStream(), options);
175 if (llvm::Error error = printer.PrintValueObject())
176 result.AppendError(toString(std::move(error)));
177 }
178
180};
181
182#pragma mark CommandObjectFrameInfo
183
184// CommandObjectFrameInfo
185
187public:
189 : CommandObjectParsed(interpreter, "frame info",
190 "List information about the current "
191 "stack frame in the current thread.",
192 "frame info",
193 eCommandRequiresFrame | eCommandTryTargetAPILock |
194 eCommandProcessMustBeLaunched |
195 eCommandProcessMustBePaused) {}
196
197 ~CommandObjectFrameInfo() override = default;
198
199protected:
200 void DoExecute(Args &command, CommandReturnObject &result) override {
201 m_exe_ctx.GetFrameRef().DumpUsingSettingsFormat(&result.GetOutputStream());
203 }
204};
205
206#pragma mark CommandObjectFrameSelect
207
208// CommandObjectFrameSelect
209
210#define LLDB_OPTIONS_frame_select
211#include "CommandOptions.inc"
212
214public:
215 class CommandOptions : public Options {
216 public:
218
219 ~CommandOptions() override = default;
220
221 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
222 ExecutionContext *execution_context) override {
224 const int short_option = m_getopt_table[option_idx].val;
225 switch (short_option) {
226 case 'r': {
227 int32_t offset = 0;
228 if (option_arg.getAsInteger(0, offset) || offset == INT32_MIN) {
230 "invalid frame offset argument '%s'", option_arg.str().c_str());
231 } else
232 relative_frame_offset = offset;
233 break;
234 }
235
236 default:
237 llvm_unreachable("Unimplemented option");
238 }
239
240 return error;
241 }
242
243 void OptionParsingStarting(ExecutionContext *execution_context) override {
244 relative_frame_offset.reset();
245 }
246
247 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
248 return llvm::ArrayRef(g_frame_select_options);
249 }
250
251 std::optional<int32_t> relative_frame_offset;
252 };
253
255 : CommandObjectParsed(interpreter, "frame select",
256 "Select the current stack frame by "
257 "index from within the current thread "
258 "(see 'thread backtrace'.)",
259 nullptr,
260 eCommandRequiresThread | eCommandTryTargetAPILock |
261 eCommandProcessMustBeLaunched |
262 eCommandProcessMustBePaused) {
264 }
265
266 ~CommandObjectFrameSelect() override = default;
267
268 Options *GetOptions() override { return &m_options; }
269
270private:
271 void SkipHiddenFrames(Thread &thread, uint32_t frame_idx) {
272 uint32_t candidate_idx = frame_idx;
273 const unsigned max_depth = 12;
274 for (unsigned num_try = 0; num_try < max_depth; ++num_try) {
275 if (candidate_idx == 0 && *m_options.relative_frame_offset == -1) {
276 candidate_idx = UINT32_MAX;
277 break;
278 }
279 candidate_idx += *m_options.relative_frame_offset;
280 if (auto candidate_sp = thread.GetStackFrameAtIndex(candidate_idx)) {
281 if (candidate_sp->IsHidden())
282 continue;
283 // Now candidate_idx is the first non-hidden frame.
284 break;
285 }
286 candidate_idx = UINT32_MAX;
287 break;
288 };
289 if (candidate_idx != UINT32_MAX)
290 m_options.relative_frame_offset = candidate_idx - frame_idx;
291 }
292
293protected:
294 void DoExecute(Args &command, CommandReturnObject &result) override {
295 // No need to check "thread" for validity as eCommandRequiresThread ensures
296 // it is valid
297 Thread *thread = m_exe_ctx.GetThreadPtr();
298
299 uint32_t frame_idx = UINT32_MAX;
300 if (m_options.relative_frame_offset) {
301 // The one and only argument is a signed relative frame index
302 frame_idx = thread->GetSelectedFrameIndex(SelectMostRelevantFrame);
303 if (frame_idx == UINT32_MAX)
304 frame_idx = 0;
305
306 // If moving up/down by one, skip over hidden frames, unless we started
307 // in a hidden frame.
308 if ((*m_options.relative_frame_offset == 1 ||
309 *m_options.relative_frame_offset == -1)) {
310 if (auto current_frame_sp = thread->GetStackFrameAtIndex(frame_idx);
311 !current_frame_sp->IsHidden())
312 SkipHiddenFrames(*thread, frame_idx);
313 }
314
315 if (*m_options.relative_frame_offset < 0) {
316 if (static_cast<int32_t>(frame_idx) >=
317 -*m_options.relative_frame_offset)
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;
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 an error, but rather to just go to the top. OTOH, start
331 // by seeing if the requested frame exists, in which case we can avoid
332 // counting the stack here...
333 const uint32_t frame_requested =
334 frame_idx + *m_options.relative_frame_offset;
335 StackFrameSP frame_sp = thread->GetStackFrameAtIndex(frame_requested);
336 if (frame_sp)
337 frame_idx = frame_requested;
338 else {
339 // The request went past the stack, so handle that case:
340 const uint32_t num_frames = thread->GetStackFrameCount();
341 if (static_cast<int32_t>(num_frames - frame_idx) >
342 *m_options.relative_frame_offset) {
343 frame_idx += *m_options.relative_frame_offset;
344 } else {
345 if (frame_idx == num_frames - 1) {
346 // If we are already at the top of the stack, just warn and don't
347 // reset the frame.
348 result.AppendError("already at the top of the stack");
349 return;
350 } else
351 frame_idx = num_frames - 1;
352 }
353 }
354 }
355 } else {
356 if (command.GetArgumentCount() > 1) {
358 "too many arguments; expected frame-index, saw '%s'.\n",
359 command[0].c_str());
360 m_options.GenerateOptionUsage(
361 result.GetErrorStream(), *this,
362 GetCommandInterpreter().GetDebugger().GetTerminalWidth(),
363 GetCommandInterpreter().GetDebugger().GetUseColor());
364 return;
365 }
366
367 if (command.GetArgumentCount() == 1) {
368 if (command[0].ref().getAsInteger(0, frame_idx)) {
369 result.AppendErrorWithFormat("invalid frame index argument '%s'.",
370 command[0].c_str());
371 return;
372 }
373 } else if (command.GetArgumentCount() == 0) {
374 frame_idx = thread->GetSelectedFrameIndex(SelectMostRelevantFrame);
375 if (frame_idx == UINT32_MAX) {
376 frame_idx = 0;
377 }
378 }
379 }
380
381 bool success = thread->SetSelectedFrameByIndexNoisily(
382 frame_idx, result.GetOutputStream());
383 if (success) {
384 m_exe_ctx.SetFrameSP(thread->GetSelectedFrame(SelectMostRelevantFrame));
386 } else {
387 result.AppendErrorWithFormat("Frame index (%u) out of range.\n",
388 frame_idx);
389 }
390 }
391
393};
394
395#pragma mark CommandObjectFrameVariable
396// List images with associated information
398public:
401 interpreter, "frame variable",
402 "Show variables for the current stack frame. Defaults to all "
403 "arguments and local variables in scope. Names of argument, "
404 "local, file static and file global variables can be specified.",
405 nullptr,
406 eCommandRequiresFrame | eCommandTryTargetAPILock |
407 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused |
408 eCommandRequiresProcess),
410 true), // Include the frame specific options by passing "true"
412 SetHelpLong(R"(
413Children of aggregate variables can be specified such as 'var->child.x'. In
414'frame variable', the operators -> and [] do not invoke operator overloads if
415they exist, but directly access the specified element. If you want to trigger
416operator overloads use the expression command to print the variable instead.
417
418It is worth noting that except for overloaded operators, when printing local
419variables 'expr local_var' and 'frame var local_var' produce the same results.
420However, 'frame variable' is more efficient, since it uses debug information and
421memory reads directly, rather than parsing and evaluating an expression, which
422may even involve JITing and running code in the target program.)");
423
432 m_option_group.Finalize();
433 }
434
435 ~CommandObjectFrameVariable() override = default;
436
437 Options *GetOptions() override { return &m_option_group; }
438
439protected:
440 llvm::StringRef GetScopeString(VariableSP var_sp) {
441 if (!var_sp)
442 return llvm::StringRef();
443
444 auto vt = var_sp->GetScope();
445 bool is_synthetic = IsSyntheticValueType(vt);
446 // Clear the bit so the rest works correctly.
447 if (is_synthetic)
448 vt = GetBaseValueType(vt);
449
450 switch (vt) {
452 return is_synthetic ? "(synthetic) GLOBAL: " : "GLOBAL: ";
454 return is_synthetic ? "(synthetic) STATIC: " : "STATIC: ";
456 return is_synthetic ? "(synthetic) ARG: " : "ARG: ";
458 return is_synthetic ? "(synthetic) LOCAL: " : "LOCAL: ";
460 return is_synthetic ? "(synthetic) THREAD: " : "THREAD: ";
461 default:
462 break;
463 }
464
465 return llvm::StringRef();
466 }
467
468 /// Returns true if `scope` matches any of the options in `m_option_variable`.
469 bool ScopeRequested(lldb::ValueType scope) {
470 // If it's a synthetic variable, check if we want to show those first.
471 bool is_synthetic = IsSyntheticValueType(scope);
472 if (is_synthetic) {
473 if (!m_option_variable.show_synthetic)
474 return false;
475
476 scope = GetBaseValueType(scope);
477 }
478 switch (scope) {
481 return m_option_variable.show_globals;
483 return m_option_variable.show_args;
485 return m_option_variable.show_locals;
491 case eValueTypeVTable:
493 // The default for all other value types is is_synthetic. Aside from the
494 // modifiers above that should apply equally to synthetic and normal
495 // variables, any other synthetic variable we should default to showing.
496 return is_synthetic;
497 }
498 llvm_unreachable("Unexpected scope value");
499 }
500
501 /// Finds all the variables in `all_variables` whose name matches `regex`,
502 /// inserting them into `matches`. Variables already contained in `matches`
503 /// are not inserted again.
504 /// Nullopt is returned in case of no matches.
505 /// A sub-range of `matches` with all newly inserted variables is returned.
506 /// This may be empty if all matches were already contained in `matches`.
507 std::optional<llvm::ArrayRef<VariableSP>>
509 VariableList &matches,
510 const VariableList &all_variables) {
511 bool any_matches = false;
512 const size_t previous_num_vars = matches.GetSize();
513
514 for (const VariableSP &var : all_variables) {
515 if (!var->NameMatches(regex) || !ScopeRequested(var->GetScope()))
516 continue;
517 any_matches = true;
518 matches.AddVariableIfUnique(var);
519 }
520
521 if (any_matches)
522 return matches.toArrayRef().drop_front(previous_num_vars);
523 return std::nullopt;
524 }
525
526 void DoExecute(Args &command, CommandReturnObject &result) override {
527 // No need to check "frame" for validity as eCommandRequiresFrame ensures
528 // it is valid
529 StackFrame *frame = m_exe_ctx.GetFramePtr();
530
531 Stream &s = result.GetOutputStream();
532
533 // Using a regex should behave like looking for an exact name match: it
534 // also finds globals.
535 m_option_variable.show_globals |= m_option_variable.use_regex;
536
537 // Be careful about the stack frame, if any summary formatter runs code, it
538 // might clear the StackFrameList for the thread. So hold onto a shared
539 // pointer to the frame so it stays alive.
540
542 VariableList *variable_list =
543 frame->GetVariableList(m_option_variable.show_globals,
544 m_option_variable.show_synthetic, &error);
545
546 if (error.Fail() && (!variable_list || variable_list->GetSize() == 0)) {
547 result.AppendError(error.AsCString());
548 }
549
550 ValueObjectSP valobj_sp;
551
552 TypeSummaryImplSP summary_format_sp;
553 if (!m_option_variable.summary.IsCurrentValueEmpty())
555 ConstString(m_option_variable.summary.GetCurrentValue()),
556 summary_format_sp);
557 else if (!m_option_variable.summary_string.IsCurrentValueEmpty())
558 summary_format_sp = std::make_shared<StringSummaryFormat>(
559 TypeSummaryImpl::Flags(),
560 m_option_variable.summary_string.GetCurrentValue());
561
562 DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(
564 summary_format_sp));
565
566 const SymbolContext &sym_ctx =
567 frame->GetSymbolContext(eSymbolContextFunction);
568 if (sym_ctx.function && sym_ctx.function->IsTopLevelFunction())
569 m_option_variable.show_globals = true;
570
571 if (variable_list) {
572 const Format format = m_option_format.GetFormat();
573 options.SetFormat(format);
574
575 if (!command.empty()) {
576 VariableList regex_var_list;
577
578 // If we have any args to the variable command, we will make variable
579 // objects from them...
580 for (auto &entry : command) {
581 if (m_option_variable.use_regex) {
582 llvm::StringRef name_str = entry.ref();
583 RegularExpression regex(name_str);
584 if (regex.IsValid()) {
585 std::optional<llvm::ArrayRef<VariableSP>> results =
586 findUniqueRegexMatches(regex, regex_var_list, *variable_list);
587 if (!results) {
589 "no variables matched the regular expression '%s'.",
590 entry.c_str());
591 continue;
592 }
593 for (const VariableSP &var_sp : *results) {
594 valobj_sp = frame->GetValueObjectForFrameVariable(
595 var_sp, m_varobj_options.use_dynamic);
596 if (valobj_sp) {
597 result.GetValueObjectList().Append(valobj_sp);
598
599 std::string scope_string;
600 if (m_option_variable.show_scope)
601 scope_string = GetScopeString(var_sp).str();
602
603 if (!scope_string.empty())
604 s.PutCString(scope_string);
605
606 if (m_option_variable.show_decl &&
607 var_sp->GetDeclaration().GetFile()) {
608 bool show_fullpaths = false;
609 bool show_module = true;
610 if (var_sp->DumpDeclaration(&s, show_fullpaths,
611 show_module))
612 s.PutCString(": ");
613 }
614 auto &strm = result.GetOutputStream();
615 if (llvm::Error error = valobj_sp->Dump(strm, options))
616 result.AppendError(toString(std::move(error)));
617 }
618 }
619 } else {
620 if (llvm::Error err = regex.GetError())
621 result.AppendError(llvm::toString(std::move(err)));
622 else
624 "unknown regex error when compiling '%s'", entry.c_str());
625 }
626 } else // No regex, either exact variable names or variable
627 // expressions.
628 {
630 uint32_t expr_path_options =
635 lldb::VariableSP var_sp;
636 valobj_sp = frame->GetValueForVariableExpressionPath(
637 entry.ref(), m_varobj_options.use_dynamic, expr_path_options,
638 var_sp, error);
639 if (valobj_sp) {
640 result.GetValueObjectList().Append(valobj_sp);
641
642 std::string scope_string;
643 if (m_option_variable.show_scope)
644 scope_string = GetScopeString(var_sp).str();
645
646 if (!scope_string.empty())
647 s.PutCString(scope_string);
648 if (m_option_variable.show_decl && var_sp &&
649 var_sp->GetDeclaration().GetFile()) {
650 var_sp->GetDeclaration().DumpStopContext(&s, false);
651 s.PutCString(": ");
652 }
653
654 options.SetFormat(format);
655 options.SetVariableFormatDisplayLanguage(
656 valobj_sp->GetPreferredDisplayLanguage());
657
658 Stream &output_stream = result.GetOutputStream();
659 options.SetRootValueObjectName(
660 valobj_sp->GetParent() ? entry.c_str() : nullptr);
661 // Check only the `error` argument, because doing
662 // `valobj_sp->GetError()` will update the value and potentially
663 // return a new error that happens during the update, even if
664 // `GetValueForVariableExpressionPath` reported no errors.
665 if (error.Fail()) {
667 result.SetError(error.takeError());
668 } else {
669 // If there is an error while updating the value, it will be
670 // printed here as the contents of the value, e.g.
671 // `(int) *((int*)0) = <parent is NULL>`
672 if (llvm::Error error = valobj_sp->Dump(output_stream, options))
673 result.AppendError(toString(std::move(error)));
674 }
675
676 } else {
677 if (auto error_cstr = error.AsCString(nullptr))
678 result.AppendError(error_cstr);
679 else
681 "unable to find any variable expression path that matches "
682 "'%s'.",
683 entry.c_str());
684 }
685 }
686 }
687 } else // No command arg specified. Use variable_list, instead.
688 {
689 const size_t num_variables = variable_list->GetSize();
690 if (num_variables > 0) {
691 for (size_t i = 0; i < num_variables; i++) {
692 VariableSP var_sp = variable_list->GetVariableAtIndex(i);
693 if (!ScopeRequested(var_sp->GetScope()))
694 continue;
695 std::string scope_string;
696 if (m_option_variable.show_scope)
697 scope_string = GetScopeString(var_sp).str();
698
699 // Use the variable object code to make sure we are using the same
700 // APIs as the public API will be using...
701 valobj_sp = frame->GetValueObjectForFrameVariable(
702 var_sp, m_varobj_options.use_dynamic);
703 if (valobj_sp) {
704 result.GetValueObjectList().Append(valobj_sp);
705
706 // When dumping all variables, don't print any variables that are
707 // not in scope to avoid extra unneeded output
708 if (valobj_sp->IsInScope()) {
709 if (!valobj_sp->GetTargetSP()
710 ->GetDisplayRuntimeSupportValues() &&
711 valobj_sp->IsRuntimeSupportValue())
712 continue;
713
714 if (!scope_string.empty())
715 s.PutCString(scope_string);
716
717 if (m_option_variable.show_decl &&
718 var_sp->GetDeclaration().GetFile()) {
719 var_sp->GetDeclaration().DumpStopContext(&s, false);
720 s.PutCString(": ");
721 }
722
723 options.SetFormat(format);
724 options.SetVariableFormatDisplayLanguage(
725 valobj_sp->GetPreferredDisplayLanguage());
726 options.SetRootValueObjectName(
727 var_sp ? var_sp->GetName().AsCString(nullptr) : nullptr);
728 if (llvm::Error error =
729 valobj_sp->Dump(result.GetOutputStream(), options))
730 result.AppendError(toString(std::move(error)));
731 }
732 }
733 }
734 }
735 }
736 if (result.GetStatus() != eReturnStatusFailed)
738 }
739
740 if (m_option_variable.show_recognized_args) {
741 auto recognized_frame = frame->GetRecognizedFrame();
742 if (recognized_frame) {
743 ValueObjectListSP recognized_arg_list =
744 recognized_frame->GetRecognizedArguments();
745 if (recognized_arg_list) {
746 for (auto &rec_value_sp : recognized_arg_list->GetObjects()) {
747 result.GetValueObjectList().Append(rec_value_sp);
748 options.SetFormat(m_option_format.GetFormat());
749 options.SetVariableFormatDisplayLanguage(
750 rec_value_sp->GetPreferredDisplayLanguage());
751 options.SetRootValueObjectName(
752 rec_value_sp->GetName().AsCString(nullptr));
753 if (llvm::Error error =
754 rec_value_sp->Dump(result.GetOutputStream(), options))
755 result.AppendError(toString(std::move(error)));
756 }
757 }
758 }
759 }
760
761 m_interpreter.PrintWarningsIfNecessary(result.GetOutputStream(),
764 // Increment statistics.
766 if (result.Succeeded())
767 target_stats.GetFrameVariableStats().NotifySuccess();
768 else
769 target_stats.GetFrameVariableStats().NotifyFailure();
770 }
771
776};
777
778#pragma mark CommandObjectFrameRecognizer
779
780#define LLDB_OPTIONS_frame_recognizer_add
781#include "CommandOptions.inc"
782
784private:
785 class CommandOptions : public Options {
786 public:
787 CommandOptions() = default;
788 ~CommandOptions() override = default;
789
790 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
791 ExecutionContext *execution_context) override {
793 const int short_option = m_getopt_table[option_idx].val;
794
795 switch (short_option) {
796 case 'f': {
797 bool value, success;
798 value = OptionArgParser::ToBoolean(option_arg, true, &success);
799 if (success) {
801 } else {
803 "invalid boolean value '%s' passed for -f option",
804 option_arg.str().c_str());
805 }
806 } break;
807 case 'l':
808 m_class_name = std::string(option_arg);
809 break;
810 case 's':
811 m_module = std::string(option_arg);
812 break;
813 case 'n':
814 m_symbols.push_back(std::string(option_arg));
815 break;
816 case 'x':
817 m_regex = true;
818 break;
819 default:
820 llvm_unreachable("Unimplemented option");
821 }
822
823 return error;
824 }
825
826 void OptionParsingStarting(ExecutionContext *execution_context) override {
827 m_module = "";
828 m_symbols.clear();
829 m_class_name = "";
830 m_regex = false;
832 }
833
834 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
835 return llvm::ArrayRef(g_frame_recognizer_add_options);
836 }
837
838 // Instance variables to hold the values for command options.
839 std::string m_class_name;
840 std::string m_module;
841 std::vector<std::string> m_symbols;
844 };
845
847
848 Options *GetOptions() override { return &m_options; }
849
850protected:
851 void DoExecute(Args &command, CommandReturnObject &result) override;
852
853public:
855 : CommandObjectParsed(interpreter, "frame recognizer add",
856 "Add a new frame recognizer.", nullptr) {
857 SetHelpLong(R"(
858Frame recognizers allow for retrieving information about special frames based on
859ABI, arguments or other special properties of that frame, even without source
860code or debug info. Currently, one use case is to extract function arguments
861that would otherwise be unaccesible, or augment existing arguments.
862
863Adding a custom frame recognizer is possible by implementing a Python class
864and using the 'frame recognizer add' command. The Python class should have a
865'get_recognized_arguments' method and it will receive an argument of type
866lldb.SBFrame representing the current frame that we are trying to recognize.
867The method should return a (possibly empty) list of lldb.SBValue objects that
868represent the recognized arguments.
869
870An example of a recognizer that retrieves the file descriptor values from libc
871functions 'read', 'write' and 'close' follows:
872
873 class LibcFdRecognizer(object):
874 def get_recognized_arguments(self, frame):
875 if frame.name in ["read", "write", "close"]:
876 fd = frame.EvaluateExpression("$arg1").unsigned
877 target = frame.thread.process.target
878 value = target.CreateValueFromExpression("fd", "(int)%d" % fd)
879 return [value]
880 return []
881
882The file containing this implementation can be imported via 'command script
883import' and then we can register this recognizer with 'frame recognizer add'.
884It's important to restrict the recognizer to the libc library (which is
885libsystem_kernel.dylib on macOS) to avoid matching functions with the same name
886in other modules:
887
888(lldb) command script import .../fd_recognizer.py
889(lldb) frame recognizer add -l fd_recognizer.LibcFdRecognizer -n read -s libsystem_kernel.dylib
890
891When the program is stopped at the beginning of the 'read' function in libc, we
892can view the recognizer arguments in 'frame variable':
893
894(lldb) b read
895(lldb) r
896Process 1234 stopped
897* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.3
898 frame #0: 0x00007fff06013ca0 libsystem_kernel.dylib`read
899(lldb) frame variable
900(int) fd = 3
901
902 )");
903 }
904 ~CommandObjectFrameRecognizerAdd() override = default;
905};
906
908 CommandReturnObject &result) {
909#if LLDB_ENABLE_PYTHON
910 if (m_options.m_class_name.empty()) {
912 "%s needs a Python class name (-l argument).\n", m_cmd_name.c_str());
913 return;
914 }
915
916 if (m_options.m_module.empty()) {
917 result.AppendErrorWithFormat("%s needs a module name (-s argument).\n",
918 m_cmd_name.c_str());
919 return;
920 }
921
922 if (m_options.m_symbols.empty()) {
924 "%s needs at least one symbol name (-n argument).\n",
925 m_cmd_name.c_str());
926 return;
927 }
928
929 if (m_options.m_regex && m_options.m_symbols.size() > 1) {
931 "%s needs only one symbol regular expression (-n argument).\n",
932 m_cmd_name.c_str());
933 return;
934 }
935
937
938 if (interpreter &&
939 !interpreter->CheckObjectExists(m_options.m_class_name.c_str())) {
940 result.AppendWarning("the provided class does not exist - please define it "
941 "before attempting to use this frame recognizer");
942 }
943
944 StackFrameRecognizerSP recognizer_sp =
946 interpreter, m_options.m_class_name.c_str()));
947 if (m_options.m_regex) {
948 auto module = std::make_shared<RegularExpression>(m_options.m_module);
949 auto func =
950 std::make_shared<RegularExpression>(m_options.m_symbols.front());
952 recognizer_sp, module, func, Mangled::NamePreference::ePreferDemangled,
953 m_options.m_first_instruction_only);
954 } else {
955 auto module = ConstString(m_options.m_module);
956 std::vector<ConstString> symbols(m_options.m_symbols.begin(),
957 m_options.m_symbols.end());
959 recognizer_sp, module, symbols,
961 m_options.m_first_instruction_only);
962 }
963#endif
964
966}
967
969public:
971 : CommandObjectParsed(interpreter, "frame recognizer clear",
972 "Delete all frame recognizers.", nullptr) {}
973
975
976protected:
981};
982
983static void
984PrintRecognizerDetails(Stream &strm, const std::string &name, bool enabled,
985 const std::string &module,
986 llvm::ArrayRef<lldb_private::ConstString> symbols,
987 Mangled::NamePreference symbol_mangling, bool regexp) {
988 if (!enabled)
989 strm << "[disabled] ";
990
991 strm << name << ", ";
992
993 if (!module.empty())
994 strm << "module " << module << ", ";
995
996 switch (symbol_mangling) {
997 case Mangled::NamePreference ::ePreferMangled:
998 strm << "mangled symbol ";
999 break;
1000 case Mangled::NamePreference ::ePreferDemangled:
1001 strm << "demangled symbol ";
1002 break;
1003 case Mangled::NamePreference ::ePreferDemangledWithoutArguments:
1004 strm << "demangled (no args) symbol ";
1005 break;
1006 }
1007
1008 if (regexp)
1009 strm << "regex ";
1010
1011 llvm::interleaveComma(symbols, strm);
1012}
1013
1014// Base class for commands which accept a single frame recognizer as an argument
1016public:
1018 const char *name,
1019 const char *help = nullptr,
1020 const char *syntax = nullptr,
1021 uint32_t flags = 0)
1022 : CommandObjectParsed(interpreter, name, help, syntax, flags) {
1024 }
1025
1026 void
1028 OptionElementVector &opt_element_vector) override {
1029 if (request.GetCursorIndex() != 0)
1030 return;
1031
1033 [&request](uint32_t rid, bool enabled, std::string rname,
1034 std::string module,
1035 llvm::ArrayRef<lldb_private::ConstString> symbols,
1036 Mangled::NamePreference symbol_mangling, bool regexp) {
1037 StreamString strm;
1038 if (rname.empty())
1039 rname = "(internal)";
1040
1041 PrintRecognizerDetails(strm, rname, enabled, module, symbols,
1042 symbol_mangling, regexp);
1043
1044 request.TryCompleteCurrentArg(std::to_string(rid), strm.GetString());
1045 });
1046 }
1047
1049 uint32_t recognizer_id) = 0;
1050
1051 void DoExecute(Args &command, CommandReturnObject &result) override {
1052 uint32_t recognizer_id;
1053 if (!llvm::to_integer(command.GetArgumentAtIndex(0), recognizer_id)) {
1054 result.AppendErrorWithFormat("'%s' is not a valid recognizer id.\n",
1055 command.GetArgumentAtIndex(0));
1056 return;
1057 }
1058
1059 DoExecuteWithId(result, recognizer_id);
1060 }
1061};
1062
1065public:
1068 interpreter, "frame recognizer enable",
1069 "Enable a frame recognizer by id.", nullptr) {
1071 }
1072
1074
1075protected:
1077 uint32_t recognizer_id) override {
1078 auto &recognizer_mgr = GetTarget().GetFrameRecognizerManager();
1079 if (!recognizer_mgr.SetEnabledForID(recognizer_id, true)) {
1080 result.AppendErrorWithFormat("'%u' is not a valid recognizer id.\n",
1081 recognizer_id);
1082 return;
1083 }
1085 }
1086};
1087
1090public:
1093 interpreter, "frame recognizer disable",
1094 "Disable a frame recognizer by id.", nullptr) {
1096 }
1097
1099
1100protected:
1102 uint32_t recognizer_id) override {
1103 auto &recognizer_mgr = GetTarget().GetFrameRecognizerManager();
1104 if (!recognizer_mgr.SetEnabledForID(recognizer_id, false)) {
1105 result.AppendErrorWithFormat("'%u' is not a valid recognizer id.\n",
1106 recognizer_id);
1107 return;
1108 }
1110 }
1111};
1112
1115public:
1118 interpreter, "frame recognizer delete",
1119 "Delete an existing frame recognizer by id.", nullptr) {
1121 }
1122
1124
1125protected:
1127 uint32_t recognizer_id) override {
1128 auto &recognizer_mgr = GetTarget().GetFrameRecognizerManager();
1129 if (!recognizer_mgr.RemoveRecognizerWithID(recognizer_id)) {
1130 result.AppendErrorWithFormat("'%u' is not a valid recognizer id.\n",
1131 recognizer_id);
1132 return;
1133 }
1135 }
1136};
1137
1139public:
1141 : CommandObjectParsed(interpreter, "frame recognizer list",
1142 "Show a list of active frame recognizers.",
1143 nullptr) {}
1144
1146
1147protected:
1148 void DoExecute(Args &command, CommandReturnObject &result) override {
1149 bool any_printed = false;
1151 [&result,
1152 &any_printed](uint32_t recognizer_id, bool enabled, std::string name,
1153 std::string module, llvm::ArrayRef<ConstString> symbols,
1154 Mangled::NamePreference symbol_mangling, bool regexp) {
1155 Stream &stream = result.GetOutputStream();
1156
1157 if (name.empty())
1158 name = "(internal)";
1159
1160 stream << std::to_string(recognizer_id) << ": ";
1161 PrintRecognizerDetails(stream, name, enabled, module, symbols,
1162 symbol_mangling, regexp);
1163
1164 stream.EOL();
1165 stream.Flush();
1166
1167 any_printed = true;
1168 });
1169
1170 if (any_printed)
1172 else {
1173 result.GetOutputStream().PutCString("no matching results found.\n");
1175 }
1176 }
1177};
1178
1180public:
1183 interpreter, "frame recognizer info",
1184 "Show which frame recognizer is applied a stack frame (if any).",
1185 nullptr) {
1187 }
1188
1190
1191protected:
1192 void DoExecute(Args &command, CommandReturnObject &result) override {
1193 const char *frame_index_str = command.GetArgumentAtIndex(0);
1194 uint32_t frame_index;
1195 if (!llvm::to_integer(frame_index_str, frame_index)) {
1196 result.AppendErrorWithFormat("'%s' is not a valid frame index.",
1197 frame_index_str);
1198 return;
1199 }
1200
1201 Process *process = m_exe_ctx.GetProcessPtr();
1202 if (process == nullptr) {
1203 result.AppendError("no process");
1204 return;
1205 }
1206 Thread *thread = m_exe_ctx.GetThreadPtr();
1207 if (thread == nullptr) {
1208 result.AppendError("no thread");
1209 return;
1210 }
1211 if (command.GetArgumentCount() != 1) {
1212 result.AppendErrorWithFormat(
1213 "'%s' takes exactly one frame index argument.\n", m_cmd_name.c_str());
1214 return;
1215 }
1216
1217 StackFrameSP frame_sp = thread->GetStackFrameAtIndex(frame_index);
1218 if (!frame_sp) {
1219 result.AppendErrorWithFormat("no frame with index %u", frame_index);
1220 return;
1221 }
1222
1223 auto recognizer =
1225
1226 Stream &output_stream = result.GetOutputStream();
1227 output_stream.Printf("frame %d ", frame_index);
1228 if (recognizer) {
1229 output_stream << "is recognized by ";
1230 output_stream << recognizer->GetName();
1231 } else {
1232 output_stream << "not recognized by any recognizer";
1233 }
1234 output_stream.EOL();
1236 }
1237};
1238
1240public:
1243 interpreter, "frame recognizer",
1244 "Commands for editing and viewing frame recognizers.",
1245 "frame recognizer [<sub-command-options>] ") {
1247 interpreter)));
1249 interpreter)));
1251 interpreter)));
1253 "enable",
1256 "disable",
1259 "delete",
1262 "clear",
1264 }
1265
1266 ~CommandObjectFrameRecognizer() override = default;
1267};
1268
1269#pragma mark CommandObjectMultiwordFrame
1270
1271// CommandObjectMultiwordFrame
1272
1274 CommandInterpreter &interpreter)
1275 : CommandObjectMultiword(interpreter, "frame",
1276 "Commands for selecting and "
1277 "examining the current "
1278 "thread's stack frames.",
1279 "frame <subcommand> [<subcommand-options>]") {
1280 LoadSubCommand("diagnose",
1282 LoadSubCommand("info",
1283 CommandObjectSP(new CommandObjectFrameInfo(interpreter)));
1284 LoadSubCommand("select",
1285 CommandObjectSP(new CommandObjectFrameSelect(interpreter)));
1286 LoadSubCommand("variable",
1288#if LLDB_ENABLE_PYTHON
1290 interpreter)));
1291#endif
1292}
1293
static void PrintRecognizerDetails(Stream &strm, const std::string &name, bool enabled, const std::string &module, llvm::ArrayRef< lldb_private::ConstString > symbols, Mangled::NamePreference symbol_mangling, bool regexp)
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)
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
CommandObjectFrameRecognizerDelete(CommandInterpreter &interpreter)
void DoExecuteWithId(CommandReturnObject &result, uint32_t recognizer_id) override
CommandObjectFrameRecognizerDisable(CommandInterpreter &interpreter)
void DoExecuteWithId(CommandReturnObject &result, uint32_t recognizer_id) override
~CommandObjectFrameRecognizerDisable() override=default
void DoExecuteWithId(CommandReturnObject &result, uint32_t recognizer_id) override
CommandObjectFrameRecognizerEnable(CommandInterpreter &interpreter)
~CommandObjectFrameRecognizerEnable() override=default
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
void SkipHiddenFrames(Thread &thread, uint32_t frame_idx)
~CommandObjectFrameSelect() override=default
CommandObjectFrameSelect(CommandInterpreter &interpreter)
Options * GetOptions() override
void DoExecute(Args &command, CommandReturnObject &result) 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
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,...
CommandObjectWithFrameRecognizerArg(CommandInterpreter &interpreter, const char *name, const char *help=nullptr, const char *syntax=nullptr, uint32_t flags=0)
virtual void DoExecuteWithId(CommandReturnObject &result, uint32_t recognizer_id)=0
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:120
const char * GetArgumentAtIndex(size_t idx) const
Gets the NULL terminated C string argument pointer for the argument at index idx.
Definition Args.cpp:273
bool empty() const
Definition Args.h:122
CommandObjectMultiwordFrame(CommandInterpreter &interpreter)
bool LoadSubCommand(llvm::StringRef cmd_name, const lldb::CommandObjectSP &command_obj) override
CommandObjectMultiword(CommandInterpreter &interpreter, const char *name, const char *help=nullptr, const char *syntax=nullptr, uint32_t flags=0)
CommandObjectParsed(CommandInterpreter &interpreter, const char *name, const char *help=nullptr, const char *syntax=nullptr, uint32_t flags=0)
virtual void SetHelpLong(llvm::StringRef str)
void AddSimpleArgumentList(lldb::CommandArgumentType arg_type, ArgumentRepetitionType repetition_type=eArgRepeatPlain)
CommandInterpreter & GetCommandInterpreter()
CommandInterpreter & m_interpreter
void AppendError(llvm::StringRef in_string)
const ValueObjectList & GetValueObjectList() const
void SetStatus(lldb::ReturnStatus status)
void AppendErrorWithFormat(const char *format,...) __attribute__((format(printf
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={})
std::function< bool(ConstString, ConstString, const DumpValueObjectOptions &, Stream &)> DeclPrintingHelper
DumpValueObjectOptions & SetDeclPrintingHelper(DeclPrintingHelper helper)
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
bool IsTopLevelFunction()
Get whether this function represents a 'top-level' function.
Definition Function.cpp:524
static const uint32_t OPTION_GROUP_GDB_FMT
static const uint32_t OPTION_GROUP_FORMAT
A command line option parsing protocol class.
Definition Options.h:58
std::vector< Option > m_getopt_table
Definition Options.h:198
A plug-in interface definition class for debugging a process.
Definition Process.h:355
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.
void AddRecognizer(lldb::StackFrameRecognizerSP recognizer, ConstString module, llvm::ArrayRef< ConstString > symbols, Mangled::NamePreference symbol_mangling, bool first_instruction_only=true)
Add a new recognizer that triggers on a given symbol name.
void ForEach(std::function< void(uint32_t recognizer_id, bool enabled, std::string recognizer_name, std::string module, llvm::ArrayRef< ConstString > symbols, Mangled::NamePreference name_preference, bool regexp)> const &callback)
lldb::StackFrameRecognizerSP GetRecognizerForFrame(lldb::StackFrameSP frame)
virtual lldb::ValueObjectSP GetValueForVariableExpressionPath(llvm::StringRef var_expr, lldb::DynamicValueType use_dynamic, uint32_t options, lldb::VariableSP &var_sp, Status &error, lldb::DILMode mode=lldb::eDILModeFull)
Create a ValueObject for a variable name / pathname, possibly including simple dereference/child sele...
@ eExpressionPathOptionsInspectAnonymousUnions
Definition StackFrame.h:59
@ eExpressionPathOptionsAllowDirectIVarAccess
Definition StackFrame.h:58
virtual lldb::ValueObjectSP GetValueObjectForFrameVariable(const lldb::VariableSP &variable_sp, lldb::DynamicValueType use_dynamic)
Create a ValueObject for a given Variable in this StackFrame.
virtual VariableList * GetVariableList(bool get_file_globals, bool include_synthetic_vars, Status *error_ptr)
Retrieve the list of variables whose scope either:
virtual const SymbolContext & GetSymbolContext(lldb::SymbolContextItem resolve_scope)
Provide a SymbolContext for this StackFrame's current pc value.
virtual lldb::RecognizedStackFrameSP GetRecognizedFrame()
An error handling class.
Definition Status.h:118
static Status FromErrorStringWithFormat(const char *format,...) __attribute__((format(printf
Definition Status.cpp:106
static lldb::ValueObjectSP GetCrashingDereference(lldb::StopInfoSP &stop_info_sp, lldb::addr_t *crashing_address=nullptr)
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:132
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:153
Function * function
The Function for a given query.
A class that represents statistics for a since lldb_private::Target.
Definition Statistics.h:312
StatsSuccessFail & GetFrameVariableStats()
Definition Statistics.h:327
TargetStats & GetStatistics()
Definition Target.h:1895
StackFrameRecognizerManager & GetFrameRecognizerManager()
Definition Target.h:1718
void Append(const lldb::ValueObjectSP &val_obj_sp)
bool AddVariableIfUnique(const lldb::VariableSP &var_sp)
lldb::VariableSP GetVariableAtIndex(size_t idx) const
llvm::ArrayRef< lldb::VariableSP > toArrayRef()
#define LLDB_OPT_SET_1
#define LLDB_OPT_SET_ALL
#define UINT32_MAX
@ SelectMostRelevantFrame
A class that represents a running process on the host machine.
constexpr bool IsSyntheticValueType(lldb::ValueType vt)
Return true if vt represents a synthetic value, false if not.
Definition ValueType.h:27
std::vector< OptionArgElement > OptionElementVector
Definition Options.h:43
constexpr lldb::ValueType GetBaseValueType(lldb::ValueType vt)
Get the base value type - for when we don't care if the value is synthetic or not,...
Definition ValueType.h:17
std::string toString(FormatterBytecode::OpCodes op)
std::shared_ptr< lldb_private::StackFrame > StackFrameSP
std::shared_ptr< lldb_private::TypeSummaryImpl > TypeSummaryImplSP
std::shared_ptr< lldb_private::CommandObject > CommandObjectSP
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
Format
Display format definitions.
std::shared_ptr< lldb_private::ValueObjectList > ValueObjectListSP
@ eReturnStatusFailed
@ eReturnStatusSuccessFinishResult
@ eReturnStatusSuccessFinishNoResult
@ eArgTypeRecognizerID
std::shared_ptr< lldb_private::Variable > VariableSP
std::shared_ptr< lldb_private::StackFrameRecognizer > StackFrameRecognizerSP
std::shared_ptr< lldb_private::StopInfo > StopInfoSP
@ eValueTypeVTableEntry
function pointer in virtual function table
@ eValueTypeVTable
virtual function table
@ 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)