Coverage Report

Created: 2023-09-30 09:22

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