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