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#include "llvm/ADT/StringExtras.h"
36#include "llvm/ADT/StringRef.h"
37
38#include <memory>
39#include <optional>
40#include <string>
41
42using namespace lldb;
43using namespace lldb_private;
44
45#pragma mark CommandObjectFrameDiagnose
46
47// CommandObjectFrameInfo
48
49// CommandObjectFrameDiagnose
50
51#define LLDB_OPTIONS_frame_diag
52#include "CommandOptions.inc"
53
55public:
56 class CommandOptions : public Options {
57 public:
59
60 ~CommandOptions() override = default;
61
62 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
63 ExecutionContext *execution_context) override {
65 const int short_option = m_getopt_table[option_idx].val;
66 switch (short_option) {
67 case 'r':
68 reg = ConstString(option_arg);
69 break;
70
71 case 'a': {
72 address.emplace();
73 if (option_arg.getAsInteger(0, *address)) {
74 address.reset();
76 "invalid address argument '%s'", option_arg.str().c_str());
77 }
78 } break;
79
80 case 'o': {
81 offset.emplace();
82 if (option_arg.getAsInteger(0, *offset)) {
83 offset.reset();
85 "invalid offset argument '%s'", option_arg.str().c_str());
86 }
87 } break;
88
89 default:
90 llvm_unreachable("Unimplemented option");
91 }
92
93 return error;
94 }
95
96 void OptionParsingStarting(ExecutionContext *execution_context) override {
97 address.reset();
98 reg.reset();
99 offset.reset();
100 }
101
102 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
103 return llvm::ArrayRef(g_frame_diag_options);
104 }
105
106 // Options.
107 std::optional<lldb::addr_t> address;
108 std::optional<ConstString> reg;
109 std::optional<int64_t> offset;
110 };
111
113 : CommandObjectParsed(interpreter, "frame diagnose",
114 "Try to determine what path the current stop "
115 "location used to get to a register or address",
116 nullptr,
117 eCommandRequiresThread | eCommandTryTargetAPILock |
118 eCommandProcessMustBeLaunched |
119 eCommandProcessMustBePaused) {
121 }
122
123 ~CommandObjectFrameDiagnose() override = default;
124
125 Options *GetOptions() override { return &m_options; }
126
127protected:
128 void DoExecute(Args &command, CommandReturnObject &result) override {
129 Thread *thread = m_exe_ctx.GetThreadPtr();
130 StackFrameSP frame_sp = thread->GetSelectedFrame(SelectMostRelevantFrame);
131
132 ValueObjectSP valobj_sp;
133
134 if (m_options.address) {
135 if (m_options.reg || m_options.offset) {
136 result.AppendError(
137 "`frame diagnose --address` is incompatible with other arguments.");
138 return;
139 }
140 valobj_sp = frame_sp->GuessValueForAddress(*m_options.address);
141 } else if (m_options.reg) {
142 valobj_sp = frame_sp->GuessValueForRegisterAndOffset(
143 *m_options.reg, m_options.offset.value_or(0));
144 } else {
145 StopInfoSP stop_info_sp = thread->GetStopInfo();
146 if (!stop_info_sp) {
147 result.AppendError("no arguments provided, and no stop info");
148 return;
149 }
150
151 valobj_sp = StopInfo::GetCrashingDereference(stop_info_sp);
152 }
153
154 if (!valobj_sp) {
155 result.AppendError("no diagnosis available");
156 return;
157 }
158
159 result.GetValueObjectList().Append(valobj_sp);
161 [&valobj_sp](ConstString type, ConstString var,
162 const DumpValueObjectOptions &opts,
163 Stream &stream) -> bool {
164 const ValueObject::GetExpressionPathFormat format = ValueObject::
165 GetExpressionPathFormat::eGetExpressionPathFormatHonorPointers;
166 valobj_sp->GetExpressionPath(stream, format);
167 stream.PutCString(" =");
168 return true;
169 };
170
172 options.SetDeclPrintingHelper(helper);
173 // We've already handled the case where the value object sp is null, so
174 // this is just to make sure future changes don't skip that:
175 assert(valobj_sp.get() && "Must have a valid ValueObject to print");
176 ValueObjectPrinter printer(*valobj_sp, &result.GetOutputStream(), options);
177 if (llvm::Error error = printer.PrintValueObject())
178 result.AppendError(toString(std::move(error)));
179 else
181 }
182
184};
185
186#pragma mark CommandObjectFrameInfo
187
188// CommandObjectFrameInfo
189
191public:
193 : CommandObjectParsed(interpreter, "frame info",
194 "List information about the current "
195 "stack frame in the current thread.",
196 "frame info",
197 eCommandRequiresFrame | eCommandTryTargetAPILock |
198 eCommandProcessMustBeLaunched |
199 eCommandProcessMustBePaused) {}
200
201 ~CommandObjectFrameInfo() override = default;
202
203protected:
204 void DoExecute(Args &command, CommandReturnObject &result) override {
205 m_exe_ctx.GetFrameRef().DumpUsingSettingsFormat(&result.GetOutputStream());
207 }
208};
209
210#pragma mark CommandObjectFrameSelect
211
212// CommandObjectFrameSelect
213
214#define LLDB_OPTIONS_frame_select
215#include "CommandOptions.inc"
216
218public:
219 class CommandOptions : public Options {
220 public:
222
223 ~CommandOptions() override = default;
224
225 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
226 ExecutionContext *execution_context) override {
228 const int short_option = m_getopt_table[option_idx].val;
229 switch (short_option) {
230 case 'r': {
231 int32_t offset = 0;
232 if (option_arg.getAsInteger(0, offset) || offset == INT32_MIN) {
234 "invalid frame offset argument '%s'", option_arg.str().c_str());
235 } else
236 relative_frame_offset = offset;
237 break;
238 }
239
240 default:
241 llvm_unreachable("Unimplemented option");
242 }
243
244 return error;
245 }
246
247 void OptionParsingStarting(ExecutionContext *execution_context) override {
248 relative_frame_offset.reset();
249 }
250
251 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
252 return llvm::ArrayRef(g_frame_select_options);
253 }
254
255 std::optional<int32_t> relative_frame_offset;
256 };
257
259 : CommandObjectParsed(interpreter, "frame select",
260 "Select the current stack frame by "
261 "index from within the current thread "
262 "(see 'thread backtrace'.)",
263 nullptr,
264 eCommandRequiresThread | eCommandTryTargetAPILock |
265 eCommandProcessMustBeLaunched |
266 eCommandProcessMustBePaused) {
268 }
269
270 ~CommandObjectFrameSelect() override = default;
271
272 Options *GetOptions() override { return &m_options; }
273
274private:
275 void SkipHiddenFrames(Thread &thread, uint32_t frame_idx) {
276 uint32_t candidate_idx = frame_idx;
277 const unsigned max_depth = 12;
278 for (unsigned num_try = 0; num_try < max_depth; ++num_try) {
279 if (candidate_idx == 0 && *m_options.relative_frame_offset == -1) {
280 candidate_idx = UINT32_MAX;
281 break;
282 }
283 candidate_idx += *m_options.relative_frame_offset;
284 if (auto candidate_sp = thread.GetStackFrameAtIndex(candidate_idx)) {
285 if (candidate_sp->IsHidden())
286 continue;
287 // Now candidate_idx is the first non-hidden frame.
288 break;
289 }
290 candidate_idx = UINT32_MAX;
291 break;
292 };
293 if (candidate_idx != UINT32_MAX)
294 m_options.relative_frame_offset = candidate_idx - frame_idx;
295 }
296
297protected:
298 void DoExecute(Args &command, CommandReturnObject &result) override {
299 // No need to check "thread" for validity as eCommandRequiresThread ensures
300 // it is valid
301 Thread *thread = m_exe_ctx.GetThreadPtr();
302
303 uint32_t frame_idx = UINT32_MAX;
304 if (m_options.relative_frame_offset) {
305 // The one and only argument is a signed relative frame index
306 frame_idx = thread->GetSelectedFrameIndex(SelectMostRelevantFrame);
307 if (frame_idx == UINT32_MAX)
308 frame_idx = 0;
309
310 // If moving up/down by one, skip over hidden frames, unless we started
311 // in a hidden frame.
312 if ((*m_options.relative_frame_offset == 1 ||
313 *m_options.relative_frame_offset == -1)) {
314 if (auto current_frame_sp = thread->GetStackFrameAtIndex(frame_idx);
315 !current_frame_sp->IsHidden())
316 SkipHiddenFrames(*thread, frame_idx);
317 }
318
319 if (*m_options.relative_frame_offset < 0) {
320 if (static_cast<int32_t>(frame_idx) >=
321 -*m_options.relative_frame_offset)
322 frame_idx += *m_options.relative_frame_offset;
323 else {
324 if (frame_idx == 0) {
325 // If you are already at the bottom of the stack, then just warn
326 // and don't reset the frame.
327 result.AppendError("already at the bottom of the stack");
328 return;
329 } else
330 frame_idx = 0;
331 }
332 } else if (*m_options.relative_frame_offset > 0) {
333 // I don't want "up 20" where "20" takes you past the top of the stack
334 // to produce an error, but rather to just go to the top. OTOH, start
335 // by seeing if the requested frame exists, in which case we can avoid
336 // counting the stack here...
337 const uint32_t frame_requested =
338 frame_idx + *m_options.relative_frame_offset;
339 StackFrameSP frame_sp = thread->GetStackFrameAtIndex(frame_requested);
340 if (frame_sp)
341 frame_idx = frame_requested;
342 else {
343 // The request went past the stack, so handle that case:
344 const uint32_t num_frames = thread->GetStackFrameCount();
345 if (static_cast<int32_t>(num_frames - frame_idx) >
346 *m_options.relative_frame_offset) {
347 frame_idx += *m_options.relative_frame_offset;
348 } else {
349 if (frame_idx == num_frames - 1) {
350 // If we are already at the top of the stack, just warn and don't
351 // reset the frame.
352 result.AppendError("already at the top of the stack");
353 return;
354 } else
355 frame_idx = num_frames - 1;
356 }
357 }
358 }
359 } else {
360 if (command.GetArgumentCount() > 1) {
362 "too many arguments; expected frame-index, saw '%s'",
363 command[0].c_str());
364 m_options.GenerateOptionUsage(
365 result.GetErrorStream(), *this,
366 GetCommandInterpreter().GetDebugger().GetTerminalWidth(),
367 GetCommandInterpreter().GetDebugger().GetUseColor());
368 return;
369 }
370
371 if (command.GetArgumentCount() == 1) {
372 if (command[0].ref().getAsInteger(0, frame_idx)) {
373 result.AppendErrorWithFormat("invalid frame index argument '%s'",
374 command[0].c_str());
375 return;
376 }
377 } else if (command.GetArgumentCount() == 0) {
378 frame_idx = thread->GetSelectedFrameIndex(SelectMostRelevantFrame);
379 if (frame_idx == UINT32_MAX) {
380 frame_idx = 0;
381 }
382 }
383 }
384
385 bool success = thread->SetSelectedFrameByIndexNoisily(
386 frame_idx, result.GetOutputStream());
387 if (success) {
388 m_exe_ctx.SetFrameSP(thread->GetSelectedFrame(SelectMostRelevantFrame));
390 } else {
391 result.AppendErrorWithFormat("Frame index (%u) out of range", frame_idx);
392 }
393 }
394
396};
397
398#pragma mark CommandObjectFrameVariable
399// List images with associated information
401public:
404 interpreter, "frame variable",
405 "Show variables for the current stack frame. Defaults to all "
406 "arguments and local variables in scope. Names of argument, "
407 "local, file static and file global variables can be specified.",
408 nullptr,
409 eCommandRequiresFrame | eCommandTryTargetAPILock |
410 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused |
411 eCommandRequiresProcess),
413 true), // Include the frame specific options by passing "true"
415 SetHelpLong(R"(
416Children of aggregate variables can be specified such as 'var->child.x'. In
417'frame variable', the operators -> and [] do not invoke operator overloads if
418they exist, but directly access the specified element. If you want to trigger
419operator overloads use the expression command to print the variable instead.
420
421It is worth noting that except for overloaded operators, when printing local
422variables 'expr local_var' and 'frame var local_var' produce the same results.
423However, 'frame variable' is more efficient, since it uses debug information and
424memory reads directly, rather than parsing and evaluating an expression, which
425may even involve JITing and running code in the target program.)");
426
435 m_option_group.Finalize();
436 }
437
438 ~CommandObjectFrameVariable() override = default;
439
440 Options *GetOptions() override { return &m_option_group; }
441
442 // `frame variable` repeats by incrementing the printing depth. When the depth
443 // is too shallow, hitting enter a few times will quickly expand the data.
444 std::optional<std::string> GetRepeatCommand(Args &current_command_args,
445 uint32_t index) override {
446 llvm::StringRef depth_opt = "--depth";
447
448 Args repeat_args;
449 auto increment_option =
450 [&](llvm::StringRef option) -> std::optional<std::string> {
451 uint32_t num;
452 bool failed = option.getAsInteger(10, num);
453 if (failed)
454 return std::nullopt;
455 return llvm::utostr(num + 1);
456 };
457
458 bool has_depth_option = false;
459 bool increment_next_arg = false;
460 for (const auto &entry : current_command_args) {
461 llvm::StringRef arg = entry.ref();
462
463 if (arg == "-" || arg == "--") {
464 repeat_args.AppendArgument(arg);
465 continue;
466 }
467
468 if (increment_next_arg) {
469 increment_next_arg = false;
470 if (auto maybe_opt = increment_option(arg)) {
471 repeat_args.AppendArgument(*maybe_opt);
472 continue;
473 }
474 }
475
476 if (depth_opt.starts_with(arg) || arg == "-D") {
477 repeat_args.AppendArgument(arg);
478 increment_next_arg = true;
479 has_depth_option = true;
480 continue;
481 }
482 if (arg.consume_front("-D")) {
483 if (auto maybe_opt = increment_option(arg)) {
484 repeat_args.AppendArgument(llvm::formatv("-D{0}", *maybe_opt).str());
485 has_depth_option = true;
486 continue;
487 }
488 }
489
490 repeat_args.AppendArgument(arg);
491 }
492
493 if (!has_depth_option) {
494 // Access the default max-depth from the target. This is because
495 // GetRepeatCommand is called before ParseOptions, which is when
496 // m_varobj_options.max_depth becomes assigned.
497 if (auto target_sp = GetCommandInterpreter().GetSelectedTarget()) {
498 auto [default_depth, _] =
499 target_sp->GetMaximumDepthOfChildrenToDisplay();
500 // Insert the depth after `frame variable`, before positional args.
501 assert(repeat_args[0].ref() == "frame" && "expects resolved command");
502 repeat_args.InsertArgumentAtIndex(2, "--depth");
503 repeat_args.InsertArgumentAtIndex(3, llvm::utostr(default_depth + 1));
505 }
506
507 std::string repeat_command;
508 if (!repeat_args.GetQuotedCommandString(repeat_command))
509 return std::nullopt;
510 return repeat_command;
511 }
512
513protected:
514 llvm::StringRef GetScopeString(VariableSP var_sp) {
515 if (!var_sp)
516 return llvm::StringRef();
517
518 auto vt = var_sp->GetScope();
519 bool is_synthetic = IsSyntheticValueType(vt);
520 // Clear the bit so the rest works correctly.
521 if (is_synthetic)
522 vt = GetBaseValueType(vt);
523
524 switch (vt) {
526 return is_synthetic ? "(synthetic) GLOBAL: " : "GLOBAL: ";
528 return is_synthetic ? "(synthetic) STATIC: " : "STATIC: ";
530 return is_synthetic ? "(synthetic) ARG: " : "ARG: ";
532 return is_synthetic ? "(synthetic) LOCAL: " : "LOCAL: ";
534 return is_synthetic ? "(synthetic) THREAD: " : "THREAD: ";
535 default:
536 break;
537 }
538
539 return llvm::StringRef();
540 }
541
542 /// Returns true if `scope` matches any of the options in `m_option_variable`.
543 bool ScopeRequested(lldb::ValueType scope) {
544 // If it's a synthetic variable, check if we want to show those first.
545 bool is_synthetic = IsSyntheticValueType(scope);
546 if (is_synthetic) {
547 if (!m_option_variable.show_synthetic)
548 return false;
549
550 scope = GetBaseValueType(scope);
551 }
552 switch (scope) {
555 return m_option_variable.show_globals;
557 return m_option_variable.show_args;
559 return m_option_variable.show_locals;
565 case eValueTypeVTable:
567 // The default for all other value types is is_synthetic. Aside from the
568 // modifiers above that should apply equally to synthetic and normal
569 // variables, any other synthetic variable we should default to showing.
570 return is_synthetic;
572 llvm_unreachable("This flag was unset");
573 }
574 llvm_unreachable("Unexpected scope value");
575 }
576
577 /// Finds all the variables in `all_variables` whose name matches `regex`,
578 /// inserting them into `matches`. Variables already contained in `matches`
579 /// are not inserted again.
580 /// Nullopt is returned in case of no matches.
581 /// A sub-range of `matches` with all newly inserted variables is returned.
582 /// This may be empty if all matches were already contained in `matches`.
583 std::optional<llvm::ArrayRef<VariableSP>>
585 VariableList &matches,
586 const VariableList &all_variables) {
587 bool any_matches = false;
588 const size_t previous_num_vars = matches.GetSize();
589
590 for (const VariableSP &var : all_variables) {
591 if (!var->NameMatches(regex) || !ScopeRequested(var->GetScope()))
592 continue;
593 any_matches = true;
594 matches.AddVariableIfUnique(var);
595 }
596
597 if (any_matches)
598 return matches.toArrayRef().drop_front(previous_num_vars);
599 return std::nullopt;
600 }
601
602 void DoExecute(Args &command, CommandReturnObject &result) override {
603 // No need to check "frame" for validity as eCommandRequiresFrame ensures
604 // it is valid
605 StackFrame *frame = m_exe_ctx.GetFramePtr();
606
607 Stream &s = result.GetOutputStream();
608
609 // Using a regex should behave like looking for an exact name match: it
610 // also finds globals.
611 m_option_variable.show_globals |= m_option_variable.use_regex;
612
613 // Be careful about the stack frame, if any summary formatter runs code, it
614 // might clear the StackFrameList for the thread. So hold onto a shared
615 // pointer to the frame so it stays alive.
616
618 VariableList *variable_list =
619 frame->GetVariableList(m_option_variable.show_globals,
620 m_option_variable.show_synthetic, &error);
621
622 if (error.Fail() && (!variable_list || variable_list->GetSize() == 0)) {
623 result.AppendError(error.AsCString());
624 }
625
626 ValueObjectSP valobj_sp;
627
628 TypeSummaryImplSP summary_format_sp;
629 if (!m_option_variable.summary.IsCurrentValueEmpty())
631 ConstString(m_option_variable.summary.GetCurrentValue()),
632 summary_format_sp);
633 else if (!m_option_variable.summary_string.IsCurrentValueEmpty())
634 summary_format_sp = std::make_shared<StringSummaryFormat>(
635 TypeSummaryImpl::Flags(),
636 m_option_variable.summary_string.GetCurrentValue());
637
638 DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(
640 summary_format_sp));
641
642 const SymbolContext &sym_ctx =
643 frame->GetSymbolContext(eSymbolContextFunction);
644 if (sym_ctx.function && sym_ctx.function->IsTopLevelFunction())
645 m_option_variable.show_globals = true;
646
647 ValueObjectListSP recognized_arg_list;
648 if (m_option_variable.show_recognized_args)
649 if (auto recognized_frame = frame->GetRecognizedFrame())
650 recognized_arg_list = recognized_frame->GetRecognizedArguments();
651
652 const Format format = m_option_format.GetFormat();
653 options.SetFormat(format);
654
655 auto print_value = [&result, options](ValueObjectSP valobj_sp) {
656 result.GetValueObjectList().Append(valobj_sp);
657 if (auto error = valobj_sp->Dump(result.GetOutputStream(), options))
658 result.AppendError(toString(std::move(error)));
659 };
660
661 if (variable_list) {
662 if (!command.empty()) {
663 VariableList regex_var_list;
664
665 // If we have any args to the variable command, we will make variable
666 // objects from them...
667 for (auto &entry : command) {
668 if (m_option_variable.use_regex) {
669 llvm::StringRef name_str = entry.ref();
670 RegularExpression regex(name_str);
671 if (regex.IsValid()) {
672 std::optional<llvm::ArrayRef<VariableSP>> results =
673 findUniqueRegexMatches(regex, regex_var_list, *variable_list);
674 if (!results) {
675 // No variables matched. Try recognized args as fallback.
676 bool found_recognized = false;
677 if (recognized_arg_list)
678 for (auto &rec_value_sp : recognized_arg_list->GetObjects())
679 if (regex.Execute(rec_value_sp->GetName())) {
680 found_recognized = true;
681 print_value(rec_value_sp);
682 }
683 if (!found_recognized) {
685 "no variables matched the regular expression '%s'",
686 entry.c_str());
687 }
688 continue;
689 }
690 for (const VariableSP &var_sp : *results) {
691 valobj_sp = frame->GetValueObjectForFrameVariable(
692 var_sp, m_varobj_options.use_dynamic);
693 if (valobj_sp) {
694 result.GetValueObjectList().Append(valobj_sp);
695
696 std::string scope_string;
697 if (m_option_variable.show_scope)
698 scope_string = GetScopeString(var_sp).str();
699
700 if (!scope_string.empty())
701 s.PutCString(scope_string);
702
703 if (m_option_variable.show_decl &&
704 var_sp->GetDeclaration().GetFile()) {
705 bool show_fullpaths = false;
706 bool show_module = true;
707 if (var_sp->DumpDeclaration(&s, show_fullpaths,
708 show_module))
709 s.PutCString(": ");
710 }
711 auto &strm = result.GetOutputStream();
712 if (llvm::Error error = valobj_sp->Dump(strm, options))
713 result.AppendError(toString(std::move(error)));
714 }
715 }
716 } else {
717 if (llvm::Error err = regex.GetError())
718 result.AppendError(llvm::toString(std::move(err)));
719 else
721 "unknown regex error when compiling '%s'", entry.c_str());
722 }
723 } else // No regex, either exact variable names or variable
724 // expressions.
725 {
727 uint32_t expr_path_options =
732 lldb::VariableSP var_sp;
733 valobj_sp = frame->GetValueForVariableExpressionPath(
734 entry.ref(), m_varobj_options.use_dynamic, expr_path_options,
735 var_sp, error);
736 // Check only the `error` argument, because doing
737 // `valobj_sp->GetError()` will update the value and potentially
738 // return a new error that happens during the update, even if
739 // `GetValueForVariableExpressionPath` reported no errors.
740 if (valobj_sp && error.Success()) {
741 result.GetValueObjectList().Append(valobj_sp);
742
743 std::string scope_string;
744 if (m_option_variable.show_scope)
745 scope_string = GetScopeString(var_sp).str();
746
747 if (!scope_string.empty())
748 s.PutCString(scope_string);
749 if (m_option_variable.show_decl && var_sp &&
750 var_sp->GetDeclaration().GetFile()) {
751 var_sp->GetDeclaration().DumpStopContext(&s, false);
752 s.PutCString(": ");
753 }
754
755 options.SetFormat(format);
756 options.SetVariableFormatDisplayLanguage(
757 valobj_sp->GetPreferredDisplayLanguage());
758
759 Stream &output_stream = result.GetOutputStream();
760 options.SetRootValueObjectName(
761 valobj_sp->GetParent() ? entry.c_str() : nullptr);
762
763 // If there is an error while updating the value, it will be
764 // printed here as the contents of the value, e.g.
765 // `(int) *((int*)0) = <parent is NULL>`
766 if (llvm::Error error = valobj_sp->Dump(output_stream, options))
767 result.AppendError(toString(std::move(error)));
768 } else {
769 // Variable lookup failed. Check recognized args as a fallback.
770 bool found_recognized = false;
771 if (recognized_arg_list)
772 for (auto &obj_sp : recognized_arg_list->GetObjects())
773 if (obj_sp->GetName() == entry.ref()) {
774 found_recognized = true;
775 print_value(obj_sp);
776 break;
777 }
778 if (!found_recognized) {
779 if (error.Fail())
780 result.SetError(error.takeError());
781 else
783 "unable to find any variable expression path that "
784 "matches '%s'",
785 entry.c_str());
786 }
787 }
788 }
789 }
790 } else // No command arg specified. Use variable_list, instead.
791 {
792 const size_t num_variables = variable_list->GetSize();
793 if (num_variables > 0) {
794 for (size_t i = 0; i < num_variables; i++) {
795 VariableSP var_sp = variable_list->GetVariableAtIndex(i);
796 if (!ScopeRequested(var_sp->GetScope()))
797 continue;
798 std::string scope_string;
799 if (m_option_variable.show_scope)
800 scope_string = GetScopeString(var_sp).str();
801
802 // Use the variable object code to make sure we are using the same
803 // APIs as the public API will be using...
804 valobj_sp = frame->GetValueObjectForFrameVariable(
805 var_sp, m_varobj_options.use_dynamic);
806 if (valobj_sp) {
807 result.GetValueObjectList().Append(valobj_sp);
808
809 // When dumping all variables, don't print any variables that are
810 // not in scope to avoid extra unneeded output
811 if (valobj_sp->IsInScope()) {
812 if (!valobj_sp->GetTargetSP()
813 ->GetDisplayRuntimeSupportValues() &&
814 valobj_sp->IsRuntimeSupportValue())
815 continue;
816
817 if (!scope_string.empty())
818 s.PutCString(scope_string);
819
820 if (m_option_variable.show_decl &&
821 var_sp->GetDeclaration().GetFile()) {
822 var_sp->GetDeclaration().DumpStopContext(&s, false);
823 s.PutCString(": ");
824 }
825
826 options.SetFormat(format);
827 options.SetVariableFormatDisplayLanguage(
828 valobj_sp->GetPreferredDisplayLanguage());
829 options.SetRootValueObjectName(
830 var_sp ? var_sp->GetName().AsCString(nullptr) : nullptr);
831 if (llvm::Error error =
832 valobj_sp->Dump(result.GetOutputStream(), options))
833 result.AppendError(toString(std::move(error)));
834 }
835 }
836 }
837 }
838 }
839 if (result.GetStatus() != eReturnStatusFailed)
841 }
842
843 if (recognized_arg_list && (command.empty() || !variable_list))
844 for (auto &rec_value_sp : recognized_arg_list->GetObjects())
845 print_value(rec_value_sp);
846
847 m_interpreter.PrintWarningsIfNecessary(result.GetOutputStream(),
850 // Increment statistics.
851 TargetStats &target_stats = GetTarget()->GetStatistics();
852 if (result.Succeeded())
853 target_stats.GetFrameVariableStats().NotifySuccess();
854 else
855 target_stats.GetFrameVariableStats().NotifyFailure();
856 }
857
862};
863
864#pragma mark CommandObjectFrameRecognizer
865
866#define LLDB_OPTIONS_frame_recognizer_add
867#include "CommandOptions.inc"
868
870private:
871 class CommandOptions : public Options {
872 public:
873 CommandOptions() = default;
874 ~CommandOptions() override = default;
875
876 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
877 ExecutionContext *execution_context) override {
879 const int short_option = m_getopt_table[option_idx].val;
880
881 switch (short_option) {
882 case 'f': {
883 bool value, success;
884 value = OptionArgParser::ToBoolean(option_arg, true, &success);
885 if (success) {
887 } else {
889 "invalid boolean value '%s' passed for -f option",
890 option_arg.str().c_str());
891 }
892 } break;
893 case 'l':
894 m_class_name = std::string(option_arg);
895 break;
896 case 's':
897 m_module = std::string(option_arg);
898 break;
899 case 'n':
900 m_symbols.push_back(std::string(option_arg));
901 break;
902 case 'x':
903 m_regex = true;
904 break;
905 default:
906 llvm_unreachable("Unimplemented option");
907 }
908
909 return error;
910 }
911
912 void OptionParsingStarting(ExecutionContext *execution_context) override {
913 m_module = "";
914 m_symbols.clear();
915 m_class_name = "";
916 m_regex = false;
918 }
919
920 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
921 return llvm::ArrayRef(g_frame_recognizer_add_options);
922 }
923
924 // Instance variables to hold the values for command options.
925 std::string m_class_name;
926 std::string m_module;
927 std::vector<std::string> m_symbols;
930 };
931
933
934 Options *GetOptions() override { return &m_options; }
935
936protected:
937 void DoExecute(Args &command, CommandReturnObject &result) override;
938
939public:
941 : CommandObjectParsed(interpreter, "frame recognizer add",
942 "Add a new frame recognizer.", nullptr,
943 eCommandAllowsDummyTarget) {
944 SetHelpLong(R"(
945Frame recognizers allow for retrieving information about special frames based on
946ABI, arguments or other special properties of that frame, even without source
947code or debug info. Currently, one use case is to extract function arguments
948that would otherwise be unaccesible, or augment existing arguments.
949
950Adding a custom frame recognizer is possible by implementing a Python class
951and using the 'frame recognizer add' command. The Python class should have a
952'get_recognized_arguments' method and it will receive an argument of type
953lldb.SBFrame representing the current frame that we are trying to recognize.
954The method should return a (possibly empty) list of lldb.SBValue objects that
955represent the recognized arguments.
956
957An example of a recognizer that retrieves the file descriptor values from libc
958functions 'read', 'write' and 'close' follows:
959
960 class LibcFdRecognizer(object):
961 def get_recognized_arguments(self, frame):
962 if frame.name in ["read", "write", "close"]:
963 fd = frame.EvaluateExpression("$arg1").unsigned
964 target = frame.thread.process.target
965 value = target.CreateValueFromExpression("fd", "(int)%d" % fd)
966 return [value]
967 return []
968
969The file containing this implementation can be imported via 'command script
970import' and then we can register this recognizer with 'frame recognizer add'.
971It's important to restrict the recognizer to the libc library (which is
972libsystem_kernel.dylib on macOS) to avoid matching functions with the same name
973in other modules:
974
975(lldb) command script import .../fd_recognizer.py
976(lldb) frame recognizer add -l fd_recognizer.LibcFdRecognizer -n read -s libsystem_kernel.dylib
977
978When the program is stopped at the beginning of the 'read' function in libc, we
979can view the recognizer arguments in 'frame variable':
980
981(lldb) b read
982(lldb) r
983Process 1234 stopped
984* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.3
985 frame #0: 0x00007fff06013ca0 libsystem_kernel.dylib`read
986(lldb) frame variable
987(int) fd = 3
988
989 )");
990 }
991 ~CommandObjectFrameRecognizerAdd() override = default;
992};
993
995 CommandReturnObject &result) {
996#if LLDB_ENABLE_PYTHON
997 if (m_options.m_class_name.empty()) {
998 result.AppendErrorWithFormat("%s needs a Python class name (-l argument)",
999 m_cmd_name.c_str());
1000 return;
1001 }
1002
1003 if (m_options.m_module.empty()) {
1004 result.AppendErrorWithFormat("%s needs a module name (-s argument)",
1005 m_cmd_name.c_str());
1006 return;
1007 }
1008
1009 if (m_options.m_symbols.empty()) {
1010 result.AppendErrorWithFormat(
1011 "%s needs at least one symbol name (-n argument)", m_cmd_name.c_str());
1012 return;
1013 }
1014
1015 if (m_options.m_regex && m_options.m_symbols.size() > 1) {
1016 result.AppendErrorWithFormat(
1017 "%s needs only one symbol regular expression (-n argument)",
1018 m_cmd_name.c_str());
1019 return;
1020 }
1021
1023
1024 if (interpreter &&
1025 !interpreter->CheckObjectExists(m_options.m_class_name.c_str())) {
1026 result.AppendWarning("the provided class does not exist - please define it "
1027 "before attempting to use this frame recognizer");
1028 }
1029
1030 StackFrameRecognizerSP recognizer_sp =
1032 interpreter, m_options.m_class_name.c_str()));
1033 if (m_options.m_regex) {
1034 auto module = std::make_shared<RegularExpression>(m_options.m_module);
1035 auto func =
1036 std::make_shared<RegularExpression>(m_options.m_symbols.front());
1038 recognizer_sp, module, func, Mangled::NamePreference::ePreferDemangled,
1039 m_options.m_first_instruction_only);
1040 } else {
1041 auto module = ConstString(m_options.m_module);
1042 std::vector<ConstString> symbols(m_options.m_symbols.begin(),
1043 m_options.m_symbols.end());
1045 recognizer_sp, module, symbols,
1047 m_options.m_first_instruction_only);
1048 }
1049#endif
1050
1052}
1053
1055public:
1057 : CommandObjectParsed(interpreter, "frame recognizer clear",
1058 "Delete all frame recognizers.", nullptr,
1059 eCommandAllowsDummyTarget) {}
1060
1062
1063protected:
1068};
1069
1070static void
1071PrintRecognizerDetails(Stream &strm, const std::string &name, bool enabled,
1072 const std::string &module,
1073 llvm::ArrayRef<lldb_private::ConstString> symbols,
1074 Mangled::NamePreference symbol_mangling, bool regexp) {
1075 if (!enabled)
1076 strm << "[disabled] ";
1077
1078 strm << name << ", ";
1079
1080 if (!module.empty())
1081 strm << "module " << module << ", ";
1082
1083 switch (symbol_mangling) {
1084 case Mangled::NamePreference ::ePreferMangled:
1085 strm << "mangled symbol ";
1086 break;
1087 case Mangled::NamePreference ::ePreferDemangled:
1088 strm << "demangled symbol ";
1089 break;
1090 case Mangled::NamePreference ::ePreferDemangledWithoutArguments:
1091 strm << "demangled (no args) symbol ";
1092 break;
1093 }
1094
1095 if (regexp)
1096 strm << "regex ";
1097
1098 llvm::interleaveComma(symbols, strm);
1099}
1100
1101// Base class for commands which accept a single frame recognizer as an argument
1103public:
1105 const char *name,
1106 const char *help = nullptr,
1107 const char *syntax = nullptr,
1108 uint32_t flags = 0)
1109 : CommandObjectParsed(interpreter, name, help, syntax, flags) {
1111 }
1112
1113 void
1115 OptionElementVector &opt_element_vector) override {
1116 if (request.GetCursorIndex() != 0)
1117 return;
1118
1120 [&request](uint32_t rid, bool enabled, std::string rname,
1121 std::string module,
1122 llvm::ArrayRef<lldb_private::ConstString> symbols,
1123 Mangled::NamePreference symbol_mangling, bool regexp) {
1124 StreamString strm;
1125 if (rname.empty())
1126 rname = "(internal)";
1127
1128 PrintRecognizerDetails(strm, rname, enabled, module, symbols,
1129 symbol_mangling, regexp);
1130
1131 request.TryCompleteCurrentArg(std::to_string(rid), strm.GetString());
1132 });
1133 }
1134
1136 uint32_t recognizer_id) = 0;
1137
1138 void DoExecute(Args &command, CommandReturnObject &result) override {
1139 uint32_t recognizer_id;
1140 if (!llvm::to_integer(command.GetArgumentAtIndex(0), recognizer_id)) {
1141 result.AppendErrorWithFormat("'%s' is not a valid recognizer id",
1142 command.GetArgumentAtIndex(0));
1143 return;
1144 }
1145
1146 DoExecuteWithId(result, recognizer_id);
1147 }
1148};
1149
1152public:
1155 interpreter, "frame recognizer enable",
1156 "Enable a frame recognizer by id.", nullptr,
1157 eCommandAllowsDummyTarget) {
1159 }
1160
1162
1163protected:
1165 uint32_t recognizer_id) override {
1166 auto &recognizer_mgr = GetTarget()->GetFrameRecognizerManager();
1167 if (!recognizer_mgr.SetEnabledForID(recognizer_id, true)) {
1168 result.AppendErrorWithFormat("'%u' is not a valid recognizer id",
1169 recognizer_id);
1170 return;
1171 }
1173 }
1174};
1175
1178public:
1181 interpreter, "frame recognizer disable",
1182 "Disable a frame recognizer by id.", nullptr,
1183 eCommandAllowsDummyTarget) {
1185 }
1186
1188
1189protected:
1191 uint32_t recognizer_id) override {
1192 auto &recognizer_mgr = GetTarget()->GetFrameRecognizerManager();
1193 if (!recognizer_mgr.SetEnabledForID(recognizer_id, false)) {
1194 result.AppendErrorWithFormat("'%u' is not a valid recognizer id",
1195 recognizer_id);
1196 return;
1197 }
1199 }
1200};
1201
1204public:
1207 interpreter, "frame recognizer delete",
1208 "Delete an existing frame recognizer by id.", nullptr,
1209 eCommandAllowsDummyTarget) {
1211 }
1212
1214
1215protected:
1217 uint32_t recognizer_id) override {
1218 auto &recognizer_mgr = GetTarget()->GetFrameRecognizerManager();
1219 if (!recognizer_mgr.RemoveRecognizerWithID(recognizer_id)) {
1220 result.AppendErrorWithFormat("'%u' is not a valid recognizer id",
1221 recognizer_id);
1222 return;
1223 }
1225 }
1226};
1227
1229public:
1231 : CommandObjectParsed(interpreter, "frame recognizer list",
1232 "Show a list of active frame recognizers.", nullptr,
1233 eCommandAllowsDummyTarget) {}
1234
1236
1237protected:
1238 void DoExecute(Args &command, CommandReturnObject &result) override {
1239 bool any_printed = false;
1241 [&result,
1242 &any_printed](uint32_t recognizer_id, bool enabled, std::string name,
1243 std::string module, llvm::ArrayRef<ConstString> symbols,
1244 Mangled::NamePreference symbol_mangling, bool regexp) {
1245 Stream &stream = result.GetOutputStream();
1246
1247 if (name.empty())
1248 name = "(internal)";
1249
1250 stream << std::to_string(recognizer_id) << ": ";
1251 PrintRecognizerDetails(stream, name, enabled, module, symbols,
1252 symbol_mangling, regexp);
1253
1254 stream.EOL();
1255 stream.Flush();
1256
1257 any_printed = true;
1258 });
1259
1260 if (any_printed)
1262 else {
1263 result.GetOutputStream().PutCString("no matching results found.\n");
1265 }
1266 }
1267};
1268
1270public:
1273 interpreter, "frame recognizer info",
1274 "Show which frame recognizer is applied a stack frame (if any).",
1275 nullptr, eCommandAllowsDummyTarget) {
1277 }
1278
1280
1281protected:
1282 void DoExecute(Args &command, CommandReturnObject &result) override {
1283 const char *frame_index_str = command.GetArgumentAtIndex(0);
1284 uint32_t frame_index;
1285 if (!llvm::to_integer(frame_index_str, frame_index)) {
1286 result.AppendErrorWithFormat("'%s' is not a valid frame index",
1287 frame_index_str);
1288 return;
1289 }
1290
1291 Process *process = m_exe_ctx.GetProcessPtr();
1292 if (process == nullptr) {
1293 result.AppendError("no process");
1294 return;
1295 }
1296 Thread *thread = m_exe_ctx.GetThreadPtr();
1297 if (thread == nullptr) {
1298 result.AppendError("no thread");
1299 return;
1300 }
1301 if (command.GetArgumentCount() != 1) {
1302 result.AppendErrorWithFormat(
1303 "'%s' takes exactly one frame index argument", m_cmd_name.c_str());
1304 return;
1305 }
1306
1307 StackFrameSP frame_sp = thread->GetStackFrameAtIndex(frame_index);
1308 if (!frame_sp) {
1309 result.AppendErrorWithFormat("no frame with index %u", frame_index);
1310 return;
1311 }
1312
1313 auto recognizer =
1315 frame_sp);
1316
1317 Stream &output_stream = result.GetOutputStream();
1318 output_stream.Printf("frame %d ", frame_index);
1319 if (recognizer) {
1320 output_stream << "is recognized by ";
1321 output_stream << recognizer->GetName();
1322 } else {
1323 output_stream << "not recognized by any recognizer";
1324 }
1325 output_stream.EOL();
1327 }
1328};
1329
1331public:
1334 interpreter, "frame recognizer",
1335 "Commands for editing and viewing frame recognizers.",
1336 "frame recognizer [<sub-command-options>] ") {
1338 interpreter)));
1340 interpreter)));
1342 interpreter)));
1344 "enable",
1347 "disable",
1350 "delete",
1353 "clear",
1355 }
1356
1357 ~CommandObjectFrameRecognizer() override = default;
1358};
1359
1360#pragma mark CommandObjectMultiwordFrame
1361
1362// CommandObjectMultiwordFrame
1363
1365 CommandInterpreter &interpreter)
1366 : CommandObjectMultiword(interpreter, "frame",
1367 "Commands for selecting and "
1368 "examining the current "
1369 "thread's stack frames.",
1370 "frame <subcommand> [<subcommand-options>]") {
1371 LoadSubCommand("diagnose",
1373 LoadSubCommand("info",
1374 CommandObjectSP(new CommandObjectFrameInfo(interpreter)));
1375 LoadSubCommand("select",
1376 CommandObjectSP(new CommandObjectFrameSelect(interpreter)));
1377 LoadSubCommand("variable",
1379#if LLDB_ENABLE_PYTHON
1381 interpreter)));
1382#endif
1383}
1384
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
std::optional< std::string > GetRepeatCommand(Args &current_command_args, uint32_t index) override
Get the command that appropriate for a "repeat" of the current command.
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
void AppendArgument(llvm::StringRef arg_str, char quote_char='\0')
Appends a new argument to the end of the list argument list.
Definition Args.cpp:332
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
void InsertArgumentAtIndex(size_t idx, llvm::StringRef arg_str, char quote_char='\0')
Insert the argument value at index idx to arg_str.
Definition Args.cpp:336
bool empty() const
Definition Args.h:122
bool GetQuotedCommandString(std::string &command) const
Definition Args.cpp:232
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
Target * GetTarget()
Get the target this command should operate on.
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:515
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:359
bool IsValid() const
Test if this object contains a valid regular expression.
bool Execute(llvm::StringRef string, llvm::SmallVectorImpl< llvm::StringRef > *matches=nullptr) const
Execute a regular expression match using the compiled regular expression that is already in this obje...
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:57
@ eExpressionPathOptionsAllowDirectIVarAccess
Definition StackFrame.h:56
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:134
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:155
Function * function
The Function for a given query.
A class that represents statistics for a since lldb_private::Target.
Definition Statistics.h:309
StatsSuccessFail & GetFrameVariableStats()
Definition Statistics.h:324
TargetStats & GetStatistics()
Definition Target.h:2181
StackFrameRecognizerManager & GetFrameRecognizerManager()
Definition Target.h:1995
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
@ eValueTypeVTableEntry
function pointer in virtual function table
@ eValueTypeSyntheticFlag
A flag that indicates if the value type is synthetic or not.
@ 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
std::shared_ptr< lldb_private::StackFrameRecognizer > StackFrameRecognizerSP
std::shared_ptr< lldb_private::StopInfo > StopInfoSP
static bool ToBoolean(llvm::StringRef s, bool fail_value, bool *success_ptr)