13 #include "lldb/Host/Config.h"
39 #pragma mark CommandObjectFrameDiagnose
45 #define LLDB_OPTIONS_frame_diag
46 #include "CommandOptions.inc"
59 const int short_option = m_getopt_table[option_idx].val;
60 switch (short_option) {
67 if (option_arg.getAsInteger(0, *address)) {
69 error.SetErrorStringWithFormat(
"invalid address argument '%s'",
70 option_arg.str().c_str());
76 if (option_arg.getAsInteger(0, *offset)) {
78 error.SetErrorStringWithFormat(
"invalid offset argument '%s'",
79 option_arg.str().c_str());
84 llvm_unreachable(
"Unimplemented option");
97 return llvm::makeArrayRef(g_frame_diag_options);
102 llvm::Optional<ConstString>
reg;
108 "Try to determine what path the current stop "
109 "location used to get to a register or address",
111 eCommandRequiresThread | eCommandTryTargetAPILock |
112 eCommandProcessMustBeLaunched |
113 eCommandProcessMustBePaused) {
123 arg.push_back(index_arg);
126 m_arguments.push_back(arg);
135 Thread *thread = m_exe_ctx.GetThreadPtr();
138 ValueObjectSP valobj_sp;
140 if (m_options.address) {
141 if (m_options.reg || m_options.offset) {
143 "`frame diagnose --address` is incompatible with other arguments.");
146 valobj_sp = frame_sp->GuessValueForAddress(m_options.address.getValue());
147 }
else if (m_options.reg) {
148 valobj_sp = frame_sp->GuessValueForRegisterAndOffset(
149 m_options.reg.getValue(), m_options.offset.value_or(0));
153 result.
AppendError(
"No arguments provided, and no stop info.");
157 valobj_sp = StopInfo::GetCrashingDereference(stop_info_sp);
170 GetExpressionPathFormat::eGetExpressionPathFormatHonorPointers;
171 valobj_sp->GetExpressionPath(stream, format);
172 stream.PutCString(
" =");
188 #pragma mark CommandObjectFrameInfo
196 "List information about the current "
197 "stack frame in the current thread.",
199 eCommandRequiresFrame | eCommandTryTargetAPILock |
200 eCommandProcessMustBeLaunched |
201 eCommandProcessMustBePaused) {}
207 m_exe_ctx.GetFrameRef().DumpUsingSettingsFormat(&result.
GetOutputStream());
213 #pragma mark CommandObjectFrameSelect
217 #define LLDB_OPTIONS_frame_select
218 #include "CommandOptions.inc"
231 const int short_option = m_getopt_table[option_idx].val;
232 switch (short_option) {
235 if (option_arg.getAsInteger(0, offset) || offset == INT32_MIN) {
236 error.SetErrorStringWithFormat(
"invalid frame offset argument '%s'",
237 option_arg.str().c_str());
239 relative_frame_offset = offset;
244 llvm_unreachable(
"Unimplemented option");
251 relative_frame_offset.reset();
255 return llvm::makeArrayRef(g_frame_select_options);
263 "Select the current stack frame by "
264 "index from within the current thread "
265 "(see 'thread backtrace'.)",
267 eCommandRequiresThread | eCommandTryTargetAPILock |
268 eCommandProcessMustBeLaunched |
269 eCommandProcessMustBePaused) {
279 arg.push_back(index_arg);
282 m_arguments.push_back(arg);
293 CommandCompletions::InvokeCommonCompletionCallbacks(
294 GetCommandInterpreter(), CommandCompletions::eFrameIndexCompletion,
304 Thread *thread = m_exe_ctx.GetThreadPtr();
307 if (m_options.relative_frame_offset) {
313 if (*m_options.relative_frame_offset < 0) {
314 if (
static_cast<int32_t
>(frame_idx) >=
315 -*m_options.relative_frame_offset)
316 frame_idx += *m_options.relative_frame_offset;
318 if (frame_idx == 0) {
321 result.
AppendError(
"Already at the bottom of the stack.");
326 }
else if (*m_options.relative_frame_offset > 0) {
332 if (
static_cast<int32_t
>(num_frames - frame_idx) >
333 *m_options.relative_frame_offset)
334 frame_idx += *m_options.relative_frame_offset;
336 if (frame_idx == num_frames - 1) {
339 result.
AppendError(
"Already at the top of the stack.");
342 frame_idx = num_frames - 1;
348 "too many arguments; expected frame-index, saw '%s'.\n",
350 m_options.GenerateOptionUsage(
352 GetCommandInterpreter().GetDebugger().GetTerminalWidth());
357 if (command[0].ref().getAsInteger(0, frame_idx)) {
386 #pragma mark CommandObjectFrameVariable
392 interpreter,
"frame variable",
393 "Show variables for the current stack frame. Defaults to all "
394 "arguments and local variables in scope. Names of argument, "
395 "local, file static and file global variables can be specified.",
397 eCommandRequiresFrame | eCommandTryTargetAPILock |
398 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused |
399 eCommandRequiresProcess),
404 Children of aggregate variables can be specified such as 'var->child.x'. In
405 'frame variable', the operators -> and [] do not invoke operator overloads if
406 they exist, but directly access the specified element. If you want to trigger
407 operator overloads use the expression command to print the variable instead.
409 It is worth noting that except for overloaded operators, when printing local
410 variables 'expr local_var' and 'frame var local_var' produce the same results.
411 However, 'frame variable' is more efficient, since it uses debug information and
412 memory reads directly, rather than parsing and evaluating an expression, which
413 may even involve JITing and running code in the target program.)");
424 arg.push_back(var_name_arg);
427 m_arguments.push_back(arg);
430 m_option_group.Append(&m_option_format,
431 OptionGroupFormat::OPTION_GROUP_FORMAT |
432 OptionGroupFormat::OPTION_GROUP_GDB_FMT,
435 m_option_group.Finalize();
446 CommandCompletions::InvokeCommonCompletionCallbacks(
447 GetCommandInterpreter(), CommandCompletions::eVariablePathCompletion,
454 return llvm::StringRef();
456 switch (var_sp->GetScope()) {
471 return llvm::StringRef();
489 ValueObjectSP valobj_sp;
491 TypeSummaryImplSP summary_format_sp;
492 if (!m_option_variable.summary.IsCurrentValueEmpty())
493 DataVisualization::NamedSummaryFormats::GetSummaryFormat(
494 ConstString(m_option_variable.summary.GetCurrentValue()),
496 else if (!m_option_variable.summary_string.IsCurrentValueEmpty())
497 summary_format_sp = std::make_shared<StringSummaryFormat>(
499 m_option_variable.summary_string.GetCurrentValue());
508 m_option_variable.show_globals =
true;
511 const Format format = m_option_format.GetFormat();
514 if (!command.
empty()) {
519 for (
auto &entry : command) {
520 if (m_option_variable.use_regex) {
521 const size_t regex_start_index = regex_var_list.
GetSize();
522 llvm::StringRef name_str = entry.ref();
525 size_t num_matches = 0;
526 const size_t num_new_regex_vars =
529 if (num_new_regex_vars > 0) {
530 for (
size_t regex_idx = regex_start_index,
531 end_index = regex_var_list.
GetSize();
532 regex_idx < end_index; ++regex_idx) {
536 var_sp, m_varobj_options.use_dynamic);
539 if (m_option_variable.show_scope)
540 scope_string = GetScopeString(var_sp).str();
542 if (!scope_string.empty())
545 if (m_option_variable.show_decl &&
546 var_sp->GetDeclaration().GetFile()) {
547 bool show_fullpaths =
false;
548 bool show_module =
true;
549 if (var_sp->DumpDeclaration(&s, show_fullpaths,
557 }
else if (num_matches == 0) {
559 "no variables matched the regular expression '%s'.",
567 "unknown regex error when compiling '%s'", entry.c_str());
574 StackFrame::eExpressionPathOptionCheckPtrVsMember |
575 StackFrame::eExpressionPathOptionsAllowDirectIVarAccess |
576 StackFrame::eExpressionPathOptionsInspectAnonymousUnions;
577 lldb::VariableSP var_sp;
579 entry.ref(), m_varobj_options.use_dynamic, expr_path_options,
583 if (m_option_variable.show_scope)
584 scope_string = GetScopeString(var_sp).str();
586 if (!scope_string.empty())
588 if (m_option_variable.show_decl && var_sp &&
589 var_sp->GetDeclaration().GetFile()) {
590 var_sp->GetDeclaration().DumpStopContext(&s,
false);
596 valobj_sp->GetPreferredDisplayLanguage());
600 valobj_sp->GetParent() ? entry.c_str() :
nullptr);
601 valobj_sp->Dump(output_stream, options);
603 if (
auto error_cstr =
error.AsCString(
nullptr))
607 "unable to find any variable expression path that matches "
615 const size_t num_variables = variable_list->
GetSize();
616 if (num_variables > 0) {
617 for (
size_t i = 0; i < num_variables; i++) {
619 switch (var_sp->GetScope()) {
621 if (!m_option_variable.show_globals)
625 if (!m_option_variable.show_globals)
629 if (!m_option_variable.show_args)
633 if (!m_option_variable.show_locals)
641 if (m_option_variable.show_scope)
642 scope_string = GetScopeString(var_sp).str();
647 var_sp, m_varobj_options.use_dynamic);
651 if (valobj_sp->IsInScope()) {
652 if (!valobj_sp->GetTargetSP()
653 ->GetDisplayRuntimeSupportValues() &&
654 valobj_sp->IsRuntimeSupportValue())
657 if (!scope_string.empty())
660 if (m_option_variable.show_decl &&
661 var_sp->GetDeclaration().GetFile()) {
662 var_sp->GetDeclaration().DumpStopContext(&s,
false);
668 valobj_sp->GetPreferredDisplayLanguage());
670 var_sp ? var_sp->GetName().AsCString() :
nullptr);
681 if (m_option_variable.show_recognized_args) {
683 if (recognized_frame) {
684 ValueObjectListSP recognized_arg_list =
685 recognized_frame->GetRecognizedArguments();
686 if (recognized_arg_list) {
687 for (
auto &rec_value_sp : recognized_arg_list->GetObjects()) {
688 options.
SetFormat(m_option_format.GetFormat());
690 rec_value_sp->GetPreferredDisplayLanguage());
703 TargetStats &target_stats = GetSelectedOrDummyTarget().GetStatistics();
717 #pragma mark CommandObjectFrameRecognizer
719 #define LLDB_OPTIONS_frame_recognizer_add
720 #include "CommandOptions.inc"
732 const int short_option = m_getopt_table[option_idx].val;
734 switch (short_option) {
737 value = OptionArgParser::ToBoolean(option_arg,
true, &success);
739 m_first_instruction_only = value;
741 error.SetErrorStringWithFormat(
742 "invalid boolean value '%s' passed for -f option",
743 option_arg.str().c_str());
759 llvm_unreachable(
"Unimplemented option");
770 m_first_instruction_only =
true;
774 return llvm::makeArrayRef(g_frame_recognizer_add_options);
795 "Add a new frame recognizer.", nullptr) {
797 Frame recognizers allow for retrieving information about special frames based on
798 ABI, arguments or other special properties of that frame, even without source
799 code or debug info. Currently, one use case is to extract function arguments
800 that would otherwise be unaccesible, or augment existing arguments.
802 Adding a custom frame recognizer is possible by implementing a Python class
803 and using the 'frame recognizer add' command. The Python class should have a
804 'get_recognized_arguments' method and it will receive an argument of type
805 lldb.SBFrame representing the current frame that we are trying to recognize.
806 The method should return a (possibly empty) list of lldb.SBValue objects that
807 represent the recognized arguments.
809 An example of a recognizer that retrieves the file descriptor values from libc
810 functions 'read', 'write' and 'close' follows:
812 class LibcFdRecognizer(object):
813 def get_recognized_arguments(self, frame):
814 if frame.name in ["read", "write", "close"]:
815 fd = frame.EvaluateExpression("$arg1").unsigned
816 value = lldb.target.CreateValueFromExpression("fd", "(int)%d" % fd)
820 The file containing this implementation can be imported via 'command script
821 import' and then we can register this recognizer with 'frame recognizer add'.
822 It's important to restrict the recognizer to the libc library (which is
823 libsystem_kernel.dylib on macOS) to avoid matching functions with the same name
826 (lldb) command script import .../fd_recognizer.py
827 (lldb) frame recognizer add -l fd_recognizer.LibcFdRecognizer -n read -s libsystem_kernel.dylib
829 When the program is stopped at the beginning of the 'read' function in libc, we
830 can view the recognizer arguments in 'frame variable':
835 * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.3
836 frame #0: 0x00007fff06013ca0 libsystem_kernel.dylib`read
837 (lldb) frame variable
847 #if LLDB_ENABLE_PYTHON
848 if (m_options.m_class_name.empty()) {
850 "%s needs a Python class name (-l argument).\n", m_cmd_name.c_str());
854 if (m_options.m_module.empty()) {
860 if (m_options.m_symbols.empty()) {
862 "%s needs at least one symbol name (-n argument).\n",
867 if (m_options.m_regex && m_options.m_symbols.size() > 1) {
869 "%s needs only one symbol regular expression (-n argument).\n",
878 result.
AppendWarning(
"The provided class does not exist - please define it "
879 "before attempting to use this frame recognizer");
882 StackFrameRecognizerSP recognizer_sp =
884 interpreter, m_options.m_class_name.c_str()));
885 if (m_options.m_regex) {
890 GetSelectedOrDummyTarget().GetFrameRecognizerManager().AddRecognizer(
891 recognizer_sp, module, func, m_options.m_first_instruction_only);
894 std::vector<ConstString> symbols(m_options.m_symbols.begin(),
895 m_options.m_symbols.end());
896 GetSelectedOrDummyTarget().GetFrameRecognizerManager().AddRecognizer(
897 recognizer_sp, module, symbols, m_options.m_first_instruction_only);
909 "Delete all frame recognizers.", nullptr) {}
915 GetSelectedOrDummyTarget()
916 .GetFrameRecognizerManager()
917 .RemoveAllRecognizers();
927 "Delete an existing frame recognizer by id.",
930 m_arguments.push_back({thread_arg});
941 GetSelectedOrDummyTarget().GetFrameRecognizerManager().ForEach(
943 llvm::ArrayRef<lldb_private::ConstString> symbols,
947 rname =
"(internal)";
951 strm <<
", module " << module;
952 if (!symbols.empty())
953 for (
auto &symbol : symbols)
954 strm <<
", symbol " << symbol;
965 if (!m_interpreter.Confirm(
966 "About to delete all frame recognizers, do you want to do that?",
972 GetSelectedOrDummyTarget()
973 .GetFrameRecognizerManager()
974 .RemoveAllRecognizers();
992 if (!GetSelectedOrDummyTarget()
993 .GetFrameRecognizerManager()
994 .RemoveRecognizerWithID(recognizer_id)) {
1008 "Show a list of active frame recognizers.",
1015 bool any_printed =
false;
1016 GetSelectedOrDummyTarget().GetFrameRecognizerManager().ForEach(
1017 [&result, &any_printed](
1019 llvm::ArrayRef<ConstString> symbols,
bool regexp) {
1023 name =
"(internal)";
1025 stream << std::to_string(recognizer_id) <<
": " << name;
1026 if (!module.empty())
1027 stream <<
", module " << module;
1028 if (!symbols.empty())
1029 for (
auto &symbol : symbols)
1030 stream <<
", symbol " << symbol;
1032 stream <<
" (regexp)";
1054 interpreter,
"frame recognizer info",
1055 "Show which frame recognizer is applied a stack frame (if any).",
1066 arg.push_back(index_arg);
1069 m_arguments.push_back(arg);
1078 if (!llvm::to_integer(frame_index_str, frame_index)) {
1084 Process *process = m_exe_ctx.GetProcessPtr();
1085 if (process ==
nullptr) {
1089 Thread *thread = m_exe_ctx.GetThreadPtr();
1090 if (thread ==
nullptr) {
1096 "'%s' takes exactly one frame index argument.\n", m_cmd_name.c_str());
1106 auto recognizer = GetSelectedOrDummyTarget()
1107 .GetFrameRecognizerManager()
1108 .GetRecognizerForFrame(frame_sp);
1111 output_stream.
Printf(
"frame %d ", frame_index);
1113 output_stream <<
"is recognized by ";
1114 output_stream << recognizer->GetName();
1116 output_stream <<
"not recognized by any recognizer";
1118 output_stream.
EOL();
1128 interpreter,
"frame recognizer",
1129 "Commands for editing and viewing frame recognizers.",
1130 "frame recognizer [<sub-command-options>] ") {
1148 #pragma mark CommandObjectMultiwordFrame
1152 CommandObjectMultiwordFrame::CommandObjectMultiwordFrame(
1155 "Commands for selecting and "
1156 "examing the current "
1157 "thread's stack frames.",
1158 "frame <subcommand> [<subcommand-options>]") {
1167 #if LLDB_ENABLE_PYTHON