LLDB mainline
FormatEntity.cpp
Go to the documentation of this file.
1//===-- FormatEntity.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//===----------------------------------------------------------------------===//
8
10
11#include "lldb/Core/Address.h"
13#include "lldb/Core/Debugger.h"
15#include "lldb/Core/Module.h"
22#include "lldb/Symbol/Block.h"
27#include "lldb/Symbol/Symbol.h"
34#include "lldb/Target/Process.h"
39#include "lldb/Target/Target.h"
40#include "lldb/Target/Thread.h"
46#include "lldb/Utility/Log.h"
48#include "lldb/Utility/Status.h"
49#include "lldb/Utility/Stream.h"
55#include "lldb/lldb-defines.h"
56#include "lldb/lldb-forward.h"
57#include "llvm/ADT/STLExtras.h"
58#include "llvm/ADT/StringRef.h"
59#include "llvm/Support/Compiler.h"
60#include "llvm/Support/Regex.h"
61#include "llvm/TargetParser/Triple.h"
62
63#include <cassert>
64#include <cctype>
65#include <cinttypes>
66#include <cstdio>
67#include <cstdlib>
68#include <cstring>
69#include <memory>
70#include <type_traits>
71#include <utility>
72
73namespace lldb_private {
75}
76namespace lldb_private {
77struct RegisterInfo;
78}
79
80using namespace lldb;
81using namespace lldb_private;
82
86
88
90 Definition("*", EntryType::ParentString)};
91
93 Definition("load", EntryType::AddressLoad),
94 Definition("file", EntryType::AddressFile)};
95
97 Definition("basename", EntryType::ParentNumber, FileKind::Basename),
98 Definition("dirname", EntryType::ParentNumber, FileKind::Dirname),
99 Definition("fullpath", EntryType::ParentNumber, FileKind::Fullpath)};
100
102 Definition("index", EntryType::FrameIndex),
103 Definition("pc", EntryType::FrameRegisterPC),
104 Definition("fp", EntryType::FrameRegisterFP),
105 Definition("sp", EntryType::FrameRegisterSP),
106 Definition("flags", EntryType::FrameRegisterTypeFlags),
107 Definition("no-debug", EntryType::FrameNoDebug),
108 Entry::DefinitionWithChildren("reg", EntryType::FrameRegisterByName,
110 Definition("is-artificial", EntryType::FrameIsArtificial),
111 Definition("kind", EntryType::FrameKind),
112 Definition("borrowed-info", EntryType::FrameBorrowedInfo),
113};
114
116 Definition("id", EntryType::FunctionID),
117 Definition("name", EntryType::FunctionName),
118 Definition("name-without-args", EntryType::FunctionNameNoArgs),
119 Definition("name-with-args", EntryType::FunctionNameWithArgs),
120 Definition("mangled-name", EntryType::FunctionMangledName),
121 Definition("addr-offset", EntryType::FunctionAddrOffset),
122 Definition("concrete-only-addr-offset-no-padding",
123 EntryType::FunctionAddrOffsetConcrete),
124 Definition("line-offset", EntryType::FunctionLineOffset),
125 Definition("pc-offset", EntryType::FunctionPCOffset),
126 Definition("initial-function", EntryType::FunctionInitial),
127 Definition("changed", EntryType::FunctionChanged),
128 Definition("is-optimized", EntryType::FunctionIsOptimized),
129 Definition("is-inlined", EntryType::FunctionIsInlined),
130 Definition("prefix", EntryType::FunctionPrefix),
131 Definition("scope", EntryType::FunctionScope),
132 Definition("basename", EntryType::FunctionBasename),
133 Definition("name-qualifiers", EntryType::FunctionNameQualifiers),
134 Definition("template-arguments", EntryType::FunctionTemplateArguments),
135 Definition("formatted-arguments", EntryType::FunctionFormattedArguments),
136 Definition("return-left", EntryType::FunctionReturnLeft),
137 Definition("return-right", EntryType::FunctionReturnRight),
138 Definition("qualifiers", EntryType::FunctionQualifiers),
139 Definition("suffix", EntryType::FunctionSuffix),
140};
141
143 Entry::DefinitionWithChildren("file", EntryType::LineEntryFile,
145 Definition("number", EntryType::LineEntryLineNumber),
146 Definition("column", EntryType::LineEntryColumn),
147 Definition("start-addr", EntryType::LineEntryStartAddress),
148 Definition("end-addr", EntryType::LineEntryEndAddress),
149};
150
152 "file", EntryType::ModuleFile, g_file_child_entries)};
153
155 Definition("id", EntryType::ProcessID),
156 Definition("name", EntryType::ProcessFile, FileKind::Basename),
157 Entry::DefinitionWithChildren("file", EntryType::ProcessFile,
159
161 Definition("*", EntryType::ParentString)};
162
164 Definition("*", EntryType::ParentString)};
165
167 Definition("id", EntryType::ThreadID),
168 Definition("protocol_id", EntryType::ThreadProtocolID),
169 Definition("index", EntryType::ThreadIndexID),
170 Entry::DefinitionWithChildren("info", EntryType::ThreadInfo,
172 Definition("queue", EntryType::ThreadQueue),
173 Definition("name", EntryType::ThreadName),
174 Definition("stop-reason", EntryType::ThreadStopReason),
175 Definition("stop-reason-raw", EntryType::ThreadStopReasonRaw),
176 Definition("return-value", EntryType::ThreadReturnValue),
177 Definition("completed-expression", EntryType::ThreadCompletedExpression)};
178
180 Definition("arch", EntryType::TargetArch),
181 Entry::DefinitionWithChildren("file", EntryType::TargetFile,
183
185 Definition("count", EntryType::ProgressCount),
186 Definition("message", EntryType::ProgressMessage)};
187
188#define _TO_STR2(_val) #_val
189#define _TO_STR(_val) _TO_STR2(_val)
190
206
222
243
245 Definition("frame", EntryType::ScriptFrame),
246 Definition("process", EntryType::ScriptProcess),
247 Definition("target", EntryType::ScriptTarget),
248 Definition("thread", EntryType::ScriptThread),
249 Definition("var", EntryType::ScriptVariable),
250 Definition("svar", EntryType::ScriptVariableSynthetic),
251 Definition("thread", EntryType::ScriptThread)};
252
254 Entry::DefinitionWithChildren("addr", EntryType::AddressLoadOrFile,
256 Definition("addr-file-or-load", EntryType::AddressLoadOrFile),
257 Entry::DefinitionWithChildren("ansi", EntryType::Invalid, g_ansi_entries),
258 Definition("current-pc-arrow", EntryType::CurrentPCArrow),
259 Entry::DefinitionWithChildren("file", EntryType::File,
261 Definition("language", EntryType::Lang),
262 Entry::DefinitionWithChildren("frame", EntryType::Invalid,
264 Entry::DefinitionWithChildren("function", EntryType::Invalid,
266 Entry::DefinitionWithChildren("line", EntryType::Invalid,
268 Entry::DefinitionWithChildren("module", EntryType::Invalid,
270 Entry::DefinitionWithChildren("process", EntryType::Invalid,
272 Entry::DefinitionWithChildren("script", EntryType::Invalid,
274 Entry::DefinitionWithChildren("svar", EntryType::VariableSynthetic,
276 Entry::DefinitionWithChildren("thread", EntryType::Invalid,
278 Entry::DefinitionWithChildren("target", EntryType::Invalid,
280 Entry::DefinitionWithChildren("var", EntryType::Variable,
281 g_var_child_entries, true),
282 Entry::DefinitionWithChildren("progress", EntryType::Invalid,
284 Definition("separator", EntryType::Separator),
285};
286
288 "<root>", EntryType::Root, g_top_level_entries);
289
290FormatEntity::Entry::Entry(Type t, const char *s, const char *f)
291 : string(s ? s : ""), printf_format(f ? f : ""), children_stack({{}}),
292 type(t) {}
293
295 : string(s.data(), s.size()), children_stack({{}}), type(Type::String) {}
296
298 : string(1, ch), printf_format(), children_stack({{}}), type(Type::String) {
299}
300
301std::vector<Entry> &FormatEntity::Entry::GetChildren() {
302 assert(level < children_stack.size());
303 return children_stack[level];
304}
305
307 auto &entries = GetChildren();
308 if (entries.empty() || entries.back().type != Entry::Type::String)
309 entries.push_back(Entry(ch));
310 else
311 entries.back().string.append(1, ch);
312}
313
314void FormatEntity::Entry::AppendText(const llvm::StringRef &s) {
315 auto &entries = GetChildren();
316 if (entries.empty() || entries.back().type != Entry::Type::String)
317 entries.push_back(Entry(s));
318 else
319 entries.back().string.append(s.data(), s.size());
320}
321
322void FormatEntity::Entry::AppendText(const char *cstr) {
323 return AppendText(llvm::StringRef(cstr));
324}
325
327 auto &entries = GetChildren();
328 entries.push_back(entry);
329}
330
332 assert(type == Entry::Type::Scope);
333 children_stack.emplace_back();
334 level++;
335}
336
337#define ENUM_TO_CSTR(eee) \
338 case FormatEntity::Entry::Type::eee: \
339 return #eee
340
342 switch (t) {
422 }
423 return "???";
424}
425
426#undef ENUM_TO_CSTR
427
428void FormatEntity::Entry::Dump(Stream &s, int depth) const {
429 s.Printf("%*.*s%-20s: ", depth * 2, depth * 2, "", TypeToCString(type));
430 if (fmt != eFormatDefault)
431 s.Printf("lldb-format = %s, ", FormatManager::GetFormatAsCString(fmt));
432 if (!string.empty())
433 s.Printf("string = \"%s\"", string.c_str());
434 if (!printf_format.empty())
435 s.Printf("printf_format = \"%s\"", printf_format.c_str());
436 if (number != 0)
437 s.Printf("number = %" PRIu64 " (0x%" PRIx64 "), ", number, number);
438 if (deref)
439 s.PutCString("deref = true, ");
440 s.EOL();
441 for (const auto &children : children_stack) {
442 for (const auto &child : children)
443 child.Dump(s, depth + 1);
444 }
445}
446
447template <typename T>
449 const ExecutionContext *exe_ctx, T t,
450 const char *script_function_name) {
451 Target *target = Target::GetTargetFromContexts(exe_ctx, sc);
452
453 if (target) {
454 ScriptInterpreter *script_interpreter =
456 if (script_interpreter) {
458 std::string script_output;
459
460 if (script_interpreter->RunScriptFormatKeyword(script_function_name, t,
461 script_output, error) &&
462 error.Success()) {
463 s.PutCString(script_output.c_str());
464 return true;
465 } else {
466 s.Printf("<error: %s>", error.AsCString());
467 }
468 }
469 }
470 return false;
471}
472
474 const ExecutionContext *exe_ctx,
475 const Address &addr,
476 bool print_file_addr_or_load_addr) {
477 Target *target = Target::GetTargetFromContexts(exe_ctx, sc);
478
479 addr_t vaddr = addr.GetLoadAddress(target);
480 if (vaddr == LLDB_INVALID_ADDRESS)
481 vaddr = addr.GetFileAddress();
482 if (vaddr == LLDB_INVALID_ADDRESS)
483 return false;
484
485 int addr_width = 0;
486 if (target)
487 addr_width = target->GetArchitecture().GetAddressByteSize() * 2;
488 if (addr_width == 0)
489 addr_width = 16;
490
491 if (print_file_addr_or_load_addr) {
492 ExecutionContextScope *exe_scope =
493 exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr;
494 addr.Dump(&s, exe_scope, Address::DumpStyleLoadAddress,
496 } else {
497 s.Printf("0x%*.*" PRIx64, addr_width, addr_width, vaddr);
498 }
499
500 return true;
501}
502
504 const ExecutionContext *exe_ctx,
505 const Address &format_addr,
506 bool concrete_only, bool no_padding,
507 bool print_zero_offsets) {
508 if (format_addr.IsValid()) {
509 Address func_addr;
510
511 if (sc) {
512 if (sc->function) {
513 func_addr = sc->function->GetAddress();
514 if (sc->block && !concrete_only) {
515 // Check to make sure we aren't in an inline function. If we are, use
516 // the inline block range that contains "format_addr" since blocks
517 // can be discontiguous.
518 Block *inline_block = sc->block->GetContainingInlinedBlock();
519 AddressRange inline_range;
520 if (inline_block && inline_block->GetRangeContainingAddress(
521 format_addr, inline_range))
522 func_addr = inline_range.GetBaseAddress();
523 }
524 } else if (sc->symbol && sc->symbol->ValueIsAddress())
525 func_addr = sc->symbol->GetAddressRef();
526 }
527
528 if (func_addr.IsValid()) {
529 const char *addr_offset_padding = no_padding ? "" : " ";
530
531 if (func_addr.GetModule() == format_addr.GetModule()) {
532 addr_t func_file_addr = func_addr.GetFileAddress();
533 addr_t addr_file_addr = format_addr.GetFileAddress();
534 if (addr_file_addr > func_file_addr ||
535 (addr_file_addr == func_file_addr && print_zero_offsets)) {
536 s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding,
537 addr_file_addr - func_file_addr);
538 } else if (addr_file_addr < func_file_addr) {
539 s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding,
540 func_file_addr - addr_file_addr);
541 }
542 return true;
543 } else {
544 Target *target = Target::GetTargetFromContexts(exe_ctx, sc);
545 if (target) {
546 addr_t func_load_addr = func_addr.GetLoadAddress(target);
547 addr_t addr_load_addr = format_addr.GetLoadAddress(target);
548 if (addr_load_addr > func_load_addr ||
549 (addr_load_addr == func_load_addr && print_zero_offsets)) {
550 s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding,
551 addr_load_addr - func_load_addr);
552 } else if (addr_load_addr < func_load_addr) {
553 s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding,
554 func_load_addr - addr_load_addr);
555 }
556 return true;
557 }
558 }
559 }
560 }
561 return false;
562}
563
564static bool ScanBracketedRange(llvm::StringRef subpath,
565 size_t &close_bracket_index,
566 const char *&var_name_final_if_array_range,
567 int64_t &index_lower, int64_t &index_higher) {
569 close_bracket_index = llvm::StringRef::npos;
570 const size_t open_bracket_index = subpath.find('[');
571 if (open_bracket_index == llvm::StringRef::npos) {
572 LLDB_LOGF(log,
573 "[ScanBracketedRange] no bracketed range, skipping entirely");
574 return false;
575 }
576
577 close_bracket_index = subpath.find(']', open_bracket_index + 1);
578
579 if (close_bracket_index == llvm::StringRef::npos) {
580 LLDB_LOGF(log,
581 "[ScanBracketedRange] no bracketed range, skipping entirely");
582 return false;
583 } else {
584 var_name_final_if_array_range = subpath.data() + open_bracket_index;
585
586 if (close_bracket_index - open_bracket_index == 1) {
587 LLDB_LOGF(
588 log,
589 "[ScanBracketedRange] '[]' detected.. going from 0 to end of data");
590 index_lower = 0;
591 } else {
592 const size_t separator_index = subpath.find('-', open_bracket_index + 1);
593
594 if (separator_index == llvm::StringRef::npos) {
595 const char *index_lower_cstr = subpath.data() + open_bracket_index + 1;
596 index_lower = ::strtoul(index_lower_cstr, nullptr, 0);
597 index_higher = index_lower;
598 LLDB_LOGF(log,
599 "[ScanBracketedRange] [%" PRId64
600 "] detected, high index is same",
601 index_lower);
602 } else {
603 const char *index_lower_cstr = subpath.data() + open_bracket_index + 1;
604 const char *index_higher_cstr = subpath.data() + separator_index + 1;
605 index_lower = ::strtoul(index_lower_cstr, nullptr, 0);
606 index_higher = ::strtoul(index_higher_cstr, nullptr, 0);
607 LLDB_LOGF(log,
608 "[ScanBracketedRange] [%" PRId64 "-%" PRId64 "] detected",
609 index_lower, index_higher);
610 }
611 if (index_lower > index_higher && index_higher > 0) {
612 LLDB_LOGF(log, "[ScanBracketedRange] swapping indices");
613 const int64_t temp = index_lower;
614 index_lower = index_higher;
615 index_higher = temp;
616 }
617 }
618 }
619 return true;
620}
621
622static bool DumpFile(Stream &s, const FileSpec &file, FileKind file_kind) {
623 switch (file_kind) {
625 break;
626
628 if (!file.GetFilename().empty()) {
629 s << file.GetFilename();
630 return true;
631 }
632 break;
633
635 if (!file.GetDirectory().empty()) {
636 s << file.GetDirectory();
637 return true;
638 }
639 break;
640
642 if (file) {
643 s << file;
644 return true;
645 }
646 break;
647 }
648 return false;
649}
650
651static bool DumpRegister(Stream &s, StackFrame *frame, RegisterKind reg_kind,
652 uint32_t reg_num, Format format) {
653 if (frame) {
654 RegisterContext *reg_ctx = frame->GetRegisterContext().get();
655
656 if (reg_ctx) {
657 const uint32_t lldb_reg_num =
658 reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num);
659 if (lldb_reg_num != LLDB_INVALID_REGNUM) {
660 const RegisterInfo *reg_info =
661 reg_ctx->GetRegisterInfoAtIndex(lldb_reg_num);
662 if (reg_info) {
663 RegisterValue reg_value;
664 if (reg_ctx->ReadRegister(reg_info, reg_value)) {
665 DumpRegisterValue(reg_value, s, *reg_info, false, false, format);
666 return true;
667 }
668 }
669 }
670 }
671 }
672 return false;
673}
674
676 bool deref_pointer) {
678 std::string name_to_deref = llvm::formatv("[{0}]", index);
679 LLDB_LOG(log, "[ExpandIndexedExpression] name to deref: {0}", name_to_deref);
687 name_to_deref, &reason_to_stop, &final_value_type, options, &what_next);
688 if (!item) {
689 LLDB_LOGF(log,
690 "[ExpandIndexedExpression] ERROR: why stopping = %d,"
691 " final_value_type %d",
692 reason_to_stop, final_value_type);
693 } else {
694 LLDB_LOGF(log,
695 "[ExpandIndexedExpression] ALL RIGHT: why stopping = %d,"
696 " final_value_type %d",
697 reason_to_stop, final_value_type);
698 }
699 return item;
700}
701
724
725/// Options supported by format_provider<T> for integral arithmetic types.
726/// See table in FormatProviders.h.
727static llvm::Regex LLVMFormatPattern{"x[-+]?\\d*|n|d", llvm::Regex::IgnoreCase};
728
729static bool DumpValueWithLLVMFormat(Stream &s, llvm::StringRef options,
730 ValueObject &valobj) {
731 std::string formatted;
732 std::string llvm_format = ("{0:" + options + "}").str();
733
734 auto type_info = valobj.GetTypeInfo();
735 if ((type_info & eTypeIsInteger) && LLVMFormatPattern.match(options)) {
736 if (type_info & eTypeIsSigned) {
737 bool success = false;
738 int64_t integer = valobj.GetValueAsSigned(0, &success);
739 if (success)
740 formatted = llvm::formatv(llvm_format.data(), integer);
741 } else {
742 bool success = false;
743 uint64_t integer = valobj.GetValueAsUnsigned(0, &success);
744 if (success)
745 formatted = llvm::formatv(llvm_format.data(), integer);
746 }
747 }
748
749 if (formatted.empty())
750 return false;
751
752 s.Write(formatted.data(), formatted.size());
753 return true;
754}
755
757 const FormatEntity::Entry &entry,
758 ValueObject *valobj) {
759 if (valobj == nullptr)
760 return false;
761
763 enum Format custom_format = eFormatInvalid;
765 entry.string.empty()
768
769 bool do_deref_pointer = entry.deref;
770 bool is_script = false;
771 switch (entry.type) {
773 is_script = true;
774 break;
775
777 custom_format = entry.fmt;
779 break;
780
782 is_script = true;
783 [[fallthrough]];
785 custom_format = entry.fmt;
787 if (!valobj->IsSynthetic()) {
788 valobj = valobj->GetSyntheticValue().get();
789 if (valobj == nullptr)
790 return false;
791 }
792 break;
793
794 default:
795 return false;
796 }
797
807 SyntheticChildrenTraversal::Both);
808 ValueObject *target = nullptr;
809 const char *var_name_final_if_array_range = nullptr;
810 size_t close_bracket_index = llvm::StringRef::npos;
811 int64_t index_lower = -1;
812 int64_t index_higher = -1;
813 bool is_array_range = false;
814 bool was_plain_var = false;
815 bool was_var_format = false;
816 bool was_var_indexed = false;
821
822 if (is_script) {
823 return RunScriptFormatKeyword(s, m_sc, m_exe_ctx, valobj,
824 entry.string.c_str());
825 }
826
827 auto split = llvm::StringRef(entry.string).split(':');
828 auto subpath = split.first;
829 auto llvm_format = split.second;
830
831 // simplest case ${var}, just print valobj's value
832 if (subpath.empty()) {
833 if (entry.printf_format.empty() && entry.fmt == eFormatDefault &&
835 was_plain_var = true;
836 else
837 was_var_format = true;
838 target = valobj;
839 } else // this is ${var.something} or multiple .something nested
840 {
841 if (subpath[0] == '[')
842 was_var_indexed = true;
843 ScanBracketedRange(subpath, close_bracket_index,
844 var_name_final_if_array_range, index_lower,
845 index_higher);
846
848
849 LLDB_LOG(log, "[Debugger::FormatPrompt] symbol to expand: {0}", subpath);
850
851 target =
852 valobj
853 ->GetValueForExpressionPath(subpath, &reason_to_stop,
854 &final_value_type, options, &what_next)
855 .get();
856
857 if (!target) {
858 LLDB_LOGF(log,
859 "[Debugger::FormatPrompt] ERROR: why stopping = %d,"
860 " final_value_type %d",
861 reason_to_stop, final_value_type);
862 return false;
863 } else {
864 LLDB_LOGF(log,
865 "[Debugger::FormatPrompt] ALL RIGHT: why stopping = %d,"
866 " final_value_type %d",
867 reason_to_stop, final_value_type);
868 target = target
870 target->GetDynamicValueType(), true)
871 .get();
872 }
873 }
874
875 is_array_range =
876 (final_value_type ==
878 final_value_type ==
880
881 do_deref_pointer =
883
884 if (do_deref_pointer && !is_array_range) {
885 // I have not deref-ed yet, let's do it
886 // this happens when we are not going through
887 // GetValueForVariableExpressionPath to get to the target ValueObject
889 target = target->Dereference(error).get();
890 if (error.Fail()) {
891 LLDB_LOGF(log, "[Debugger::FormatPrompt] ERROR: %s\n",
892 error.AsCString("unknown"));
893 return false;
894 }
895 do_deref_pointer = false;
896 }
897
898 if (!target) {
899 LLDB_LOGF(log, "[Debugger::FormatPrompt] could not calculate target for "
900 "prompt expression");
901 return false;
902 }
903
904 // we do not want to use the summary for a bitfield of type T:n if we were
905 // originally dealing with just a T - that would get us into an endless
906 // recursion
907 if (target->IsBitfield() && was_var_indexed) {
908 // TODO: check for a (T:n)-specific summary - we should still obey that
909 StreamString bitfield_name;
910 bitfield_name.Format("{0}:{1}", target->GetTypeName(),
911 target->GetBitfieldBitSize());
912 auto type_sp = std::make_shared<TypeNameSpecifierImpl>(
913 bitfield_name.GetString(), lldb::eFormatterMatchExact);
914 if (val_obj_display ==
918 }
919
920 // TODO use flags for these
921 const uint32_t type_info_flags =
922 target->GetCompilerType().GetTypeInfo(nullptr);
923 bool is_array = (type_info_flags & eTypeIsArray) != 0;
924 bool is_pointer = (type_info_flags & eTypeIsPointer) != 0;
925 bool is_aggregate = target->GetCompilerType().IsAggregateType();
926
927 if ((is_array || is_pointer) && (!is_array_range) &&
928 val_obj_display ==
930 // wrong, but there
931 // are some
932 // exceptions
933 {
934 StreamString str_temp;
935 LLDB_LOGF(log,
936 "[Debugger::FormatPrompt] I am into array || pointer && !range");
937
938 if (target->HasSpecialPrintableRepresentation(val_obj_display,
939 custom_format)) {
940 // try to use the special cases
941 bool success = target->DumpPrintableRepresentation(
942 str_temp, val_obj_display, custom_format);
943 LLDB_LOGF(log, "[Debugger::FormatPrompt] special cases did%s match",
944 success ? "" : "n't");
945
946 // should not happen
947 if (success)
948 s << str_temp.GetString();
949 return true;
950 } else {
951 if (was_plain_var) // if ${var}
952 {
953 s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
954 } else if (is_pointer) // if pointer, value is the address stored
955 {
957 s, val_obj_display, custom_format,
959 }
960 return true;
961 }
962 }
963
964 // if directly trying to print ${var}, and this is an aggregate, display a
965 // nice type @ location message
966 if (is_aggregate && was_plain_var) {
967 s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
968 return true;
969 }
970
971 // if directly trying to print ${var%V}, and this is an aggregate, do not let
972 // the user do it
973 if (is_aggregate &&
974 ((was_var_format &&
975 val_obj_display ==
977 s << "<invalid use of aggregate type>";
978 return true;
979 }
980
981 if (!is_array_range) {
982 if (!llvm_format.empty()) {
983 if (DumpValueWithLLVMFormat(s, llvm_format, *target)) {
984 LLDB_LOGF(log, "dumping using llvm format");
985 return true;
986 } else {
987 LLDB_LOG(
988 log,
989 "empty output using llvm format '{0}' - with type info flags {1}",
990 entry.printf_format, target->GetTypeInfo());
991 }
992 }
993 LLDB_LOGF(log, "dumping ordinary printable output");
994 return target->DumpPrintableRepresentation(s, val_obj_display,
995 custom_format);
996 } else {
997 LLDB_LOGF(log,
998 "[Debugger::FormatPrompt] checking if I can handle as array");
999 if (!is_array && !is_pointer)
1000 return false;
1001 LLDB_LOGF(log, "[Debugger::FormatPrompt] handle as array");
1002 StreamString special_directions_stream;
1003 llvm::StringRef special_directions;
1004 if (close_bracket_index != llvm::StringRef::npos &&
1005 subpath.size() > close_bracket_index) {
1006 llvm::StringRef additional_data(
1007 subpath.drop_front(close_bracket_index + 1));
1008 special_directions_stream
1009 << "${"
1010 << llvm::formatv("{0}var{1}", do_deref_pointer ? "*" : "",
1011 additional_data);
1012
1013 if (entry.fmt != eFormatDefault) {
1014 const char format_char =
1016 if (format_char != '\0')
1017 special_directions_stream.Printf("%%%c", format_char);
1018 else {
1019 const char *format_cstr =
1021 special_directions_stream.Printf("%%%s", format_cstr);
1022 }
1023 } else if (entry.number != 0) {
1024 const char style_char = ConvertValueObjectStyleToChar(
1026 if (style_char)
1027 special_directions_stream.Printf("%%%c", style_char);
1028 }
1029 special_directions_stream.PutChar('}');
1030 special_directions =
1031 llvm::StringRef(special_directions_stream.GetString());
1032 }
1033
1034 // let us display items index_lower thru index_higher of this array
1035 s.PutChar('[');
1036
1037 if (index_higher < 0)
1038 index_higher = valobj->GetNumChildrenIgnoringErrors() - 1;
1039
1040 uint32_t max_num_children =
1041 target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay();
1042
1043 bool success = true;
1044 for (int64_t index = index_lower; index <= index_higher; ++index) {
1045 ValueObject *item = ExpandIndexedExpression(target, index, false).get();
1046
1047 if (!item) {
1048 LLDB_LOGF(log,
1049 "[Debugger::FormatPrompt] ERROR in getting child item at "
1050 "index %" PRId64,
1051 index);
1052 } else {
1053 LLDB_LOGF(
1054 log,
1055 "[Debugger::FormatPrompt] special_directions for child item: %s",
1056 special_directions.data() ? special_directions.data() : "");
1057 }
1058
1059 if (special_directions.empty()) {
1060 success &= item->DumpPrintableRepresentation(s, val_obj_display,
1061 custom_format);
1062 } else {
1063 success &= FormatStringRef(special_directions, s, item);
1064 }
1065
1066 if (--max_num_children == 0) {
1067 s.PutCString(", ...");
1068 break;
1069 }
1070
1071 if (index < index_higher)
1072 s.PutChar(',');
1073 }
1074 s.PutChar(']');
1075 return success;
1076 }
1077}
1078
1079static bool DumpRegister(Stream &s, StackFrame *frame, const char *reg_name,
1080 Format format) {
1081 if (frame) {
1082 RegisterContext *reg_ctx = frame->GetRegisterContext().get();
1083
1084 if (reg_ctx) {
1085 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
1086 if (reg_info) {
1087 RegisterValue reg_value;
1088 if (reg_ctx->ReadRegister(reg_info, reg_value)) {
1089 DumpRegisterValue(reg_value, s, *reg_info, false, false, format);
1090 return true;
1091 }
1092 }
1093 }
1094 }
1095 return false;
1096}
1097
1099 const FormatEntity::Entry &entry,
1100 const StructuredData::ObjectSP &thread_info_dictionary,
1101 const SymbolContext *sc, const ExecutionContext *exe_ctx, Stream &s) {
1102 llvm::StringRef path(entry.string);
1103
1105 thread_info_dictionary->GetObjectForDotSeparatedPath(path);
1106
1107 if (value) {
1108 if (value->GetType() == eStructuredDataTypeInteger) {
1109 const char *token_format = "0x%4.4" PRIx64;
1110 if (!entry.printf_format.empty())
1111 token_format = entry.printf_format.c_str();
1112 s.Printf(token_format, value->GetUnsignedIntegerValue());
1113 return true;
1114 } else if (value->GetType() == eStructuredDataTypeFloat) {
1115 s.Printf("%f", value->GetAsFloat()->GetValue());
1116 return true;
1117 } else if (value->GetType() == eStructuredDataTypeString) {
1118 s.Format("{0}", value->GetAsString()->GetValue());
1119 return true;
1120 } else if (value->GetType() == eStructuredDataTypeArray) {
1121 if (value->GetAsArray()->GetSize() > 0) {
1122 s.Printf("%zu", value->GetAsArray()->GetSize());
1123 return true;
1124 }
1125 } else if (value->GetType() == eStructuredDataTypeDictionary) {
1126 s.Printf("%zu",
1127 value->GetAsDictionary()->GetKeys()->GetAsArray()->GetSize());
1128 return true;
1129 }
1130 }
1131
1132 return false;
1133}
1134
1135static inline bool IsToken(const char *var_name_begin, const char *var) {
1136 return (::strncmp(var_name_begin, var, strlen(var)) == 0);
1137}
1138
1139/// Parses the basename out of a demangled function name
1140/// that may include function arguments. Supports
1141/// template functions.
1142///
1143/// Returns pointers to the opening and closing parenthesis of
1144/// `full_name`. Can return nullptr for either parenthesis if
1145/// none is exists.
1146static std::pair<char const *, char const *>
1147ParseBaseName(char const *full_name) {
1148 const char *open_paren = strchr(full_name, '(');
1149 const char *close_paren = nullptr;
1150 const char *generic = strchr(full_name, '<');
1151 // if before the arguments list begins there is a template sign
1152 // then scan to the end of the generic args before you try to find
1153 // the arguments list
1154 if (generic && open_paren && generic < open_paren) {
1155 int generic_depth = 1;
1156 ++generic;
1157 for (; *generic && generic_depth > 0; generic++) {
1158 if (*generic == '<')
1159 generic_depth++;
1160 if (*generic == '>')
1161 generic_depth--;
1162 }
1163 if (*generic)
1164 open_paren = strchr(generic, '(');
1165 else
1166 open_paren = nullptr;
1167 }
1168
1169 if (open_paren) {
1170 if (IsToken(open_paren, "(anonymous namespace)")) {
1171 open_paren = strchr(open_paren + strlen("(anonymous namespace)"), '(');
1172 if (open_paren)
1173 close_paren = strchr(open_paren, ')');
1174 } else
1175 close_paren = strchr(open_paren, ')');
1176 }
1177
1178 return {open_paren, close_paren};
1179}
1180
1181/// Writes out the function name in 'full_name' to 'out_stream'
1182/// but replaces each argument type with the variable name
1183/// and the corresponding pretty-printed value
1185 char const *full_name,
1186 ExecutionContextScope *exe_scope,
1187 VariableList const &args) {
1188 auto [open_paren, close_paren] = ParseBaseName(full_name);
1189 if (open_paren)
1190 out_stream.Write(full_name, open_paren - full_name + 1);
1191 else {
1192 out_stream.PutCString(full_name);
1193 out_stream.PutChar('(');
1194 }
1195
1196 FormatEntity::PrettyPrintFunctionArguments(out_stream, args, exe_scope);
1197
1198 if (close_paren)
1199 out_stream.PutCString(close_paren);
1200 else
1201 out_stream.PutChar(')');
1202}
1203
1205 assert(sc.function);
1206
1207 if (sc.block)
1208 if (Block *inline_block = sc.block->GetContainingInlinedBlock())
1209 return inline_block->GetBlockVariableList(true);
1210
1211 return sc.function->GetBlock(true).GetBlockVariableList(true);
1212}
1213
1215 const ExecutionContext *exe_ctx,
1216 const SymbolContext &sc) {
1217 assert(sc.function);
1218
1219 ExecutionContextScope *exe_scope =
1220 exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr;
1221
1222 const char *cstr = sc.GetPossiblyInlinedFunctionName()
1224 .AsCString(nullptr);
1225 if (!cstr)
1226 return false;
1227
1228 VariableList args;
1229 if (auto variable_list_sp = GetFunctionVariableList(sc))
1231 args);
1232
1233 if (args.GetSize() > 0) {
1234 PrettyPrintFunctionNameWithArgs(s, cstr, exe_scope, args);
1235 } else {
1236 s.PutCString(cstr);
1237 }
1238
1239 return true;
1240}
1241
1243 const ExecutionContext *exe_ctx,
1244 const SymbolContext &sc) {
1245 Language *language_plugin = nullptr;
1246 bool language_plugin_handled = false;
1247 StreamString ss;
1248 if (sc.function)
1249 language_plugin = Language::FindPlugin(sc.function->GetLanguage());
1250 else if (sc.symbol)
1251 language_plugin = Language::FindPlugin(sc.symbol->GetLanguage());
1252
1253 if (language_plugin)
1254 language_plugin_handled = language_plugin->GetFunctionDisplayName(
1256
1257 if (language_plugin_handled) {
1258 s << ss.GetString();
1259 return true;
1260 }
1261
1262 if (sc.function)
1263 return PrintFunctionNameWithArgs(s, exe_ctx, sc);
1264
1265 if (!sc.symbol)
1266 return false;
1267
1268 const char *cstr = sc.symbol->GetName().AsCString(nullptr);
1269 if (!cstr)
1270 return false;
1271
1272 s.PutCString(cstr);
1273
1274 return true;
1275}
1276
1278 assert(m_sc);
1279
1280 Language *language_plugin = nullptr;
1281 if (m_sc->function)
1282 language_plugin = Language::FindPlugin(m_sc->function->GetLanguage());
1283 else if (m_sc->symbol)
1284 language_plugin = Language::FindPlugin(m_sc->symbol->GetLanguage());
1285
1286 if (!language_plugin)
1287 return false;
1288
1289 FormatEntity::Entry format = language_plugin->GetFunctionNameFormat();
1290
1291 // Bail on invalid or empty format.
1292 if (!format || format == FormatEntity::Entry(Entry::Type::Root))
1293 return false;
1294
1295 StreamString name_stream;
1296 const bool success = Format(format, name_stream, /*valobj=*/nullptr);
1297 if (success)
1298 s << name_stream.GetString();
1299
1300 return success;
1301}
1302
1303bool FormatEntity::Formatter::FormatStringRef(const llvm::StringRef &format_str,
1304 Stream &s, ValueObject *valobj) {
1305 if (!format_str.empty()) {
1307 Status error = FormatEntity::Parse(format_str, root);
1308 if (error.Success()) {
1309 return Format(root, s, valobj);
1310 }
1311 }
1312 return false;
1313}
1314
1316 ValueObject *valobj) {
1317 if (IsInvalidRecursiveFormat(entry.type)) {
1319 "Error: detected recursive format entity: {0}",
1321 return false;
1322 }
1323
1324 auto entry_stack_guard = PushEntryType(entry.type);
1325
1326 switch (entry.type) {
1328 case Entry::Type::ParentNumber: // Only used for
1329 // FormatEntity::Entry::Definition encoding
1330 case Entry::Type::ParentString: // Only used for
1331 // FormatEntity::Entry::Definition encoding
1332 return false;
1335 Debugger &debugger = target->GetDebugger();
1336 if (debugger.GetUseColor()) {
1337 s.PutCString(entry.string);
1338 }
1339 }
1340 // Always return true, so colors being disabled is transparent.
1341 return true;
1342
1343 case Entry::Type::Root:
1344 for (const auto &child : entry.children_stack[0]) {
1345 if (!Format(child, s, valobj)) {
1346 return false; // If any item of root fails, then the formatting fails
1347 }
1348 }
1349 return true; // Only return true if all items succeeded
1350
1352 s.PutCString(entry.string);
1353 return true;
1354
1355 case Entry::Type::Scope: {
1356 StreamString scope_stream;
1357 auto format_children = [&](const std::vector<Entry> &children) {
1358 scope_stream.Clear();
1359 for (const auto &child : children) {
1360 if (!Format(child, scope_stream, valobj))
1361 return false;
1362 }
1363 return true;
1364 };
1365
1366 for (auto &children : entry.children_stack) {
1367 if (format_children(children)) {
1368 s.Write(scope_stream.GetString().data(),
1369 scope_stream.GetString().size());
1370 return true;
1371 }
1372 }
1373
1374 return true; // Scopes always successfully print themselves
1375 }
1376
1381 return DumpValue(s, entry, valobj);
1382
1386 return (
1387 m_addr != nullptr && m_addr->IsValid() &&
1390
1392 if (m_exe_ctx) {
1393 Process *process = m_exe_ctx->GetProcessPtr();
1394 if (process) {
1395 const char *format = "%" PRIu64;
1396 if (!entry.printf_format.empty())
1397 format = entry.printf_format.c_str();
1398 s.Printf(format, process->GetID());
1399 return true;
1400 }
1401 }
1402 return false;
1403
1405 if (m_exe_ctx) {
1406 Process *process = m_exe_ctx->GetProcessPtr();
1407 if (process) {
1408 Module *exe_module = process->GetTarget().GetExecutableModulePointer();
1409 if (exe_module) {
1410 if (DumpFile(s, exe_module->GetFileSpec(), (FileKind)entry.number))
1411 return true;
1412 }
1413 }
1414 }
1415 return false;
1416
1418 if (m_exe_ctx) {
1419 Process *process = m_exe_ctx->GetProcessPtr();
1420 if (process)
1421 return RunScriptFormatKeyword(s, m_sc, m_exe_ctx, process,
1422 entry.string.c_str());
1423 }
1424 return false;
1425
1427 if (m_exe_ctx) {
1428 Thread *thread = m_exe_ctx->GetThreadPtr();
1429 if (thread) {
1430 const char *format = "0x%4.4" PRIx64;
1431 if (!entry.printf_format.empty()) {
1432 // Watch for the special "tid" format...
1433 if (entry.printf_format == "tid") {
1434 // TODO(zturner): Rather than hardcoding this to be platform
1435 // specific, it should be controlled by a setting and the default
1436 // value of the setting can be different depending on the platform.
1437 Target &target = thread->GetProcess()->GetTarget();
1438 ArchSpec arch(target.GetArchitecture());
1439 llvm::Triple::OSType ostype = arch.IsValid()
1440 ? arch.GetTriple().getOS()
1441 : llvm::Triple::UnknownOS;
1442 if (ostype == llvm::Triple::FreeBSD ||
1443 ostype == llvm::Triple::Linux ||
1444 ostype == llvm::Triple::NetBSD ||
1445 ostype == llvm::Triple::OpenBSD) {
1446 format = "%" PRIu64;
1447 }
1448 } else {
1449 format = entry.printf_format.c_str();
1450 }
1451 }
1452 s.Printf(format, thread->GetID());
1453 return true;
1454 }
1455 }
1456 return false;
1457
1459 if (m_exe_ctx) {
1460 Thread *thread = m_exe_ctx->GetThreadPtr();
1461 if (thread) {
1462 const char *format = "0x%4.4" PRIx64;
1463 if (!entry.printf_format.empty())
1464 format = entry.printf_format.c_str();
1465 s.Printf(format, thread->GetProtocolID());
1466 return true;
1467 }
1468 }
1469 return false;
1470
1472 if (m_exe_ctx) {
1473 Thread *thread = m_exe_ctx->GetThreadPtr();
1474 if (thread) {
1475 const char *format = "%" PRIu32;
1476 if (!entry.printf_format.empty())
1477 format = entry.printf_format.c_str();
1478 s.Printf(format, thread->GetIndexID());
1479 return true;
1480 }
1481 }
1482 return false;
1483
1485 if (m_exe_ctx) {
1486 Thread *thread = m_exe_ctx->GetThreadPtr();
1487 if (thread) {
1488 const char *cstr = thread->GetName();
1489 if (cstr && cstr[0]) {
1490 s.PutCString(cstr);
1491 return true;
1492 }
1493 }
1494 }
1495 return false;
1496
1498 if (m_exe_ctx) {
1499 Thread *thread = m_exe_ctx->GetThreadPtr();
1500 if (thread) {
1501 const char *cstr = thread->GetQueueName();
1502 if (cstr && cstr[0]) {
1503 s.PutCString(cstr);
1504 return true;
1505 }
1506 }
1507 }
1508 return false;
1509
1511 if (m_exe_ctx) {
1512 if (Thread *thread = m_exe_ctx->GetThreadPtr()) {
1513 std::string stop_description = thread->GetStopDescription();
1514 if (!stop_description.empty()) {
1515 s.PutCString(stop_description);
1516 return true;
1517 }
1518 }
1519 }
1520 return false;
1521
1523 if (m_exe_ctx) {
1524 if (Thread *thread = m_exe_ctx->GetThreadPtr()) {
1525 std::string stop_description = thread->GetStopDescriptionRaw();
1526 if (!stop_description.empty()) {
1527 s.PutCString(stop_description);
1528 return true;
1529 }
1530 }
1531 }
1532 return false;
1533
1535 if (m_exe_ctx) {
1536 Thread *thread = m_exe_ctx->GetThreadPtr();
1537 if (thread) {
1538 StopInfoSP stop_info_sp = thread->GetStopInfo();
1539 if (stop_info_sp && stop_info_sp->IsValid()) {
1540 ValueObjectSP return_valobj_sp =
1541 StopInfo::GetReturnValueObject(stop_info_sp);
1542 if (return_valobj_sp) {
1543 if (llvm::Error error = return_valobj_sp->Dump(s)) {
1544 s << "error: " << toString(std::move(error));
1545 return false;
1546 }
1547 return true;
1548 }
1549 }
1550 }
1551 }
1552 return false;
1553
1555 if (m_exe_ctx) {
1556 Thread *thread = m_exe_ctx->GetThreadPtr();
1557 if (thread) {
1558 StopInfoSP stop_info_sp = thread->GetStopInfo();
1559 if (stop_info_sp && stop_info_sp->IsValid()) {
1560 ExpressionVariableSP expression_var_sp =
1561 StopInfo::GetExpressionVariable(stop_info_sp);
1562 if (expression_var_sp && expression_var_sp->GetValueObject()) {
1563 if (llvm::Error error =
1564 expression_var_sp->GetValueObject()->Dump(s)) {
1565 s << "error: " << toString(std::move(error));
1566 return false;
1567 }
1568 return true;
1569 }
1570 }
1571 }
1572 }
1573 return false;
1574
1576 if (m_exe_ctx) {
1577 Thread *thread = m_exe_ctx->GetThreadPtr();
1578 if (thread)
1579 return RunScriptFormatKeyword(s, m_sc, m_exe_ctx, thread,
1580 entry.string.c_str());
1581 }
1582 return false;
1583
1585 if (m_exe_ctx) {
1586 Thread *thread = m_exe_ctx->GetThreadPtr();
1587 if (thread) {
1588 StructuredData::ObjectSP object_sp = thread->GetExtendedInfo();
1589 if (object_sp &&
1590 object_sp->GetType() == eStructuredDataTypeDictionary) {
1591 if (FormatThreadExtendedInfoRecurse(entry, object_sp, m_sc, m_exe_ctx,
1592 s))
1593 return true;
1594 }
1595 }
1596 }
1597 return false;
1598
1600 if (m_exe_ctx) {
1601 Target *target = m_exe_ctx->GetTargetPtr();
1602 if (target) {
1603 const ArchSpec &arch = target->GetArchitecture();
1604 if (arch.IsValid()) {
1606 return true;
1607 }
1608 }
1609 }
1610 return false;
1611
1613 if (m_exe_ctx) {
1614 if (Target *target = m_exe_ctx->GetTargetPtr()) {
1615 if (Module *exe_module = target->GetExecutableModulePointer()) {
1616 if (DumpFile(s, exe_module->GetFileSpec(), (FileKind)entry.number))
1617 return true;
1618 }
1619 }
1620 }
1621 return false;
1622
1624 if (m_exe_ctx) {
1625 Target *target = m_exe_ctx->GetTargetPtr();
1626 if (target)
1627 return RunScriptFormatKeyword(s, m_sc, m_exe_ctx, target,
1628 entry.string.c_str());
1629 }
1630 return false;
1631
1633 if (m_sc) {
1634 Module *module = m_sc->module_sp.get();
1635 if (module) {
1636 if (DumpFile(s, module->GetFileSpec(), (FileKind)entry.number))
1637 return true;
1638 }
1639 }
1640 return false;
1641
1642 case Entry::Type::File:
1643 if (m_sc) {
1644 CompileUnit *cu = m_sc->comp_unit;
1645 if (cu) {
1646 if (DumpFile(s, cu->GetPrimaryFile(), (FileKind)entry.number))
1647 return true;
1648 }
1649 }
1650 return false;
1651
1652 case Entry::Type::Lang:
1653 if (m_sc) {
1654 CompileUnit *cu = m_sc->comp_unit;
1655 if (cu) {
1656 const char *lang_name =
1658 if (lang_name) {
1659 s.PutCString(lang_name);
1660 return true;
1661 }
1662 }
1663 }
1664 return false;
1665
1667 if (m_exe_ctx) {
1668 StackFrame *frame = m_exe_ctx->GetFramePtr();
1669 if (frame) {
1670 const char *format = "%" PRIu32;
1671 if (!entry.printf_format.empty())
1672 format = entry.printf_format.c_str();
1673 s.Printf(format, frame->GetFrameIndex());
1674 return true;
1675 }
1676 }
1677 return false;
1678
1680 if (m_exe_ctx) {
1681 StackFrame *frame = m_exe_ctx->GetFramePtr();
1682 if (frame) {
1683 const Address &pc_addr = frame->GetFrameCodeAddress();
1684 if (pc_addr.IsValid())
1685 if (DumpAddressAndContent(s, m_sc, m_exe_ctx, pc_addr, false))
1686 return true;
1687 }
1688 }
1689 return false;
1690
1692 if (m_exe_ctx) {
1693 StackFrame *frame = m_exe_ctx->GetFramePtr();
1694 if (frame) {
1696 (lldb::Format)entry.number))
1697 return true;
1698 }
1699 }
1700 return false;
1701
1703 if (m_exe_ctx) {
1704 StackFrame *frame = m_exe_ctx->GetFramePtr();
1705 if (frame) {
1707 (lldb::Format)entry.number))
1708 return true;
1709 }
1710 }
1711 return false;
1712
1714 if (m_exe_ctx) {
1715 StackFrame *frame = m_exe_ctx->GetFramePtr();
1716 if (frame) {
1717 if (DumpRegister(s, frame, eRegisterKindGeneric,
1719 return true;
1720 }
1721 }
1722 return false;
1723
1725 if (m_exe_ctx) {
1726 StackFrame *frame = m_exe_ctx->GetFramePtr();
1727 if (frame) {
1728 return !frame->HasDebugInformation();
1729 }
1730 }
1731 return true;
1732
1734 if (m_exe_ctx) {
1735 StackFrame *frame = m_exe_ctx->GetFramePtr();
1736 if (frame) {
1737 if (DumpRegister(s, frame, entry.string.c_str(),
1738 (lldb::Format)entry.number))
1739 return true;
1740 }
1741 }
1742 return false;
1743
1745 if (m_exe_ctx)
1746 if (StackFrame *frame = m_exe_ctx->GetFramePtr())
1747 return frame->IsArtificial();
1748 return false;
1749 }
1750
1752 if (m_exe_ctx)
1753 if (StackFrame *frame = m_exe_ctx->GetFramePtr()) {
1754 if (frame->IsSynthetic())
1755 s.PutCString(" [synthetic]");
1756 else if (frame->IsHistorical())
1757 s.PutCString(" [history]");
1758 return true;
1759 }
1760 return false;
1761 }
1762
1764 if (m_exe_ctx)
1765 if (StackFrame *frame = m_exe_ctx->GetFramePtr()) {
1766 if (BorrowedStackFrame *borrowed_frame =
1767 llvm::dyn_cast<BorrowedStackFrame>(frame)) {
1768 if (lldb::StackFrameSP borrowed_from_sp =
1769 borrowed_frame->GetBorrowedFrame()) {
1770 s.Printf(" [borrowed from frame #%u]",
1771 borrowed_from_sp->GetFrameIndex());
1772 return true;
1773 }
1774 }
1775 }
1776 return false;
1777 }
1778
1780 if (m_exe_ctx) {
1781 StackFrame *frame = m_exe_ctx->GetFramePtr();
1782 if (frame)
1783 return RunScriptFormatKeyword(s, m_sc, m_exe_ctx, frame,
1784 entry.string.c_str());
1785 }
1786 return false;
1787
1789 if (m_sc) {
1790 if (m_sc->function) {
1791 s.Printf("function{0x%8.8" PRIx64 "}", m_sc->function->GetID());
1792 return true;
1793 } else if (m_sc->symbol) {
1794 s.Printf("symbol[%u]", m_sc->symbol->GetID());
1795 return true;
1796 }
1797 }
1798 return false;
1799
1801 return m_function_changed;
1802
1804 return m_initial_function;
1805
1807 if (m_sc) {
1808 Language *language_plugin = nullptr;
1809 bool language_plugin_handled = false;
1810 StreamString ss;
1811
1812 if (m_sc->function)
1813 language_plugin = Language::FindPlugin(m_sc->function->GetLanguage());
1814 else if (m_sc->symbol)
1815 language_plugin = Language::FindPlugin(m_sc->symbol->GetLanguage());
1816
1817 if (language_plugin)
1818 language_plugin_handled = language_plugin->GetFunctionDisplayName(
1820
1821 if (language_plugin_handled) {
1822 s << ss.GetString();
1823 return true;
1824 }
1825
1826 const char *name = m_sc->GetPossiblyInlinedFunctionName()
1828 .AsCString(nullptr);
1829 if (name) {
1830 s.PutCString(name);
1831 return true;
1832 }
1833 }
1834
1835 // Fallback to frame methods if available.
1836 if (m_exe_ctx) {
1837 StackFrame *frame = m_exe_ctx->GetFramePtr();
1838 if (frame) {
1839 const char *name = frame->GetFunctionName();
1840 if (name) {
1841 s.PutCString(name);
1842 return true;
1843 }
1844 }
1845 }
1846 return false;
1847 }
1848
1850 if (m_sc) {
1851 Language *language_plugin = nullptr;
1852 bool language_plugin_handled = false;
1853 StreamString ss;
1854 if (m_sc->function)
1855 language_plugin = Language::FindPlugin(m_sc->function->GetLanguage());
1856 else if (m_sc->symbol)
1857 language_plugin = Language::FindPlugin(m_sc->symbol->GetLanguage());
1858
1859 if (language_plugin)
1860 language_plugin_handled = language_plugin->GetFunctionDisplayName(
1861 *m_sc, m_exe_ctx,
1863
1864 if (language_plugin_handled) {
1865 s << ss.GetString();
1866 return true;
1867 }
1868
1869 const char *name =
1870 m_sc->GetPossiblyInlinedFunctionName()
1871 .GetName(
1873 .AsCString(nullptr);
1874 if (name) {
1875 s.PutCString(name);
1876 return true;
1877 }
1878 }
1879
1880 // Fallback to frame methods if available.
1881 if (m_exe_ctx) {
1882 StackFrame *frame = m_exe_ctx->GetFramePtr();
1883 if (frame) {
1884 const char *name = frame->GetFunctionName();
1885 if (name) {
1886 s.PutCString(name);
1887 return true;
1888 }
1889 }
1890 }
1891 return false;
1892 }
1893
1904 Language *language_plugin = nullptr;
1905 if (m_sc->function)
1906 language_plugin = Language::FindPlugin(m_sc->function->GetLanguage());
1907 else if (m_sc->symbol)
1908 language_plugin = Language::FindPlugin(m_sc->symbol->GetLanguage());
1909
1910 if (!language_plugin)
1911 return false;
1912
1913 return language_plugin->HandleFrameFormatVariable(*m_sc, m_exe_ctx,
1914 entry.type, s);
1915 }
1916
1918 if (m_sc) {
1920 return true;
1921
1923 return true;
1924 }
1925
1926 // Fallback to frame methods if available.
1927 if (m_exe_ctx) {
1928 StackFrame *frame = m_exe_ctx->GetFramePtr();
1929 if (frame) {
1930 const char *name = frame->GetDisplayFunctionName();
1931 if (name) {
1932 s.PutCString(name);
1933 return true;
1934 }
1935 }
1936 }
1937 return false;
1938 }
1940 if (!m_sc)
1941 return false;
1942
1943 const char *name = m_sc->GetPossiblyInlinedFunctionName()
1945 .AsCString(nullptr);
1946 if (!name)
1947 return false;
1948
1949 s.PutCString(name);
1950
1951 return true;
1952 }
1954 if (m_addr) {
1956 false, false))
1957 return true;
1958 }
1959 return false;
1960
1962 if (m_addr) {
1963 if (DumpAddressOffsetFromFunction(s, m_sc, m_exe_ctx, *m_addr, true, true,
1964 true))
1965 return true;
1966 }
1967 return false;
1968
1970 if (m_sc)
1972 s, m_sc, m_exe_ctx, m_sc->line_entry.range.GetBaseAddress(), false,
1973 false, false));
1974 return false;
1975
1977 if (m_exe_ctx) {
1978 StackFrame *frame = m_exe_ctx->GetFramePtr();
1979 if (frame)
1981 frame->GetFrameCodeAddress(), false,
1982 false, false))
1983 return true;
1984 }
1985 return false;
1986
1988 return m_function_changed;
1989
1991 bool is_optimized = false;
1992 if (m_sc && m_sc->function && m_sc->function->GetIsOptimized()) {
1993 is_optimized = true;
1994 }
1995 return is_optimized;
1996 }
1997
1999 return m_sc && m_sc->block && m_sc->block->GetInlinedFunctionInfo();
2000 }
2001
2003 return m_initial_function;
2004
2006 if (m_sc && m_sc->line_entry.IsValid()) {
2007 if (DumpFile(s, m_sc->line_entry.GetFile(), (FileKind)entry.number))
2008 return true;
2009 }
2010 return false;
2011
2013 if (m_sc && m_sc->line_entry.IsValid()) {
2014 const char *format = "%" PRIu32;
2015 if (!entry.printf_format.empty())
2016 format = entry.printf_format.c_str();
2017 s.Printf(format, m_sc->line_entry.line);
2018 return true;
2019 }
2020 return false;
2021
2023 if (m_sc && m_sc->line_entry.IsValid() && m_sc->line_entry.column) {
2024 const char *format = "%" PRIu32;
2025 if (!entry.printf_format.empty())
2026 format = entry.printf_format.c_str();
2027 s.Printf(format, m_sc->line_entry.column);
2028 return true;
2029 }
2030 return false;
2031
2034 if (m_sc && m_sc->line_entry.range.GetBaseAddress().IsValid()) {
2035 Address addr = m_sc->line_entry.range.GetBaseAddress();
2036
2038 addr.Slide(m_sc->line_entry.range.GetByteSize());
2039 if (DumpAddressAndContent(s, m_sc, m_exe_ctx, addr, false))
2040 return true;
2041 }
2042 return false;
2043
2045 if (m_addr && m_exe_ctx && m_exe_ctx->GetFramePtr()) {
2046 RegisterContextSP reg_ctx =
2047 m_exe_ctx->GetFramePtr()->GetRegisterContextSP();
2048 if (reg_ctx) {
2049 addr_t pc_loadaddr = reg_ctx->GetPC();
2050 if (pc_loadaddr != LLDB_INVALID_ADDRESS) {
2051 Address pc;
2052 pc.SetLoadAddress(pc_loadaddr, m_exe_ctx->GetTargetPtr());
2053 if (pc == *m_addr) {
2054 s.PutCString("-> ");
2055 return true;
2056 }
2057 }
2058 }
2059 s.PutCString(" ");
2060 return true;
2061 }
2062 return false;
2063
2066 if (auto progress = target->GetDebugger().GetCurrentProgressReport()) {
2067 if (progress->total != UINT64_MAX) {
2068 s.Format("[{0:N}/{1:N}]", progress->completed, progress->total);
2069 return true;
2070 }
2071 }
2072 }
2073 return false;
2074
2077 if (auto progress = target->GetDebugger().GetCurrentProgressReport()) {
2078 s.PutCString(progress->message);
2079 return true;
2080 }
2081 }
2082 return false;
2083
2086 s << target->GetDebugger().GetSeparator();
2087 return true;
2088 }
2089 return false;
2090 }
2091
2092 return false;
2093}
2094
2096 const Definition *parent) {
2097 if (parent->children) {
2098 const size_t n = parent->num_children;
2099 for (size_t i = 0; i < n; ++i) {
2100 if (i > 0)
2101 s.PutCString(", ");
2102 s.Printf("\"%s\"", parent->children[i].name);
2103 }
2104 return true;
2105 }
2106 return false;
2107}
2108
2109static Status ParseEntry(const llvm::StringRef &format_str,
2110 const Definition *parent, FormatEntity::Entry &entry) {
2111 Status error;
2112
2113 const size_t sep_pos = format_str.find_first_of(".[:");
2114 const char sep_char =
2115 (sep_pos == llvm::StringRef::npos) ? '\0' : format_str[sep_pos];
2116 llvm::StringRef key = format_str.substr(0, sep_pos);
2117
2118 const size_t n = parent->num_children;
2119 for (size_t i = 0; i < n; ++i) {
2120 const Definition *entry_def = parent->children + i;
2121 if (key == entry_def->name || entry_def->name[0] == '*') {
2122 llvm::StringRef value;
2123 if (sep_char)
2124 value =
2125 format_str.substr(sep_pos + (entry_def->keep_separator ? 0 : 1));
2126 switch (entry_def->type) {
2128 entry.string = format_str.str();
2129 return error; // Success
2130
2132 entry.number = entry_def->data;
2133 return error; // Success
2134
2136 entry.type = entry_def->type;
2137 entry.string = entry_def->string;
2138 return error; // Success
2139
2140 default:
2141 entry.type = entry_def->type;
2142 break;
2143 }
2144
2145 if (value.empty()) {
2146 if (entry_def->type == FormatEntity::Entry::Type::Invalid) {
2147 if (entry_def->children) {
2148 StreamString error_strm;
2149 error_strm.Printf("'%s' can't be specified on its own, you must "
2150 "access one of its children: ",
2151 entry_def->name);
2152 DumpCommaSeparatedChildEntryNames(error_strm, entry_def);
2153 error =
2154 Status::FromErrorStringWithFormat("%s", error_strm.GetData());
2155 } else if (sep_char == ':') {
2156 // Any value whose separator is a with a ':' means this value has a
2157 // string argument that needs to be stored in the entry (like
2158 // "${script.var:}"). In this case the string value is the empty
2159 // string which is ok.
2160 } else {
2162 "%s", "invalid entry definitions");
2163 }
2164 }
2165 } else {
2166 if (entry_def->children) {
2167 error = ParseEntry(value, entry_def, entry);
2168 } else if (sep_char == ':') {
2169 // Any value whose separator is a with a ':' means this value has a
2170 // string argument that needs to be stored in the entry (like
2171 // "${script.var:modulename.function}")
2172 entry.string = value.str();
2173 } else {
2175 "'%s' followed by '%s' but it has no children", key.str().c_str(),
2176 value.str().c_str());
2177 }
2178 }
2179 return error;
2180 }
2181 }
2182 StreamString error_strm;
2184 error_strm.Printf(
2185 "invalid top level item '%s'. Valid top level items are: ",
2186 key.str().c_str());
2187 else
2188 error_strm.Printf("invalid member '%s' in '%s'. Valid members are: ",
2189 key.str().c_str(), parent->name);
2190 DumpCommaSeparatedChildEntryNames(error_strm, parent);
2191 error = Status::FromErrorStringWithFormat("%s", error_strm.GetData());
2192 return error;
2193}
2194
2195static const Definition *FindEntry(const llvm::StringRef &format_str,
2196 const Definition *parent,
2197 llvm::StringRef &remainder) {
2198 Status error;
2199
2200 std::pair<llvm::StringRef, llvm::StringRef> p = format_str.split('.');
2201 const size_t n = parent->num_children;
2202 for (size_t i = 0; i < n; ++i) {
2203 const Definition *entry_def = parent->children + i;
2204 if (p.first == entry_def->name || entry_def->name[0] == '*') {
2205 if (p.second.empty()) {
2206 if (format_str.back() == '.')
2207 remainder = format_str.drop_front(format_str.size() - 1);
2208 else
2209 remainder = llvm::StringRef(); // Exact match
2210 return entry_def;
2211 } else {
2212 if (entry_def->children) {
2213 return FindEntry(p.second, entry_def, remainder);
2214 } else {
2215 remainder = p.second;
2216 return entry_def;
2217 }
2218 }
2219 }
2220 }
2221 remainder = format_str;
2222 return parent;
2223}
2224
2225static Status ParseInternal(llvm::StringRef &format, Entry &parent_entry,
2226 uint32_t depth) {
2227 Status error;
2228 while (!format.empty() && error.Success()) {
2229 const size_t non_special_chars = format.find_first_of("${}\\|");
2230
2231 if (non_special_chars == llvm::StringRef::npos) {
2232 // No special characters, just string bytes so add them and we are done
2233 parent_entry.AppendText(format);
2234 return error;
2235 }
2236
2237 if (non_special_chars > 0) {
2238 // We have a special character, so add all characters before these as a
2239 // plain string
2240 parent_entry.AppendText(format.substr(0, non_special_chars));
2241 format = format.drop_front(non_special_chars);
2242 }
2243
2244 switch (format[0]) {
2245 case '\0':
2246 return error;
2247
2248 case '{': {
2249 format = format.drop_front(); // Skip the '{'
2250 Entry scope_entry(Entry::Type::Scope);
2251 error = ParseInternal(format, scope_entry, depth + 1);
2252 if (error.Fail())
2253 return error;
2254 parent_entry.AppendEntry(std::move(scope_entry));
2255 } break;
2256
2257 case '}':
2258 if (depth == 0)
2259 error = Status::FromErrorString("unmatched '}' character");
2260 else
2261 format =
2262 format
2263 .drop_front(); // Skip the '}' as we are at the end of the scope
2264 return error;
2265
2266 case '|':
2267 format = format.drop_front(); // Skip the '|'
2268 if (parent_entry.type == Entry::Type::Scope)
2269 parent_entry.StartAlternative();
2270 else
2271 parent_entry.AppendChar('|');
2272 break;
2273
2274 case '\\': {
2275 format = format.drop_front(); // Skip the '\' character
2276 if (format.empty()) {
2278 "'\\' character was not followed by another character");
2279 return error;
2280 }
2281
2282 const char desens_char = format[0];
2283 format = format.drop_front(); // Skip the desensitized char character
2284 switch (desens_char) {
2285 case 'a':
2286 parent_entry.AppendChar('\a');
2287 break;
2288 case 'b':
2289 parent_entry.AppendChar('\b');
2290 break;
2291 case 'f':
2292 parent_entry.AppendChar('\f');
2293 break;
2294 case 'n':
2295 parent_entry.AppendChar('\n');
2296 break;
2297 case 'r':
2298 parent_entry.AppendChar('\r');
2299 break;
2300 case 't':
2301 parent_entry.AppendChar('\t');
2302 break;
2303 case 'v':
2304 parent_entry.AppendChar('\v');
2305 break;
2306 case '\'':
2307 parent_entry.AppendChar('\'');
2308 break;
2309 case '\\':
2310 parent_entry.AppendChar('\\');
2311 break;
2312 case '0':
2313 // 1 to 3 octal chars
2314 {
2315 // Make a string that can hold onto the initial zero char, up to 3
2316 // octal digits, and a terminating NULL.
2317 char oct_str[5] = {0, 0, 0, 0, 0};
2318
2319 int i;
2320 for (i = 0; (format[i] >= '0' && format[i] <= '7') && i < 4; ++i)
2321 oct_str[i] = format[i];
2322
2323 // We don't want to consume the last octal character since the main
2324 // for loop will do this for us, so we advance p by one less than i
2325 // (even if i is zero)
2326 format = format.drop_front(i);
2327 unsigned long octal_value = ::strtoul(oct_str, nullptr, 8);
2328 if (octal_value <= UINT8_MAX) {
2329 parent_entry.AppendChar((char)octal_value);
2330 } else {
2332 "octal number is larger than a single byte");
2333 return error;
2334 }
2335 }
2336 break;
2337
2338 case 'x':
2339 // hex number in the format
2340 if (isxdigit(format[0])) {
2341 // Make a string that can hold onto two hex chars plus a
2342 // null terminator
2343 char hex_str[3] = {0, 0, 0};
2344 hex_str[0] = format[0];
2345
2346 format = format.drop_front();
2347
2348 if (isxdigit(format[0])) {
2349 hex_str[1] = format[0];
2350 format = format.drop_front();
2351 }
2352
2353 unsigned long hex_value = strtoul(hex_str, nullptr, 16);
2354 if (hex_value <= UINT8_MAX) {
2355 parent_entry.AppendChar((char)hex_value);
2356 } else {
2358 "hex number is larger than a single byte");
2359 return error;
2360 }
2361 } else {
2362 parent_entry.AppendChar(desens_char);
2363 }
2364 break;
2365
2366 default:
2367 // Just desensitize any other character by just printing what came
2368 // after the '\'
2369 parent_entry.AppendChar(desens_char);
2370 break;
2371 }
2372 } break;
2373
2374 case '$':
2375 format = format.drop_front(); // Skip the '$'
2376 if (format.empty() || format.front() != '{') {
2377 // Print '$' when not followed by '{'.
2378 parent_entry.AppendText("$");
2379 } else {
2380 format = format.drop_front(); // Skip the '{'
2381
2382 llvm::StringRef variable, variable_format;
2383 error = FormatEntity::ExtractVariableInfo(format, variable,
2384 variable_format);
2385 if (error.Fail())
2386 return error;
2387 bool verify_is_thread_id = false;
2388 Entry entry;
2389 if (!variable_format.empty()) {
2390 entry.printf_format = variable_format.str();
2391
2392 // If the format contains a '%' we are going to assume this is a
2393 // printf style format. So if you want to format your thread ID
2394 // using "0x%llx" you can use: ${thread.id%0x%llx}
2395 //
2396 // If there is no '%' in the format, then it is assumed to be a
2397 // LLDB format name, or one of the extended formats specified in
2398 // the switch statement below.
2399
2400 if (entry.printf_format.find('%') == std::string::npos) {
2401 bool clear_printf = false;
2402
2403 if (entry.printf_format.size() == 1) {
2404 switch (entry.printf_format[0]) {
2405 case '@': // if this is an @ sign, print ObjC description
2406 entry.number = ValueObject::
2407 eValueObjectRepresentationStyleLanguageSpecific;
2408 clear_printf = true;
2409 break;
2410 case 'V': // if this is a V, print the value using the default
2411 // format
2412 entry.number =
2414 clear_printf = true;
2415 break;
2416 case 'L': // if this is an L, print the location of the value
2417 entry.number =
2419 clear_printf = true;
2420 break;
2421 case 'S': // if this is an S, print the summary after all
2422 entry.number =
2424 clear_printf = true;
2425 break;
2426 case '#': // if this is a '#', print the number of children
2427 entry.number =
2429 clear_printf = true;
2430 break;
2431 case 'T': // if this is a 'T', print the type
2433 clear_printf = true;
2434 break;
2435 case 'N': // if this is a 'N', print the name
2437 clear_printf = true;
2438 break;
2439 case '>': // if this is a '>', print the expression path
2440 entry.number =
2442 clear_printf = true;
2443 break;
2444 }
2445 }
2446
2447 if (entry.number == 0) {
2449 entry.printf_format.c_str(), entry.fmt)) {
2450 clear_printf = true;
2451 } else if (entry.printf_format == "tid") {
2452 verify_is_thread_id = true;
2453 } else {
2455 "invalid format: '%s'", entry.printf_format.c_str());
2456 return error;
2457 }
2458 }
2459
2460 // Our format string turned out to not be a printf style format
2461 // so lets clear the string
2462 if (clear_printf)
2463 entry.printf_format.clear();
2464 }
2465 }
2466
2467 // Check for dereferences
2468 if (variable[0] == '*') {
2469 entry.deref = true;
2470 variable = variable.drop_front();
2471 }
2472
2473 error = ParseEntry(variable, &g_root, entry);
2474 if (error.Fail())
2475 return error;
2476
2477 llvm::StringRef entry_string(entry.string);
2478 if (entry_string.contains(':')) {
2479 auto [_, llvm_format] = entry_string.split(':');
2480 if (!llvm_format.empty() && !LLVMFormatPattern.match(llvm_format)) {
2482 "invalid llvm format: '%s'", llvm_format.data());
2483 return error;
2484 }
2485 }
2486
2487 if (verify_is_thread_id) {
2488 if (entry.type != Entry::Type::ThreadID &&
2491 "the 'tid' format can only be used on "
2492 "${thread.id} and ${thread.protocol_id}");
2493 }
2494 }
2495
2496 switch (entry.type) {
2499 if (entry.number == 0) {
2500 if (entry.string.empty())
2502 else
2503 entry.number =
2505 }
2506 break;
2507 default:
2508 // Make sure someone didn't try to dereference anything but ${var}
2509 // or ${svar}
2510 if (entry.deref) {
2512 "${%s} can't be dereferenced, only ${var} and ${svar} can.",
2513 variable.str().c_str());
2514 return error;
2515 }
2516 }
2517 parent_entry.AppendEntry(std::move(entry));
2518 }
2519 break;
2520 }
2521 }
2522 return error;
2523}
2524
2525Status FormatEntity::ExtractVariableInfo(llvm::StringRef &format_str,
2526 llvm::StringRef &variable_name,
2527 llvm::StringRef &variable_format) {
2528 Status error;
2529 variable_name = llvm::StringRef();
2530 variable_format = llvm::StringRef();
2531
2532 const size_t paren_pos = format_str.find('}');
2533 if (paren_pos != llvm::StringRef::npos) {
2534 const size_t percent_pos = format_str.find('%');
2535 if (percent_pos < paren_pos) {
2536 if (percent_pos > 0) {
2537 if (percent_pos > 1)
2538 variable_name = format_str.substr(0, percent_pos);
2539 variable_format =
2540 format_str.substr(percent_pos + 1, paren_pos - (percent_pos + 1));
2541 }
2542 } else {
2543 variable_name = format_str.substr(0, paren_pos);
2544 }
2545 // Strip off elements and the formatting and the trailing '}'
2546 format_str = format_str.substr(paren_pos + 1);
2547 } else {
2549 "missing terminating '}' character for '${%s'",
2550 format_str.str().c_str());
2551 }
2552 return error;
2553}
2554
2556 llvm::StringRef variable_name,
2557 llvm::StringRef variable_format) {
2558 if (variable_name.empty() || variable_name == ".fullpath") {
2559 file_spec.Dump(s.AsRawOstream());
2560 return true;
2561 } else if (variable_name == ".basename") {
2562 s.PutCString(file_spec.GetFilename());
2563 return true;
2564 } else if (variable_name == ".dirname") {
2565 s.PutCString(file_spec.GetFilename());
2566 return true;
2567 }
2568 return false;
2569}
2570
2571static std::string MakeMatch(const llvm::StringRef &prefix,
2572 const char *suffix) {
2573 std::string match(prefix.str());
2574 match.append(suffix);
2575 return match;
2576}
2577
2578static void AddMatches(const Definition *def, const llvm::StringRef &prefix,
2579 const llvm::StringRef &match_prefix,
2580 StringList &matches) {
2581 const size_t n = def->num_children;
2582 if (n > 0) {
2583 for (size_t i = 0; i < n; ++i) {
2584 if (match_prefix.empty())
2585 matches.AppendString(MakeMatch(prefix, def->children[i].name));
2586 else if (strncmp(def->children[i].name, match_prefix.data(),
2587 match_prefix.size()) == 0)
2588 matches.AppendString(
2589 MakeMatch(prefix, def->children[i].name + match_prefix.size()));
2590 }
2591 }
2592}
2593
2595 llvm::StringRef str = request.GetCursorArgumentPrefix();
2596
2597 const size_t dollar_pos = str.rfind('$');
2598 if (dollar_pos == llvm::StringRef::npos)
2599 return;
2600
2601 // Hitting TAB after $ at the end of the string add a "{"
2602 if (dollar_pos == str.size() - 1) {
2603 std::string match = str.str();
2604 match.append("{");
2605 request.AddCompletion(match);
2606 return;
2607 }
2608
2609 if (str[dollar_pos + 1] != '{')
2610 return;
2611
2612 const size_t close_pos = str.find('}', dollar_pos + 2);
2613 if (close_pos != llvm::StringRef::npos)
2614 return;
2615
2616 const size_t format_pos = str.find('%', dollar_pos + 2);
2617 if (format_pos != llvm::StringRef::npos)
2618 return;
2619
2620 llvm::StringRef partial_variable(str.substr(dollar_pos + 2));
2621 if (partial_variable.empty()) {
2622 // Suggest all top level entities as we are just past "${"
2623 StringList new_matches;
2624 AddMatches(&g_root, str, llvm::StringRef(), new_matches);
2625 request.AddCompletions(new_matches);
2626 return;
2627 }
2628
2629 // We have a partially specified variable, find it
2630 llvm::StringRef remainder;
2631 const Definition *entry_def = FindEntry(partial_variable, &g_root, remainder);
2632 if (!entry_def)
2633 return;
2634
2635 const size_t n = entry_def->num_children;
2636
2637 if (remainder.empty()) {
2638 // Exact match
2639 if (n > 0) {
2640 // "${thread.info" <TAB>
2641 request.AddCompletion(MakeMatch(str, "."));
2642 } else {
2643 // "${thread.id" <TAB>
2644 request.AddCompletion(MakeMatch(str, "}"));
2645 }
2646 } else if (remainder == ".") {
2647 // "${thread." <TAB>
2648 StringList new_matches;
2649 AddMatches(entry_def, str, llvm::StringRef(), new_matches);
2650 request.AddCompletions(new_matches);
2651 } else {
2652 // We have a partial match
2653 // "${thre" <TAB>
2654 StringList new_matches;
2655 AddMatches(entry_def, str, remainder, new_matches);
2656 request.AddCompletions(new_matches);
2657 }
2658}
2659
2661 Stream &out_stream, VariableList const &args,
2662 ExecutionContextScope *exe_scope) {
2663 const size_t num_args = args.GetSize();
2664 for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) {
2665 std::string buffer;
2666
2667 VariableSP var_sp(args.GetVariableAtIndex(arg_idx));
2668 ValueObjectSP var_value_sp(ValueObjectVariable::Create(exe_scope, var_sp));
2669 StreamString ss;
2670 llvm::StringRef var_representation;
2671 const char *var_name = var_value_sp->GetName().GetCString();
2672 if (var_value_sp->GetCompilerType().IsValid()) {
2673 if (exe_scope && exe_scope->CalculateTarget())
2674 var_value_sp = var_value_sp->GetQualifiedRepresentationIfAvailable(
2675 exe_scope->CalculateTarget()
2676 ->TargetProperties::GetPreferDynamicValue(),
2677 exe_scope->CalculateTarget()
2678 ->TargetProperties::GetEnableSyntheticValue());
2679 if (var_value_sp->GetCompilerType().IsAggregateType() &&
2682 .SetHideItemNames(false)
2683 .SetShowMembersOneLiner(true),
2684 "");
2685 format.FormatObject(var_value_sp.get(), buffer, TypeSummaryOptions());
2686 var_representation = buffer;
2687 } else
2688 var_value_sp->DumpPrintableRepresentation(
2689 ss,
2691 eValueObjectRepresentationStyleSummary,
2694 }
2695
2696 if (!ss.GetString().empty())
2697 var_representation = ss.GetString();
2698 if (arg_idx > 0)
2699 out_stream.PutCString(", ");
2700 if (var_value_sp->GetError().Success()) {
2701 if (!var_representation.empty())
2702 out_stream.Printf("%s=%s", var_name, var_representation.str().c_str());
2703 else
2704 out_stream.Printf("%s=%s at %s", var_name,
2705 var_value_sp->GetTypeName().GetCString(),
2706 var_value_sp->GetLocationAsCString());
2707 } else
2708 out_stream.Printf("%s=<unavailable>", var_name);
2709 }
2710}
2711
2712Status FormatEntity::Parse(const llvm::StringRef &format_str, Entry &entry) {
2713 entry.Clear();
2714 entry.type = Entry::Type::Root;
2715 llvm::StringRef modifiable_format(format_str);
2716 return ParseInternal(modifiable_format, entry, 0);
2717}
2718
2720 // It is expected that Scope and Root format entities recursively call Format.
2721 //
2722 // Variable may also be formatted recursively in some special cases. The main
2723 // use-case being array summary strings, in which case Format will call itself
2724 // with the subrange ValueObject and apply a freshly created Variable entry.
2725 // E.g., ${var[1-3]} will format the [1-3] range with ${var%S}.
2726 static constexpr std::array s_permitted_recursive_entities = {
2728
2729 if (llvm::is_contained(s_permitted_recursive_entities, type))
2730 return false;
2731
2732 return llvm::is_contained(m_entry_type_stack, type);
2733}
#define ANSI_ESC_START
#define ANSI_BG_COLOR_PURPLE
#define ANSI_CTRL_UNDERLINE
#define ANSI_BG_COLOR_RED
#define ANSI_FG_COLOR_BLACK
#define ANSI_BG_COLOR_YELLOW
#define ANSI_BG_COLOR_BLACK
#define ANSI_FG_COLOR_YELLOW
#define ANSI_FG_COLOR_PURPLE
#define ANSI_BG_COLOR_CYAN
#define ANSI_BG_COLOR_GREEN
#define ANSI_CTRL_SLOW_BLINK
#define ANSI_FG_COLOR_RED
#define ANSI_BG_COLOR_BLUE
#define ANSI_CTRL_ITALIC
#define ANSI_FG_COLOR_CYAN
#define ANSI_CTRL_FAST_BLINK
#define ANSI_CTRL_CROSSED_OUT
#define ANSI_CTRL_IMAGE_NEGATIVE
#define ANSI_BG_COLOR_WHITE
#define ANSI_CTRL_CONCEAL
#define ANSI_FG_COLOR_GREEN
#define ANSI_CTRL_FAINT
#define ANSI_FG_COLOR_BLUE
#define ANSI_CTRL_NORMAL
#define ANSI_CTRL_BOLD
#define ANSI_FG_COLOR_WHITE
#define ANSI_ESC_END
static llvm::raw_ostream & error(Stream &strm)
#define integer
#define ENUM_TO_CSTR(eee)
static void AddMatches(const Definition *def, const llvm::StringRef &prefix, const llvm::StringRef &match_prefix, StringList &matches)
static std::pair< char const *, char const * > ParseBaseName(char const *full_name)
Parses the basename out of a demangled function name that may include function arguments.
static const Definition * FindEntry(const llvm::StringRef &format_str, const Definition *parent, llvm::StringRef &remainder)
constexpr Definition g_frame_child_entries[]
constexpr Definition g_ansi_bg_entries[]
static bool ScanBracketedRange(llvm::StringRef subpath, size_t &close_bracket_index, const char *&var_name_final_if_array_range, int64_t &index_lower, int64_t &index_higher)
static bool RunScriptFormatKeyword(Stream &s, const SymbolContext *sc, const ExecutionContext *exe_ctx, T t, const char *script_function_name)
static bool DumpFile(Stream &s, const FileSpec &file, FileKind file_kind)
lldb_private::FormatEntity::Entry::Definition Definition
constexpr Definition g_script_child_entries[]
static Status ParseInternal(llvm::StringRef &format, Entry &parent_entry, uint32_t depth)
constexpr Definition g_file_child_entries[]
static Status ParseEntry(const llvm::StringRef &format_str, const Definition *parent, FormatEntity::Entry &entry)
static std::string MakeMatch(const llvm::StringRef &prefix, const char *suffix)
static ValueObjectSP ExpandIndexedExpression(ValueObject *valobj, size_t index, bool deref_pointer)
static bool HandleFunctionNameWithArgs(Stream &s, const ExecutionContext *exe_ctx, const SymbolContext &sc)
constexpr Definition g_string_entry[]
constexpr Definition g_root
static bool PrintFunctionNameWithArgs(Stream &s, const ExecutionContext *exe_ctx, const SymbolContext &sc)
static bool DumpCommaSeparatedChildEntryNames(Stream &s, const Definition *parent)
constexpr Definition g_svar_child_entries[]
constexpr Definition g_var_child_entries[]
static bool IsToken(const char *var_name_begin, const char *var)
static llvm::Regex LLVMFormatPattern
Options supported by format_provider<T> for integral arithmetic types.
constexpr Definition g_top_level_entries[]
static char ConvertValueObjectStyleToChar(ValueObject::ValueObjectRepresentationStyle style)
constexpr Definition g_line_child_entries[]
static void PrettyPrintFunctionNameWithArgs(Stream &out_stream, char const *full_name, ExecutionContextScope *exe_scope, VariableList const &args)
Writes out the function name in 'full_name' to 'out_stream' but replaces each argument type with the ...
constexpr Definition g_function_child_entries[]
FileKind
@ FileError
@ Dirname
@ Basename
@ Fullpath
constexpr Definition g_module_child_entries[]
constexpr Definition g_ansi_entries[]
constexpr Definition g_process_child_entries[]
static bool DumpValueWithLLVMFormat(Stream &s, llvm::StringRef options, ValueObject &valobj)
static bool DumpAddressAndContent(Stream &s, const SymbolContext *sc, const ExecutionContext *exe_ctx, const Address &addr, bool print_file_addr_or_load_addr)
FormatEntity::Entry::Type EntryType
static VariableListSP GetFunctionVariableList(const SymbolContext &sc)
static bool DumpAddressOffsetFromFunction(Stream &s, const SymbolContext *sc, const ExecutionContext *exe_ctx, const Address &format_addr, bool concrete_only, bool no_padding, bool print_zero_offsets)
constexpr Definition g_progress_child_entries[]
static bool DumpRegister(Stream &s, StackFrame *frame, RegisterKind reg_kind, uint32_t reg_num, Format format)
constexpr Definition g_ansi_fg_entries[]
constexpr Definition g_addr_entries[]
constexpr Definition g_target_child_entries[]
constexpr Definition g_thread_child_entries[]
#define _TO_STR(_val)
static bool FormatThreadExtendedInfoRecurse(const FormatEntity::Entry &entry, const StructuredData::ObjectSP &thread_info_dictionary, const SymbolContext *sc, const ExecutionContext *exe_ctx, Stream &s)
FormatEntity::Entry Entry
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition Log.h:375
#define LLDB_LOGF(log,...)
Definition Log.h:389
A section + offset based address range class.
Address & GetBaseAddress()
Get accessor for the base address of the range.
A section + offset based address class.
Definition Address.h:62
lldb::addr_t GetLoadAddress(Target *target) const
Get the load address.
Definition Address.cpp:303
@ DumpStyleModuleWithFileAddress
Display as the file address with the module name prepended (if any).
Definition Address.h:93
@ DumpStyleLoadAddress
Display as the load address (if resolved).
Definition Address.h:99
bool Slide(int64_t offset)
Definition Address.h:446
bool Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, DumpStyle fallback_style=DumpStyleInvalid, uint32_t addr_byte_size=UINT32_MAX, bool all_ranges=false, std::optional< Stream::HighlightSettings > settings=std::nullopt) const
Dump a description of this object to a Stream.
Definition Address.cpp:398
lldb::ModuleSP GetModule() const
Get accessor for the module for this address.
Definition Address.cpp:275
lldb::addr_t GetFileAddress() const
Get the file address.
Definition Address.cpp:283
bool IsValid() const
Check if the object state is valid.
Definition Address.h:355
An architecture specification class.
Definition ArchSpec.h:32
uint32_t GetAddressByteSize() const
Returns the size in bytes of an address of the current architecture.
Definition ArchSpec.cpp:894
bool IsValid() const
Tests if this ArchSpec is valid.
Definition ArchSpec.h:455
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition ArchSpec.h:547
const char * GetArchitectureName() const
Returns a static string representing the current architecture.
Definition ArchSpec.cpp:745
A class that describes a single lexical block.
Definition Block.h:41
lldb::VariableListSP GetBlockVariableList(bool can_create)
Get the variable list for this block only.
Definition Block.cpp:382
Block * GetContainingInlinedBlock()
Get the inlined block that contains this block.
Definition Block.cpp:206
bool GetRangeContainingAddress(const Address &addr, AddressRange &range)
Definition Block.cpp:248
"lldb/Target/BorrowedStackFrame.h"
A class that describes a compilation unit.
Definition CompileUnit.h:43
const FileSpec & GetPrimaryFile() const
Return the primary source spec associated with this compile unit.
lldb::LanguageType GetLanguage()
uint32_t GetTypeInfo(CompilerType *pointee_or_element_compiler_type=nullptr) const
"lldb/Utility/ArgCompletionRequest.h"
void AddCompletion(llvm::StringRef completion, llvm::StringRef description="", CompletionMode mode=CompletionMode::Normal)
Adds a possible completion string.
void AddCompletions(const StringList &completions)
Adds multiple possible completion strings.
llvm::StringRef GetCursorArgumentPrefix() const
const char * AsCString(const char *value_if_empty) const
Get the string value as a C string.
static bool ShouldPrintAsOneLiner(ValueObject &valobj)
static lldb::TypeSummaryImplSP GetSummaryForType(lldb::TypeNameSpecifierImplSP type_sp)
A class to manage flag bits.
Definition Debugger.h:103
bool GetUseColor() const
Definition Debugger.cpp:543
ScriptInterpreter * GetScriptInterpreter(bool can_create=true, std::optional< lldb::ScriptLanguage > language={})
"lldb/Target/ExecutionContextScope.h" Inherit from this if your object can reconstruct its execution ...
virtual lldb::TargetSP CalculateTarget()=0
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
ExecutionContextScope * GetBestExecutionContextScope() const
A file utility class.
Definition FileSpec.h:56
llvm::StringRef GetFilename() const
Filename string const get accessor.
Definition FileSpec.h:248
llvm::StringRef GetDirectory() const
Directory string const get accessor.
Definition FileSpec.h:233
void Dump(llvm::raw_ostream &s) const
Dump this object to a Stream.
Definition FileSpec.cpp:341
const SymbolContext *const m_sc
auto PushEntryType(Entry::Type type)
While the returned llvm::scope_exit is alive, the specified type is tracked by this Formatter object ...
const ExecutionContext *const m_exe_ctx
llvm::SmallVector< Entry::Type, 1 > m_entry_type_stack
bool Format(const Entry &entry, Stream &s, ValueObject *valobj=nullptr)
bool FormatStringRef(const llvm::StringRef &format, Stream &s, ValueObject *valobj)
bool IsInvalidRecursiveFormat(Entry::Type type)
Returns true if Format has been called for an Entry with the specified type recusrively.
bool DumpValue(Stream &s, const FormatEntity::Entry &entry, ValueObject *valobj)
static const char * GetFormatAsCString(lldb::Format format)
static bool GetFormatFromCString(const char *format_cstr, lldb::Format &format)
static char GetFormatAsFormatChar(lldb::Format format)
const Address & GetAddress() const
Return the address of the function (its entry point).
Definition Function.h:439
lldb::LanguageType GetLanguage() const
Definition Function.cpp:713
Block & GetBlock(bool can_create)
Get accessor for the block list.
Definition Function.cpp:401
virtual bool HandleFrameFormatVariable(const SymbolContext &sc, const ExecutionContext *exe_ctx, FormatEntity::Entry::Type type, Stream &s)
Definition Language.h:431
static Language * FindPlugin(lldb::LanguageType language)
Definition Language.cpp:86
static const char * GetNameForLanguageType(lldb::LanguageType language)
Returns the internal LLDB name for the specified language.
Definition Language.cpp:334
virtual bool GetFunctionDisplayName(const SymbolContext &sc, const ExecutionContext *exe_ctx, FunctionNameRepresentation representation, Stream &s)
Definition Language.cpp:599
virtual FormatEntity::Entry GetFunctionNameFormat() const
Definition Language.h:564
@ ePreferDemangledWithoutArguments
Definition Mangled.h:39
ConstString GetName(NamePreference preference=ePreferDemangled) const
Best name get accessor.
Definition Mangled.cpp:257
A class that describes an executable image and its associated object and symbol files.
Definition Module.h:91
const FileSpec & GetFileSpec() const
Get const accessor for the module file specification.
Definition Module.h:447
A plug-in interface definition class for debugging a process.
Definition Process.h:369
lldb::pid_t GetID() const
Returns the pid of the process or LLDB_INVALID_PROCESS_ID if there is no known pid.
Definition Process.h:554
Target & GetTarget()
Get the target object pointer for this module.
Definition Process.h:1270
virtual uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num)
Convert from a given register numbering scheme to the lldb register numbering scheme.
virtual const RegisterInfo * GetRegisterInfoAtIndex(size_t reg)=0
const RegisterInfo * GetRegisterInfoByName(llvm::StringRef reg_name, uint32_t start_idx=0)
virtual bool ReadRegister(const RegisterInfo *reg_info, RegisterValue &reg_value)=0
virtual bool RunScriptFormatKeyword(const char *impl_function, Process *process, std::string &output, Status &error)
This base class provides an interface to stack frames.
Definition StackFrame.h:44
virtual const char * GetFunctionName()
Get the frame's demangled name.
virtual lldb::RegisterContextSP GetRegisterContext()
Get the RegisterContext for this frame, if possible.
virtual const char * GetDisplayFunctionName()
Get the frame's demangled display name.
virtual uint32_t GetFrameIndex() const
Query this frame to find what frame it is in this Thread's StackFrameList.
virtual bool HasDebugInformation()
Determine whether this StackFrame has debug information available or not.
virtual const Address & GetFrameCodeAddress()
Get an Address for the current pc value in this StackFrame.
An error handling class.
Definition Status.h:118
static Status FromErrorStringWithFormat(const char *format,...) __attribute__((format(printf
Definition Status.cpp:106
static Status FromErrorString(const char *str)
Definition Status.h:141
static lldb::ExpressionVariableSP GetExpressionVariable(lldb::StopInfoSP &stop_info_sp)
static lldb::ValueObjectSP GetReturnValueObject(lldb::StopInfoSP &stop_info_sp)
const char * GetData() const
llvm::StringRef GetString() const
A stream class that can stream formatted output to a file.
Definition Stream.h:28
void Format(const char *format, Args &&... args)
Forwards the arguments to llvm::formatv and writes to the stream.
Definition Stream.h:370
size_t Write(const void *src, size_t src_len)
Output character bytes to the stream.
Definition Stream.h:111
llvm::raw_ostream & AsRawOstream()
Returns a raw_ostream that forwards the data to this Stream object.
Definition Stream.h:405
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
size_t PutChar(char ch)
Definition Stream.cpp:131
size_t EOL()
Output and End of Line character to the stream.
Definition Stream.cpp:155
void AppendString(const std::string &s)
std::shared_ptr< Object > ObjectSP
Defines a symbol context baton that can be handed other debug core functions.
Function * function
The Function for a given query.
Block * block
The Block for a given query.
Symbol * symbol
The Symbol for a given query.
Mangled GetPossiblyInlinedFunctionName() const
If available, will return the function name according to the specified mangling preference.
bool ValueIsAddress() const
Definition Symbol.cpp:191
lldb::LanguageType GetLanguage() const
Definition Symbol.h:154
Address & GetAddressRef()
Definition Symbol.h:78
ConstString GetName() const
Definition Symbol.cpp:612
Module * GetExecutableModulePointer()
Definition Target.cpp:1664
static Target * GetTargetFromContexts(const ExecutionContext *exe_ctx_ptr, const SymbolContext *sc_ptr)
Definition Target.cpp:2973
Debugger & GetDebugger() const
Definition Target.h:1365
const ArchSpec & GetArchitecture() const
Definition Target.h:1324
static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope, const lldb::VariableSP &var_sp)
virtual uint32_t GetBitfieldBitSize()
bool DumpPrintableRepresentation(Stream &s, ValueObjectRepresentationStyle val_obj_display=eValueObjectRepresentationStyleSummary, lldb::Format custom_format=lldb::eFormatInvalid, PrintableRepresentationSpecialCases special=PrintableRepresentationSpecialCases::eAllow, bool do_dump_error=true)
lldb::ValueObjectSP GetSyntheticValue()
@ eExpressionPathScanEndReasonEndOfString
Out of data to parse.
@ eExpressionPathAftermathNothing
Just return it.
@ eExpressionPathAftermathDereference
Dereference the target.
lldb::ValueObjectSP GetValueForExpressionPath(llvm::StringRef expression, ExpressionPathScanEndReason *reason_to_stop=nullptr, ExpressionPathEndResultType *final_value_type=nullptr, const GetValueForExpressionPathOptions &options=GetValueForExpressionPathOptions::DefaultOptions(), ExpressionPathAftermath *final_task_on_target=nullptr)
virtual uint64_t GetValueAsUnsigned(uint64_t fail_value, bool *success=nullptr)
virtual ConstString GetTypeName()
lldb::DynamicValueType GetDynamicValueType()
uint32_t GetTypeInfo(CompilerType *pointee_or_element_compiler_type=nullptr)
lldb::ValueObjectSP GetQualifiedRepresentationIfAvailable(lldb::DynamicValueType dynValue, bool synthValue)
lldb::TargetSP GetTargetSP() const
@ eExpressionPathEndResultTypePlain
Anything but...
@ eExpressionPathEndResultTypeBoundedRange
A range [low-high].
@ eExpressionPathEndResultTypeUnboundedRange
A range [].
virtual lldb::ValueObjectSP Dereference(Status &error)
CompilerType GetCompilerType()
bool HasSpecialPrintableRepresentation(ValueObjectRepresentationStyle val_obj_display, lldb::Format custom_format)
virtual const char * GetLocationAsCString()
virtual int64_t GetValueAsSigned(int64_t fail_value, bool *success=nullptr)
virtual bool IsSynthetic()
uint32_t GetNumChildrenIgnoringErrors(uint32_t max=UINT32_MAX)
Like GetNumChildren but returns 0 on error.
lldb::VariableSP GetVariableAtIndex(size_t idx) const
size_t AppendVariablesWithScope(lldb::ValueType type, VariableList &var_list, bool if_unique=true)
#define UINT64_MAX
#define LLDB_REGNUM_GENERIC_SP
#define LLDB_REGNUM_GENERIC_FLAGS
#define LLDB_INVALID_ADDRESS
#define LLDB_INVALID_REGNUM
#define LLDB_REGNUM_GENERIC_FP
bool FormatFileSpec(const FileSpec &file, Stream &s, llvm::StringRef elements, llvm::StringRef element_format)
Status Parse(const llvm::StringRef &format, Entry &entry)
Status ExtractVariableInfo(llvm::StringRef &format_str, llvm::StringRef &variable_name, llvm::StringRef &variable_format)
void PrettyPrintFunctionArguments(Stream &out_stream, VariableList const &args, ExecutionContextScope *exe_scope)
For each variable in 'args' this function writes the variable name and it's pretty-printed value repr...
void AutoComplete(lldb_private::CompletionRequest &request)
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:338
void DumpRegisterValue(const RegisterValue &reg_val, Stream &s, const RegisterInfo &reg_info, bool prefix_with_name, bool prefix_with_alt_name, lldb::Format format, uint32_t reg_name_right_align_at=0, ExecutionContextScope *exe_scope=nullptr, bool print_type=false, lldb::TargetSP target_sp=nullptr)
std::string toString(FormatterBytecode::OpCodes op)
std::shared_ptr< lldb_private::StackFrame > StackFrameSP
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
std::shared_ptr< lldb_private::ExpressionVariable > ExpressionVariableSP
Format
Display format definitions.
std::shared_ptr< lldb_private::VariableList > VariableListSP
std::shared_ptr< lldb_private::Variable > VariableSP
@ eValueTypeVariableArgument
function argument variables
std::shared_ptr< lldb_private::StopInfo > StopInfoSP
uint64_t addr_t
Definition lldb-types.h:80
@ eStructuredDataTypeFloat
@ eStructuredDataTypeDictionary
@ eStructuredDataTypeInteger
@ eStructuredDataTypeArray
@ eStructuredDataTypeString
std::shared_ptr< lldb_private::RegisterContext > RegisterContextSP
RegisterKind
Register numbering types.
@ eRegisterKindGeneric
insn ptr reg, stack ptr reg, etc not specific to any particular target
const char * name
The name/string placeholder that corresponds to this definition.
const Definition * children
An array of "num_children" Definition entries.
const bool keep_separator
Whether the separator is kept during parsing or not.
const char * string
Insert this exact string into the output.
const uint64_t data
Data that is returned as the value of the format string.
const uint32_t num_children
The number of children of this node in the tree of format strings.
const Entry::Type type
Entry::Type corresponding to this definition.
void Dump(Stream &s, int depth=0) const
Entry(Type t=Type::Invalid, const char *s=nullptr, const char *f=nullptr)
void AppendText(const llvm::StringRef &s)
static constexpr Definition DefinitionWithChildren(const char *name, const FormatEntity::Entry::Type t, const Definition(&children)[N], bool keep_separator=false)
llvm::SmallVector< std::vector< Entry >, 1 > children_stack
A stack of children entries, used by Scope entries to provide alterantive children.
std::vector< Entry > & GetChildren()
static const char * TypeToCString(Type t)
void AppendEntry(const Entry &&entry)
Every register is described in detail including its name, alternate name (optional),...
bool FormatObject(ValueObject *valobj, std::string &dest, const TypeSummaryOptions &options) override
GetValueForExpressionPathOptions & SetSyntheticChildrenTraversal(SyntheticChildrenTraversal traverse)
GetValueForExpressionPathOptions & DoAllowFragileIVar()
GetValueForExpressionPathOptions & DontCheckDotVsArrowSyntax()
GetValueForExpressionPathOptions & DoAllowBitfieldSyntax()