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