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
757static bool DumpValue(Stream &s, const SymbolContext *sc,
758 const ExecutionContext *exe_ctx,
759 const FormatEntity::Entry &entry, ValueObject *valobj) {
760 if (valobj == nullptr)
761 return false;
762
764 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, sc, exe_ctx, valobj, entry.string.c_str());
825 }
826
827 auto split = llvm::StringRef(entry.string).split(':');
828 auto subpath = split.first;
829 auto llvm_format = split.second;
830
831 // simplest case ${var}, just print valobj's value
832 if (subpath.empty()) {
833 if (entry.printf_format.empty() && entry.fmt == eFormatDefault &&
835 was_plain_var = true;
836 else
837 was_var_format = true;
838 target = valobj;
839 } else // this is ${var.something} or multiple .something nested
840 {
841 if (subpath[0] == '[')
842 was_var_indexed = true;
843 ScanBracketedRange(subpath, close_bracket_index,
844 var_name_final_if_array_range, index_lower,
845 index_higher);
846
848
849 LLDB_LOG(log, "[Debugger::FormatPrompt] symbol to expand: {0}", subpath);
850
851 target =
852 valobj
853 ->GetValueForExpressionPath(subpath, &reason_to_stop,
854 &final_value_type, options, &what_next)
855 .get();
856
857 if (!target) {
858 LLDB_LOGF(log,
859 "[Debugger::FormatPrompt] ERROR: why stopping = %d,"
860 " final_value_type %d",
861 reason_to_stop, final_value_type);
862 return false;
863 } else {
864 LLDB_LOGF(log,
865 "[Debugger::FormatPrompt] ALL RIGHT: why stopping = %d,"
866 " final_value_type %d",
867 reason_to_stop, final_value_type);
868 target = target
870 target->GetDynamicValueType(), true)
871 .get();
872 }
873 }
874
875 is_array_range =
876 (final_value_type ==
878 final_value_type ==
880
881 do_deref_pointer =
883
884 if (do_deref_pointer && !is_array_range) {
885 // I have not deref-ed yet, let's do it
886 // this happens when we are not going through
887 // GetValueForVariableExpressionPath to get to the target ValueObject
889 target = target->Dereference(error).get();
890 if (error.Fail()) {
891 LLDB_LOGF(log, "[Debugger::FormatPrompt] ERROR: %s\n",
892 error.AsCString("unknown"));
893 return false;
894 }
895 do_deref_pointer = false;
896 }
897
898 if (!target) {
899 LLDB_LOGF(log, "[Debugger::FormatPrompt] could not calculate target for "
900 "prompt expression");
901 return false;
902 }
903
904 // we do not want to use the summary for a bitfield of type T:n if we were
905 // originally dealing with just a T - that would get us into an endless
906 // recursion
907 if (target->IsBitfield() && was_var_indexed) {
908 // TODO: check for a (T:n)-specific summary - we should still obey that
909 StreamString bitfield_name;
910 bitfield_name.Printf("%s:%d", target->GetTypeName().AsCString(),
911 target->GetBitfieldBitSize());
912 auto type_sp = std::make_shared<TypeNameSpecifierImpl>(
913 bitfield_name.GetString(), lldb::eFormatterMatchExact);
914 if (val_obj_display ==
918 }
919
920 // TODO use flags for these
921 const uint32_t type_info_flags =
922 target->GetCompilerType().GetTypeInfo(nullptr);
923 bool is_array = (type_info_flags & eTypeIsArray) != 0;
924 bool is_pointer = (type_info_flags & eTypeIsPointer) != 0;
925 bool is_aggregate = target->GetCompilerType().IsAggregateType();
926
927 if ((is_array || is_pointer) && (!is_array_range) &&
928 val_obj_display ==
930 // wrong, but there
931 // are some
932 // exceptions
933 {
934 StreamString str_temp;
935 LLDB_LOGF(log,
936 "[Debugger::FormatPrompt] I am into array || pointer && !range");
937
938 if (target->HasSpecialPrintableRepresentation(val_obj_display,
939 custom_format)) {
940 // try to use the special cases
941 bool success = target->DumpPrintableRepresentation(
942 str_temp, val_obj_display, custom_format);
943 LLDB_LOGF(log, "[Debugger::FormatPrompt] special cases did%s match",
944 success ? "" : "n't");
945
946 // should not happen
947 if (success)
948 s << str_temp.GetString();
949 return true;
950 } else {
951 if (was_plain_var) // if ${var}
952 {
953 s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
954 } else if (is_pointer) // if pointer, value is the address stored
955 {
957 s, val_obj_display, custom_format,
959 }
960 return true;
961 }
962 }
963
964 // if directly trying to print ${var}, and this is an aggregate, display a
965 // nice type @ location message
966 if (is_aggregate && was_plain_var) {
967 s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
968 return true;
969 }
970
971 // if directly trying to print ${var%V}, and this is an aggregate, do not let
972 // the user do it
973 if (is_aggregate &&
974 ((was_var_format &&
975 val_obj_display ==
977 s << "<invalid use of aggregate type>";
978 return true;
979 }
980
981 if (!is_array_range) {
982 if (!llvm_format.empty()) {
983 if (DumpValueWithLLVMFormat(s, llvm_format, *target)) {
984 LLDB_LOGF(log, "dumping using llvm format");
985 return true;
986 } else {
987 LLDB_LOG(
988 log,
989 "empty output using llvm format '{0}' - with type info flags {1}",
990 entry.printf_format, target->GetTypeInfo());
991 }
992 }
993 LLDB_LOGF(log, "dumping ordinary printable output");
994 return target->DumpPrintableRepresentation(s, val_obj_display,
995 custom_format);
996 } else {
997 LLDB_LOGF(log,
998 "[Debugger::FormatPrompt] checking if I can handle as array");
999 if (!is_array && !is_pointer)
1000 return false;
1001 LLDB_LOGF(log, "[Debugger::FormatPrompt] handle as array");
1002 StreamString special_directions_stream;
1003 llvm::StringRef special_directions;
1004 if (close_bracket_index != llvm::StringRef::npos &&
1005 subpath.size() > close_bracket_index) {
1006 ConstString additional_data(subpath.drop_front(close_bracket_index + 1));
1007 special_directions_stream.Printf("${%svar%s", do_deref_pointer ? "*" : "",
1008 additional_data.GetCString());
1009
1010 if (entry.fmt != eFormatDefault) {
1011 const char format_char =
1013 if (format_char != '\0')
1014 special_directions_stream.Printf("%%%c", format_char);
1015 else {
1016 const char *format_cstr =
1018 special_directions_stream.Printf("%%%s", format_cstr);
1019 }
1020 } else if (entry.number != 0) {
1021 const char style_char = ConvertValueObjectStyleToChar(
1023 if (style_char)
1024 special_directions_stream.Printf("%%%c", style_char);
1025 }
1026 special_directions_stream.PutChar('}');
1027 special_directions =
1028 llvm::StringRef(special_directions_stream.GetString());
1029 }
1030
1031 // let us display items index_lower thru index_higher of this array
1032 s.PutChar('[');
1033
1034 if (index_higher < 0)
1035 index_higher = valobj->GetNumChildrenIgnoringErrors() - 1;
1036
1037 uint32_t max_num_children =
1038 target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay();
1039
1040 bool success = true;
1041 for (int64_t index = index_lower; index <= index_higher; ++index) {
1042 ValueObject *item = ExpandIndexedExpression(target, index, false).get();
1043
1044 if (!item) {
1045 LLDB_LOGF(log,
1046 "[Debugger::FormatPrompt] ERROR in getting child item at "
1047 "index %" PRId64,
1048 index);
1049 } else {
1050 LLDB_LOGF(
1051 log,
1052 "[Debugger::FormatPrompt] special_directions for child item: %s",
1053 special_directions.data() ? special_directions.data() : "");
1054 }
1055
1056 if (special_directions.empty()) {
1057 success &= item->DumpPrintableRepresentation(s, val_obj_display,
1058 custom_format);
1059 } else {
1061 special_directions, s, sc, exe_ctx, nullptr, item, false, false);
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 const ExecutionContext *exe_ctx,
1277 const SymbolContext *sc) {
1278 assert(sc);
1279
1280 Language *language_plugin = nullptr;
1281 if (sc->function)
1282 language_plugin = Language::FindPlugin(sc->function->GetLanguage());
1283 else if (sc->symbol)
1284 language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
1285
1286 if (!language_plugin)
1287 return false;
1288
1289 FormatEntity::Entry format = language_plugin->GetFunctionNameFormat();
1290
1291 // Bail on invalid or empty format.
1292 if (!format || format == FormatEntity::Entry(Entry::Type::Root))
1293 return false;
1294
1295 StreamString name_stream;
1296 const bool success =
1297 FormatEntity::Format(format, name_stream, sc, exe_ctx, /*addr=*/nullptr,
1298 /*valobj=*/nullptr, /*function_changed=*/false,
1299 /*initial_function=*/false);
1300 if (success)
1301 s << name_stream.GetString();
1302
1303 return success;
1304}
1305
1306bool FormatEntity::FormatStringRef(const llvm::StringRef &format_str, Stream &s,
1307 const SymbolContext *sc,
1308 const ExecutionContext *exe_ctx,
1309 const Address *addr, ValueObject *valobj,
1310 bool function_changed,
1311 bool initial_function) {
1312 if (!format_str.empty()) {
1314 Status error = FormatEntity::Parse(format_str, root);
1315 if (error.Success()) {
1316 return FormatEntity::Format(root, s, sc, exe_ctx, addr, valobj,
1317 function_changed, initial_function);
1318 }
1319 }
1320 return false;
1321}
1322
1323bool FormatEntity::Format(const Entry &entry, Stream &s,
1324 const SymbolContext *sc,
1325 const ExecutionContext *exe_ctx, const Address *addr,
1326 ValueObject *valobj, bool function_changed,
1327 bool initial_function) {
1328 switch (entry.type) {
1330 case Entry::Type::ParentNumber: // Only used for
1331 // FormatEntity::Entry::Definition encoding
1332 case Entry::Type::ParentString: // Only used for
1333 // FormatEntity::Entry::Definition encoding
1334 return false;
1336 if (Target *target = Target::GetTargetFromContexts(exe_ctx, sc)) {
1337 Debugger &debugger = target->GetDebugger();
1338 if (debugger.GetUseColor()) {
1339 s.PutCString(entry.string);
1340 }
1341 }
1342 // Always return true, so colors being disabled is transparent.
1343 return true;
1344
1345 case Entry::Type::Root:
1346 for (const auto &child : entry.children_stack[0]) {
1347 if (!Format(child, s, sc, exe_ctx, addr, valobj, function_changed,
1348 initial_function)) {
1349 return false; // If any item of root fails, then the formatting fails
1350 }
1351 }
1352 return true; // Only return true if all items succeeded
1353
1355 s.PutCString(entry.string);
1356 return true;
1357
1358 case Entry::Type::Scope: {
1359 StreamString scope_stream;
1360 auto format_children = [&](const std::vector<Entry> &children) {
1361 scope_stream.Clear();
1362 for (const auto &child : children) {
1363 if (!Format(child, scope_stream, sc, exe_ctx, addr, valobj,
1364 function_changed, initial_function))
1365 return false;
1366 }
1367 return true;
1368 };
1369
1370 for (auto &children : entry.children_stack) {
1371 if (format_children(children)) {
1372 s.Write(scope_stream.GetString().data(),
1373 scope_stream.GetString().size());
1374 return true;
1375 }
1376 }
1377
1378 return true; // Scopes always successfully print themselves
1379 }
1380
1385 return DumpValue(s, sc, exe_ctx, entry, valobj);
1386
1390 return (
1391 addr != nullptr && addr->IsValid() &&
1392 DumpAddressAndContent(s, sc, exe_ctx, *addr,
1394
1396 if (exe_ctx) {
1397 Process *process = exe_ctx->GetProcessPtr();
1398 if (process) {
1399 const char *format = "%" PRIu64;
1400 if (!entry.printf_format.empty())
1401 format = entry.printf_format.c_str();
1402 s.Printf(format, process->GetID());
1403 return true;
1404 }
1405 }
1406 return false;
1407
1409 if (exe_ctx) {
1410 Process *process = exe_ctx->GetProcessPtr();
1411 if (process) {
1412 Module *exe_module = process->GetTarget().GetExecutableModulePointer();
1413 if (exe_module) {
1414 if (DumpFile(s, exe_module->GetFileSpec(), (FileKind)entry.number))
1415 return true;
1416 }
1417 }
1418 }
1419 return false;
1420
1422 if (exe_ctx) {
1423 Process *process = exe_ctx->GetProcessPtr();
1424 if (process)
1425 return RunScriptFormatKeyword(s, sc, exe_ctx, process,
1426 entry.string.c_str());
1427 }
1428 return false;
1429
1431 if (exe_ctx) {
1432 Thread *thread = exe_ctx->GetThreadPtr();
1433 if (thread) {
1434 const char *format = "0x%4.4" PRIx64;
1435 if (!entry.printf_format.empty()) {
1436 // Watch for the special "tid" format...
1437 if (entry.printf_format == "tid") {
1438 // TODO(zturner): Rather than hardcoding this to be platform
1439 // specific, it should be controlled by a setting and the default
1440 // value of the setting can be different depending on the platform.
1441 Target &target = thread->GetProcess()->GetTarget();
1442 ArchSpec arch(target.GetArchitecture());
1443 llvm::Triple::OSType ostype = arch.IsValid()
1444 ? arch.GetTriple().getOS()
1445 : llvm::Triple::UnknownOS;
1446 if (ostype == llvm::Triple::FreeBSD ||
1447 ostype == llvm::Triple::Linux ||
1448 ostype == llvm::Triple::NetBSD ||
1449 ostype == llvm::Triple::OpenBSD) {
1450 format = "%" PRIu64;
1451 }
1452 } else {
1453 format = entry.printf_format.c_str();
1454 }
1455 }
1456 s.Printf(format, thread->GetID());
1457 return true;
1458 }
1459 }
1460 return false;
1461
1463 if (exe_ctx) {
1464 Thread *thread = exe_ctx->GetThreadPtr();
1465 if (thread) {
1466 const char *format = "0x%4.4" PRIx64;
1467 if (!entry.printf_format.empty())
1468 format = entry.printf_format.c_str();
1469 s.Printf(format, thread->GetProtocolID());
1470 return true;
1471 }
1472 }
1473 return false;
1474
1476 if (exe_ctx) {
1477 Thread *thread = exe_ctx->GetThreadPtr();
1478 if (thread) {
1479 const char *format = "%" PRIu32;
1480 if (!entry.printf_format.empty())
1481 format = entry.printf_format.c_str();
1482 s.Printf(format, thread->GetIndexID());
1483 return true;
1484 }
1485 }
1486 return false;
1487
1489 if (exe_ctx) {
1490 Thread *thread = exe_ctx->GetThreadPtr();
1491 if (thread) {
1492 const char *cstr = thread->GetName();
1493 if (cstr && cstr[0]) {
1494 s.PutCString(cstr);
1495 return true;
1496 }
1497 }
1498 }
1499 return false;
1500
1502 if (exe_ctx) {
1503 Thread *thread = exe_ctx->GetThreadPtr();
1504 if (thread) {
1505 const char *cstr = thread->GetQueueName();
1506 if (cstr && cstr[0]) {
1507 s.PutCString(cstr);
1508 return true;
1509 }
1510 }
1511 }
1512 return false;
1513
1515 if (exe_ctx) {
1516 if (Thread *thread = exe_ctx->GetThreadPtr()) {
1517 std::string stop_description = thread->GetStopDescription();
1518 if (!stop_description.empty()) {
1519 s.PutCString(stop_description);
1520 return true;
1521 }
1522 }
1523 }
1524 return false;
1525
1527 if (exe_ctx) {
1528 if (Thread *thread = exe_ctx->GetThreadPtr()) {
1529 std::string stop_description = thread->GetStopDescriptionRaw();
1530 if (!stop_description.empty()) {
1531 s.PutCString(stop_description);
1532 return true;
1533 }
1534 }
1535 }
1536 return false;
1537
1539 if (exe_ctx) {
1540 Thread *thread = exe_ctx->GetThreadPtr();
1541 if (thread) {
1542 StopInfoSP stop_info_sp = thread->GetStopInfo();
1543 if (stop_info_sp && stop_info_sp->IsValid()) {
1544 ValueObjectSP return_valobj_sp =
1545 StopInfo::GetReturnValueObject(stop_info_sp);
1546 if (return_valobj_sp) {
1547 if (llvm::Error error = return_valobj_sp->Dump(s)) {
1548 s << "error: " << toString(std::move(error));
1549 return false;
1550 }
1551 return true;
1552 }
1553 }
1554 }
1555 }
1556 return false;
1557
1559 if (exe_ctx) {
1560 Thread *thread = exe_ctx->GetThreadPtr();
1561 if (thread) {
1562 StopInfoSP stop_info_sp = thread->GetStopInfo();
1563 if (stop_info_sp && stop_info_sp->IsValid()) {
1564 ExpressionVariableSP expression_var_sp =
1565 StopInfo::GetExpressionVariable(stop_info_sp);
1566 if (expression_var_sp && expression_var_sp->GetValueObject()) {
1567 if (llvm::Error error =
1568 expression_var_sp->GetValueObject()->Dump(s)) {
1569 s << "error: " << toString(std::move(error));
1570 return false;
1571 }
1572 return true;
1573 }
1574 }
1575 }
1576 }
1577 return false;
1578
1580 if (exe_ctx) {
1581 Thread *thread = exe_ctx->GetThreadPtr();
1582 if (thread)
1583 return RunScriptFormatKeyword(s, sc, exe_ctx, thread,
1584 entry.string.c_str());
1585 }
1586 return false;
1587
1589 if (exe_ctx) {
1590 Thread *thread = exe_ctx->GetThreadPtr();
1591 if (thread) {
1592 StructuredData::ObjectSP object_sp = thread->GetExtendedInfo();
1593 if (object_sp &&
1594 object_sp->GetType() == eStructuredDataTypeDictionary) {
1595 if (FormatThreadExtendedInfoRecurse(entry, object_sp, sc, exe_ctx, s))
1596 return true;
1597 }
1598 }
1599 }
1600 return false;
1601
1603 if (exe_ctx) {
1604 Target *target = exe_ctx->GetTargetPtr();
1605 if (target) {
1606 const ArchSpec &arch = target->GetArchitecture();
1607 if (arch.IsValid()) {
1609 return true;
1610 }
1611 }
1612 }
1613 return false;
1614
1616 if (exe_ctx) {
1617 if (Target *target = exe_ctx->GetTargetPtr()) {
1618 if (Module *exe_module = target->GetExecutableModulePointer()) {
1619 if (DumpFile(s, exe_module->GetFileSpec(), (FileKind)entry.number))
1620 return true;
1621 }
1622 }
1623 }
1624 return false;
1625
1627 if (exe_ctx) {
1628 Target *target = exe_ctx->GetTargetPtr();
1629 if (target)
1630 return RunScriptFormatKeyword(s, sc, exe_ctx, target,
1631 entry.string.c_str());
1632 }
1633 return false;
1634
1636 if (sc) {
1637 Module *module = sc->module_sp.get();
1638 if (module) {
1639 if (DumpFile(s, module->GetFileSpec(), (FileKind)entry.number))
1640 return true;
1641 }
1642 }
1643 return false;
1644
1645 case Entry::Type::File:
1646 if (sc) {
1647 CompileUnit *cu = sc->comp_unit;
1648 if (cu) {
1649 if (DumpFile(s, cu->GetPrimaryFile(), (FileKind)entry.number))
1650 return true;
1651 }
1652 }
1653 return false;
1654
1655 case Entry::Type::Lang:
1656 if (sc) {
1657 CompileUnit *cu = sc->comp_unit;
1658 if (cu) {
1659 const char *lang_name =
1661 if (lang_name) {
1662 s.PutCString(lang_name);
1663 return true;
1664 }
1665 }
1666 }
1667 return false;
1668
1670 if (exe_ctx) {
1671 StackFrame *frame = exe_ctx->GetFramePtr();
1672 if (frame) {
1673 const char *format = "%" PRIu32;
1674 if (!entry.printf_format.empty())
1675 format = entry.printf_format.c_str();
1676 s.Printf(format, frame->GetFrameIndex());
1677 return true;
1678 }
1679 }
1680 return false;
1681
1683 if (exe_ctx) {
1684 StackFrame *frame = exe_ctx->GetFramePtr();
1685 if (frame) {
1686 const Address &pc_addr = frame->GetFrameCodeAddress();
1687 if (pc_addr.IsValid())
1688 if (DumpAddressAndContent(s, sc, exe_ctx, pc_addr, false))
1689 return true;
1690 }
1691 }
1692 return false;
1693
1695 if (exe_ctx) {
1696 StackFrame *frame = exe_ctx->GetFramePtr();
1697 if (frame) {
1699 (lldb::Format)entry.number))
1700 return true;
1701 }
1702 }
1703 return false;
1704
1706 if (exe_ctx) {
1707 StackFrame *frame = exe_ctx->GetFramePtr();
1708 if (frame) {
1710 (lldb::Format)entry.number))
1711 return true;
1712 }
1713 }
1714 return false;
1715
1717 if (exe_ctx) {
1718 StackFrame *frame = exe_ctx->GetFramePtr();
1719 if (frame) {
1720 if (DumpRegister(s, frame, eRegisterKindGeneric,
1722 return true;
1723 }
1724 }
1725 return false;
1726
1728 if (exe_ctx) {
1729 StackFrame *frame = exe_ctx->GetFramePtr();
1730 if (frame) {
1731 return !frame->HasDebugInformation();
1732 }
1733 }
1734 return true;
1735
1737 if (exe_ctx) {
1738 StackFrame *frame = exe_ctx->GetFramePtr();
1739 if (frame) {
1740 if (DumpRegister(s, frame, entry.string.c_str(),
1741 (lldb::Format)entry.number))
1742 return true;
1743 }
1744 }
1745 return false;
1746
1748 if (exe_ctx)
1749 if (StackFrame *frame = exe_ctx->GetFramePtr())
1750 return frame->IsArtificial();
1751 return false;
1752 }
1753
1755 if (exe_ctx)
1756 if (StackFrame *frame = exe_ctx->GetFramePtr()) {
1757 if (frame->IsSynthetic())
1758 s.PutCString(" [synthetic]");
1759 else if (frame->IsHistorical())
1760 s.PutCString(" [history]");
1761 return true;
1762 }
1763 return false;
1764 }
1765
1767 if (exe_ctx)
1768 if (StackFrame *frame = exe_ctx->GetFramePtr()) {
1769 if (BorrowedStackFrame *borrowed_frame =
1770 llvm::dyn_cast<BorrowedStackFrame>(frame)) {
1771 if (lldb::StackFrameSP borrowed_from_sp =
1772 borrowed_frame->GetBorrowedFrame()) {
1773 s.Printf(" [borrowed from frame #%u]",
1774 borrowed_from_sp->GetFrameIndex());
1775 return true;
1776 }
1777 }
1778 }
1779 return false;
1780 }
1781
1783 if (exe_ctx) {
1784 StackFrame *frame = exe_ctx->GetFramePtr();
1785 if (frame)
1786 return RunScriptFormatKeyword(s, sc, exe_ctx, frame,
1787 entry.string.c_str());
1788 }
1789 return false;
1790
1792 if (sc) {
1793 if (sc->function) {
1794 s.Printf("function{0x%8.8" PRIx64 "}", sc->function->GetID());
1795 return true;
1796 } else if (sc->symbol) {
1797 s.Printf("symbol[%u]", sc->symbol->GetID());
1798 return true;
1799 }
1800 }
1801 return false;
1802
1804 return function_changed;
1805
1807 return initial_function;
1808
1810 if (sc) {
1811 Language *language_plugin = nullptr;
1812 bool language_plugin_handled = false;
1813 StreamString ss;
1814
1815 if (sc->function)
1816 language_plugin = Language::FindPlugin(sc->function->GetLanguage());
1817 else if (sc->symbol)
1818 language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
1819
1820 if (language_plugin)
1821 language_plugin_handled = language_plugin->GetFunctionDisplayName(
1823
1824 if (language_plugin_handled) {
1825 s << ss.GetString();
1826 return true;
1827 }
1828
1829 const char *name = sc->GetPossiblyInlinedFunctionName()
1831 .AsCString();
1832 if (name) {
1833 s.PutCString(name);
1834 return true;
1835 }
1836 }
1837
1838 // Fallback to frame methods if available.
1839 if (exe_ctx) {
1840 StackFrame *frame = exe_ctx->GetFramePtr();
1841 if (frame) {
1842 const char *name = frame->GetFunctionName();
1843 if (name) {
1844 s.PutCString(name);
1845 return true;
1846 }
1847 }
1848 }
1849 return false;
1850 }
1851
1853 if (sc) {
1854 Language *language_plugin = nullptr;
1855 bool language_plugin_handled = false;
1856 StreamString ss;
1857 if (sc->function)
1858 language_plugin = Language::FindPlugin(sc->function->GetLanguage());
1859 else if (sc->symbol)
1860 language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
1861
1862 if (language_plugin)
1863 language_plugin_handled = language_plugin->GetFunctionDisplayName(
1865 ss);
1866
1867 if (language_plugin_handled) {
1868 s << ss.GetString();
1869 return true;
1870 }
1871
1872 const char *name =
1874 .GetName(
1876 .AsCString();
1877 if (name) {
1878 s.PutCString(name);
1879 return true;
1880 }
1881 }
1882
1883 // Fallback to frame methods if available.
1884 if (exe_ctx) {
1885 StackFrame *frame = exe_ctx->GetFramePtr();
1886 if (frame) {
1887 const char *name = frame->GetFunctionName();
1888 if (name) {
1889 s.PutCString(name);
1890 return true;
1891 }
1892 }
1893 }
1894 return false;
1895 }
1896
1907 Language *language_plugin = nullptr;
1908 if (sc->function)
1909 language_plugin = Language::FindPlugin(sc->function->GetLanguage());
1910 else if (sc->symbol)
1911 language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
1912
1913 if (!language_plugin)
1914 return false;
1915
1916 return language_plugin->HandleFrameFormatVariable(*sc, exe_ctx, entry.type,
1917 s);
1918 }
1919
1921 if (sc) {
1922 if (FormatFunctionNameForLanguage(s, exe_ctx, sc))
1923 return true;
1924
1925 if (HandleFunctionNameWithArgs(s, exe_ctx, *sc))
1926 return true;
1927 }
1928
1929 // Fallback to frame methods if available.
1930 if (exe_ctx) {
1931 StackFrame *frame = exe_ctx->GetFramePtr();
1932 if (frame) {
1933 const char *name = frame->GetDisplayFunctionName();
1934 if (name) {
1935 s.PutCString(name);
1936 return true;
1937 }
1938 }
1939 }
1940 return false;
1941 }
1943 if (!sc)
1944 return false;
1945
1946 const char *name = sc->GetPossiblyInlinedFunctionName()
1948 .AsCString();
1949 if (!name)
1950 return false;
1951
1952 s.PutCString(name);
1953
1954 return true;
1955 }
1957 if (addr) {
1958 if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, *addr, false, false,
1959 false))
1960 return true;
1961 }
1962 return false;
1963
1965 if (addr) {
1966 if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, *addr, true, true,
1967 true))
1968 return true;
1969 }
1970 return false;
1971
1973 if (sc)
1975 s, sc, exe_ctx, sc->line_entry.range.GetBaseAddress(), false, false,
1976 false));
1977 return false;
1978
1980 if (exe_ctx) {
1981 StackFrame *frame = exe_ctx->GetFramePtr();
1982 if (frame)
1983 if (DumpAddressOffsetFromFunction(s, sc, exe_ctx,
1984 frame->GetFrameCodeAddress(), false,
1985 false, false))
1986 return true;
1987 }
1988 return false;
1989
1991 return function_changed;
1992
1994 bool is_optimized = false;
1995 if (sc && sc->function && sc->function->GetIsOptimized()) {
1996 is_optimized = true;
1997 }
1998 return is_optimized;
1999 }
2000
2002 return sc && sc->block && sc->block->GetInlinedFunctionInfo();
2003 }
2004
2006 return initial_function;
2007
2009 if (sc && sc->line_entry.IsValid()) {
2010 if (DumpFile(s, sc->line_entry.GetFile(), (FileKind)entry.number))
2011 return true;
2012 }
2013 return false;
2014
2016 if (sc && sc->line_entry.IsValid()) {
2017 const char *format = "%" PRIu32;
2018 if (!entry.printf_format.empty())
2019 format = entry.printf_format.c_str();
2020 s.Printf(format, sc->line_entry.line);
2021 return true;
2022 }
2023 return false;
2024
2026 if (sc && sc->line_entry.IsValid() && sc->line_entry.column) {
2027 const char *format = "%" PRIu32;
2028 if (!entry.printf_format.empty())
2029 format = entry.printf_format.c_str();
2030 s.Printf(format, sc->line_entry.column);
2031 return true;
2032 }
2033 return false;
2034
2037 if (sc && sc->line_entry.range.GetBaseAddress().IsValid()) {
2039
2041 addr.Slide(sc->line_entry.range.GetByteSize());
2042 if (DumpAddressAndContent(s, sc, exe_ctx, addr, false))
2043 return true;
2044 }
2045 return false;
2046
2048 if (addr && exe_ctx && exe_ctx->GetFramePtr()) {
2049 RegisterContextSP reg_ctx =
2050 exe_ctx->GetFramePtr()->GetRegisterContextSP();
2051 if (reg_ctx) {
2052 addr_t pc_loadaddr = reg_ctx->GetPC();
2053 if (pc_loadaddr != LLDB_INVALID_ADDRESS) {
2054 Address pc;
2055 pc.SetLoadAddress(pc_loadaddr, exe_ctx->GetTargetPtr());
2056 if (pc == *addr) {
2057 s.Printf("-> ");
2058 return true;
2059 }
2060 }
2061 }
2062 s.Printf(" ");
2063 return true;
2064 }
2065 return false;
2066
2068 if (Target *target = Target::GetTargetFromContexts(exe_ctx, sc)) {
2069 if (auto progress = target->GetDebugger().GetCurrentProgressReport()) {
2070 if (progress->total != UINT64_MAX) {
2071 s.Format("[{0:N}/{1:N}]", progress->completed, progress->total);
2072 return true;
2073 }
2074 }
2075 }
2076 return false;
2077
2079 if (Target *target = Target::GetTargetFromContexts(exe_ctx, sc)) {
2080 if (auto progress = target->GetDebugger().GetCurrentProgressReport()) {
2081 s.PutCString(progress->message);
2082 return true;
2083 }
2084 }
2085 return false;
2086
2088 if (Target *target = Target::GetTargetFromContexts(exe_ctx, sc)) {
2089 s << target->GetDebugger().GetSeparator();
2090 return true;
2091 }
2092 return false;
2093 }
2094
2095 return false;
2096}
2097
2099 const Definition *parent) {
2100 if (parent->children) {
2101 const size_t n = parent->num_children;
2102 for (size_t i = 0; i < n; ++i) {
2103 if (i > 0)
2104 s.PutCString(", ");
2105 s.Printf("\"%s\"", parent->children[i].name);
2106 }
2107 return true;
2108 }
2109 return false;
2110}
2111
2112static Status ParseEntry(const llvm::StringRef &format_str,
2113 const Definition *parent, FormatEntity::Entry &entry) {
2114 Status error;
2115
2116 const size_t sep_pos = format_str.find_first_of(".[:");
2117 const char sep_char =
2118 (sep_pos == llvm::StringRef::npos) ? '\0' : format_str[sep_pos];
2119 llvm::StringRef key = format_str.substr(0, sep_pos);
2120
2121 const size_t n = parent->num_children;
2122 for (size_t i = 0; i < n; ++i) {
2123 const Definition *entry_def = parent->children + i;
2124 if (key == entry_def->name || entry_def->name[0] == '*') {
2125 llvm::StringRef value;
2126 if (sep_char)
2127 value =
2128 format_str.substr(sep_pos + (entry_def->keep_separator ? 0 : 1));
2129 switch (entry_def->type) {
2131 entry.string = format_str.str();
2132 return error; // Success
2133
2135 entry.number = entry_def->data;
2136 return error; // Success
2137
2139 entry.type = entry_def->type;
2140 entry.string = entry_def->string;
2141 return error; // Success
2142
2143 default:
2144 entry.type = entry_def->type;
2145 break;
2146 }
2147
2148 if (value.empty()) {
2149 if (entry_def->type == FormatEntity::Entry::Type::Invalid) {
2150 if (entry_def->children) {
2151 StreamString error_strm;
2152 error_strm.Printf("'%s' can't be specified on its own, you must "
2153 "access one of its children: ",
2154 entry_def->name);
2155 DumpCommaSeparatedChildEntryNames(error_strm, entry_def);
2156 error =
2157 Status::FromErrorStringWithFormat("%s", error_strm.GetData());
2158 } else if (sep_char == ':') {
2159 // Any value whose separator is a with a ':' means this value has a
2160 // string argument that needs to be stored in the entry (like
2161 // "${script.var:}"). In this case the string value is the empty
2162 // string which is ok.
2163 } else {
2165 "%s", "invalid entry definitions");
2166 }
2167 }
2168 } else {
2169 if (entry_def->children) {
2170 error = ParseEntry(value, entry_def, entry);
2171 } else if (sep_char == ':') {
2172 // Any value whose separator is a with a ':' means this value has a
2173 // string argument that needs to be stored in the entry (like
2174 // "${script.var:modulename.function}")
2175 entry.string = value.str();
2176 } else {
2178 "'%s' followed by '%s' but it has no children", key.str().c_str(),
2179 value.str().c_str());
2180 }
2181 }
2182 return error;
2183 }
2184 }
2185 StreamString error_strm;
2187 error_strm.Printf(
2188 "invalid top level item '%s'. Valid top level items are: ",
2189 key.str().c_str());
2190 else
2191 error_strm.Printf("invalid member '%s' in '%s'. Valid members are: ",
2192 key.str().c_str(), parent->name);
2193 DumpCommaSeparatedChildEntryNames(error_strm, parent);
2194 error = Status::FromErrorStringWithFormat("%s", error_strm.GetData());
2195 return error;
2196}
2197
2198static const Definition *FindEntry(const llvm::StringRef &format_str,
2199 const Definition *parent,
2200 llvm::StringRef &remainder) {
2201 Status error;
2202
2203 std::pair<llvm::StringRef, llvm::StringRef> p = format_str.split('.');
2204 const size_t n = parent->num_children;
2205 for (size_t i = 0; i < n; ++i) {
2206 const Definition *entry_def = parent->children + i;
2207 if (p.first == entry_def->name || entry_def->name[0] == '*') {
2208 if (p.second.empty()) {
2209 if (format_str.back() == '.')
2210 remainder = format_str.drop_front(format_str.size() - 1);
2211 else
2212 remainder = llvm::StringRef(); // Exact match
2213 return entry_def;
2214 } else {
2215 if (entry_def->children) {
2216 return FindEntry(p.second, entry_def, remainder);
2217 } else {
2218 remainder = p.second;
2219 return entry_def;
2220 }
2221 }
2222 }
2223 }
2224 remainder = format_str;
2225 return parent;
2226}
2227
2228static Status ParseInternal(llvm::StringRef &format, Entry &parent_entry,
2229 uint32_t depth) {
2230 Status error;
2231 while (!format.empty() && error.Success()) {
2232 const size_t non_special_chars = format.find_first_of("${}\\|");
2233
2234 if (non_special_chars == llvm::StringRef::npos) {
2235 // No special characters, just string bytes so add them and we are done
2236 parent_entry.AppendText(format);
2237 return error;
2238 }
2239
2240 if (non_special_chars > 0) {
2241 // We have a special character, so add all characters before these as a
2242 // plain string
2243 parent_entry.AppendText(format.substr(0, non_special_chars));
2244 format = format.drop_front(non_special_chars);
2245 }
2246
2247 switch (format[0]) {
2248 case '\0':
2249 return error;
2250
2251 case '{': {
2252 format = format.drop_front(); // Skip the '{'
2253 Entry scope_entry(Entry::Type::Scope);
2254 error = ParseInternal(format, scope_entry, depth + 1);
2255 if (error.Fail())
2256 return error;
2257 parent_entry.AppendEntry(std::move(scope_entry));
2258 } break;
2259
2260 case '}':
2261 if (depth == 0)
2262 error = Status::FromErrorString("unmatched '}' character");
2263 else
2264 format =
2265 format
2266 .drop_front(); // Skip the '}' as we are at the end of the scope
2267 return error;
2268
2269 case '|':
2270 format = format.drop_front(); // Skip the '|'
2271 if (parent_entry.type == Entry::Type::Scope)
2272 parent_entry.StartAlternative();
2273 else
2274 parent_entry.AppendChar('|');
2275 break;
2276
2277 case '\\': {
2278 format = format.drop_front(); // Skip the '\' character
2279 if (format.empty()) {
2281 "'\\' character was not followed by another character");
2282 return error;
2283 }
2284
2285 const char desens_char = format[0];
2286 format = format.drop_front(); // Skip the desensitized char character
2287 switch (desens_char) {
2288 case 'a':
2289 parent_entry.AppendChar('\a');
2290 break;
2291 case 'b':
2292 parent_entry.AppendChar('\b');
2293 break;
2294 case 'f':
2295 parent_entry.AppendChar('\f');
2296 break;
2297 case 'n':
2298 parent_entry.AppendChar('\n');
2299 break;
2300 case 'r':
2301 parent_entry.AppendChar('\r');
2302 break;
2303 case 't':
2304 parent_entry.AppendChar('\t');
2305 break;
2306 case 'v':
2307 parent_entry.AppendChar('\v');
2308 break;
2309 case '\'':
2310 parent_entry.AppendChar('\'');
2311 break;
2312 case '\\':
2313 parent_entry.AppendChar('\\');
2314 break;
2315 case '0':
2316 // 1 to 3 octal chars
2317 {
2318 // Make a string that can hold onto the initial zero char, up to 3
2319 // octal digits, and a terminating NULL.
2320 char oct_str[5] = {0, 0, 0, 0, 0};
2321
2322 int i;
2323 for (i = 0; (format[i] >= '0' && format[i] <= '7') && i < 4; ++i)
2324 oct_str[i] = format[i];
2325
2326 // We don't want to consume the last octal character since the main
2327 // for loop will do this for us, so we advance p by one less than i
2328 // (even if i is zero)
2329 format = format.drop_front(i);
2330 unsigned long octal_value = ::strtoul(oct_str, nullptr, 8);
2331 if (octal_value <= UINT8_MAX) {
2332 parent_entry.AppendChar((char)octal_value);
2333 } else {
2335 "octal number is larger than a single byte");
2336 return error;
2337 }
2338 }
2339 break;
2340
2341 case 'x':
2342 // hex number in the format
2343 if (isxdigit(format[0])) {
2344 // Make a string that can hold onto two hex chars plus a
2345 // NULL terminator
2346 char hex_str[3] = {0, 0, 0};
2347 hex_str[0] = format[0];
2348
2349 format = format.drop_front();
2350
2351 if (isxdigit(format[0])) {
2352 hex_str[1] = format[0];
2353 format = format.drop_front();
2354 }
2355
2356 unsigned long hex_value = strtoul(hex_str, nullptr, 16);
2357 if (hex_value <= UINT8_MAX) {
2358 parent_entry.AppendChar((char)hex_value);
2359 } else {
2361 "hex number is larger than a single byte");
2362 return error;
2363 }
2364 } else {
2365 parent_entry.AppendChar(desens_char);
2366 }
2367 break;
2368
2369 default:
2370 // Just desensitize any other character by just printing what came
2371 // after the '\'
2372 parent_entry.AppendChar(desens_char);
2373 break;
2374 }
2375 } break;
2376
2377 case '$':
2378 format = format.drop_front(); // Skip the '$'
2379 if (format.empty() || format.front() != '{') {
2380 // Print '$' when not followed by '{'.
2381 parent_entry.AppendText("$");
2382 } else {
2383 format = format.drop_front(); // Skip the '{'
2384
2385 llvm::StringRef variable, variable_format;
2386 error = FormatEntity::ExtractVariableInfo(format, variable,
2387 variable_format);
2388 if (error.Fail())
2389 return error;
2390 bool verify_is_thread_id = false;
2391 Entry entry;
2392 if (!variable_format.empty()) {
2393 entry.printf_format = variable_format.str();
2394
2395 // If the format contains a '%' we are going to assume this is a
2396 // printf style format. So if you want to format your thread ID
2397 // using "0x%llx" you can use: ${thread.id%0x%llx}
2398 //
2399 // If there is no '%' in the format, then it is assumed to be a
2400 // LLDB format name, or one of the extended formats specified in
2401 // the switch statement below.
2402
2403 if (entry.printf_format.find('%') == std::string::npos) {
2404 bool clear_printf = false;
2405
2406 if (entry.printf_format.size() == 1) {
2407 switch (entry.printf_format[0]) {
2408 case '@': // if this is an @ sign, print ObjC description
2409 entry.number = ValueObject::
2410 eValueObjectRepresentationStyleLanguageSpecific;
2411 clear_printf = true;
2412 break;
2413 case 'V': // if this is a V, print the value using the default
2414 // format
2415 entry.number =
2417 clear_printf = true;
2418 break;
2419 case 'L': // if this is an L, print the location of the value
2420 entry.number =
2422 clear_printf = true;
2423 break;
2424 case 'S': // if this is an S, print the summary after all
2425 entry.number =
2427 clear_printf = true;
2428 break;
2429 case '#': // if this is a '#', print the number of children
2430 entry.number =
2432 clear_printf = true;
2433 break;
2434 case 'T': // if this is a 'T', print the type
2436 clear_printf = true;
2437 break;
2438 case 'N': // if this is a 'N', print the name
2440 clear_printf = true;
2441 break;
2442 case '>': // if this is a '>', print the expression path
2443 entry.number =
2445 clear_printf = true;
2446 break;
2447 }
2448 }
2449
2450 if (entry.number == 0) {
2452 entry.printf_format.c_str(), entry.fmt)) {
2453 clear_printf = true;
2454 } else if (entry.printf_format == "tid") {
2455 verify_is_thread_id = true;
2456 } else {
2458 "invalid format: '%s'", entry.printf_format.c_str());
2459 return error;
2460 }
2461 }
2462
2463 // Our format string turned out to not be a printf style format
2464 // so lets clear the string
2465 if (clear_printf)
2466 entry.printf_format.clear();
2467 }
2468 }
2469
2470 // Check for dereferences
2471 if (variable[0] == '*') {
2472 entry.deref = true;
2473 variable = variable.drop_front();
2474 }
2475
2476 error = ParseEntry(variable, &g_root, entry);
2477 if (error.Fail())
2478 return error;
2479
2480 llvm::StringRef entry_string(entry.string);
2481 if (entry_string.contains(':')) {
2482 auto [_, llvm_format] = entry_string.split(':');
2483 if (!llvm_format.empty() && !LLVMFormatPattern.match(llvm_format)) {
2485 "invalid llvm format: '%s'", llvm_format.data());
2486 return error;
2487 }
2488 }
2489
2490 if (verify_is_thread_id) {
2491 if (entry.type != Entry::Type::ThreadID &&
2494 "the 'tid' format can only be used on "
2495 "${thread.id} and ${thread.protocol_id}");
2496 }
2497 }
2498
2499 switch (entry.type) {
2502 if (entry.number == 0) {
2503 if (entry.string.empty())
2505 else
2506 entry.number =
2508 }
2509 break;
2510 default:
2511 // Make sure someone didn't try to dereference anything but ${var}
2512 // or ${svar}
2513 if (entry.deref) {
2515 "${%s} can't be dereferenced, only ${var} and ${svar} can.",
2516 variable.str().c_str());
2517 return error;
2518 }
2519 }
2520 parent_entry.AppendEntry(std::move(entry));
2521 }
2522 break;
2523 }
2524 }
2525 return error;
2526}
2527
2528Status FormatEntity::ExtractVariableInfo(llvm::StringRef &format_str,
2529 llvm::StringRef &variable_name,
2530 llvm::StringRef &variable_format) {
2531 Status error;
2532 variable_name = llvm::StringRef();
2533 variable_format = llvm::StringRef();
2534
2535 const size_t paren_pos = format_str.find('}');
2536 if (paren_pos != llvm::StringRef::npos) {
2537 const size_t percent_pos = format_str.find('%');
2538 if (percent_pos < paren_pos) {
2539 if (percent_pos > 0) {
2540 if (percent_pos > 1)
2541 variable_name = format_str.substr(0, percent_pos);
2542 variable_format =
2543 format_str.substr(percent_pos + 1, paren_pos - (percent_pos + 1));
2544 }
2545 } else {
2546 variable_name = format_str.substr(0, paren_pos);
2547 }
2548 // Strip off elements and the formatting and the trailing '}'
2549 format_str = format_str.substr(paren_pos + 1);
2550 } else {
2552 "missing terminating '}' character for '${%s'",
2553 format_str.str().c_str());
2554 }
2555 return error;
2556}
2557
2559 llvm::StringRef variable_name,
2560 llvm::StringRef variable_format) {
2561 if (variable_name.empty() || variable_name == ".fullpath") {
2562 file_spec.Dump(s.AsRawOstream());
2563 return true;
2564 } else if (variable_name == ".basename") {
2565 s.PutCString(file_spec.GetFilename().GetStringRef());
2566 return true;
2567 } else if (variable_name == ".dirname") {
2568 s.PutCString(file_spec.GetFilename().GetStringRef());
2569 return true;
2570 }
2571 return false;
2572}
2573
2574static std::string MakeMatch(const llvm::StringRef &prefix,
2575 const char *suffix) {
2576 std::string match(prefix.str());
2577 match.append(suffix);
2578 return match;
2579}
2580
2581static void AddMatches(const Definition *def, const llvm::StringRef &prefix,
2582 const llvm::StringRef &match_prefix,
2583 StringList &matches) {
2584 const size_t n = def->num_children;
2585 if (n > 0) {
2586 for (size_t i = 0; i < n; ++i) {
2587 if (match_prefix.empty())
2588 matches.AppendString(MakeMatch(prefix, def->children[i].name));
2589 else if (strncmp(def->children[i].name, match_prefix.data(),
2590 match_prefix.size()) == 0)
2591 matches.AppendString(
2592 MakeMatch(prefix, def->children[i].name + match_prefix.size()));
2593 }
2594 }
2595}
2596
2598 llvm::StringRef str = request.GetCursorArgumentPrefix();
2599
2600 const size_t dollar_pos = str.rfind('$');
2601 if (dollar_pos == llvm::StringRef::npos)
2602 return;
2603
2604 // Hitting TAB after $ at the end of the string add a "{"
2605 if (dollar_pos == str.size() - 1) {
2606 std::string match = str.str();
2607 match.append("{");
2608 request.AddCompletion(match);
2609 return;
2610 }
2611
2612 if (str[dollar_pos + 1] != '{')
2613 return;
2614
2615 const size_t close_pos = str.find('}', dollar_pos + 2);
2616 if (close_pos != llvm::StringRef::npos)
2617 return;
2618
2619 const size_t format_pos = str.find('%', dollar_pos + 2);
2620 if (format_pos != llvm::StringRef::npos)
2621 return;
2622
2623 llvm::StringRef partial_variable(str.substr(dollar_pos + 2));
2624 if (partial_variable.empty()) {
2625 // Suggest all top level entities as we are just past "${"
2626 StringList new_matches;
2627 AddMatches(&g_root, str, llvm::StringRef(), new_matches);
2628 request.AddCompletions(new_matches);
2629 return;
2630 }
2631
2632 // We have a partially specified variable, find it
2633 llvm::StringRef remainder;
2634 const Definition *entry_def = FindEntry(partial_variable, &g_root, remainder);
2635 if (!entry_def)
2636 return;
2637
2638 const size_t n = entry_def->num_children;
2639
2640 if (remainder.empty()) {
2641 // Exact match
2642 if (n > 0) {
2643 // "${thread.info" <TAB>
2644 request.AddCompletion(MakeMatch(str, "."));
2645 } else {
2646 // "${thread.id" <TAB>
2647 request.AddCompletion(MakeMatch(str, "}"));
2648 }
2649 } else if (remainder == ".") {
2650 // "${thread." <TAB>
2651 StringList new_matches;
2652 AddMatches(entry_def, str, llvm::StringRef(), new_matches);
2653 request.AddCompletions(new_matches);
2654 } else {
2655 // We have a partial match
2656 // "${thre" <TAB>
2657 StringList new_matches;
2658 AddMatches(entry_def, str, remainder, new_matches);
2659 request.AddCompletions(new_matches);
2660 }
2661}
2662
2664 Stream &out_stream, VariableList const &args,
2665 ExecutionContextScope *exe_scope) {
2666 const size_t num_args = args.GetSize();
2667 for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) {
2668 std::string buffer;
2669
2670 VariableSP var_sp(args.GetVariableAtIndex(arg_idx));
2671 ValueObjectSP var_value_sp(ValueObjectVariable::Create(exe_scope, var_sp));
2672 StreamString ss;
2673 llvm::StringRef var_representation;
2674 const char *var_name = var_value_sp->GetName().GetCString();
2675 if (var_value_sp->GetCompilerType().IsValid()) {
2676 if (exe_scope && exe_scope->CalculateTarget())
2677 var_value_sp = var_value_sp->GetQualifiedRepresentationIfAvailable(
2678 exe_scope->CalculateTarget()
2679 ->TargetProperties::GetPreferDynamicValue(),
2680 exe_scope->CalculateTarget()
2681 ->TargetProperties::GetEnableSyntheticValue());
2682 if (var_value_sp->GetCompilerType().IsAggregateType() &&
2685 .SetHideItemNames(false)
2686 .SetShowMembersOneLiner(true),
2687 "");
2688 format.FormatObject(var_value_sp.get(), buffer, TypeSummaryOptions());
2689 var_representation = buffer;
2690 } else
2691 var_value_sp->DumpPrintableRepresentation(
2692 ss,
2694 eValueObjectRepresentationStyleSummary,
2697 }
2698
2699 if (!ss.GetString().empty())
2700 var_representation = ss.GetString();
2701 if (arg_idx > 0)
2702 out_stream.PutCString(", ");
2703 if (var_value_sp->GetError().Success()) {
2704 if (!var_representation.empty())
2705 out_stream.Printf("%s=%s", var_name, var_representation.str().c_str());
2706 else
2707 out_stream.Printf("%s=%s at %s", var_name,
2708 var_value_sp->GetTypeName().GetCString(),
2709 var_value_sp->GetLocationAsCString());
2710 } else
2711 out_stream.Printf("%s=<unavailable>", var_name);
2712 }
2713}
2714
2715Status FormatEntity::Parse(const llvm::StringRef &format_str, Entry &entry) {
2716 entry.Clear();
2717 entry.type = Entry::Type::Root;
2718 llvm::StringRef modifiable_format(format_str);
2719 return ParseInternal(modifiable_format, entry, 0);
2720}
#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)
static bool FormatFunctionNameForLanguage(Stream &s, const ExecutionContext *exe_ctx, const SymbolContext *sc)
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[]
static bool DumpValue(Stream &s, const SymbolContext *sc, const ExecutionContext *exe_ctx, const FormatEntity::Entry &entry, ValueObject *valobj)
#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.
lldb::addr_t GetByteSize() const
Get accessor for the byte size of this 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
const InlineFunctionInfo * GetInlinedFunctionInfo() const
Get const accessor for any inlined function information.
Definition Block.h:268
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
StackFrame * GetFramePtr() const
Returns a pointer to the frame object.
Target * GetTargetPtr() const
Returns a pointer to the target object.
Process * GetProcessPtr() const
Returns a pointer to the process object.
Thread * GetThreadPtr() const
Returns a pointer to the thread object.
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
static const char * GetFormatAsCString(lldb::Format format)
static bool GetFormatFromCString(const char *format_cstr, lldb::Format &format)
static char GetFormatAsFormatChar(lldb::Format format)
bool GetIsOptimized()
Get whether compiler optimizations were enabled for this function.
Definition Function.cpp:512
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.
const lldb::RegisterContextSP & GetRegisterContextSP() const
Definition StackFrame.h:248
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.
lldb::ModuleSP module_sp
The Module for a given query.
CompileUnit * comp_unit
The CompileUnit for a given query.
Symbol * symbol
The Symbol for a given query.
LineEntry line_entry
The LineEntry for a given query.
Mangled GetPossiblyInlinedFunctionName() const
If available, will return the function name according to the specified mangling preference.
uint32_t GetID() const
Definition Symbol.h:137
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)
bool Format(const Entry &entry, Stream &s, const SymbolContext *sc, const ExecutionContext *exe_ctx, const Address *addr, ValueObject *valobj, bool function_changed, bool initial_function)
Status ExtractVariableInfo(llvm::StringRef &format_str, llvm::StringRef &variable_name, llvm::StringRef &variable_format)
bool FormatStringRef(const llvm::StringRef &format, Stream &s, const SymbolContext *sc, const ExecutionContext *exe_ctx, const Address *addr, ValueObject *valobj, bool function_changed, bool initial_function)
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)
uint16_t column
The column number of the source line, or zero if there is no column information.
Definition LineEntry.h:155
bool IsValid() const
Check if a line entry object is valid.
Definition LineEntry.cpp:35
AddressRange range
The section offset address range for this line entry.
Definition LineEntry.h:137
uint32_t line
The source line number, or LLDB_INVALID_LINE_NUMBER if there is no line number information.
Definition LineEntry.h:151
const FileSpec & GetFile() const
Helper to access the file.
Definition LineEntry.h:134
Every register is described in detail including its name, alternate name (optional),...
bool FormatObject(ValueObject *valobj, std::string &dest, const TypeSummaryOptions &options) override
lldb::user_id_t GetID() const
Get accessor for the user ID.
Definition UserID.h:47
GetValueForExpressionPathOptions & SetSyntheticChildrenTraversal(SyntheticChildrenTraversal traverse)
GetValueForExpressionPathOptions & DoAllowFragileIVar()
GetValueForExpressionPathOptions & DontCheckDotVsArrowSyntax()
GetValueForExpressionPathOptions & DoAllowBitfieldSyntax()