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