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