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"
23#include "lldb/Symbol/Block.h"
28#include "lldb/Symbol/Symbol.h"
35#include "lldb/Target/Process.h"
40#include "lldb/Target/Target.h"
41#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::FrameRegisterTypeFlags),
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.PutCString("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.PutCString(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().empty()) {
630 s << file.GetFilename();
631 return true;
632 }
633 break;
634
636 if (!file.GetDirectory().empty()) {
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.Format("{0}:{1}", target->GetTypeName(),
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 llvm::StringRef additional_data(
1008 subpath.drop_front(close_bracket_index + 1));
1009 special_directions_stream
1010 << "${"
1011 << llvm::formatv("{0}var{1}", do_deref_pointer ? "*" : "",
1012 additional_data);
1013
1014 if (entry.fmt != eFormatDefault) {
1015 const char format_char =
1017 if (format_char != '\0')
1018 special_directions_stream.Printf("%%%c", format_char);
1019 else {
1020 const char *format_cstr =
1022 special_directions_stream.Printf("%%%s", format_cstr);
1023 }
1024 } else if (entry.number != 0) {
1025 const char style_char = ConvertValueObjectStyleToChar(
1027 if (style_char)
1028 special_directions_stream.Printf("%%%c", style_char);
1029 }
1030 special_directions_stream.PutChar('}');
1031 special_directions =
1032 llvm::StringRef(special_directions_stream.GetString());
1033 }
1034
1035 // let us display items index_lower thru index_higher of this array
1036 s.PutChar('[');
1037
1038 if (index_higher < 0)
1039 index_higher = valobj->GetNumChildrenIgnoringErrors() - 1;
1040
1041 uint32_t max_num_children =
1042 target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay();
1043
1044 bool success = true;
1045 for (int64_t index = index_lower; index <= index_higher; ++index) {
1046 ValueObject *item = ExpandIndexedExpression(target, index, false).get();
1047
1048 if (!item) {
1049 LLDB_LOGF(log,
1050 "[Debugger::FormatPrompt] ERROR in getting child item at "
1051 "index %" PRId64,
1052 index);
1053 } else {
1054 LLDB_LOGF(
1055 log,
1056 "[Debugger::FormatPrompt] special_directions for child item: %s",
1057 special_directions.data() ? special_directions.data() : "");
1058 }
1059
1060 if (special_directions.empty()) {
1061 success &= item->DumpPrintableRepresentation(s, val_obj_display,
1062 custom_format);
1063 } else {
1064 success &= FormatStringRef(special_directions, s, item);
1065 }
1066
1067 if (--max_num_children == 0) {
1068 s.PutCString(", ...");
1069 break;
1070 }
1071
1072 if (index < index_higher)
1073 s.PutChar(',');
1074 }
1075 s.PutChar(']');
1076 return success;
1077 }
1078}
1079
1080static bool DumpRegister(Stream &s, StackFrame *frame, const char *reg_name,
1081 Format format) {
1082 if (frame) {
1083 RegisterContext *reg_ctx = frame->GetRegisterContext().get();
1084
1085 if (reg_ctx) {
1086 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
1087 if (reg_info) {
1088 RegisterValue reg_value;
1089 if (reg_ctx->ReadRegister(reg_info, reg_value)) {
1090 DumpRegisterValue(reg_value, s, *reg_info, false, false, format);
1091 return true;
1092 }
1093 }
1094 }
1095 }
1096 return false;
1097}
1098
1100 const FormatEntity::Entry &entry,
1101 const StructuredData::ObjectSP &thread_info_dictionary,
1102 const SymbolContext *sc, const ExecutionContext *exe_ctx, Stream &s) {
1103 llvm::StringRef path(entry.string);
1104
1106 thread_info_dictionary->GetObjectForDotSeparatedPath(path);
1107
1108 if (value) {
1109 if (value->GetType() == eStructuredDataTypeInteger) {
1110 const char *token_format = "0x%4.4" PRIx64;
1111 if (!entry.printf_format.empty())
1112 token_format = entry.printf_format.c_str();
1113 s.Printf(token_format, value->GetUnsignedIntegerValue());
1114 return true;
1115 } else if (value->GetType() == eStructuredDataTypeFloat) {
1116 s.Printf("%f", value->GetAsFloat()->GetValue());
1117 return true;
1118 } else if (value->GetType() == eStructuredDataTypeString) {
1119 s.Format("{0}", value->GetAsString()->GetValue());
1120 return true;
1121 } else if (value->GetType() == eStructuredDataTypeArray) {
1122 if (value->GetAsArray()->GetSize() > 0) {
1123 s.Printf("%zu", value->GetAsArray()->GetSize());
1124 return true;
1125 }
1126 } else if (value->GetType() == eStructuredDataTypeDictionary) {
1127 s.Printf("%zu",
1128 value->GetAsDictionary()->GetKeys()->GetAsArray()->GetSize());
1129 return true;
1130 }
1131 }
1132
1133 return false;
1134}
1135
1136static inline bool IsToken(const char *var_name_begin, const char *var) {
1137 return (::strncmp(var_name_begin, var, strlen(var)) == 0);
1138}
1139
1140/// Parses the basename out of a demangled function name
1141/// that may include function arguments. Supports
1142/// template functions.
1143///
1144/// Returns pointers to the opening and closing parenthesis of
1145/// `full_name`. Can return nullptr for either parenthesis if
1146/// none is exists.
1147static std::pair<char const *, char const *>
1148ParseBaseName(char const *full_name) {
1149 const char *open_paren = strchr(full_name, '(');
1150 const char *close_paren = nullptr;
1151 const char *generic = strchr(full_name, '<');
1152 // if before the arguments list begins there is a template sign
1153 // then scan to the end of the generic args before you try to find
1154 // the arguments list
1155 if (generic && open_paren && generic < open_paren) {
1156 int generic_depth = 1;
1157 ++generic;
1158 for (; *generic && generic_depth > 0; generic++) {
1159 if (*generic == '<')
1160 generic_depth++;
1161 if (*generic == '>')
1162 generic_depth--;
1163 }
1164 if (*generic)
1165 open_paren = strchr(generic, '(');
1166 else
1167 open_paren = nullptr;
1168 }
1169
1170 if (open_paren) {
1171 if (IsToken(open_paren, "(anonymous namespace)")) {
1172 open_paren = strchr(open_paren + strlen("(anonymous namespace)"), '(');
1173 if (open_paren)
1174 close_paren = strchr(open_paren, ')');
1175 } else
1176 close_paren = strchr(open_paren, ')');
1177 }
1178
1179 return {open_paren, close_paren};
1180}
1181
1182/// Writes out the function name in 'full_name' to 'out_stream'
1183/// but replaces each argument type with the variable name
1184/// and the corresponding pretty-printed value
1186 char const *full_name,
1187 ExecutionContextScope *exe_scope,
1188 VariableList const &args) {
1189 auto [open_paren, close_paren] = ParseBaseName(full_name);
1190 if (open_paren)
1191 out_stream.Write(full_name, open_paren - full_name + 1);
1192 else {
1193 out_stream.PutCString(full_name);
1194 out_stream.PutChar('(');
1195 }
1196
1197 FormatEntity::PrettyPrintFunctionArguments(out_stream, args, exe_scope);
1198
1199 if (close_paren)
1200 out_stream.PutCString(close_paren);
1201 else
1202 out_stream.PutChar(')');
1203}
1204
1206 assert(sc.function);
1207
1208 if (sc.block)
1209 if (Block *inline_block = sc.block->GetContainingInlinedBlock())
1210 return inline_block->GetBlockVariableList(true);
1211
1212 return sc.function->GetBlock(true).GetBlockVariableList(true);
1213}
1214
1216 const ExecutionContext *exe_ctx,
1217 const SymbolContext &sc) {
1218 assert(sc.function);
1219
1220 ExecutionContextScope *exe_scope =
1221 exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr;
1222
1223 const char *cstr = sc.GetPossiblyInlinedFunctionName()
1225 .AsCString(nullptr);
1226 if (!cstr)
1227 return false;
1228
1229 VariableList args;
1230 if (auto variable_list_sp = GetFunctionVariableList(sc))
1232 args);
1233
1234 if (args.GetSize() > 0) {
1235 PrettyPrintFunctionNameWithArgs(s, cstr, exe_scope, args);
1236 } else {
1237 s.PutCString(cstr);
1238 }
1239
1240 return true;
1241}
1242
1244 const ExecutionContext *exe_ctx,
1245 const SymbolContext &sc) {
1246 Language *language_plugin = nullptr;
1247 bool language_plugin_handled = false;
1248 StreamString ss;
1249 if (sc.function)
1250 language_plugin = Language::FindPlugin(sc.function->GetLanguage());
1251 else if (sc.symbol)
1252 language_plugin = Language::FindPlugin(sc.symbol->GetLanguage());
1253
1254 if (language_plugin)
1255 language_plugin_handled = language_plugin->GetFunctionDisplayName(
1257
1258 if (language_plugin_handled) {
1259 s << ss.GetString();
1260 return true;
1261 }
1262
1263 if (sc.function)
1264 return PrintFunctionNameWithArgs(s, exe_ctx, sc);
1265
1266 if (!sc.symbol)
1267 return false;
1268
1269 const char *cstr = sc.symbol->GetName().AsCString(nullptr);
1270 if (!cstr)
1271 return false;
1272
1273 s.PutCString(cstr);
1274
1275 return true;
1276}
1277
1279 assert(m_sc);
1280
1281 Language *language_plugin = nullptr;
1282 if (m_sc->function)
1283 language_plugin = Language::FindPlugin(m_sc->function->GetLanguage());
1284 else if (m_sc->symbol)
1285 language_plugin = Language::FindPlugin(m_sc->symbol->GetLanguage());
1286
1287 if (!language_plugin)
1288 return false;
1289
1290 FormatEntity::Entry format = language_plugin->GetFunctionNameFormat();
1291
1292 // Bail on invalid or empty format.
1293 if (!format || format == FormatEntity::Entry(Entry::Type::Root))
1294 return false;
1295
1296 StreamString name_stream;
1297 const bool success = Format(format, name_stream, /*valobj=*/nullptr);
1298 if (success)
1299 s << name_stream.GetString();
1300
1301 return success;
1302}
1303
1304bool FormatEntity::Formatter::FormatStringRef(const llvm::StringRef &format_str,
1305 Stream &s, ValueObject *valobj) {
1306 if (!format_str.empty()) {
1308 Status error = FormatEntity::Parse(format_str, root);
1309 if (error.Success()) {
1310 return Format(root, s, valobj);
1311 }
1312 }
1313 return false;
1314}
1315
1317 ValueObject *valobj) {
1318 if (IsInvalidRecursiveFormat(entry.type)) {
1320 "Error: detected recursive format entity: {0}",
1322 return false;
1323 }
1324
1325 auto entry_stack_guard = PushEntryType(entry.type);
1326
1327 switch (entry.type) {
1329 case Entry::Type::ParentNumber: // Only used for
1330 // FormatEntity::Entry::Definition encoding
1331 case Entry::Type::ParentString: // Only used for
1332 // FormatEntity::Entry::Definition encoding
1333 return false;
1336 Debugger &debugger = target->GetDebugger();
1337 if (debugger.GetUseColor()) {
1338 s.PutCString(entry.string);
1339 }
1340 }
1341 // Always return true, so colors being disabled is transparent.
1342 return true;
1343
1344 case Entry::Type::Root:
1345 for (const auto &child : entry.children_stack[0]) {
1346 if (!Format(child, s, valobj)) {
1347 return false; // If any item of root fails, then the formatting fails
1348 }
1349 }
1350 return true; // Only return true if all items succeeded
1351
1353 s.PutCString(entry.string);
1354 return true;
1355
1356 case Entry::Type::Scope: {
1357 StreamString scope_stream;
1358 auto format_children = [&](const std::vector<Entry> &children) {
1359 scope_stream.Clear();
1360 for (const auto &child : children) {
1361 if (!Format(child, scope_stream, valobj))
1362 return false;
1363 }
1364 return true;
1365 };
1366
1367 for (auto &children : entry.children_stack) {
1368 if (format_children(children)) {
1369 s.Write(scope_stream.GetString().data(),
1370 scope_stream.GetString().size());
1371 return true;
1372 }
1373 }
1374
1375 return true; // Scopes always successfully print themselves
1376 }
1377
1382 return DumpValue(s, entry, valobj);
1383
1387 return (
1388 m_addr != nullptr && m_addr->IsValid() &&
1391
1393 if (m_exe_ctx) {
1394 Process *process = m_exe_ctx->GetProcessPtr();
1395 if (process) {
1396 const char *format = "%" PRIu64;
1397 if (!entry.printf_format.empty())
1398 format = entry.printf_format.c_str();
1399 s.Printf(format, process->GetID());
1400 return true;
1401 }
1402 }
1403 return false;
1404
1406 if (m_exe_ctx) {
1407 Process *process = m_exe_ctx->GetProcessPtr();
1408 if (process) {
1409 Module *exe_module = process->GetTarget().GetExecutableModulePointer();
1410 if (exe_module) {
1411 if (DumpFile(s, exe_module->GetFileSpec(), (FileKind)entry.number))
1412 return true;
1413 }
1414 }
1415 }
1416 return false;
1417
1419 if (m_exe_ctx) {
1420 Process *process = m_exe_ctx->GetProcessPtr();
1421 if (process)
1422 return RunScriptFormatKeyword(s, m_sc, m_exe_ctx, process,
1423 entry.string.c_str());
1424 }
1425 return false;
1426
1428 if (m_exe_ctx) {
1429 Thread *thread = m_exe_ctx->GetThreadPtr();
1430 if (thread) {
1431 const char *format = "0x%4.4" PRIx64;
1432 if (!entry.printf_format.empty()) {
1433 // Watch for the special "tid" format...
1434 if (entry.printf_format == "tid") {
1435 // TODO(zturner): Rather than hardcoding this to be platform
1436 // specific, it should be controlled by a setting and the default
1437 // value of the setting can be different depending on the platform.
1438 Target &target = thread->GetProcess()->GetTarget();
1439 ArchSpec arch(target.GetArchitecture());
1440 llvm::Triple::OSType ostype = arch.IsValid()
1441 ? arch.GetTriple().getOS()
1442 : llvm::Triple::UnknownOS;
1443 if (ostype == llvm::Triple::FreeBSD ||
1444 ostype == llvm::Triple::Linux ||
1445 ostype == llvm::Triple::NetBSD ||
1446 ostype == llvm::Triple::OpenBSD) {
1447 format = "%" PRIu64;
1448 }
1449 } else {
1450 format = entry.printf_format.c_str();
1451 }
1452 }
1453 s.Printf(format, thread->GetID());
1454 return true;
1455 }
1456 }
1457 return false;
1458
1460 if (m_exe_ctx) {
1461 Thread *thread = m_exe_ctx->GetThreadPtr();
1462 if (thread) {
1463 const char *format = "0x%4.4" PRIx64;
1464 if (!entry.printf_format.empty())
1465 format = entry.printf_format.c_str();
1466 s.Printf(format, thread->GetProtocolID());
1467 return true;
1468 }
1469 }
1470 return false;
1471
1473 if (m_exe_ctx) {
1474 Thread *thread = m_exe_ctx->GetThreadPtr();
1475 if (thread) {
1476 const char *format = "%" PRIu32;
1477 if (!entry.printf_format.empty())
1478 format = entry.printf_format.c_str();
1479 s.Printf(format, thread->GetIndexID());
1480 return true;
1481 }
1482 }
1483 return false;
1484
1486 if (m_exe_ctx) {
1487 Thread *thread = m_exe_ctx->GetThreadPtr();
1488 if (thread) {
1489 const char *cstr = thread->GetName();
1490 if (cstr && cstr[0]) {
1491 s.PutCString(cstr);
1492 return true;
1493 }
1494 }
1495 }
1496 return false;
1497
1499 if (m_exe_ctx) {
1500 Thread *thread = m_exe_ctx->GetThreadPtr();
1501 if (thread) {
1502 const char *cstr = thread->GetQueueName();
1503 if (cstr && cstr[0]) {
1504 s.PutCString(cstr);
1505 return true;
1506 }
1507 }
1508 }
1509 return false;
1510
1512 if (m_exe_ctx) {
1513 if (Thread *thread = m_exe_ctx->GetThreadPtr()) {
1514 std::string stop_description = thread->GetStopDescription();
1515 if (!stop_description.empty()) {
1516 s.PutCString(stop_description);
1517 return true;
1518 }
1519 }
1520 }
1521 return false;
1522
1524 if (m_exe_ctx) {
1525 if (Thread *thread = m_exe_ctx->GetThreadPtr()) {
1526 std::string stop_description = thread->GetStopDescriptionRaw();
1527 if (!stop_description.empty()) {
1528 s.PutCString(stop_description);
1529 return true;
1530 }
1531 }
1532 }
1533 return false;
1534
1536 if (m_exe_ctx) {
1537 Thread *thread = m_exe_ctx->GetThreadPtr();
1538 if (thread) {
1539 StopInfoSP stop_info_sp = thread->GetStopInfo();
1540 if (stop_info_sp && stop_info_sp->IsValid()) {
1541 ValueObjectSP return_valobj_sp =
1542 StopInfo::GetReturnValueObject(stop_info_sp);
1543 if (return_valobj_sp) {
1544 DumpValueObjectOptions options;
1545 if (return_valobj_sp->IsDynamic())
1547 if (return_valobj_sp->DoesProvideSyntheticValue())
1548 options.SetUseSyntheticValue(true);
1549 if (llvm::Error error = return_valobj_sp->Dump(s, options)) {
1550 s << "error: " << toString(std::move(error));
1551 return false;
1552 }
1553 return true;
1554 }
1555 }
1556 }
1557 }
1558 return false;
1559
1561 if (m_exe_ctx) {
1562 Thread *thread = m_exe_ctx->GetThreadPtr();
1563 if (thread) {
1564 StopInfoSP stop_info_sp = thread->GetStopInfo();
1565 if (stop_info_sp && stop_info_sp->IsValid()) {
1566 ExpressionVariableSP expression_var_sp =
1567 StopInfo::GetExpressionVariable(stop_info_sp);
1568 if (expression_var_sp && expression_var_sp->GetValueObject()) {
1569 if (llvm::Error error =
1570 expression_var_sp->GetValueObject()->Dump(s)) {
1571 s << "error: " << toString(std::move(error));
1572 return false;
1573 }
1574 return true;
1575 }
1576 }
1577 }
1578 }
1579 return false;
1580
1582 if (m_exe_ctx) {
1583 Thread *thread = m_exe_ctx->GetThreadPtr();
1584 if (thread)
1585 return RunScriptFormatKeyword(s, m_sc, m_exe_ctx, thread,
1586 entry.string.c_str());
1587 }
1588 return false;
1589
1591 if (m_exe_ctx) {
1592 Thread *thread = m_exe_ctx->GetThreadPtr();
1593 if (thread) {
1594 StructuredData::ObjectSP object_sp = thread->GetExtendedInfo();
1595 if (object_sp &&
1596 object_sp->GetType() == eStructuredDataTypeDictionary) {
1597 if (FormatThreadExtendedInfoRecurse(entry, object_sp, m_sc, m_exe_ctx,
1598 s))
1599 return true;
1600 }
1601 }
1602 }
1603 return false;
1604
1606 if (m_exe_ctx) {
1607 Target *target = m_exe_ctx->GetTargetPtr();
1608 if (target) {
1609 const ArchSpec &arch = target->GetArchitecture();
1610 if (arch.IsValid()) {
1612 return true;
1613 }
1614 }
1615 }
1616 return false;
1617
1619 if (m_exe_ctx) {
1620 if (Target *target = m_exe_ctx->GetTargetPtr()) {
1621 if (Module *exe_module = target->GetExecutableModulePointer()) {
1622 if (DumpFile(s, exe_module->GetFileSpec(), (FileKind)entry.number))
1623 return true;
1624 }
1625 }
1626 }
1627 return false;
1628
1630 if (m_exe_ctx) {
1631 Target *target = m_exe_ctx->GetTargetPtr();
1632 if (target)
1633 return RunScriptFormatKeyword(s, m_sc, m_exe_ctx, target,
1634 entry.string.c_str());
1635 }
1636 return false;
1637
1639 if (m_sc) {
1640 Module *module = m_sc->module_sp.get();
1641 if (module) {
1642 if (DumpFile(s, module->GetFileSpec(), (FileKind)entry.number))
1643 return true;
1644 }
1645 }
1646 return false;
1647
1648 case Entry::Type::File:
1649 if (m_sc) {
1650 CompileUnit *cu = m_sc->comp_unit;
1651 if (cu) {
1652 if (DumpFile(s, cu->GetPrimaryFile(), (FileKind)entry.number))
1653 return true;
1654 }
1655 }
1656 return false;
1657
1658 case Entry::Type::Lang:
1659 if (m_sc) {
1660 CompileUnit *cu = m_sc->comp_unit;
1661 if (cu) {
1662 const char *lang_name =
1664 if (lang_name) {
1665 s.PutCString(lang_name);
1666 return true;
1667 }
1668 }
1669 }
1670 return false;
1671
1673 if (m_exe_ctx) {
1674 StackFrame *frame = m_exe_ctx->GetFramePtr();
1675 if (frame) {
1676 const char *format = "%" PRIu32;
1677 if (!entry.printf_format.empty())
1678 format = entry.printf_format.c_str();
1679 s.Printf(format, frame->GetFrameIndex());
1680 return true;
1681 }
1682 }
1683 return false;
1684
1686 if (m_exe_ctx) {
1687 StackFrame *frame = m_exe_ctx->GetFramePtr();
1688 if (frame) {
1689 const Address &pc_addr = frame->GetFrameCodeAddress();
1690 if (pc_addr.IsValid())
1691 if (DumpAddressAndContent(s, m_sc, m_exe_ctx, pc_addr, false))
1692 return true;
1693 }
1694 }
1695 return false;
1696
1698 if (m_exe_ctx) {
1699 StackFrame *frame = m_exe_ctx->GetFramePtr();
1700 if (frame) {
1702 (lldb::Format)entry.number))
1703 return true;
1704 }
1705 }
1706 return false;
1707
1709 if (m_exe_ctx) {
1710 StackFrame *frame = m_exe_ctx->GetFramePtr();
1711 if (frame) {
1713 (lldb::Format)entry.number))
1714 return true;
1715 }
1716 }
1717 return false;
1718
1720 if (m_exe_ctx) {
1721 StackFrame *frame = m_exe_ctx->GetFramePtr();
1722 if (frame) {
1723 if (DumpRegister(s, frame, eRegisterKindGeneric,
1725 return true;
1726 }
1727 }
1728 return false;
1729
1731 if (m_exe_ctx) {
1732 StackFrame *frame = m_exe_ctx->GetFramePtr();
1733 if (frame) {
1734 return !frame->HasDebugInformation();
1735 }
1736 }
1737 return true;
1738
1740 if (m_exe_ctx) {
1741 StackFrame *frame = m_exe_ctx->GetFramePtr();
1742 if (frame) {
1743 if (DumpRegister(s, frame, entry.string.c_str(),
1744 (lldb::Format)entry.number))
1745 return true;
1746 }
1747 }
1748 return false;
1749
1751 if (m_exe_ctx)
1752 if (StackFrame *frame = m_exe_ctx->GetFramePtr())
1753 return frame->IsArtificial();
1754 return false;
1755 }
1756
1758 if (m_exe_ctx)
1759 if (StackFrame *frame = m_exe_ctx->GetFramePtr()) {
1760 if (frame->IsSynthetic())
1761 s.PutCString(" [synthetic]");
1762 else if (frame->IsHistorical())
1763 s.PutCString(" [history]");
1764 return true;
1765 }
1766 return false;
1767 }
1768
1770 if (m_exe_ctx)
1771 if (StackFrame *frame = m_exe_ctx->GetFramePtr()) {
1772 if (BorrowedStackFrame *borrowed_frame =
1773 llvm::dyn_cast<BorrowedStackFrame>(frame)) {
1774 if (lldb::StackFrameSP borrowed_from_sp =
1775 borrowed_frame->GetBorrowedFrame()) {
1776 s.Printf(" [borrowed from frame #%u]",
1777 borrowed_from_sp->GetFrameIndex());
1778 return true;
1779 }
1780 }
1781 }
1782 return false;
1783 }
1784
1786 if (m_exe_ctx) {
1787 StackFrame *frame = m_exe_ctx->GetFramePtr();
1788 if (frame)
1789 return RunScriptFormatKeyword(s, m_sc, m_exe_ctx, frame,
1790 entry.string.c_str());
1791 }
1792 return false;
1793
1795 if (m_sc) {
1796 if (m_sc->function) {
1797 s.Printf("function{0x%8.8" PRIx64 "}", m_sc->function->GetID());
1798 return true;
1799 } else if (m_sc->symbol) {
1800 s.Printf("symbol[%u]", m_sc->symbol->GetID());
1801 return true;
1802 }
1803 }
1804 return false;
1805
1807 return m_function_changed;
1808
1810 return m_initial_function;
1811
1813 if (m_sc) {
1814 Language *language_plugin = nullptr;
1815 bool language_plugin_handled = false;
1816 StreamString ss;
1817
1818 if (m_sc->function)
1819 language_plugin = Language::FindPlugin(m_sc->function->GetLanguage());
1820 else if (m_sc->symbol)
1821 language_plugin = Language::FindPlugin(m_sc->symbol->GetLanguage());
1822
1823 if (language_plugin)
1824 language_plugin_handled = language_plugin->GetFunctionDisplayName(
1826
1827 if (language_plugin_handled) {
1828 s << ss.GetString();
1829 return true;
1830 }
1831
1832 const char *name = m_sc->GetPossiblyInlinedFunctionName()
1834 .AsCString(nullptr);
1835 if (name) {
1836 s.PutCString(name);
1837 return true;
1838 }
1839 }
1840
1841 // Fallback to frame methods if available.
1842 if (m_exe_ctx) {
1843 StackFrame *frame = m_exe_ctx->GetFramePtr();
1844 if (frame) {
1845 const char *name = frame->GetFunctionName();
1846 if (name) {
1847 s.PutCString(name);
1848 return true;
1849 }
1850 }
1851 }
1852 return false;
1853 }
1854
1856 if (m_sc) {
1857 Language *language_plugin = nullptr;
1858 bool language_plugin_handled = false;
1859 StreamString ss;
1860 if (m_sc->function)
1861 language_plugin = Language::FindPlugin(m_sc->function->GetLanguage());
1862 else if (m_sc->symbol)
1863 language_plugin = Language::FindPlugin(m_sc->symbol->GetLanguage());
1864
1865 if (language_plugin)
1866 language_plugin_handled = language_plugin->GetFunctionDisplayName(
1867 *m_sc, m_exe_ctx,
1869
1870 if (language_plugin_handled) {
1871 s << ss.GetString();
1872 return true;
1873 }
1874
1875 const char *name =
1876 m_sc->GetPossiblyInlinedFunctionName()
1877 .GetName(
1879 .AsCString(nullptr);
1880 if (name) {
1881 s.PutCString(name);
1882 return true;
1883 }
1884 }
1885
1886 // Fallback to frame methods if available.
1887 if (m_exe_ctx) {
1888 StackFrame *frame = m_exe_ctx->GetFramePtr();
1889 if (frame) {
1890 const char *name = frame->GetFunctionName();
1891 if (name) {
1892 s.PutCString(name);
1893 return true;
1894 }
1895 }
1896 }
1897 return false;
1898 }
1899
1910 Language *language_plugin = nullptr;
1911 if (m_sc->function)
1912 language_plugin = Language::FindPlugin(m_sc->function->GetLanguage());
1913 else if (m_sc->symbol)
1914 language_plugin = Language::FindPlugin(m_sc->symbol->GetLanguage());
1915
1916 if (!language_plugin)
1917 return false;
1918
1919 return language_plugin->HandleFrameFormatVariable(*m_sc, m_exe_ctx,
1920 entry.type, s);
1921 }
1922
1924 if (m_sc) {
1926 return true;
1927
1929 return true;
1930 }
1931
1932 // Fallback to frame methods if available.
1933 if (m_exe_ctx) {
1934 StackFrame *frame = m_exe_ctx->GetFramePtr();
1935 if (frame) {
1936 const char *name = frame->GetDisplayFunctionName();
1937 if (name) {
1938 s.PutCString(name);
1939 return true;
1940 }
1941 }
1942 }
1943 return false;
1944 }
1946 if (!m_sc)
1947 return false;
1948
1949 const char *name = m_sc->GetPossiblyInlinedFunctionName()
1951 .AsCString(nullptr);
1952 if (!name)
1953 return false;
1954
1955 s.PutCString(name);
1956
1957 return true;
1958 }
1960 if (m_addr) {
1962 false, false))
1963 return true;
1964 }
1965 return false;
1966
1968 if (m_addr) {
1969 if (DumpAddressOffsetFromFunction(s, m_sc, m_exe_ctx, *m_addr, true, true,
1970 true))
1971 return true;
1972 }
1973 return false;
1974
1976 if (m_sc)
1978 s, m_sc, m_exe_ctx, m_sc->line_entry.range.GetBaseAddress(), false,
1979 false, false));
1980 return false;
1981
1983 if (m_exe_ctx) {
1984 StackFrame *frame = m_exe_ctx->GetFramePtr();
1985 if (frame)
1987 frame->GetFrameCodeAddress(), false,
1988 false, false))
1989 return true;
1990 }
1991 return false;
1992
1994 return m_function_changed;
1995
1997 bool is_optimized = false;
1998 if (m_sc && m_sc->function && m_sc->function->GetIsOptimized()) {
1999 is_optimized = true;
2000 }
2001 return is_optimized;
2002 }
2003
2005 return m_sc && m_sc->block && m_sc->block->GetInlinedFunctionInfo();
2006 }
2007
2009 return m_initial_function;
2010
2012 if (m_sc && m_sc->line_entry.IsValid()) {
2013 if (DumpFile(s, m_sc->line_entry.GetFile(), (FileKind)entry.number))
2014 return true;
2015 }
2016 return false;
2017
2019 if (m_sc && m_sc->line_entry.IsValid()) {
2020 const char *format = "%" PRIu32;
2021 if (!entry.printf_format.empty())
2022 format = entry.printf_format.c_str();
2023 s.Printf(format, m_sc->line_entry.line);
2024 return true;
2025 }
2026 return false;
2027
2029 if (m_sc && m_sc->line_entry.IsValid() && m_sc->line_entry.column) {
2030 const char *format = "%" PRIu32;
2031 if (!entry.printf_format.empty())
2032 format = entry.printf_format.c_str();
2033 s.Printf(format, m_sc->line_entry.column);
2034 return true;
2035 }
2036 return false;
2037
2040 if (m_sc && m_sc->line_entry.range.GetBaseAddress().IsValid()) {
2041 Address addr = m_sc->line_entry.range.GetBaseAddress();
2042
2044 addr.Slide(m_sc->line_entry.range.GetByteSize());
2045 if (DumpAddressAndContent(s, m_sc, m_exe_ctx, addr, false))
2046 return true;
2047 }
2048 return false;
2049
2051 if (m_addr && m_exe_ctx && m_exe_ctx->GetFramePtr()) {
2052 RegisterContextSP reg_ctx =
2053 m_exe_ctx->GetFramePtr()->GetRegisterContextSP();
2054 if (reg_ctx) {
2055 addr_t pc_loadaddr = reg_ctx->GetPC();
2056 if (pc_loadaddr != LLDB_INVALID_ADDRESS) {
2057 Address pc;
2058 pc.SetLoadAddress(pc_loadaddr, m_exe_ctx->GetTargetPtr());
2059 if (pc == *m_addr) {
2060 s.PutCString("-> ");
2061 return true;
2062 }
2063 }
2064 }
2065 s.PutCString(" ");
2066 return true;
2067 }
2068 return false;
2069
2072 if (auto progress = target->GetDebugger().GetCurrentProgressReport()) {
2073 if (progress->total != UINT64_MAX) {
2074 s.Format("[{0:N}/{1:N}]", progress->completed, progress->total);
2075 return true;
2076 }
2077 }
2078 }
2079 return false;
2080
2083 if (auto progress = target->GetDebugger().GetCurrentProgressReport()) {
2084 s.PutCString(progress->message);
2085 return true;
2086 }
2087 }
2088 return false;
2089
2092 s << target->GetDebugger().GetSeparator();
2093 return true;
2094 }
2095 return false;
2096 }
2097
2098 return false;
2099}
2100
2102 const Definition *parent) {
2103 if (parent->children) {
2104 const size_t n = parent->num_children;
2105 for (size_t i = 0; i < n; ++i) {
2106 if (i > 0)
2107 s.PutCString(", ");
2108 s.Printf("\"%s\"", parent->children[i].name);
2109 }
2110 return true;
2111 }
2112 return false;
2113}
2114
2115static Status ParseEntry(const llvm::StringRef &format_str,
2116 const Definition *parent, FormatEntity::Entry &entry) {
2117 Status error;
2118
2119 const size_t sep_pos = format_str.find_first_of(".[:");
2120 const char sep_char =
2121 (sep_pos == llvm::StringRef::npos) ? '\0' : format_str[sep_pos];
2122 llvm::StringRef key = format_str.substr(0, sep_pos);
2123
2124 const size_t n = parent->num_children;
2125 for (size_t i = 0; i < n; ++i) {
2126 const Definition *entry_def = parent->children + i;
2127 if (key == entry_def->name || entry_def->name[0] == '*') {
2128 llvm::StringRef value;
2129 if (sep_char)
2130 value =
2131 format_str.substr(sep_pos + (entry_def->keep_separator ? 0 : 1));
2132 switch (entry_def->type) {
2134 entry.string = format_str.str();
2135 return error; // Success
2136
2138 entry.number = entry_def->data;
2139 return error; // Success
2140
2142 entry.type = entry_def->type;
2143 entry.string = entry_def->string;
2144 return error; // Success
2145
2146 default:
2147 entry.type = entry_def->type;
2148 break;
2149 }
2150
2151 if (value.empty()) {
2152 if (entry_def->type == FormatEntity::Entry::Type::Invalid) {
2153 if (entry_def->children) {
2154 StreamString error_strm;
2155 error_strm.Printf("'%s' can't be specified on its own, you must "
2156 "access one of its children: ",
2157 entry_def->name);
2158 DumpCommaSeparatedChildEntryNames(error_strm, entry_def);
2159 error =
2160 Status::FromErrorStringWithFormat("%s", error_strm.GetData());
2161 } else if (sep_char == ':') {
2162 // Any value whose separator is a with a ':' means this value has a
2163 // string argument that needs to be stored in the entry (like
2164 // "${script.var:}"). In this case the string value is the empty
2165 // string which is ok.
2166 } else {
2168 "%s", "invalid entry definitions");
2169 }
2170 }
2171 } else {
2172 if (entry_def->children) {
2173 error = ParseEntry(value, entry_def, entry);
2174 } else if (sep_char == ':') {
2175 // Any value whose separator is a with a ':' means this value has a
2176 // string argument that needs to be stored in the entry (like
2177 // "${script.var:modulename.function}")
2178 entry.string = value.str();
2179 } else {
2181 "'%s' followed by '%s' but it has no children", key.str().c_str(),
2182 value.str().c_str());
2183 }
2184 }
2185 return error;
2186 }
2187 }
2188 StreamString error_strm;
2190 error_strm.Printf(
2191 "invalid top level item '%s'. Valid top level items are: ",
2192 key.str().c_str());
2193 else
2194 error_strm.Printf("invalid member '%s' in '%s'. Valid members are: ",
2195 key.str().c_str(), parent->name);
2196 DumpCommaSeparatedChildEntryNames(error_strm, parent);
2197 error = Status::FromErrorStringWithFormat("%s", error_strm.GetData());
2198 return error;
2199}
2200
2201static const Definition *FindEntry(const llvm::StringRef &format_str,
2202 const Definition *parent,
2203 llvm::StringRef &remainder) {
2204 Status error;
2205
2206 std::pair<llvm::StringRef, llvm::StringRef> p = format_str.split('.');
2207 const size_t n = parent->num_children;
2208 for (size_t i = 0; i < n; ++i) {
2209 const Definition *entry_def = parent->children + i;
2210 if (p.first == entry_def->name || entry_def->name[0] == '*') {
2211 if (p.second.empty()) {
2212 if (format_str.back() == '.')
2213 remainder = format_str.drop_front(format_str.size() - 1);
2214 else
2215 remainder = llvm::StringRef(); // Exact match
2216 return entry_def;
2217 } else {
2218 if (entry_def->children) {
2219 return FindEntry(p.second, entry_def, remainder);
2220 } else {
2221 remainder = p.second;
2222 return entry_def;
2223 }
2224 }
2225 }
2226 }
2227 remainder = format_str;
2228 return parent;
2229}
2230
2231static Status ParseInternal(llvm::StringRef &format, Entry &parent_entry,
2232 uint32_t depth) {
2233 Status error;
2234 while (!format.empty() && error.Success()) {
2235 const size_t non_special_chars = format.find_first_of("${}\\|");
2236
2237 if (non_special_chars == llvm::StringRef::npos) {
2238 // No special characters, just string bytes so add them and we are done
2239 parent_entry.AppendText(format);
2240 return error;
2241 }
2242
2243 if (non_special_chars > 0) {
2244 // We have a special character, so add all characters before these as a
2245 // plain string
2246 parent_entry.AppendText(format.substr(0, non_special_chars));
2247 format = format.drop_front(non_special_chars);
2248 }
2249
2250 switch (format[0]) {
2251 case '\0':
2252 return error;
2253
2254 case '{': {
2255 format = format.drop_front(); // Skip the '{'
2256 Entry scope_entry(Entry::Type::Scope);
2257 error = ParseInternal(format, scope_entry, depth + 1);
2258 if (error.Fail())
2259 return error;
2260 parent_entry.AppendEntry(std::move(scope_entry));
2261 } break;
2262
2263 case '}':
2264 if (depth == 0)
2265 error = Status::FromErrorString("unmatched '}' character");
2266 else
2267 format =
2268 format
2269 .drop_front(); // Skip the '}' as we are at the end of the scope
2270 return error;
2271
2272 case '|':
2273 format = format.drop_front(); // Skip the '|'
2274 if (parent_entry.type == Entry::Type::Scope)
2275 parent_entry.StartAlternative();
2276 else
2277 parent_entry.AppendChar('|');
2278 break;
2279
2280 case '\\': {
2281 format = format.drop_front(); // Skip the '\' character
2282 if (format.empty()) {
2284 "'\\' character was not followed by another character");
2285 return error;
2286 }
2287
2288 const char desens_char = format[0];
2289 format = format.drop_front(); // Skip the desensitized char character
2290 switch (desens_char) {
2291 case 'a':
2292 parent_entry.AppendChar('\a');
2293 break;
2294 case 'b':
2295 parent_entry.AppendChar('\b');
2296 break;
2297 case 'f':
2298 parent_entry.AppendChar('\f');
2299 break;
2300 case 'n':
2301 parent_entry.AppendChar('\n');
2302 break;
2303 case 'r':
2304 parent_entry.AppendChar('\r');
2305 break;
2306 case 't':
2307 parent_entry.AppendChar('\t');
2308 break;
2309 case 'v':
2310 parent_entry.AppendChar('\v');
2311 break;
2312 case '\'':
2313 parent_entry.AppendChar('\'');
2314 break;
2315 case '\\':
2316 parent_entry.AppendChar('\\');
2317 break;
2318 case '0':
2319 // 1 to 3 octal chars
2320 {
2321 // Make a string that can hold onto the initial zero char, up to 3
2322 // octal digits, and a terminating NULL.
2323 char oct_str[5] = {0, 0, 0, 0, 0};
2324
2325 int i;
2326 for (i = 0; (format[i] >= '0' && format[i] <= '7') && i < 4; ++i)
2327 oct_str[i] = format[i];
2328
2329 // We don't want to consume the last octal character since the main
2330 // for loop will do this for us, so we advance p by one less than i
2331 // (even if i is zero)
2332 format = format.drop_front(i);
2333 unsigned long octal_value = ::strtoul(oct_str, nullptr, 8);
2334 if (octal_value <= UINT8_MAX) {
2335 parent_entry.AppendChar((char)octal_value);
2336 } else {
2338 "octal number is larger than a single byte");
2339 return error;
2340 }
2341 }
2342 break;
2343
2344 case 'x':
2345 // hex number in the format
2346 if (isxdigit(format[0])) {
2347 // Make a string that can hold onto two hex chars plus a
2348 // null terminator
2349 char hex_str[3] = {0, 0, 0};
2350 hex_str[0] = format[0];
2351
2352 format = format.drop_front();
2353
2354 if (isxdigit(format[0])) {
2355 hex_str[1] = format[0];
2356 format = format.drop_front();
2357 }
2358
2359 unsigned long hex_value = strtoul(hex_str, nullptr, 16);
2360 if (hex_value <= UINT8_MAX) {
2361 parent_entry.AppendChar((char)hex_value);
2362 } else {
2364 "hex number is larger than a single byte");
2365 return error;
2366 }
2367 } else {
2368 parent_entry.AppendChar(desens_char);
2369 }
2370 break;
2371
2372 default:
2373 // Just desensitize any other character by just printing what came
2374 // after the '\'
2375 parent_entry.AppendChar(desens_char);
2376 break;
2377 }
2378 } break;
2379
2380 case '$':
2381 format = format.drop_front(); // Skip the '$'
2382 if (format.empty() || format.front() != '{') {
2383 // Print '$' when not followed by '{'.
2384 parent_entry.AppendText("$");
2385 } else {
2386 format = format.drop_front(); // Skip the '{'
2387
2388 llvm::StringRef variable, variable_format;
2389 error = FormatEntity::ExtractVariableInfo(format, variable,
2390 variable_format);
2391 if (error.Fail())
2392 return error;
2393 bool verify_is_thread_id = false;
2394 Entry entry;
2395 if (!variable_format.empty()) {
2396 entry.printf_format = variable_format.str();
2397
2398 // If the format contains a '%' we are going to assume this is a
2399 // printf style format. So if you want to format your thread ID
2400 // using "0x%llx" you can use: ${thread.id%0x%llx}
2401 //
2402 // If there is no '%' in the format, then it is assumed to be a
2403 // LLDB format name, or one of the extended formats specified in
2404 // the switch statement below.
2405
2406 if (entry.printf_format.find('%') == std::string::npos) {
2407 bool clear_printf = false;
2408
2409 if (entry.printf_format.size() == 1) {
2410 switch (entry.printf_format[0]) {
2411 case '@': // if this is an @ sign, print ObjC description
2412 entry.number = ValueObject::
2413 eValueObjectRepresentationStyleLanguageSpecific;
2414 clear_printf = true;
2415 break;
2416 case 'V': // if this is a V, print the value using the default
2417 // format
2418 entry.number =
2420 clear_printf = true;
2421 break;
2422 case 'L': // if this is an L, print the location of the value
2423 entry.number =
2425 clear_printf = true;
2426 break;
2427 case 'S': // if this is an S, print the summary after all
2428 entry.number =
2430 clear_printf = true;
2431 break;
2432 case '#': // if this is a '#', print the number of children
2433 entry.number =
2435 clear_printf = true;
2436 break;
2437 case 'T': // if this is a 'T', print the type
2439 clear_printf = true;
2440 break;
2441 case 'N': // if this is a 'N', print the name
2443 clear_printf = true;
2444 break;
2445 case '>': // if this is a '>', print the expression path
2446 entry.number =
2448 clear_printf = true;
2449 break;
2450 }
2451 }
2452
2453 if (entry.number == 0) {
2455 entry.printf_format.c_str(), entry.fmt)) {
2456 clear_printf = true;
2457 } else if (entry.printf_format == "tid") {
2458 verify_is_thread_id = true;
2459 } else {
2461 "invalid format: '%s'", entry.printf_format.c_str());
2462 return error;
2463 }
2464 }
2465
2466 // Our format string turned out to not be a printf style format
2467 // so lets clear the string
2468 if (clear_printf)
2469 entry.printf_format.clear();
2470 }
2471 }
2472
2473 // Check for dereferences
2474 if (variable[0] == '*') {
2475 entry.deref = true;
2476 variable = variable.drop_front();
2477 }
2478
2479 error = ParseEntry(variable, &g_root, entry);
2480 if (error.Fail())
2481 return error;
2482
2483 llvm::StringRef entry_string(entry.string);
2484 if (entry_string.contains(':')) {
2485 auto [_, llvm_format] = entry_string.split(':');
2486 if (!llvm_format.empty() && !LLVMFormatPattern.match(llvm_format)) {
2488 "invalid llvm format: '%s'", llvm_format.data());
2489 return error;
2490 }
2491 }
2492
2493 if (verify_is_thread_id) {
2494 if (entry.type != Entry::Type::ThreadID &&
2497 "the 'tid' format can only be used on "
2498 "${thread.id} and ${thread.protocol_id}");
2499 }
2500 }
2501
2502 switch (entry.type) {
2505 if (entry.number == 0) {
2506 if (entry.string.empty())
2508 else
2509 entry.number =
2511 }
2512 break;
2513 default:
2514 // Make sure someone didn't try to dereference anything but ${var}
2515 // or ${svar}
2516 if (entry.deref) {
2518 "${%s} can't be dereferenced, only ${var} and ${svar} can.",
2519 variable.str().c_str());
2520 return error;
2521 }
2522 }
2523 parent_entry.AppendEntry(std::move(entry));
2524 }
2525 break;
2526 }
2527 }
2528 return error;
2529}
2530
2531Status FormatEntity::ExtractVariableInfo(llvm::StringRef &format_str,
2532 llvm::StringRef &variable_name,
2533 llvm::StringRef &variable_format) {
2534 Status error;
2535 variable_name = llvm::StringRef();
2536 variable_format = llvm::StringRef();
2537
2538 const size_t paren_pos = format_str.find('}');
2539 if (paren_pos != llvm::StringRef::npos) {
2540 const size_t percent_pos = format_str.find('%');
2541 if (percent_pos < paren_pos) {
2542 if (percent_pos > 0) {
2543 if (percent_pos > 1)
2544 variable_name = format_str.substr(0, percent_pos);
2545 variable_format =
2546 format_str.substr(percent_pos + 1, paren_pos - (percent_pos + 1));
2547 }
2548 } else {
2549 variable_name = format_str.substr(0, paren_pos);
2550 }
2551 // Strip off elements and the formatting and the trailing '}'
2552 format_str = format_str.substr(paren_pos + 1);
2553 } else {
2555 "missing terminating '}' character for '${%s'",
2556 format_str.str().c_str());
2557 }
2558 return error;
2559}
2560
2562 llvm::StringRef variable_name,
2563 llvm::StringRef variable_format) {
2564 if (variable_name.empty() || variable_name == ".fullpath") {
2565 file_spec.Dump(s.AsRawOstream());
2566 return true;
2567 } else if (variable_name == ".basename") {
2568 s.PutCString(file_spec.GetFilename());
2569 return true;
2570 } else if (variable_name == ".dirname") {
2571 s.PutCString(file_spec.GetFilename());
2572 return true;
2573 }
2574 return false;
2575}
2576
2577static std::string MakeMatch(const llvm::StringRef &prefix,
2578 const char *suffix) {
2579 std::string match(prefix.str());
2580 match.append(suffix);
2581 return match;
2582}
2583
2584static void AddMatches(const Definition *def, const llvm::StringRef &prefix,
2585 const llvm::StringRef &match_prefix,
2586 StringList &matches) {
2587 const size_t n = def->num_children;
2588 if (n > 0) {
2589 for (size_t i = 0; i < n; ++i) {
2590 if (match_prefix.empty())
2591 matches.AppendString(MakeMatch(prefix, def->children[i].name));
2592 else if (strncmp(def->children[i].name, match_prefix.data(),
2593 match_prefix.size()) == 0)
2594 matches.AppendString(
2595 MakeMatch(prefix, def->children[i].name + match_prefix.size()));
2596 }
2597 }
2598}
2599
2601 llvm::StringRef str = request.GetCursorArgumentPrefix();
2602
2603 const size_t dollar_pos = str.rfind('$');
2604 if (dollar_pos == llvm::StringRef::npos)
2605 return;
2606
2607 // Hitting TAB after $ at the end of the string add a "{"
2608 if (dollar_pos == str.size() - 1) {
2609 std::string match = str.str();
2610 match.append("{");
2611 request.AddCompletion(match);
2612 return;
2613 }
2614
2615 if (str[dollar_pos + 1] != '{')
2616 return;
2617
2618 const size_t close_pos = str.find('}', dollar_pos + 2);
2619 if (close_pos != llvm::StringRef::npos)
2620 return;
2621
2622 const size_t format_pos = str.find('%', dollar_pos + 2);
2623 if (format_pos != llvm::StringRef::npos)
2624 return;
2625
2626 llvm::StringRef partial_variable(str.substr(dollar_pos + 2));
2627 if (partial_variable.empty()) {
2628 // Suggest all top level entities as we are just past "${"
2629 StringList new_matches;
2630 AddMatches(&g_root, str, llvm::StringRef(), new_matches);
2631 request.AddCompletions(new_matches);
2632 return;
2633 }
2634
2635 // We have a partially specified variable, find it
2636 llvm::StringRef remainder;
2637 const Definition *entry_def = FindEntry(partial_variable, &g_root, remainder);
2638 if (!entry_def)
2639 return;
2640
2641 const size_t n = entry_def->num_children;
2642
2643 if (remainder.empty()) {
2644 // Exact match
2645 if (n > 0) {
2646 // "${thread.info" <TAB>
2647 request.AddCompletion(MakeMatch(str, "."));
2648 } else {
2649 // "${thread.id" <TAB>
2650 request.AddCompletion(MakeMatch(str, "}"));
2651 }
2652 } else if (remainder == ".") {
2653 // "${thread." <TAB>
2654 StringList new_matches;
2655 AddMatches(entry_def, str, llvm::StringRef(), new_matches);
2656 request.AddCompletions(new_matches);
2657 } else {
2658 // We have a partial match
2659 // "${thre" <TAB>
2660 StringList new_matches;
2661 AddMatches(entry_def, str, remainder, new_matches);
2662 request.AddCompletions(new_matches);
2663 }
2664}
2665
2667 Stream &out_stream, VariableList const &args,
2668 ExecutionContextScope *exe_scope) {
2669 const size_t num_args = args.GetSize();
2670 for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) {
2671 std::string buffer;
2672
2673 VariableSP var_sp(args.GetVariableAtIndex(arg_idx));
2674 ValueObjectSP var_value_sp(ValueObjectVariable::Create(exe_scope, var_sp));
2675 StreamString ss;
2676 llvm::StringRef var_representation;
2677 const char *var_name = var_value_sp->GetName().GetCString();
2678 if (var_value_sp->GetCompilerType().IsValid()) {
2679 if (exe_scope && exe_scope->CalculateTarget())
2680 var_value_sp = var_value_sp->GetQualifiedRepresentationIfAvailable(
2681 exe_scope->CalculateTarget()
2682 ->TargetProperties::GetPreferDynamicValue(),
2683 exe_scope->CalculateTarget()
2684 ->TargetProperties::GetEnableSyntheticValue());
2685 if (var_value_sp->GetCompilerType().IsAggregateType() &&
2688 .SetHideItemNames(false)
2689 .SetShowMembersOneLiner(true),
2690 "");
2691 format.FormatObject(var_value_sp.get(), buffer, TypeSummaryOptions());
2692 var_representation = buffer;
2693 } else
2694 var_value_sp->DumpPrintableRepresentation(
2695 ss,
2697 eValueObjectRepresentationStyleSummary,
2700 }
2701
2702 if (!ss.GetString().empty())
2703 var_representation = ss.GetString();
2704 if (arg_idx > 0)
2705 out_stream.PutCString(", ");
2706 if (var_value_sp->GetError().Success()) {
2707 if (!var_representation.empty())
2708 out_stream.Printf("%s=%s", var_name, var_representation.str().c_str());
2709 else
2710 out_stream.Printf("%s=%s at %s", var_name,
2711 var_value_sp->GetTypeName().GetCString(),
2712 var_value_sp->GetLocationAsCString());
2713 } else
2714 out_stream.Printf("%s=<unavailable>", var_name);
2715 }
2716}
2717
2718Status FormatEntity::Parse(const llvm::StringRef &format_str, Entry &entry) {
2719 entry.Clear();
2720 entry.type = Entry::Type::Root;
2721 llvm::StringRef modifiable_format(format_str);
2722 return ParseInternal(modifiable_format, entry, 0);
2723}
2724
2726 // It is expected that Scope and Root format entities recursively call Format.
2727 //
2728 // Variable may also be formatted recursively in some special cases. The main
2729 // use-case being array summary strings, in which case Format will call itself
2730 // with the subrange ValueObject and apply a freshly created Variable entry.
2731 // E.g., ${var[1-3]} will format the [1-3] range with ${var%S}.
2732 static constexpr std::array s_permitted_recursive_entities = {
2734
2735 if (llvm::is_contained(s_permitted_recursive_entities, type))
2736 return false;
2737
2738 return llvm::is_contained(m_entry_type_stack, type);
2739}
#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:710
bool IsValid() const
Tests if this ArchSpec is valid.
Definition ArchSpec.h:375
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition ArchSpec.h:465
const char * GetArchitectureName() const
Returns a static string representing the current architecture.
Definition ArchSpec.cpp:568
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:106
bool GetUseColor() const
Definition Debugger.cpp:544
ScriptInterpreter * GetScriptInterpreter(bool can_create=true, std::optional< lldb::ScriptLanguage > language={})
DumpValueObjectOptions & SetUseSyntheticValue(bool use_synthetic=true)
DumpValueObjectOptions & SetUseDynamicType(lldb::DynamicValueType dyn=lldb::eNoDynamicValues)
"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:430
static Language * FindPlugin(lldb::LanguageType language)
Definition Language.cpp:89
static const char * GetNameForLanguageType(lldb::LanguageType language)
Returns the internal LLDB name for the specified language.
Definition Language.cpp:348
virtual bool GetFunctionDisplayName(const SymbolContext &sc, const ExecutionContext *exe_ctx, FunctionNameRepresentation representation, Stream &s)
Definition Language.cpp:613
virtual FormatEntity::Entry GetFunctionNameFormat() const
Definition Language.h:563
@ ePreferDemangledWithoutArguments
Definition Mangled.h:41
ConstString GetName(NamePreference preference=ePreferDemangled) const
Best name get accessor.
Definition Mangled.cpp:297
A class that describes an executable image and its associated object and symbol files.
Definition Module.h:92
const FileSpec & GetFileSpec() const
Get const accessor for the module file specification.
Definition Module.h:448
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:192
lldb::LanguageType GetLanguage() const
Definition Symbol.h:154
Address & GetAddressRef()
Definition Symbol.h:78
ConstString GetName() const
Definition Symbol.cpp:615
Module * GetExecutableModulePointer()
Definition Target.cpp:1668
static Target * GetTargetFromContexts(const ExecutionContext *exe_ctx_ptr, const SymbolContext *sc_ptr)
Definition Target.cpp:2982
Debugger & GetDebugger() const
Definition Target.h:1366
const ArchSpec & GetArchitecture() const
Definition Target.h:1325
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
@ eDynamicCanRunTarget
@ 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()