15ffd83dbSDimitry Andric //===-- FormatEntity.cpp --------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include "lldb/Core/FormatEntity.h"
100b57cec5SDimitry Andric
110b57cec5SDimitry Andric #include "lldb/Core/Address.h"
120b57cec5SDimitry Andric #include "lldb/Core/AddressRange.h"
130b57cec5SDimitry Andric #include "lldb/Core/Debugger.h"
140b57cec5SDimitry Andric #include "lldb/Core/DumpRegisterValue.h"
150b57cec5SDimitry Andric #include "lldb/Core/Module.h"
160b57cec5SDimitry Andric #include "lldb/Core/ValueObject.h"
170b57cec5SDimitry Andric #include "lldb/Core/ValueObjectVariable.h"
180b57cec5SDimitry Andric #include "lldb/DataFormatters/DataVisualization.h"
190b57cec5SDimitry Andric #include "lldb/DataFormatters/FormatClasses.h"
200b57cec5SDimitry Andric #include "lldb/DataFormatters/FormatManager.h"
210b57cec5SDimitry Andric #include "lldb/DataFormatters/TypeSummary.h"
220b57cec5SDimitry Andric #include "lldb/Expression/ExpressionVariable.h"
230b57cec5SDimitry Andric #include "lldb/Interpreter/CommandInterpreter.h"
240b57cec5SDimitry Andric #include "lldb/Symbol/Block.h"
250b57cec5SDimitry Andric #include "lldb/Symbol/CompileUnit.h"
260b57cec5SDimitry Andric #include "lldb/Symbol/CompilerType.h"
270b57cec5SDimitry Andric #include "lldb/Symbol/Function.h"
280b57cec5SDimitry Andric #include "lldb/Symbol/LineEntry.h"
290b57cec5SDimitry Andric #include "lldb/Symbol/Symbol.h"
300b57cec5SDimitry Andric #include "lldb/Symbol/SymbolContext.h"
310b57cec5SDimitry Andric #include "lldb/Symbol/VariableList.h"
320b57cec5SDimitry Andric #include "lldb/Target/ExecutionContext.h"
330b57cec5SDimitry Andric #include "lldb/Target/ExecutionContextScope.h"
340b57cec5SDimitry Andric #include "lldb/Target/Language.h"
350b57cec5SDimitry Andric #include "lldb/Target/Process.h"
360b57cec5SDimitry Andric #include "lldb/Target/RegisterContext.h"
370b57cec5SDimitry Andric #include "lldb/Target/SectionLoadList.h"
380b57cec5SDimitry Andric #include "lldb/Target/StackFrame.h"
390b57cec5SDimitry Andric #include "lldb/Target/StopInfo.h"
400b57cec5SDimitry Andric #include "lldb/Target/Target.h"
410b57cec5SDimitry Andric #include "lldb/Target/Thread.h"
420b57cec5SDimitry Andric #include "lldb/Utility/AnsiTerminal.h"
430b57cec5SDimitry Andric #include "lldb/Utility/ArchSpec.h"
44fe6060f1SDimitry Andric #include "lldb/Utility/CompletionRequest.h"
450b57cec5SDimitry Andric #include "lldb/Utility/ConstString.h"
460b57cec5SDimitry Andric #include "lldb/Utility/FileSpec.h"
4781ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h"
480b57cec5SDimitry Andric #include "lldb/Utility/Log.h"
490b57cec5SDimitry Andric #include "lldb/Utility/RegisterValue.h"
50fe6060f1SDimitry Andric #include "lldb/Utility/Status.h"
510b57cec5SDimitry Andric #include "lldb/Utility/Stream.h"
520b57cec5SDimitry Andric #include "lldb/Utility/StreamString.h"
530b57cec5SDimitry Andric #include "lldb/Utility/StringList.h"
540b57cec5SDimitry Andric #include "lldb/Utility/StructuredData.h"
550b57cec5SDimitry Andric #include "lldb/lldb-defines.h"
560b57cec5SDimitry Andric #include "lldb/lldb-forward.h"
570b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
580b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
590b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
60fe013be4SDimitry Andric #include "llvm/TargetParser/Triple.h"
610b57cec5SDimitry Andric
62fe6060f1SDimitry Andric #include <cctype>
63fe6060f1SDimitry Andric #include <cinttypes>
64fe6060f1SDimitry Andric #include <cstdio>
65fe6060f1SDimitry Andric #include <cstdlib>
66fe6060f1SDimitry Andric #include <cstring>
670b57cec5SDimitry Andric #include <memory>
680b57cec5SDimitry Andric #include <type_traits>
690b57cec5SDimitry Andric #include <utility>
700b57cec5SDimitry Andric
710b57cec5SDimitry Andric namespace lldb_private {
720b57cec5SDimitry Andric class ScriptInterpreter;
730b57cec5SDimitry Andric }
740b57cec5SDimitry Andric namespace lldb_private {
750b57cec5SDimitry Andric struct RegisterInfo;
760b57cec5SDimitry Andric }
770b57cec5SDimitry Andric
780b57cec5SDimitry Andric using namespace lldb;
790b57cec5SDimitry Andric using namespace lldb_private;
800b57cec5SDimitry Andric
81fe6060f1SDimitry Andric using Definition = lldb_private::FormatEntity::Entry::Definition;
82fe6060f1SDimitry Andric using Entry = FormatEntity::Entry;
83fe6060f1SDimitry Andric using EntryType = FormatEntity::Entry::Type;
84fe6060f1SDimitry Andric
850b57cec5SDimitry Andric enum FileKind { FileError = 0, Basename, Dirname, Fullpath };
860b57cec5SDimitry Andric
87fe6060f1SDimitry Andric constexpr Definition g_string_entry[] = {
88fe6060f1SDimitry Andric Definition("*", EntryType::ParentString)};
890b57cec5SDimitry Andric
90fe6060f1SDimitry Andric constexpr Definition g_addr_entries[] = {
91fe6060f1SDimitry Andric Definition("load", EntryType::AddressLoad),
92fe6060f1SDimitry Andric Definition("file", EntryType::AddressFile)};
93fe6060f1SDimitry Andric
94fe6060f1SDimitry Andric constexpr Definition g_file_child_entries[] = {
95fe6060f1SDimitry Andric Definition("basename", EntryType::ParentNumber, FileKind::Basename),
96fe6060f1SDimitry Andric Definition("dirname", EntryType::ParentNumber, FileKind::Dirname),
97fe6060f1SDimitry Andric Definition("fullpath", EntryType::ParentNumber, FileKind::Fullpath)};
98fe6060f1SDimitry Andric
99fe6060f1SDimitry Andric constexpr Definition g_frame_child_entries[] = {
100fe6060f1SDimitry Andric Definition("index", EntryType::FrameIndex),
101fe6060f1SDimitry Andric Definition("pc", EntryType::FrameRegisterPC),
102fe6060f1SDimitry Andric Definition("fp", EntryType::FrameRegisterFP),
103fe6060f1SDimitry Andric Definition("sp", EntryType::FrameRegisterSP),
104fe6060f1SDimitry Andric Definition("flags", EntryType::FrameRegisterFlags),
105fe6060f1SDimitry Andric Definition("no-debug", EntryType::FrameNoDebug),
106fe6060f1SDimitry Andric Entry::DefinitionWithChildren("reg", EntryType::FrameRegisterByName,
107fe6060f1SDimitry Andric g_string_entry),
108fe6060f1SDimitry Andric Definition("is-artificial", EntryType::FrameIsArtificial),
1090b57cec5SDimitry Andric };
1100b57cec5SDimitry Andric
111fe6060f1SDimitry Andric constexpr Definition g_function_child_entries[] = {
112fe6060f1SDimitry Andric Definition("id", EntryType::FunctionID),
113fe6060f1SDimitry Andric Definition("name", EntryType::FunctionName),
114fe6060f1SDimitry Andric Definition("name-without-args", EntryType::FunctionNameNoArgs),
115fe6060f1SDimitry Andric Definition("name-with-args", EntryType::FunctionNameWithArgs),
116fe6060f1SDimitry Andric Definition("mangled-name", EntryType::FunctionMangledName),
117fe6060f1SDimitry Andric Definition("addr-offset", EntryType::FunctionAddrOffset),
118fe6060f1SDimitry Andric Definition("concrete-only-addr-offset-no-padding",
119fe6060f1SDimitry Andric EntryType::FunctionAddrOffsetConcrete),
120fe6060f1SDimitry Andric Definition("line-offset", EntryType::FunctionLineOffset),
121fe6060f1SDimitry Andric Definition("pc-offset", EntryType::FunctionPCOffset),
122fe6060f1SDimitry Andric Definition("initial-function", EntryType::FunctionInitial),
123fe6060f1SDimitry Andric Definition("changed", EntryType::FunctionChanged),
124fe6060f1SDimitry Andric Definition("is-optimized", EntryType::FunctionIsOptimized)};
1250b57cec5SDimitry Andric
126fe6060f1SDimitry Andric constexpr Definition g_line_child_entries[] = {
127fe6060f1SDimitry Andric Entry::DefinitionWithChildren("file", EntryType::LineEntryFile,
128fe6060f1SDimitry Andric g_file_child_entries),
129fe6060f1SDimitry Andric Definition("number", EntryType::LineEntryLineNumber),
130fe6060f1SDimitry Andric Definition("column", EntryType::LineEntryColumn),
131fe6060f1SDimitry Andric Definition("start-addr", EntryType::LineEntryStartAddress),
132fe6060f1SDimitry Andric Definition("end-addr", EntryType::LineEntryEndAddress),
1330b57cec5SDimitry Andric };
1340b57cec5SDimitry Andric
135fe6060f1SDimitry Andric constexpr Definition g_module_child_entries[] = {Entry::DefinitionWithChildren(
136fe6060f1SDimitry Andric "file", EntryType::ModuleFile, g_file_child_entries)};
1370b57cec5SDimitry Andric
138fe6060f1SDimitry Andric constexpr Definition g_process_child_entries[] = {
139fe6060f1SDimitry Andric Definition("id", EntryType::ProcessID),
140fe6060f1SDimitry Andric Definition("name", EntryType::ProcessFile, FileKind::Basename),
141fe6060f1SDimitry Andric Entry::DefinitionWithChildren("file", EntryType::ProcessFile,
142fe6060f1SDimitry Andric g_file_child_entries)};
1430b57cec5SDimitry Andric
144fe6060f1SDimitry Andric constexpr Definition g_svar_child_entries[] = {
145fe6060f1SDimitry Andric Definition("*", EntryType::ParentString)};
1460b57cec5SDimitry Andric
147fe6060f1SDimitry Andric constexpr Definition g_var_child_entries[] = {
148fe6060f1SDimitry Andric Definition("*", EntryType::ParentString)};
1490b57cec5SDimitry Andric
150fe6060f1SDimitry Andric constexpr Definition g_thread_child_entries[] = {
151fe6060f1SDimitry Andric Definition("id", EntryType::ThreadID),
152fe6060f1SDimitry Andric Definition("protocol_id", EntryType::ThreadProtocolID),
153fe6060f1SDimitry Andric Definition("index", EntryType::ThreadIndexID),
154fe6060f1SDimitry Andric Entry::DefinitionWithChildren("info", EntryType::ThreadInfo,
155fe6060f1SDimitry Andric g_string_entry),
156fe6060f1SDimitry Andric Definition("queue", EntryType::ThreadQueue),
157fe6060f1SDimitry Andric Definition("name", EntryType::ThreadName),
158fe6060f1SDimitry Andric Definition("stop-reason", EntryType::ThreadStopReason),
159fe6060f1SDimitry Andric Definition("stop-reason-raw", EntryType::ThreadStopReasonRaw),
160fe6060f1SDimitry Andric Definition("return-value", EntryType::ThreadReturnValue),
161fe6060f1SDimitry Andric Definition("completed-expression", EntryType::ThreadCompletedExpression)};
1620b57cec5SDimitry Andric
163fe6060f1SDimitry Andric constexpr Definition g_target_child_entries[] = {
164fe6060f1SDimitry Andric Definition("arch", EntryType::TargetArch)};
1650b57cec5SDimitry Andric
1660b57cec5SDimitry Andric #define _TO_STR2(_val) #_val
1670b57cec5SDimitry Andric #define _TO_STR(_val) _TO_STR2(_val)
1680b57cec5SDimitry Andric
169fe6060f1SDimitry Andric constexpr Definition g_ansi_fg_entries[] = {
170fe6060f1SDimitry Andric Definition("black",
1710b57cec5SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLACK) ANSI_ESC_END),
172fe6060f1SDimitry Andric Definition("red", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_RED) ANSI_ESC_END),
173fe6060f1SDimitry Andric Definition("green",
1740b57cec5SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_GREEN) ANSI_ESC_END),
175fe6060f1SDimitry Andric Definition("yellow",
1760b57cec5SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_YELLOW) ANSI_ESC_END),
177fe6060f1SDimitry Andric Definition("blue", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLUE) ANSI_ESC_END),
178fe6060f1SDimitry Andric Definition("purple",
1790b57cec5SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_PURPLE) ANSI_ESC_END),
180fe6060f1SDimitry Andric Definition("cyan", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_CYAN) ANSI_ESC_END),
181fe6060f1SDimitry Andric Definition("white",
1820b57cec5SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_WHITE) ANSI_ESC_END),
1830b57cec5SDimitry Andric };
1840b57cec5SDimitry Andric
185fe6060f1SDimitry Andric constexpr Definition g_ansi_bg_entries[] = {
186fe6060f1SDimitry Andric Definition("black",
1870b57cec5SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLACK) ANSI_ESC_END),
188fe6060f1SDimitry Andric Definition("red", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_RED) ANSI_ESC_END),
189fe6060f1SDimitry Andric Definition("green",
1900b57cec5SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_GREEN) ANSI_ESC_END),
191fe6060f1SDimitry Andric Definition("yellow",
1920b57cec5SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_YELLOW) ANSI_ESC_END),
193fe6060f1SDimitry Andric Definition("blue", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLUE) ANSI_ESC_END),
194fe6060f1SDimitry Andric Definition("purple",
1950b57cec5SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_PURPLE) ANSI_ESC_END),
196fe6060f1SDimitry Andric Definition("cyan", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_CYAN) ANSI_ESC_END),
197fe6060f1SDimitry Andric Definition("white",
1980b57cec5SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_WHITE) ANSI_ESC_END),
1990b57cec5SDimitry Andric };
2000b57cec5SDimitry Andric
201fe6060f1SDimitry Andric constexpr Definition g_ansi_entries[] = {
202fe6060f1SDimitry Andric Entry::DefinitionWithChildren("fg", EntryType::Invalid, g_ansi_fg_entries),
203fe6060f1SDimitry Andric Entry::DefinitionWithChildren("bg", EntryType::Invalid, g_ansi_bg_entries),
204fe6060f1SDimitry Andric Definition("normal", ANSI_ESC_START _TO_STR(ANSI_CTRL_NORMAL) ANSI_ESC_END),
205fe6060f1SDimitry Andric Definition("bold", ANSI_ESC_START _TO_STR(ANSI_CTRL_BOLD) ANSI_ESC_END),
206fe6060f1SDimitry Andric Definition("faint", ANSI_ESC_START _TO_STR(ANSI_CTRL_FAINT) ANSI_ESC_END),
207fe6060f1SDimitry Andric Definition("italic", ANSI_ESC_START _TO_STR(ANSI_CTRL_ITALIC) ANSI_ESC_END),
208fe6060f1SDimitry Andric Definition("underline",
2090b57cec5SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_CTRL_UNDERLINE) ANSI_ESC_END),
210fe6060f1SDimitry Andric Definition("slow-blink",
2110b57cec5SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_CTRL_SLOW_BLINK) ANSI_ESC_END),
212fe6060f1SDimitry Andric Definition("fast-blink",
2130b57cec5SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_CTRL_FAST_BLINK) ANSI_ESC_END),
214fe6060f1SDimitry Andric Definition("negative",
2150b57cec5SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_CTRL_IMAGE_NEGATIVE) ANSI_ESC_END),
216fe6060f1SDimitry Andric Definition("conceal",
2170b57cec5SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_CTRL_CONCEAL) ANSI_ESC_END),
218fe6060f1SDimitry Andric Definition("crossed-out",
2190b57cec5SDimitry Andric ANSI_ESC_START _TO_STR(ANSI_CTRL_CROSSED_OUT) ANSI_ESC_END),
2200b57cec5SDimitry Andric };
2210b57cec5SDimitry Andric
222fe6060f1SDimitry Andric constexpr Definition g_script_child_entries[] = {
223fe6060f1SDimitry Andric Definition("frame", EntryType::ScriptFrame),
224fe6060f1SDimitry Andric Definition("process", EntryType::ScriptProcess),
225fe6060f1SDimitry Andric Definition("target", EntryType::ScriptTarget),
226fe6060f1SDimitry Andric Definition("thread", EntryType::ScriptThread),
227fe6060f1SDimitry Andric Definition("var", EntryType::ScriptVariable),
228fe6060f1SDimitry Andric Definition("svar", EntryType::ScriptVariableSynthetic),
229fe6060f1SDimitry Andric Definition("thread", EntryType::ScriptThread)};
2300b57cec5SDimitry Andric
231fe6060f1SDimitry Andric constexpr Definition g_top_level_entries[] = {
232fe6060f1SDimitry Andric Entry::DefinitionWithChildren("addr", EntryType::AddressLoadOrFile,
233fe6060f1SDimitry Andric g_addr_entries),
234fe6060f1SDimitry Andric Definition("addr-file-or-load", EntryType::AddressLoadOrFile),
235fe6060f1SDimitry Andric Entry::DefinitionWithChildren("ansi", EntryType::Invalid, g_ansi_entries),
236fe6060f1SDimitry Andric Definition("current-pc-arrow", EntryType::CurrentPCArrow),
237fe6060f1SDimitry Andric Entry::DefinitionWithChildren("file", EntryType::File,
238fe6060f1SDimitry Andric g_file_child_entries),
239fe6060f1SDimitry Andric Definition("language", EntryType::Lang),
240fe6060f1SDimitry Andric Entry::DefinitionWithChildren("frame", EntryType::Invalid,
241fe6060f1SDimitry Andric g_frame_child_entries),
242fe6060f1SDimitry Andric Entry::DefinitionWithChildren("function", EntryType::Invalid,
243fe6060f1SDimitry Andric g_function_child_entries),
244fe6060f1SDimitry Andric Entry::DefinitionWithChildren("line", EntryType::Invalid,
245fe6060f1SDimitry Andric g_line_child_entries),
246fe6060f1SDimitry Andric Entry::DefinitionWithChildren("module", EntryType::Invalid,
247fe6060f1SDimitry Andric g_module_child_entries),
248fe6060f1SDimitry Andric Entry::DefinitionWithChildren("process", EntryType::Invalid,
249fe6060f1SDimitry Andric g_process_child_entries),
250fe6060f1SDimitry Andric Entry::DefinitionWithChildren("script", EntryType::Invalid,
251fe6060f1SDimitry Andric g_script_child_entries),
252fe6060f1SDimitry Andric Entry::DefinitionWithChildren("svar", EntryType::VariableSynthetic,
253fe6060f1SDimitry Andric g_svar_child_entries, true),
254fe6060f1SDimitry Andric Entry::DefinitionWithChildren("thread", EntryType::Invalid,
255fe6060f1SDimitry Andric g_thread_child_entries),
256fe6060f1SDimitry Andric Entry::DefinitionWithChildren("target", EntryType::Invalid,
257fe6060f1SDimitry Andric g_target_child_entries),
258fe6060f1SDimitry Andric Entry::DefinitionWithChildren("var", EntryType::Variable,
259fe6060f1SDimitry Andric g_var_child_entries, true)};
2600b57cec5SDimitry Andric
261fe6060f1SDimitry Andric constexpr Definition g_root = Entry::DefinitionWithChildren(
262fe6060f1SDimitry Andric "<root>", EntryType::Root, g_top_level_entries);
2630b57cec5SDimitry Andric
Entry(llvm::StringRef s)2640b57cec5SDimitry Andric FormatEntity::Entry::Entry(llvm::StringRef s)
2650b57cec5SDimitry Andric : string(s.data(), s.size()), printf_format(), children(),
26681ad6265SDimitry Andric type(Type::String) {}
2670b57cec5SDimitry Andric
Entry(char ch)2680b57cec5SDimitry Andric FormatEntity::Entry::Entry(char ch)
26981ad6265SDimitry Andric : string(1, ch), printf_format(), children(), type(Type::String) {}
2700b57cec5SDimitry Andric
AppendChar(char ch)2710b57cec5SDimitry Andric void FormatEntity::Entry::AppendChar(char ch) {
2720b57cec5SDimitry Andric if (children.empty() || children.back().type != Entry::Type::String)
2730b57cec5SDimitry Andric children.push_back(Entry(ch));
2740b57cec5SDimitry Andric else
2750b57cec5SDimitry Andric children.back().string.append(1, ch);
2760b57cec5SDimitry Andric }
2770b57cec5SDimitry Andric
AppendText(const llvm::StringRef & s)2780b57cec5SDimitry Andric void FormatEntity::Entry::AppendText(const llvm::StringRef &s) {
2790b57cec5SDimitry Andric if (children.empty() || children.back().type != Entry::Type::String)
2800b57cec5SDimitry Andric children.push_back(Entry(s));
2810b57cec5SDimitry Andric else
2820b57cec5SDimitry Andric children.back().string.append(s.data(), s.size());
2830b57cec5SDimitry Andric }
2840b57cec5SDimitry Andric
AppendText(const char * cstr)2850b57cec5SDimitry Andric void FormatEntity::Entry::AppendText(const char *cstr) {
2860b57cec5SDimitry Andric return AppendText(llvm::StringRef(cstr));
2870b57cec5SDimitry Andric }
2880b57cec5SDimitry Andric
2890b57cec5SDimitry Andric #define ENUM_TO_CSTR(eee) \
2900b57cec5SDimitry Andric case FormatEntity::Entry::Type::eee: \
2910b57cec5SDimitry Andric return #eee
2920b57cec5SDimitry Andric
TypeToCString(Type t)2930b57cec5SDimitry Andric const char *FormatEntity::Entry::TypeToCString(Type t) {
2940b57cec5SDimitry Andric switch (t) {
2950b57cec5SDimitry Andric ENUM_TO_CSTR(Invalid);
2960b57cec5SDimitry Andric ENUM_TO_CSTR(ParentNumber);
2970b57cec5SDimitry Andric ENUM_TO_CSTR(ParentString);
2980b57cec5SDimitry Andric ENUM_TO_CSTR(EscapeCode);
2990b57cec5SDimitry Andric ENUM_TO_CSTR(Root);
3000b57cec5SDimitry Andric ENUM_TO_CSTR(String);
3010b57cec5SDimitry Andric ENUM_TO_CSTR(Scope);
3020b57cec5SDimitry Andric ENUM_TO_CSTR(Variable);
3030b57cec5SDimitry Andric ENUM_TO_CSTR(VariableSynthetic);
3040b57cec5SDimitry Andric ENUM_TO_CSTR(ScriptVariable);
3050b57cec5SDimitry Andric ENUM_TO_CSTR(ScriptVariableSynthetic);
3060b57cec5SDimitry Andric ENUM_TO_CSTR(AddressLoad);
3070b57cec5SDimitry Andric ENUM_TO_CSTR(AddressFile);
3080b57cec5SDimitry Andric ENUM_TO_CSTR(AddressLoadOrFile);
3090b57cec5SDimitry Andric ENUM_TO_CSTR(ProcessID);
3100b57cec5SDimitry Andric ENUM_TO_CSTR(ProcessFile);
3110b57cec5SDimitry Andric ENUM_TO_CSTR(ScriptProcess);
3120b57cec5SDimitry Andric ENUM_TO_CSTR(ThreadID);
3130b57cec5SDimitry Andric ENUM_TO_CSTR(ThreadProtocolID);
3140b57cec5SDimitry Andric ENUM_TO_CSTR(ThreadIndexID);
3150b57cec5SDimitry Andric ENUM_TO_CSTR(ThreadName);
3160b57cec5SDimitry Andric ENUM_TO_CSTR(ThreadQueue);
3170b57cec5SDimitry Andric ENUM_TO_CSTR(ThreadStopReason);
3185ffd83dbSDimitry Andric ENUM_TO_CSTR(ThreadStopReasonRaw);
3190b57cec5SDimitry Andric ENUM_TO_CSTR(ThreadReturnValue);
3200b57cec5SDimitry Andric ENUM_TO_CSTR(ThreadCompletedExpression);
3210b57cec5SDimitry Andric ENUM_TO_CSTR(ScriptThread);
3220b57cec5SDimitry Andric ENUM_TO_CSTR(ThreadInfo);
3230b57cec5SDimitry Andric ENUM_TO_CSTR(TargetArch);
3240b57cec5SDimitry Andric ENUM_TO_CSTR(ScriptTarget);
3250b57cec5SDimitry Andric ENUM_TO_CSTR(ModuleFile);
3260b57cec5SDimitry Andric ENUM_TO_CSTR(File);
3270b57cec5SDimitry Andric ENUM_TO_CSTR(Lang);
3280b57cec5SDimitry Andric ENUM_TO_CSTR(FrameIndex);
3290b57cec5SDimitry Andric ENUM_TO_CSTR(FrameNoDebug);
3300b57cec5SDimitry Andric ENUM_TO_CSTR(FrameRegisterPC);
3310b57cec5SDimitry Andric ENUM_TO_CSTR(FrameRegisterSP);
3320b57cec5SDimitry Andric ENUM_TO_CSTR(FrameRegisterFP);
3330b57cec5SDimitry Andric ENUM_TO_CSTR(FrameRegisterFlags);
3340b57cec5SDimitry Andric ENUM_TO_CSTR(FrameRegisterByName);
3350b57cec5SDimitry Andric ENUM_TO_CSTR(FrameIsArtificial);
3360b57cec5SDimitry Andric ENUM_TO_CSTR(ScriptFrame);
3370b57cec5SDimitry Andric ENUM_TO_CSTR(FunctionID);
3380b57cec5SDimitry Andric ENUM_TO_CSTR(FunctionDidChange);
3390b57cec5SDimitry Andric ENUM_TO_CSTR(FunctionInitialFunction);
3400b57cec5SDimitry Andric ENUM_TO_CSTR(FunctionName);
3410b57cec5SDimitry Andric ENUM_TO_CSTR(FunctionNameWithArgs);
3420b57cec5SDimitry Andric ENUM_TO_CSTR(FunctionNameNoArgs);
343480093f4SDimitry Andric ENUM_TO_CSTR(FunctionMangledName);
3440b57cec5SDimitry Andric ENUM_TO_CSTR(FunctionAddrOffset);
3450b57cec5SDimitry Andric ENUM_TO_CSTR(FunctionAddrOffsetConcrete);
3460b57cec5SDimitry Andric ENUM_TO_CSTR(FunctionLineOffset);
3470b57cec5SDimitry Andric ENUM_TO_CSTR(FunctionPCOffset);
3480b57cec5SDimitry Andric ENUM_TO_CSTR(FunctionInitial);
3490b57cec5SDimitry Andric ENUM_TO_CSTR(FunctionChanged);
3500b57cec5SDimitry Andric ENUM_TO_CSTR(FunctionIsOptimized);
3510b57cec5SDimitry Andric ENUM_TO_CSTR(LineEntryFile);
3520b57cec5SDimitry Andric ENUM_TO_CSTR(LineEntryLineNumber);
3530b57cec5SDimitry Andric ENUM_TO_CSTR(LineEntryColumn);
3540b57cec5SDimitry Andric ENUM_TO_CSTR(LineEntryStartAddress);
3550b57cec5SDimitry Andric ENUM_TO_CSTR(LineEntryEndAddress);
3560b57cec5SDimitry Andric ENUM_TO_CSTR(CurrentPCArrow);
3570b57cec5SDimitry Andric }
3580b57cec5SDimitry Andric return "???";
3590b57cec5SDimitry Andric }
3600b57cec5SDimitry Andric
3610b57cec5SDimitry Andric #undef ENUM_TO_CSTR
3620b57cec5SDimitry Andric
Dump(Stream & s,int depth) const3630b57cec5SDimitry Andric void FormatEntity::Entry::Dump(Stream &s, int depth) const {
3640b57cec5SDimitry Andric s.Printf("%*.*s%-20s: ", depth * 2, depth * 2, "", TypeToCString(type));
3650b57cec5SDimitry Andric if (fmt != eFormatDefault)
3660b57cec5SDimitry Andric s.Printf("lldb-format = %s, ", FormatManager::GetFormatAsCString(fmt));
3670b57cec5SDimitry Andric if (!string.empty())
3680b57cec5SDimitry Andric s.Printf("string = \"%s\"", string.c_str());
3690b57cec5SDimitry Andric if (!printf_format.empty())
3700b57cec5SDimitry Andric s.Printf("printf_format = \"%s\"", printf_format.c_str());
3710b57cec5SDimitry Andric if (number != 0)
3720b57cec5SDimitry Andric s.Printf("number = %" PRIu64 " (0x%" PRIx64 "), ", number, number);
3730b57cec5SDimitry Andric if (deref)
3740b57cec5SDimitry Andric s.Printf("deref = true, ");
3750b57cec5SDimitry Andric s.EOL();
3760b57cec5SDimitry Andric for (const auto &child : children) {
3770b57cec5SDimitry Andric child.Dump(s, depth + 1);
3780b57cec5SDimitry Andric }
3790b57cec5SDimitry Andric }
3800b57cec5SDimitry Andric
3810b57cec5SDimitry Andric template <typename T>
RunScriptFormatKeyword(Stream & s,const SymbolContext * sc,const ExecutionContext * exe_ctx,T t,const char * script_function_name)3820b57cec5SDimitry Andric static bool RunScriptFormatKeyword(Stream &s, const SymbolContext *sc,
3830b57cec5SDimitry Andric const ExecutionContext *exe_ctx, T t,
3840b57cec5SDimitry Andric const char *script_function_name) {
3850b57cec5SDimitry Andric Target *target = Target::GetTargetFromContexts(exe_ctx, sc);
3860b57cec5SDimitry Andric
3870b57cec5SDimitry Andric if (target) {
3880b57cec5SDimitry Andric ScriptInterpreter *script_interpreter =
3890b57cec5SDimitry Andric target->GetDebugger().GetScriptInterpreter();
3900b57cec5SDimitry Andric if (script_interpreter) {
3910b57cec5SDimitry Andric Status error;
3920b57cec5SDimitry Andric std::string script_output;
3930b57cec5SDimitry Andric
3940b57cec5SDimitry Andric if (script_interpreter->RunScriptFormatKeyword(script_function_name, t,
3950b57cec5SDimitry Andric script_output, error) &&
3960b57cec5SDimitry Andric error.Success()) {
3970b57cec5SDimitry Andric s.Printf("%s", script_output.c_str());
3980b57cec5SDimitry Andric return true;
3990b57cec5SDimitry Andric } else {
4000b57cec5SDimitry Andric s.Printf("<error: %s>", error.AsCString());
4010b57cec5SDimitry Andric }
4020b57cec5SDimitry Andric }
4030b57cec5SDimitry Andric }
4040b57cec5SDimitry Andric return false;
4050b57cec5SDimitry Andric }
4060b57cec5SDimitry Andric
DumpAddressAndContent(Stream & s,const SymbolContext * sc,const ExecutionContext * exe_ctx,const Address & addr,bool print_file_addr_or_load_addr)407480093f4SDimitry Andric static bool DumpAddressAndContent(Stream &s, const SymbolContext *sc,
408480093f4SDimitry Andric const ExecutionContext *exe_ctx,
409480093f4SDimitry Andric const Address &addr,
4100b57cec5SDimitry Andric bool print_file_addr_or_load_addr) {
4110b57cec5SDimitry Andric Target *target = Target::GetTargetFromContexts(exe_ctx, sc);
4120b57cec5SDimitry Andric addr_t vaddr = LLDB_INVALID_ADDRESS;
4130b57cec5SDimitry Andric if (exe_ctx && !target->GetSectionLoadList().IsEmpty())
4140b57cec5SDimitry Andric vaddr = addr.GetLoadAddress(target);
4150b57cec5SDimitry Andric if (vaddr == LLDB_INVALID_ADDRESS)
4160b57cec5SDimitry Andric vaddr = addr.GetFileAddress();
4170b57cec5SDimitry Andric
4180b57cec5SDimitry Andric if (vaddr != LLDB_INVALID_ADDRESS) {
4190b57cec5SDimitry Andric int addr_width = 0;
4200b57cec5SDimitry Andric if (exe_ctx && target) {
4210b57cec5SDimitry Andric addr_width = target->GetArchitecture().GetAddressByteSize() * 2;
4220b57cec5SDimitry Andric }
4230b57cec5SDimitry Andric if (addr_width == 0)
4240b57cec5SDimitry Andric addr_width = 16;
4250b57cec5SDimitry Andric if (print_file_addr_or_load_addr) {
4260b57cec5SDimitry Andric ExecutionContextScope *exe_scope = nullptr;
4270b57cec5SDimitry Andric if (exe_ctx)
4280b57cec5SDimitry Andric exe_scope = exe_ctx->GetBestExecutionContextScope();
4290b57cec5SDimitry Andric addr.Dump(&s, exe_scope, Address::DumpStyleLoadAddress,
4300b57cec5SDimitry Andric Address::DumpStyleModuleWithFileAddress, 0);
4310b57cec5SDimitry Andric } else {
4320b57cec5SDimitry Andric s.Printf("0x%*.*" PRIx64, addr_width, addr_width, vaddr);
4330b57cec5SDimitry Andric }
4340b57cec5SDimitry Andric return true;
4350b57cec5SDimitry Andric }
4360b57cec5SDimitry Andric return false;
4370b57cec5SDimitry Andric }
4380b57cec5SDimitry Andric
DumpAddressOffsetFromFunction(Stream & s,const SymbolContext * sc,const ExecutionContext * exe_ctx,const Address & format_addr,bool concrete_only,bool no_padding,bool print_zero_offsets)4390b57cec5SDimitry Andric static bool DumpAddressOffsetFromFunction(Stream &s, const SymbolContext *sc,
4400b57cec5SDimitry Andric const ExecutionContext *exe_ctx,
4410b57cec5SDimitry Andric const Address &format_addr,
4420b57cec5SDimitry Andric bool concrete_only, bool no_padding,
4430b57cec5SDimitry Andric bool print_zero_offsets) {
4440b57cec5SDimitry Andric if (format_addr.IsValid()) {
4450b57cec5SDimitry Andric Address func_addr;
4460b57cec5SDimitry Andric
4470b57cec5SDimitry Andric if (sc) {
4480b57cec5SDimitry Andric if (sc->function) {
4490b57cec5SDimitry Andric func_addr = sc->function->GetAddressRange().GetBaseAddress();
4500b57cec5SDimitry Andric if (sc->block && !concrete_only) {
4510b57cec5SDimitry Andric // Check to make sure we aren't in an inline function. If we are, use
4520b57cec5SDimitry Andric // the inline block range that contains "format_addr" since blocks
4530b57cec5SDimitry Andric // can be discontiguous.
4540b57cec5SDimitry Andric Block *inline_block = sc->block->GetContainingInlinedBlock();
4550b57cec5SDimitry Andric AddressRange inline_range;
4560b57cec5SDimitry Andric if (inline_block && inline_block->GetRangeContainingAddress(
4570b57cec5SDimitry Andric format_addr, inline_range))
4580b57cec5SDimitry Andric func_addr = inline_range.GetBaseAddress();
4590b57cec5SDimitry Andric }
4600b57cec5SDimitry Andric } else if (sc->symbol && sc->symbol->ValueIsAddress())
4610b57cec5SDimitry Andric func_addr = sc->symbol->GetAddressRef();
4620b57cec5SDimitry Andric }
4630b57cec5SDimitry Andric
4640b57cec5SDimitry Andric if (func_addr.IsValid()) {
4650b57cec5SDimitry Andric const char *addr_offset_padding = no_padding ? "" : " ";
4660b57cec5SDimitry Andric
4670b57cec5SDimitry Andric if (func_addr.GetSection() == format_addr.GetSection()) {
4680b57cec5SDimitry Andric addr_t func_file_addr = func_addr.GetFileAddress();
4690b57cec5SDimitry Andric addr_t addr_file_addr = format_addr.GetFileAddress();
4700b57cec5SDimitry Andric if (addr_file_addr > func_file_addr ||
4710b57cec5SDimitry Andric (addr_file_addr == func_file_addr && print_zero_offsets)) {
4720b57cec5SDimitry Andric s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding,
4730b57cec5SDimitry Andric addr_file_addr - func_file_addr);
4740b57cec5SDimitry Andric } else if (addr_file_addr < func_file_addr) {
4750b57cec5SDimitry Andric s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding,
4760b57cec5SDimitry Andric func_file_addr - addr_file_addr);
4770b57cec5SDimitry Andric }
4780b57cec5SDimitry Andric return true;
4790b57cec5SDimitry Andric } else {
4800b57cec5SDimitry Andric Target *target = Target::GetTargetFromContexts(exe_ctx, sc);
4810b57cec5SDimitry Andric if (target) {
4820b57cec5SDimitry Andric addr_t func_load_addr = func_addr.GetLoadAddress(target);
4830b57cec5SDimitry Andric addr_t addr_load_addr = format_addr.GetLoadAddress(target);
4840b57cec5SDimitry Andric if (addr_load_addr > func_load_addr ||
4850b57cec5SDimitry Andric (addr_load_addr == func_load_addr && print_zero_offsets)) {
4860b57cec5SDimitry Andric s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding,
4870b57cec5SDimitry Andric addr_load_addr - func_load_addr);
4880b57cec5SDimitry Andric } else if (addr_load_addr < func_load_addr) {
4890b57cec5SDimitry Andric s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding,
4900b57cec5SDimitry Andric func_load_addr - addr_load_addr);
4910b57cec5SDimitry Andric }
4920b57cec5SDimitry Andric return true;
4930b57cec5SDimitry Andric }
4940b57cec5SDimitry Andric }
4950b57cec5SDimitry Andric }
4960b57cec5SDimitry Andric }
4970b57cec5SDimitry Andric return false;
4980b57cec5SDimitry Andric }
4990b57cec5SDimitry Andric
ScanBracketedRange(llvm::StringRef subpath,size_t & close_bracket_index,const char * & var_name_final_if_array_range,int64_t & index_lower,int64_t & index_higher)5000b57cec5SDimitry Andric static bool ScanBracketedRange(llvm::StringRef subpath,
5010b57cec5SDimitry Andric size_t &close_bracket_index,
5020b57cec5SDimitry Andric const char *&var_name_final_if_array_range,
5030b57cec5SDimitry Andric int64_t &index_lower, int64_t &index_higher) {
50481ad6265SDimitry Andric Log *log = GetLog(LLDBLog::DataFormatters);
5050b57cec5SDimitry Andric close_bracket_index = llvm::StringRef::npos;
5060b57cec5SDimitry Andric const size_t open_bracket_index = subpath.find('[');
5070b57cec5SDimitry Andric if (open_bracket_index == llvm::StringRef::npos) {
5089dba64beSDimitry Andric LLDB_LOGF(log,
5099dba64beSDimitry Andric "[ScanBracketedRange] no bracketed range, skipping entirely");
5100b57cec5SDimitry Andric return false;
5110b57cec5SDimitry Andric }
5120b57cec5SDimitry Andric
5130b57cec5SDimitry Andric close_bracket_index = subpath.find(']', open_bracket_index + 1);
5140b57cec5SDimitry Andric
5150b57cec5SDimitry Andric if (close_bracket_index == llvm::StringRef::npos) {
5169dba64beSDimitry Andric LLDB_LOGF(log,
5179dba64beSDimitry Andric "[ScanBracketedRange] no bracketed range, skipping entirely");
5180b57cec5SDimitry Andric return false;
5190b57cec5SDimitry Andric } else {
5200b57cec5SDimitry Andric var_name_final_if_array_range = subpath.data() + open_bracket_index;
5210b57cec5SDimitry Andric
5220b57cec5SDimitry Andric if (close_bracket_index - open_bracket_index == 1) {
5239dba64beSDimitry Andric LLDB_LOGF(
5249dba64beSDimitry Andric log,
5250b57cec5SDimitry Andric "[ScanBracketedRange] '[]' detected.. going from 0 to end of data");
5260b57cec5SDimitry Andric index_lower = 0;
5270b57cec5SDimitry Andric } else {
5280b57cec5SDimitry Andric const size_t separator_index = subpath.find('-', open_bracket_index + 1);
5290b57cec5SDimitry Andric
5300b57cec5SDimitry Andric if (separator_index == llvm::StringRef::npos) {
5310b57cec5SDimitry Andric const char *index_lower_cstr = subpath.data() + open_bracket_index + 1;
5320b57cec5SDimitry Andric index_lower = ::strtoul(index_lower_cstr, nullptr, 0);
5330b57cec5SDimitry Andric index_higher = index_lower;
5349dba64beSDimitry Andric LLDB_LOGF(log,
5359dba64beSDimitry Andric "[ScanBracketedRange] [%" PRId64
5360b57cec5SDimitry Andric "] detected, high index is same",
5370b57cec5SDimitry Andric index_lower);
5380b57cec5SDimitry Andric } else {
5390b57cec5SDimitry Andric const char *index_lower_cstr = subpath.data() + open_bracket_index + 1;
5400b57cec5SDimitry Andric const char *index_higher_cstr = subpath.data() + separator_index + 1;
5410b57cec5SDimitry Andric index_lower = ::strtoul(index_lower_cstr, nullptr, 0);
5420b57cec5SDimitry Andric index_higher = ::strtoul(index_higher_cstr, nullptr, 0);
5439dba64beSDimitry Andric LLDB_LOGF(log,
5449dba64beSDimitry Andric "[ScanBracketedRange] [%" PRId64 "-%" PRId64 "] detected",
5450b57cec5SDimitry Andric index_lower, index_higher);
5460b57cec5SDimitry Andric }
5470b57cec5SDimitry Andric if (index_lower > index_higher && index_higher > 0) {
5489dba64beSDimitry Andric LLDB_LOGF(log, "[ScanBracketedRange] swapping indices");
5490b57cec5SDimitry Andric const int64_t temp = index_lower;
5500b57cec5SDimitry Andric index_lower = index_higher;
5510b57cec5SDimitry Andric index_higher = temp;
5520b57cec5SDimitry Andric }
5530b57cec5SDimitry Andric }
5540b57cec5SDimitry Andric }
5550b57cec5SDimitry Andric return true;
5560b57cec5SDimitry Andric }
5570b57cec5SDimitry Andric
DumpFile(Stream & s,const FileSpec & file,FileKind file_kind)5580b57cec5SDimitry Andric static bool DumpFile(Stream &s, const FileSpec &file, FileKind file_kind) {
5590b57cec5SDimitry Andric switch (file_kind) {
5600b57cec5SDimitry Andric case FileKind::FileError:
5610b57cec5SDimitry Andric break;
5620b57cec5SDimitry Andric
5630b57cec5SDimitry Andric case FileKind::Basename:
5640b57cec5SDimitry Andric if (file.GetFilename()) {
5650b57cec5SDimitry Andric s << file.GetFilename();
5660b57cec5SDimitry Andric return true;
5670b57cec5SDimitry Andric }
5680b57cec5SDimitry Andric break;
5690b57cec5SDimitry Andric
5700b57cec5SDimitry Andric case FileKind::Dirname:
5710b57cec5SDimitry Andric if (file.GetDirectory()) {
5720b57cec5SDimitry Andric s << file.GetDirectory();
5730b57cec5SDimitry Andric return true;
5740b57cec5SDimitry Andric }
5750b57cec5SDimitry Andric break;
5760b57cec5SDimitry Andric
5770b57cec5SDimitry Andric case FileKind::Fullpath:
5780b57cec5SDimitry Andric if (file) {
5790b57cec5SDimitry Andric s << file;
5800b57cec5SDimitry Andric return true;
5810b57cec5SDimitry Andric }
5820b57cec5SDimitry Andric break;
5830b57cec5SDimitry Andric }
5840b57cec5SDimitry Andric return false;
5850b57cec5SDimitry Andric }
5860b57cec5SDimitry Andric
DumpRegister(Stream & s,StackFrame * frame,RegisterKind reg_kind,uint32_t reg_num,Format format)5870b57cec5SDimitry Andric static bool DumpRegister(Stream &s, StackFrame *frame, RegisterKind reg_kind,
588fe6060f1SDimitry Andric uint32_t reg_num, Format format) {
5890b57cec5SDimitry Andric if (frame) {
5900b57cec5SDimitry Andric RegisterContext *reg_ctx = frame->GetRegisterContext().get();
5910b57cec5SDimitry Andric
5920b57cec5SDimitry Andric if (reg_ctx) {
5930b57cec5SDimitry Andric const uint32_t lldb_reg_num =
5940b57cec5SDimitry Andric reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num);
5950b57cec5SDimitry Andric if (lldb_reg_num != LLDB_INVALID_REGNUM) {
5960b57cec5SDimitry Andric const RegisterInfo *reg_info =
5970b57cec5SDimitry Andric reg_ctx->GetRegisterInfoAtIndex(lldb_reg_num);
5980b57cec5SDimitry Andric if (reg_info) {
5990b57cec5SDimitry Andric RegisterValue reg_value;
6000b57cec5SDimitry Andric if (reg_ctx->ReadRegister(reg_info, reg_value)) {
601fe013be4SDimitry Andric DumpRegisterValue(reg_value, s, *reg_info, false, false, format);
6020b57cec5SDimitry Andric return true;
6030b57cec5SDimitry Andric }
6040b57cec5SDimitry Andric }
6050b57cec5SDimitry Andric }
6060b57cec5SDimitry Andric }
6070b57cec5SDimitry Andric }
6080b57cec5SDimitry Andric return false;
6090b57cec5SDimitry Andric }
6100b57cec5SDimitry Andric
ExpandIndexedExpression(ValueObject * valobj,size_t index,bool deref_pointer)6110b57cec5SDimitry Andric static ValueObjectSP ExpandIndexedExpression(ValueObject *valobj, size_t index,
6120b57cec5SDimitry Andric bool deref_pointer) {
61381ad6265SDimitry Andric Log *log = GetLog(LLDBLog::DataFormatters);
614bdd1243dSDimitry Andric std::string name_to_deref = llvm::formatv("[{0}]", index);
615bdd1243dSDimitry Andric LLDB_LOG(log, "[ExpandIndexedExpression] name to deref: {0}", name_to_deref);
6160b57cec5SDimitry Andric ValueObject::GetValueForExpressionPathOptions options;
6170b57cec5SDimitry Andric ValueObject::ExpressionPathEndResultType final_value_type;
6180b57cec5SDimitry Andric ValueObject::ExpressionPathScanEndReason reason_to_stop;
6190b57cec5SDimitry Andric ValueObject::ExpressionPathAftermath what_next =
6200b57cec5SDimitry Andric (deref_pointer ? ValueObject::eExpressionPathAftermathDereference
6210b57cec5SDimitry Andric : ValueObject::eExpressionPathAftermathNothing);
6220b57cec5SDimitry Andric ValueObjectSP item = valobj->GetValueForExpressionPath(
623bdd1243dSDimitry Andric name_to_deref, &reason_to_stop, &final_value_type, options, &what_next);
6240b57cec5SDimitry Andric if (!item) {
6259dba64beSDimitry Andric LLDB_LOGF(log,
6269dba64beSDimitry Andric "[ExpandIndexedExpression] ERROR: why stopping = %d,"
6270b57cec5SDimitry Andric " final_value_type %d",
6280b57cec5SDimitry Andric reason_to_stop, final_value_type);
6290b57cec5SDimitry Andric } else {
6309dba64beSDimitry Andric LLDB_LOGF(log,
6319dba64beSDimitry Andric "[ExpandIndexedExpression] ALL RIGHT: why stopping = %d,"
6320b57cec5SDimitry Andric " final_value_type %d",
6330b57cec5SDimitry Andric reason_to_stop, final_value_type);
6340b57cec5SDimitry Andric }
6350b57cec5SDimitry Andric return item;
6360b57cec5SDimitry Andric }
6370b57cec5SDimitry Andric
ConvertValueObjectStyleToChar(ValueObject::ValueObjectRepresentationStyle style)6380b57cec5SDimitry Andric static char ConvertValueObjectStyleToChar(
6390b57cec5SDimitry Andric ValueObject::ValueObjectRepresentationStyle style) {
6400b57cec5SDimitry Andric switch (style) {
6410b57cec5SDimitry Andric case ValueObject::eValueObjectRepresentationStyleLanguageSpecific:
6420b57cec5SDimitry Andric return '@';
6430b57cec5SDimitry Andric case ValueObject::eValueObjectRepresentationStyleValue:
6440b57cec5SDimitry Andric return 'V';
6450b57cec5SDimitry Andric case ValueObject::eValueObjectRepresentationStyleLocation:
6460b57cec5SDimitry Andric return 'L';
6470b57cec5SDimitry Andric case ValueObject::eValueObjectRepresentationStyleSummary:
6480b57cec5SDimitry Andric return 'S';
6490b57cec5SDimitry Andric case ValueObject::eValueObjectRepresentationStyleChildrenCount:
6500b57cec5SDimitry Andric return '#';
6510b57cec5SDimitry Andric case ValueObject::eValueObjectRepresentationStyleType:
6520b57cec5SDimitry Andric return 'T';
6530b57cec5SDimitry Andric case ValueObject::eValueObjectRepresentationStyleName:
6540b57cec5SDimitry Andric return 'N';
6550b57cec5SDimitry Andric case ValueObject::eValueObjectRepresentationStyleExpressionPath:
6560b57cec5SDimitry Andric return '>';
6570b57cec5SDimitry Andric }
6580b57cec5SDimitry Andric return '\0';
6590b57cec5SDimitry Andric }
6600b57cec5SDimitry Andric
DumpValue(Stream & s,const SymbolContext * sc,const ExecutionContext * exe_ctx,const FormatEntity::Entry & entry,ValueObject * valobj)6610b57cec5SDimitry Andric static bool DumpValue(Stream &s, const SymbolContext *sc,
6620b57cec5SDimitry Andric const ExecutionContext *exe_ctx,
6630b57cec5SDimitry Andric const FormatEntity::Entry &entry, ValueObject *valobj) {
6640b57cec5SDimitry Andric if (valobj == nullptr)
6650b57cec5SDimitry Andric return false;
6660b57cec5SDimitry Andric
66781ad6265SDimitry Andric Log *log = GetLog(LLDBLog::DataFormatters);
6680b57cec5SDimitry Andric Format custom_format = eFormatInvalid;
6690b57cec5SDimitry Andric ValueObject::ValueObjectRepresentationStyle val_obj_display =
6700b57cec5SDimitry Andric entry.string.empty()
6710b57cec5SDimitry Andric ? ValueObject::eValueObjectRepresentationStyleValue
6720b57cec5SDimitry Andric : ValueObject::eValueObjectRepresentationStyleSummary;
6730b57cec5SDimitry Andric
6740b57cec5SDimitry Andric bool do_deref_pointer = entry.deref;
6750b57cec5SDimitry Andric bool is_script = false;
6760b57cec5SDimitry Andric switch (entry.type) {
6770b57cec5SDimitry Andric case FormatEntity::Entry::Type::ScriptVariable:
6780b57cec5SDimitry Andric is_script = true;
6790b57cec5SDimitry Andric break;
6800b57cec5SDimitry Andric
6810b57cec5SDimitry Andric case FormatEntity::Entry::Type::Variable:
6820b57cec5SDimitry Andric custom_format = entry.fmt;
6830b57cec5SDimitry Andric val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number;
6840b57cec5SDimitry Andric break;
6850b57cec5SDimitry Andric
6860b57cec5SDimitry Andric case FormatEntity::Entry::Type::ScriptVariableSynthetic:
6870b57cec5SDimitry Andric is_script = true;
688bdd1243dSDimitry Andric [[fallthrough]];
6890b57cec5SDimitry Andric case FormatEntity::Entry::Type::VariableSynthetic:
6900b57cec5SDimitry Andric custom_format = entry.fmt;
6910b57cec5SDimitry Andric val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number;
6920b57cec5SDimitry Andric if (!valobj->IsSynthetic()) {
6930b57cec5SDimitry Andric valobj = valobj->GetSyntheticValue().get();
6940b57cec5SDimitry Andric if (valobj == nullptr)
6950b57cec5SDimitry Andric return false;
6960b57cec5SDimitry Andric }
6970b57cec5SDimitry Andric break;
6980b57cec5SDimitry Andric
6990b57cec5SDimitry Andric default:
7000b57cec5SDimitry Andric return false;
7010b57cec5SDimitry Andric }
7020b57cec5SDimitry Andric
7030b57cec5SDimitry Andric ValueObject::ExpressionPathAftermath what_next =
7040b57cec5SDimitry Andric (do_deref_pointer ? ValueObject::eExpressionPathAftermathDereference
7050b57cec5SDimitry Andric : ValueObject::eExpressionPathAftermathNothing);
7060b57cec5SDimitry Andric ValueObject::GetValueForExpressionPathOptions options;
7070b57cec5SDimitry Andric options.DontCheckDotVsArrowSyntax()
7080b57cec5SDimitry Andric .DoAllowBitfieldSyntax()
7090b57cec5SDimitry Andric .DoAllowFragileIVar()
7100b57cec5SDimitry Andric .SetSyntheticChildrenTraversal(
7110b57cec5SDimitry Andric ValueObject::GetValueForExpressionPathOptions::
7120b57cec5SDimitry Andric SyntheticChildrenTraversal::Both);
7130b57cec5SDimitry Andric ValueObject *target = nullptr;
7140b57cec5SDimitry Andric const char *var_name_final_if_array_range = nullptr;
7150b57cec5SDimitry Andric size_t close_bracket_index = llvm::StringRef::npos;
7160b57cec5SDimitry Andric int64_t index_lower = -1;
7170b57cec5SDimitry Andric int64_t index_higher = -1;
7180b57cec5SDimitry Andric bool is_array_range = false;
7190b57cec5SDimitry Andric bool was_plain_var = false;
7200b57cec5SDimitry Andric bool was_var_format = false;
7210b57cec5SDimitry Andric bool was_var_indexed = false;
7220b57cec5SDimitry Andric ValueObject::ExpressionPathScanEndReason reason_to_stop =
7230b57cec5SDimitry Andric ValueObject::eExpressionPathScanEndReasonEndOfString;
7240b57cec5SDimitry Andric ValueObject::ExpressionPathEndResultType final_value_type =
7250b57cec5SDimitry Andric ValueObject::eExpressionPathEndResultTypePlain;
7260b57cec5SDimitry Andric
7270b57cec5SDimitry Andric if (is_script) {
7280b57cec5SDimitry Andric return RunScriptFormatKeyword(s, sc, exe_ctx, valobj, entry.string.c_str());
7290b57cec5SDimitry Andric }
7300b57cec5SDimitry Andric
7310b57cec5SDimitry Andric llvm::StringRef subpath(entry.string);
7320b57cec5SDimitry Andric // simplest case ${var}, just print valobj's value
7330b57cec5SDimitry Andric if (entry.string.empty()) {
7340b57cec5SDimitry Andric if (entry.printf_format.empty() && entry.fmt == eFormatDefault &&
7350b57cec5SDimitry Andric entry.number == ValueObject::eValueObjectRepresentationStyleValue)
7360b57cec5SDimitry Andric was_plain_var = true;
7370b57cec5SDimitry Andric else
7380b57cec5SDimitry Andric was_var_format = true;
7390b57cec5SDimitry Andric target = valobj;
7400b57cec5SDimitry Andric } else // this is ${var.something} or multiple .something nested
7410b57cec5SDimitry Andric {
7420b57cec5SDimitry Andric if (entry.string[0] == '[')
7430b57cec5SDimitry Andric was_var_indexed = true;
7440b57cec5SDimitry Andric ScanBracketedRange(subpath, close_bracket_index,
7450b57cec5SDimitry Andric var_name_final_if_array_range, index_lower,
7460b57cec5SDimitry Andric index_higher);
7470b57cec5SDimitry Andric
7480b57cec5SDimitry Andric Status error;
7490b57cec5SDimitry Andric
7500b57cec5SDimitry Andric const std::string &expr_path = entry.string;
7510b57cec5SDimitry Andric
7529dba64beSDimitry Andric LLDB_LOGF(log, "[Debugger::FormatPrompt] symbol to expand: %s",
7530b57cec5SDimitry Andric expr_path.c_str());
7540b57cec5SDimitry Andric
7550b57cec5SDimitry Andric target =
7560b57cec5SDimitry Andric valobj
7570b57cec5SDimitry Andric ->GetValueForExpressionPath(expr_path.c_str(), &reason_to_stop,
7580b57cec5SDimitry Andric &final_value_type, options, &what_next)
7590b57cec5SDimitry Andric .get();
7600b57cec5SDimitry Andric
7610b57cec5SDimitry Andric if (!target) {
7629dba64beSDimitry Andric LLDB_LOGF(log,
7639dba64beSDimitry Andric "[Debugger::FormatPrompt] ERROR: why stopping = %d,"
7640b57cec5SDimitry Andric " final_value_type %d",
7650b57cec5SDimitry Andric reason_to_stop, final_value_type);
7660b57cec5SDimitry Andric return false;
7670b57cec5SDimitry Andric } else {
7689dba64beSDimitry Andric LLDB_LOGF(log,
7699dba64beSDimitry Andric "[Debugger::FormatPrompt] ALL RIGHT: why stopping = %d,"
7700b57cec5SDimitry Andric " final_value_type %d",
7710b57cec5SDimitry Andric reason_to_stop, final_value_type);
7720b57cec5SDimitry Andric target = target
7730b57cec5SDimitry Andric ->GetQualifiedRepresentationIfAvailable(
7740b57cec5SDimitry Andric target->GetDynamicValueType(), true)
7750b57cec5SDimitry Andric .get();
7760b57cec5SDimitry Andric }
7770b57cec5SDimitry Andric }
7780b57cec5SDimitry Andric
7790b57cec5SDimitry Andric is_array_range =
7800b57cec5SDimitry Andric (final_value_type ==
7810b57cec5SDimitry Andric ValueObject::eExpressionPathEndResultTypeBoundedRange ||
7820b57cec5SDimitry Andric final_value_type ==
7830b57cec5SDimitry Andric ValueObject::eExpressionPathEndResultTypeUnboundedRange);
7840b57cec5SDimitry Andric
7850b57cec5SDimitry Andric do_deref_pointer =
7860b57cec5SDimitry Andric (what_next == ValueObject::eExpressionPathAftermathDereference);
7870b57cec5SDimitry Andric
7880b57cec5SDimitry Andric if (do_deref_pointer && !is_array_range) {
7890b57cec5SDimitry Andric // I have not deref-ed yet, let's do it
7900b57cec5SDimitry Andric // this happens when we are not going through
7910b57cec5SDimitry Andric // GetValueForVariableExpressionPath to get to the target ValueObject
7920b57cec5SDimitry Andric Status error;
7930b57cec5SDimitry Andric target = target->Dereference(error).get();
7940b57cec5SDimitry Andric if (error.Fail()) {
7959dba64beSDimitry Andric LLDB_LOGF(log, "[Debugger::FormatPrompt] ERROR: %s\n",
7960b57cec5SDimitry Andric error.AsCString("unknown"));
7970b57cec5SDimitry Andric return false;
7980b57cec5SDimitry Andric }
7990b57cec5SDimitry Andric do_deref_pointer = false;
8000b57cec5SDimitry Andric }
8010b57cec5SDimitry Andric
8020b57cec5SDimitry Andric if (!target) {
8039dba64beSDimitry Andric LLDB_LOGF(log, "[Debugger::FormatPrompt] could not calculate target for "
8040b57cec5SDimitry Andric "prompt expression");
8050b57cec5SDimitry Andric return false;
8060b57cec5SDimitry Andric }
8070b57cec5SDimitry Andric
8080b57cec5SDimitry Andric // we do not want to use the summary for a bitfield of type T:n if we were
8090b57cec5SDimitry Andric // originally dealing with just a T - that would get us into an endless
8100b57cec5SDimitry Andric // recursion
8110b57cec5SDimitry Andric if (target->IsBitfield() && was_var_indexed) {
8120b57cec5SDimitry Andric // TODO: check for a (T:n)-specific summary - we should still obey that
8130b57cec5SDimitry Andric StreamString bitfield_name;
8140b57cec5SDimitry Andric bitfield_name.Printf("%s:%d", target->GetTypeName().AsCString(),
8150b57cec5SDimitry Andric target->GetBitfieldBitSize());
8160b57cec5SDimitry Andric auto type_sp = std::make_shared<TypeNameSpecifierImpl>(
817bdd1243dSDimitry Andric bitfield_name.GetString(), lldb::eFormatterMatchExact);
8180b57cec5SDimitry Andric if (val_obj_display ==
8190b57cec5SDimitry Andric ValueObject::eValueObjectRepresentationStyleSummary &&
8200b57cec5SDimitry Andric !DataVisualization::GetSummaryForType(type_sp))
8210b57cec5SDimitry Andric val_obj_display = ValueObject::eValueObjectRepresentationStyleValue;
8220b57cec5SDimitry Andric }
8230b57cec5SDimitry Andric
8240b57cec5SDimitry Andric // TODO use flags for these
8250b57cec5SDimitry Andric const uint32_t type_info_flags =
8260b57cec5SDimitry Andric target->GetCompilerType().GetTypeInfo(nullptr);
8270b57cec5SDimitry Andric bool is_array = (type_info_flags & eTypeIsArray) != 0;
8280b57cec5SDimitry Andric bool is_pointer = (type_info_flags & eTypeIsPointer) != 0;
8290b57cec5SDimitry Andric bool is_aggregate = target->GetCompilerType().IsAggregateType();
8300b57cec5SDimitry Andric
8310b57cec5SDimitry Andric if ((is_array || is_pointer) && (!is_array_range) &&
8320b57cec5SDimitry Andric val_obj_display ==
8330b57cec5SDimitry Andric ValueObject::eValueObjectRepresentationStyleValue) // this should be
8340b57cec5SDimitry Andric // wrong, but there
8350b57cec5SDimitry Andric // are some
8360b57cec5SDimitry Andric // exceptions
8370b57cec5SDimitry Andric {
8380b57cec5SDimitry Andric StreamString str_temp;
8399dba64beSDimitry Andric LLDB_LOGF(log,
8400b57cec5SDimitry Andric "[Debugger::FormatPrompt] I am into array || pointer && !range");
8410b57cec5SDimitry Andric
8420b57cec5SDimitry Andric if (target->HasSpecialPrintableRepresentation(val_obj_display,
8430b57cec5SDimitry Andric custom_format)) {
8440b57cec5SDimitry Andric // try to use the special cases
8450b57cec5SDimitry Andric bool success = target->DumpPrintableRepresentation(
8460b57cec5SDimitry Andric str_temp, val_obj_display, custom_format);
8479dba64beSDimitry Andric LLDB_LOGF(log, "[Debugger::FormatPrompt] special cases did%s match",
8480b57cec5SDimitry Andric success ? "" : "n't");
8490b57cec5SDimitry Andric
8500b57cec5SDimitry Andric // should not happen
8510b57cec5SDimitry Andric if (success)
8520b57cec5SDimitry Andric s << str_temp.GetString();
8530b57cec5SDimitry Andric return true;
8540b57cec5SDimitry Andric } else {
8550b57cec5SDimitry Andric if (was_plain_var) // if ${var}
8560b57cec5SDimitry Andric {
8570b57cec5SDimitry Andric s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
8580b57cec5SDimitry Andric } else if (is_pointer) // if pointer, value is the address stored
8590b57cec5SDimitry Andric {
8600b57cec5SDimitry Andric target->DumpPrintableRepresentation(
8610b57cec5SDimitry Andric s, val_obj_display, custom_format,
8620b57cec5SDimitry Andric ValueObject::PrintableRepresentationSpecialCases::eDisable);
8630b57cec5SDimitry Andric }
8640b57cec5SDimitry Andric return true;
8650b57cec5SDimitry Andric }
8660b57cec5SDimitry Andric }
8670b57cec5SDimitry Andric
8680b57cec5SDimitry Andric // if directly trying to print ${var}, and this is an aggregate, display a
8690b57cec5SDimitry Andric // nice type @ location message
8700b57cec5SDimitry Andric if (is_aggregate && was_plain_var) {
8710b57cec5SDimitry Andric s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
8720b57cec5SDimitry Andric return true;
8730b57cec5SDimitry Andric }
8740b57cec5SDimitry Andric
8750b57cec5SDimitry Andric // if directly trying to print ${var%V}, and this is an aggregate, do not let
8760b57cec5SDimitry Andric // the user do it
8770b57cec5SDimitry Andric if (is_aggregate &&
8780b57cec5SDimitry Andric ((was_var_format &&
8790b57cec5SDimitry Andric val_obj_display ==
8800b57cec5SDimitry Andric ValueObject::eValueObjectRepresentationStyleValue))) {
8810b57cec5SDimitry Andric s << "<invalid use of aggregate type>";
8820b57cec5SDimitry Andric return true;
8830b57cec5SDimitry Andric }
8840b57cec5SDimitry Andric
8850b57cec5SDimitry Andric if (!is_array_range) {
8869dba64beSDimitry Andric LLDB_LOGF(log,
8879dba64beSDimitry Andric "[Debugger::FormatPrompt] dumping ordinary printable output");
8880b57cec5SDimitry Andric return target->DumpPrintableRepresentation(s, val_obj_display,
8890b57cec5SDimitry Andric custom_format);
8900b57cec5SDimitry Andric } else {
8919dba64beSDimitry Andric LLDB_LOGF(log,
8929dba64beSDimitry Andric "[Debugger::FormatPrompt] checking if I can handle as array");
8930b57cec5SDimitry Andric if (!is_array && !is_pointer)
8940b57cec5SDimitry Andric return false;
8959dba64beSDimitry Andric LLDB_LOGF(log, "[Debugger::FormatPrompt] handle as array");
8960b57cec5SDimitry Andric StreamString special_directions_stream;
8970b57cec5SDimitry Andric llvm::StringRef special_directions;
8980b57cec5SDimitry Andric if (close_bracket_index != llvm::StringRef::npos &&
8990b57cec5SDimitry Andric subpath.size() > close_bracket_index) {
9000b57cec5SDimitry Andric ConstString additional_data(subpath.drop_front(close_bracket_index + 1));
9010b57cec5SDimitry Andric special_directions_stream.Printf("${%svar%s", do_deref_pointer ? "*" : "",
9020b57cec5SDimitry Andric additional_data.GetCString());
9030b57cec5SDimitry Andric
9040b57cec5SDimitry Andric if (entry.fmt != eFormatDefault) {
9050b57cec5SDimitry Andric const char format_char =
9060b57cec5SDimitry Andric FormatManager::GetFormatAsFormatChar(entry.fmt);
9070b57cec5SDimitry Andric if (format_char != '\0')
9080b57cec5SDimitry Andric special_directions_stream.Printf("%%%c", format_char);
9090b57cec5SDimitry Andric else {
9100b57cec5SDimitry Andric const char *format_cstr =
9110b57cec5SDimitry Andric FormatManager::GetFormatAsCString(entry.fmt);
9120b57cec5SDimitry Andric special_directions_stream.Printf("%%%s", format_cstr);
9130b57cec5SDimitry Andric }
9140b57cec5SDimitry Andric } else if (entry.number != 0) {
9150b57cec5SDimitry Andric const char style_char = ConvertValueObjectStyleToChar(
9160b57cec5SDimitry Andric (ValueObject::ValueObjectRepresentationStyle)entry.number);
9170b57cec5SDimitry Andric if (style_char)
9180b57cec5SDimitry Andric special_directions_stream.Printf("%%%c", style_char);
9190b57cec5SDimitry Andric }
9200b57cec5SDimitry Andric special_directions_stream.PutChar('}');
9210b57cec5SDimitry Andric special_directions =
9220b57cec5SDimitry Andric llvm::StringRef(special_directions_stream.GetString());
9230b57cec5SDimitry Andric }
9240b57cec5SDimitry Andric
9250b57cec5SDimitry Andric // let us display items index_lower thru index_higher of this array
9260b57cec5SDimitry Andric s.PutChar('[');
9270b57cec5SDimitry Andric
9280b57cec5SDimitry Andric if (index_higher < 0)
9290b57cec5SDimitry Andric index_higher = valobj->GetNumChildren() - 1;
9300b57cec5SDimitry Andric
9310b57cec5SDimitry Andric uint32_t max_num_children =
9320b57cec5SDimitry Andric target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay();
9330b57cec5SDimitry Andric
9340b57cec5SDimitry Andric bool success = true;
9350b57cec5SDimitry Andric for (int64_t index = index_lower; index <= index_higher; ++index) {
936fe6060f1SDimitry Andric ValueObject *item = ExpandIndexedExpression(target, index, false).get();
9370b57cec5SDimitry Andric
9380b57cec5SDimitry Andric if (!item) {
9399dba64beSDimitry Andric LLDB_LOGF(log,
9409dba64beSDimitry Andric "[Debugger::FormatPrompt] ERROR in getting child item at "
9410b57cec5SDimitry Andric "index %" PRId64,
9420b57cec5SDimitry Andric index);
9430b57cec5SDimitry Andric } else {
9449dba64beSDimitry Andric LLDB_LOGF(
9459dba64beSDimitry Andric log,
9460b57cec5SDimitry Andric "[Debugger::FormatPrompt] special_directions for child item: %s",
9470b57cec5SDimitry Andric special_directions.data() ? special_directions.data() : "");
9480b57cec5SDimitry Andric }
9490b57cec5SDimitry Andric
9500b57cec5SDimitry Andric if (special_directions.empty()) {
9510b57cec5SDimitry Andric success &= item->DumpPrintableRepresentation(s, val_obj_display,
9520b57cec5SDimitry Andric custom_format);
9530b57cec5SDimitry Andric } else {
9540b57cec5SDimitry Andric success &= FormatEntity::FormatStringRef(
9550b57cec5SDimitry Andric special_directions, s, sc, exe_ctx, nullptr, item, false, false);
9560b57cec5SDimitry Andric }
9570b57cec5SDimitry Andric
9580b57cec5SDimitry Andric if (--max_num_children == 0) {
9590b57cec5SDimitry Andric s.PutCString(", ...");
9600b57cec5SDimitry Andric break;
9610b57cec5SDimitry Andric }
9620b57cec5SDimitry Andric
9630b57cec5SDimitry Andric if (index < index_higher)
9640b57cec5SDimitry Andric s.PutChar(',');
9650b57cec5SDimitry Andric }
9660b57cec5SDimitry Andric s.PutChar(']');
9670b57cec5SDimitry Andric return success;
9680b57cec5SDimitry Andric }
9690b57cec5SDimitry Andric }
9700b57cec5SDimitry Andric
DumpRegister(Stream & s,StackFrame * frame,const char * reg_name,Format format)9710b57cec5SDimitry Andric static bool DumpRegister(Stream &s, StackFrame *frame, const char *reg_name,
9720b57cec5SDimitry Andric Format format) {
9730b57cec5SDimitry Andric if (frame) {
9740b57cec5SDimitry Andric RegisterContext *reg_ctx = frame->GetRegisterContext().get();
9750b57cec5SDimitry Andric
9760b57cec5SDimitry Andric if (reg_ctx) {
9770b57cec5SDimitry Andric const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
9780b57cec5SDimitry Andric if (reg_info) {
9790b57cec5SDimitry Andric RegisterValue reg_value;
9800b57cec5SDimitry Andric if (reg_ctx->ReadRegister(reg_info, reg_value)) {
981fe013be4SDimitry Andric DumpRegisterValue(reg_value, s, *reg_info, false, false, format);
9820b57cec5SDimitry Andric return true;
9830b57cec5SDimitry Andric }
9840b57cec5SDimitry Andric }
9850b57cec5SDimitry Andric }
9860b57cec5SDimitry Andric }
9870b57cec5SDimitry Andric return false;
9880b57cec5SDimitry Andric }
9890b57cec5SDimitry Andric
FormatThreadExtendedInfoRecurse(const FormatEntity::Entry & entry,const StructuredData::ObjectSP & thread_info_dictionary,const SymbolContext * sc,const ExecutionContext * exe_ctx,Stream & s)9900b57cec5SDimitry Andric static bool FormatThreadExtendedInfoRecurse(
9910b57cec5SDimitry Andric const FormatEntity::Entry &entry,
9920b57cec5SDimitry Andric const StructuredData::ObjectSP &thread_info_dictionary,
9930b57cec5SDimitry Andric const SymbolContext *sc, const ExecutionContext *exe_ctx, Stream &s) {
9940b57cec5SDimitry Andric llvm::StringRef path(entry.string);
9950b57cec5SDimitry Andric
9960b57cec5SDimitry Andric StructuredData::ObjectSP value =
9970b57cec5SDimitry Andric thread_info_dictionary->GetObjectForDotSeparatedPath(path);
9980b57cec5SDimitry Andric
9990b57cec5SDimitry Andric if (value) {
10000b57cec5SDimitry Andric if (value->GetType() == eStructuredDataTypeInteger) {
10010b57cec5SDimitry Andric const char *token_format = "0x%4.4" PRIx64;
10020b57cec5SDimitry Andric if (!entry.printf_format.empty())
10030b57cec5SDimitry Andric token_format = entry.printf_format.c_str();
1004fe013be4SDimitry Andric s.Printf(token_format, value->GetUnsignedIntegerValue());
10050b57cec5SDimitry Andric return true;
10060b57cec5SDimitry Andric } else if (value->GetType() == eStructuredDataTypeFloat) {
10070b57cec5SDimitry Andric s.Printf("%f", value->GetAsFloat()->GetValue());
10080b57cec5SDimitry Andric return true;
10090b57cec5SDimitry Andric } else if (value->GetType() == eStructuredDataTypeString) {
10100b57cec5SDimitry Andric s.Format("{0}", value->GetAsString()->GetValue());
10110b57cec5SDimitry Andric return true;
10120b57cec5SDimitry Andric } else if (value->GetType() == eStructuredDataTypeArray) {
10130b57cec5SDimitry Andric if (value->GetAsArray()->GetSize() > 0) {
10140b57cec5SDimitry Andric s.Printf("%zu", value->GetAsArray()->GetSize());
10150b57cec5SDimitry Andric return true;
10160b57cec5SDimitry Andric }
10170b57cec5SDimitry Andric } else if (value->GetType() == eStructuredDataTypeDictionary) {
10180b57cec5SDimitry Andric s.Printf("%zu",
10190b57cec5SDimitry Andric value->GetAsDictionary()->GetKeys()->GetAsArray()->GetSize());
10200b57cec5SDimitry Andric return true;
10210b57cec5SDimitry Andric }
10220b57cec5SDimitry Andric }
10230b57cec5SDimitry Andric
10240b57cec5SDimitry Andric return false;
10250b57cec5SDimitry Andric }
10260b57cec5SDimitry Andric
IsToken(const char * var_name_begin,const char * var)10270b57cec5SDimitry Andric static inline bool IsToken(const char *var_name_begin, const char *var) {
10280b57cec5SDimitry Andric return (::strncmp(var_name_begin, var, strlen(var)) == 0);
10290b57cec5SDimitry Andric }
10300b57cec5SDimitry Andric
1031bdd1243dSDimitry Andric /// Parses the basename out of a demangled function name
1032bdd1243dSDimitry Andric /// that may include function arguments. Supports
1033bdd1243dSDimitry Andric /// template functions.
1034bdd1243dSDimitry Andric ///
1035bdd1243dSDimitry Andric /// Returns pointers to the opening and closing parenthesis of
1036bdd1243dSDimitry Andric /// `full_name`. Can return nullptr for either parenthesis if
1037bdd1243dSDimitry Andric /// none is exists.
1038bdd1243dSDimitry Andric static std::pair<char const *, char const *>
ParseBaseName(char const * full_name)1039bdd1243dSDimitry Andric ParseBaseName(char const *full_name) {
1040bdd1243dSDimitry Andric const char *open_paren = strchr(full_name, '(');
1041bdd1243dSDimitry Andric const char *close_paren = nullptr;
1042bdd1243dSDimitry Andric const char *generic = strchr(full_name, '<');
1043bdd1243dSDimitry Andric // if before the arguments list begins there is a template sign
1044bdd1243dSDimitry Andric // then scan to the end of the generic args before you try to find
1045bdd1243dSDimitry Andric // the arguments list
1046bdd1243dSDimitry Andric if (generic && open_paren && generic < open_paren) {
1047bdd1243dSDimitry Andric int generic_depth = 1;
1048bdd1243dSDimitry Andric ++generic;
1049bdd1243dSDimitry Andric for (; *generic && generic_depth > 0; generic++) {
1050bdd1243dSDimitry Andric if (*generic == '<')
1051bdd1243dSDimitry Andric generic_depth++;
1052bdd1243dSDimitry Andric if (*generic == '>')
1053bdd1243dSDimitry Andric generic_depth--;
1054bdd1243dSDimitry Andric }
1055bdd1243dSDimitry Andric if (*generic)
1056bdd1243dSDimitry Andric open_paren = strchr(generic, '(');
1057bdd1243dSDimitry Andric else
1058bdd1243dSDimitry Andric open_paren = nullptr;
1059bdd1243dSDimitry Andric }
1060bdd1243dSDimitry Andric
1061bdd1243dSDimitry Andric if (open_paren) {
1062bdd1243dSDimitry Andric if (IsToken(open_paren, "(anonymous namespace)")) {
1063bdd1243dSDimitry Andric open_paren = strchr(open_paren + strlen("(anonymous namespace)"), '(');
1064bdd1243dSDimitry Andric if (open_paren)
1065bdd1243dSDimitry Andric close_paren = strchr(open_paren, ')');
1066bdd1243dSDimitry Andric } else
1067bdd1243dSDimitry Andric close_paren = strchr(open_paren, ')');
1068bdd1243dSDimitry Andric }
1069bdd1243dSDimitry Andric
1070bdd1243dSDimitry Andric return {open_paren, close_paren};
1071bdd1243dSDimitry Andric }
1072bdd1243dSDimitry Andric
1073bdd1243dSDimitry Andric /// Writes out the function name in 'full_name' to 'out_stream'
1074bdd1243dSDimitry Andric /// but replaces each argument type with the variable name
1075bdd1243dSDimitry Andric /// and the corresponding pretty-printed value
PrettyPrintFunctionNameWithArgs(Stream & out_stream,char const * full_name,ExecutionContextScope * exe_scope,VariableList const & args)1076bdd1243dSDimitry Andric static void PrettyPrintFunctionNameWithArgs(Stream &out_stream,
1077bdd1243dSDimitry Andric char const *full_name,
1078bdd1243dSDimitry Andric ExecutionContextScope *exe_scope,
1079bdd1243dSDimitry Andric VariableList const &args) {
1080bdd1243dSDimitry Andric auto [open_paren, close_paren] = ParseBaseName(full_name);
1081bdd1243dSDimitry Andric if (open_paren)
1082bdd1243dSDimitry Andric out_stream.Write(full_name, open_paren - full_name + 1);
1083bdd1243dSDimitry Andric else {
1084bdd1243dSDimitry Andric out_stream.PutCString(full_name);
1085bdd1243dSDimitry Andric out_stream.PutChar('(');
1086bdd1243dSDimitry Andric }
1087bdd1243dSDimitry Andric
1088bdd1243dSDimitry Andric FormatEntity::PrettyPrintFunctionArguments(out_stream, args, exe_scope);
1089bdd1243dSDimitry Andric
1090bdd1243dSDimitry Andric if (close_paren)
1091bdd1243dSDimitry Andric out_stream.PutCString(close_paren);
1092bdd1243dSDimitry Andric else
1093bdd1243dSDimitry Andric out_stream.PutChar(')');
1094bdd1243dSDimitry Andric }
1095bdd1243dSDimitry Andric
FormatInlinedBlock(Stream & out_stream,Block * block)1096*a58f00eaSDimitry Andric static void FormatInlinedBlock(Stream &out_stream, Block *block) {
1097*a58f00eaSDimitry Andric if (!block)
1098*a58f00eaSDimitry Andric return;
1099*a58f00eaSDimitry Andric Block *inline_block = block->GetContainingInlinedBlock();
1100*a58f00eaSDimitry Andric if (inline_block) {
1101*a58f00eaSDimitry Andric if (const InlineFunctionInfo *inline_info =
1102*a58f00eaSDimitry Andric inline_block->GetInlinedFunctionInfo()) {
1103*a58f00eaSDimitry Andric out_stream.PutCString(" [inlined] ");
1104*a58f00eaSDimitry Andric inline_info->GetName().Dump(&out_stream);
1105*a58f00eaSDimitry Andric }
1106*a58f00eaSDimitry Andric }
1107*a58f00eaSDimitry Andric }
1108*a58f00eaSDimitry Andric
FormatStringRef(const llvm::StringRef & format_str,Stream & s,const SymbolContext * sc,const ExecutionContext * exe_ctx,const Address * addr,ValueObject * valobj,bool function_changed,bool initial_function)11090b57cec5SDimitry Andric bool FormatEntity::FormatStringRef(const llvm::StringRef &format_str, Stream &s,
11100b57cec5SDimitry Andric const SymbolContext *sc,
11110b57cec5SDimitry Andric const ExecutionContext *exe_ctx,
11120b57cec5SDimitry Andric const Address *addr, ValueObject *valobj,
11130b57cec5SDimitry Andric bool function_changed,
11140b57cec5SDimitry Andric bool initial_function) {
11150b57cec5SDimitry Andric if (!format_str.empty()) {
11160b57cec5SDimitry Andric FormatEntity::Entry root;
11170b57cec5SDimitry Andric Status error = FormatEntity::Parse(format_str, root);
11180b57cec5SDimitry Andric if (error.Success()) {
11190b57cec5SDimitry Andric return FormatEntity::Format(root, s, sc, exe_ctx, addr, valobj,
11200b57cec5SDimitry Andric function_changed, initial_function);
11210b57cec5SDimitry Andric }
11220b57cec5SDimitry Andric }
11230b57cec5SDimitry Andric return false;
11240b57cec5SDimitry Andric }
11250b57cec5SDimitry Andric
FormatCString(const char * format,Stream & s,const SymbolContext * sc,const ExecutionContext * exe_ctx,const Address * addr,ValueObject * valobj,bool function_changed,bool initial_function)11260b57cec5SDimitry Andric bool FormatEntity::FormatCString(const char *format, Stream &s,
11270b57cec5SDimitry Andric const SymbolContext *sc,
11280b57cec5SDimitry Andric const ExecutionContext *exe_ctx,
11290b57cec5SDimitry Andric const Address *addr, ValueObject *valobj,
11300b57cec5SDimitry Andric bool function_changed, bool initial_function) {
11310b57cec5SDimitry Andric if (format && format[0]) {
11320b57cec5SDimitry Andric FormatEntity::Entry root;
11330b57cec5SDimitry Andric llvm::StringRef format_str(format);
11340b57cec5SDimitry Andric Status error = FormatEntity::Parse(format_str, root);
11350b57cec5SDimitry Andric if (error.Success()) {
11360b57cec5SDimitry Andric return FormatEntity::Format(root, s, sc, exe_ctx, addr, valobj,
11370b57cec5SDimitry Andric function_changed, initial_function);
11380b57cec5SDimitry Andric }
11390b57cec5SDimitry Andric }
11400b57cec5SDimitry Andric return false;
11410b57cec5SDimitry Andric }
11420b57cec5SDimitry Andric
Format(const Entry & entry,Stream & s,const SymbolContext * sc,const ExecutionContext * exe_ctx,const Address * addr,ValueObject * valobj,bool function_changed,bool initial_function)11430b57cec5SDimitry Andric bool FormatEntity::Format(const Entry &entry, Stream &s,
11440b57cec5SDimitry Andric const SymbolContext *sc,
11450b57cec5SDimitry Andric const ExecutionContext *exe_ctx, const Address *addr,
11460b57cec5SDimitry Andric ValueObject *valobj, bool function_changed,
11470b57cec5SDimitry Andric bool initial_function) {
11480b57cec5SDimitry Andric switch (entry.type) {
11490b57cec5SDimitry Andric case Entry::Type::Invalid:
11500b57cec5SDimitry Andric case Entry::Type::ParentNumber: // Only used for
11510b57cec5SDimitry Andric // FormatEntity::Entry::Definition encoding
11520b57cec5SDimitry Andric case Entry::Type::ParentString: // Only used for
11530b57cec5SDimitry Andric // FormatEntity::Entry::Definition encoding
11540b57cec5SDimitry Andric return false;
11550b57cec5SDimitry Andric case Entry::Type::EscapeCode:
11560b57cec5SDimitry Andric if (exe_ctx) {
11570b57cec5SDimitry Andric if (Target *target = exe_ctx->GetTargetPtr()) {
11580b57cec5SDimitry Andric Debugger &debugger = target->GetDebugger();
11590b57cec5SDimitry Andric if (debugger.GetUseColor()) {
11600b57cec5SDimitry Andric s.PutCString(entry.string);
11610b57cec5SDimitry Andric }
11620b57cec5SDimitry Andric }
11630b57cec5SDimitry Andric }
11640b57cec5SDimitry Andric // Always return true, so colors being disabled is transparent.
11650b57cec5SDimitry Andric return true;
11660b57cec5SDimitry Andric
11670b57cec5SDimitry Andric case Entry::Type::Root:
11680b57cec5SDimitry Andric for (const auto &child : entry.children) {
11690b57cec5SDimitry Andric if (!Format(child, s, sc, exe_ctx, addr, valobj, function_changed,
11700b57cec5SDimitry Andric initial_function)) {
11710b57cec5SDimitry Andric return false; // If any item of root fails, then the formatting fails
11720b57cec5SDimitry Andric }
11730b57cec5SDimitry Andric }
11740b57cec5SDimitry Andric return true; // Only return true if all items succeeded
11750b57cec5SDimitry Andric
11760b57cec5SDimitry Andric case Entry::Type::String:
11770b57cec5SDimitry Andric s.PutCString(entry.string);
11780b57cec5SDimitry Andric return true;
11790b57cec5SDimitry Andric
11800b57cec5SDimitry Andric case Entry::Type::Scope: {
11810b57cec5SDimitry Andric StreamString scope_stream;
11820b57cec5SDimitry Andric bool success = false;
11830b57cec5SDimitry Andric for (const auto &child : entry.children) {
11840b57cec5SDimitry Andric success = Format(child, scope_stream, sc, exe_ctx, addr, valobj,
11850b57cec5SDimitry Andric function_changed, initial_function);
11860b57cec5SDimitry Andric if (!success)
11870b57cec5SDimitry Andric break;
11880b57cec5SDimitry Andric }
11890b57cec5SDimitry Andric // Only if all items in a scope succeed, then do we print the output into
11900b57cec5SDimitry Andric // the main stream
11910b57cec5SDimitry Andric if (success)
11920b57cec5SDimitry Andric s.Write(scope_stream.GetString().data(), scope_stream.GetString().size());
11930b57cec5SDimitry Andric }
11940b57cec5SDimitry Andric return true; // Scopes always successfully print themselves
11950b57cec5SDimitry Andric
11960b57cec5SDimitry Andric case Entry::Type::Variable:
11970b57cec5SDimitry Andric case Entry::Type::VariableSynthetic:
11980b57cec5SDimitry Andric case Entry::Type::ScriptVariable:
11990b57cec5SDimitry Andric case Entry::Type::ScriptVariableSynthetic:
12000b57cec5SDimitry Andric return DumpValue(s, sc, exe_ctx, entry, valobj);
12010b57cec5SDimitry Andric
12020b57cec5SDimitry Andric case Entry::Type::AddressFile:
12030b57cec5SDimitry Andric case Entry::Type::AddressLoad:
12040b57cec5SDimitry Andric case Entry::Type::AddressLoadOrFile:
1205480093f4SDimitry Andric return (
1206480093f4SDimitry Andric addr != nullptr && addr->IsValid() &&
1207480093f4SDimitry Andric DumpAddressAndContent(s, sc, exe_ctx, *addr,
12080b57cec5SDimitry Andric entry.type == Entry::Type::AddressLoadOrFile));
12090b57cec5SDimitry Andric
12100b57cec5SDimitry Andric case Entry::Type::ProcessID:
12110b57cec5SDimitry Andric if (exe_ctx) {
12120b57cec5SDimitry Andric Process *process = exe_ctx->GetProcessPtr();
12130b57cec5SDimitry Andric if (process) {
12140b57cec5SDimitry Andric const char *format = "%" PRIu64;
12150b57cec5SDimitry Andric if (!entry.printf_format.empty())
12160b57cec5SDimitry Andric format = entry.printf_format.c_str();
12170b57cec5SDimitry Andric s.Printf(format, process->GetID());
12180b57cec5SDimitry Andric return true;
12190b57cec5SDimitry Andric }
12200b57cec5SDimitry Andric }
12210b57cec5SDimitry Andric return false;
12220b57cec5SDimitry Andric
12230b57cec5SDimitry Andric case Entry::Type::ProcessFile:
12240b57cec5SDimitry Andric if (exe_ctx) {
12250b57cec5SDimitry Andric Process *process = exe_ctx->GetProcessPtr();
12260b57cec5SDimitry Andric if (process) {
12270b57cec5SDimitry Andric Module *exe_module = process->GetTarget().GetExecutableModulePointer();
12280b57cec5SDimitry Andric if (exe_module) {
12290b57cec5SDimitry Andric if (DumpFile(s, exe_module->GetFileSpec(), (FileKind)entry.number))
12300b57cec5SDimitry Andric return true;
12310b57cec5SDimitry Andric }
12320b57cec5SDimitry Andric }
12330b57cec5SDimitry Andric }
12340b57cec5SDimitry Andric return false;
12350b57cec5SDimitry Andric
12360b57cec5SDimitry Andric case Entry::Type::ScriptProcess:
12370b57cec5SDimitry Andric if (exe_ctx) {
12380b57cec5SDimitry Andric Process *process = exe_ctx->GetProcessPtr();
12390b57cec5SDimitry Andric if (process)
12400b57cec5SDimitry Andric return RunScriptFormatKeyword(s, sc, exe_ctx, process,
12410b57cec5SDimitry Andric entry.string.c_str());
12420b57cec5SDimitry Andric }
12430b57cec5SDimitry Andric return false;
12440b57cec5SDimitry Andric
12450b57cec5SDimitry Andric case Entry::Type::ThreadID:
12460b57cec5SDimitry Andric if (exe_ctx) {
12470b57cec5SDimitry Andric Thread *thread = exe_ctx->GetThreadPtr();
12480b57cec5SDimitry Andric if (thread) {
12490b57cec5SDimitry Andric const char *format = "0x%4.4" PRIx64;
12500b57cec5SDimitry Andric if (!entry.printf_format.empty()) {
12510b57cec5SDimitry Andric // Watch for the special "tid" format...
12520b57cec5SDimitry Andric if (entry.printf_format == "tid") {
12530b57cec5SDimitry Andric // TODO(zturner): Rather than hardcoding this to be platform
12540b57cec5SDimitry Andric // specific, it should be controlled by a setting and the default
12550b57cec5SDimitry Andric // value of the setting can be different depending on the platform.
12560b57cec5SDimitry Andric Target &target = thread->GetProcess()->GetTarget();
12570b57cec5SDimitry Andric ArchSpec arch(target.GetArchitecture());
12580b57cec5SDimitry Andric llvm::Triple::OSType ostype = arch.IsValid()
12590b57cec5SDimitry Andric ? arch.GetTriple().getOS()
12600b57cec5SDimitry Andric : llvm::Triple::UnknownOS;
1261c9157d92SDimitry Andric if (ostype == llvm::Triple::FreeBSD ||
1262c9157d92SDimitry Andric ostype == llvm::Triple::Linux ||
1263c9157d92SDimitry Andric ostype == llvm::Triple::NetBSD ||
1264c9157d92SDimitry Andric ostype == llvm::Triple::OpenBSD) {
12650b57cec5SDimitry Andric format = "%" PRIu64;
12660b57cec5SDimitry Andric }
12670b57cec5SDimitry Andric } else {
12680b57cec5SDimitry Andric format = entry.printf_format.c_str();
12690b57cec5SDimitry Andric }
12700b57cec5SDimitry Andric }
12710b57cec5SDimitry Andric s.Printf(format, thread->GetID());
12720b57cec5SDimitry Andric return true;
12730b57cec5SDimitry Andric }
12740b57cec5SDimitry Andric }
12750b57cec5SDimitry Andric return false;
12760b57cec5SDimitry Andric
12770b57cec5SDimitry Andric case Entry::Type::ThreadProtocolID:
12780b57cec5SDimitry Andric if (exe_ctx) {
12790b57cec5SDimitry Andric Thread *thread = exe_ctx->GetThreadPtr();
12800b57cec5SDimitry Andric if (thread) {
12810b57cec5SDimitry Andric const char *format = "0x%4.4" PRIx64;
12820b57cec5SDimitry Andric if (!entry.printf_format.empty())
12830b57cec5SDimitry Andric format = entry.printf_format.c_str();
12840b57cec5SDimitry Andric s.Printf(format, thread->GetProtocolID());
12850b57cec5SDimitry Andric return true;
12860b57cec5SDimitry Andric }
12870b57cec5SDimitry Andric }
12880b57cec5SDimitry Andric return false;
12890b57cec5SDimitry Andric
12900b57cec5SDimitry Andric case Entry::Type::ThreadIndexID:
12910b57cec5SDimitry Andric if (exe_ctx) {
12920b57cec5SDimitry Andric Thread *thread = exe_ctx->GetThreadPtr();
12930b57cec5SDimitry Andric if (thread) {
12940b57cec5SDimitry Andric const char *format = "%" PRIu32;
12950b57cec5SDimitry Andric if (!entry.printf_format.empty())
12960b57cec5SDimitry Andric format = entry.printf_format.c_str();
12970b57cec5SDimitry Andric s.Printf(format, thread->GetIndexID());
12980b57cec5SDimitry Andric return true;
12990b57cec5SDimitry Andric }
13000b57cec5SDimitry Andric }
13010b57cec5SDimitry Andric return false;
13020b57cec5SDimitry Andric
13030b57cec5SDimitry Andric case Entry::Type::ThreadName:
13040b57cec5SDimitry Andric if (exe_ctx) {
13050b57cec5SDimitry Andric Thread *thread = exe_ctx->GetThreadPtr();
13060b57cec5SDimitry Andric if (thread) {
13070b57cec5SDimitry Andric const char *cstr = thread->GetName();
13080b57cec5SDimitry Andric if (cstr && cstr[0]) {
13090b57cec5SDimitry Andric s.PutCString(cstr);
13100b57cec5SDimitry Andric return true;
13110b57cec5SDimitry Andric }
13120b57cec5SDimitry Andric }
13130b57cec5SDimitry Andric }
13140b57cec5SDimitry Andric return false;
13150b57cec5SDimitry Andric
13160b57cec5SDimitry Andric case Entry::Type::ThreadQueue:
13170b57cec5SDimitry Andric if (exe_ctx) {
13180b57cec5SDimitry Andric Thread *thread = exe_ctx->GetThreadPtr();
13190b57cec5SDimitry Andric if (thread) {
13200b57cec5SDimitry Andric const char *cstr = thread->GetQueueName();
13210b57cec5SDimitry Andric if (cstr && cstr[0]) {
13220b57cec5SDimitry Andric s.PutCString(cstr);
13230b57cec5SDimitry Andric return true;
13240b57cec5SDimitry Andric }
13250b57cec5SDimitry Andric }
13260b57cec5SDimitry Andric }
13270b57cec5SDimitry Andric return false;
13280b57cec5SDimitry Andric
13290b57cec5SDimitry Andric case Entry::Type::ThreadStopReason:
13300b57cec5SDimitry Andric if (exe_ctx) {
13315ffd83dbSDimitry Andric if (Thread *thread = exe_ctx->GetThreadPtr()) {
13325ffd83dbSDimitry Andric std::string stop_description = thread->GetStopDescription();
13335ffd83dbSDimitry Andric if (!stop_description.empty()) {
13345ffd83dbSDimitry Andric s.PutCString(stop_description);
13350b57cec5SDimitry Andric return true;
13360b57cec5SDimitry Andric }
13370b57cec5SDimitry Andric }
13380b57cec5SDimitry Andric }
13395ffd83dbSDimitry Andric return false;
13405ffd83dbSDimitry Andric
13415ffd83dbSDimitry Andric case Entry::Type::ThreadStopReasonRaw:
13425ffd83dbSDimitry Andric if (exe_ctx) {
13435ffd83dbSDimitry Andric if (Thread *thread = exe_ctx->GetThreadPtr()) {
13445ffd83dbSDimitry Andric std::string stop_description = thread->GetStopDescriptionRaw();
13455ffd83dbSDimitry Andric if (!stop_description.empty()) {
13465ffd83dbSDimitry Andric s.PutCString(stop_description);
13475ffd83dbSDimitry Andric return true;
13485ffd83dbSDimitry Andric }
13495ffd83dbSDimitry Andric }
13500b57cec5SDimitry Andric }
13510b57cec5SDimitry Andric return false;
13520b57cec5SDimitry Andric
13530b57cec5SDimitry Andric case Entry::Type::ThreadReturnValue:
13540b57cec5SDimitry Andric if (exe_ctx) {
13550b57cec5SDimitry Andric Thread *thread = exe_ctx->GetThreadPtr();
13560b57cec5SDimitry Andric if (thread) {
13570b57cec5SDimitry Andric StopInfoSP stop_info_sp = thread->GetStopInfo();
13580b57cec5SDimitry Andric if (stop_info_sp && stop_info_sp->IsValid()) {
13590b57cec5SDimitry Andric ValueObjectSP return_valobj_sp =
13600b57cec5SDimitry Andric StopInfo::GetReturnValueObject(stop_info_sp);
13610b57cec5SDimitry Andric if (return_valobj_sp) {
13620b57cec5SDimitry Andric return_valobj_sp->Dump(s);
13630b57cec5SDimitry Andric return true;
13640b57cec5SDimitry Andric }
13650b57cec5SDimitry Andric }
13660b57cec5SDimitry Andric }
13670b57cec5SDimitry Andric }
13680b57cec5SDimitry Andric return false;
13690b57cec5SDimitry Andric
13700b57cec5SDimitry Andric case Entry::Type::ThreadCompletedExpression:
13710b57cec5SDimitry Andric if (exe_ctx) {
13720b57cec5SDimitry Andric Thread *thread = exe_ctx->GetThreadPtr();
13730b57cec5SDimitry Andric if (thread) {
13740b57cec5SDimitry Andric StopInfoSP stop_info_sp = thread->GetStopInfo();
13750b57cec5SDimitry Andric if (stop_info_sp && stop_info_sp->IsValid()) {
13760b57cec5SDimitry Andric ExpressionVariableSP expression_var_sp =
13770b57cec5SDimitry Andric StopInfo::GetExpressionVariable(stop_info_sp);
13780b57cec5SDimitry Andric if (expression_var_sp && expression_var_sp->GetValueObject()) {
13790b57cec5SDimitry Andric expression_var_sp->GetValueObject()->Dump(s);
13800b57cec5SDimitry Andric return true;
13810b57cec5SDimitry Andric }
13820b57cec5SDimitry Andric }
13830b57cec5SDimitry Andric }
13840b57cec5SDimitry Andric }
13850b57cec5SDimitry Andric return false;
13860b57cec5SDimitry Andric
13870b57cec5SDimitry Andric case Entry::Type::ScriptThread:
13880b57cec5SDimitry Andric if (exe_ctx) {
13890b57cec5SDimitry Andric Thread *thread = exe_ctx->GetThreadPtr();
13900b57cec5SDimitry Andric if (thread)
13910b57cec5SDimitry Andric return RunScriptFormatKeyword(s, sc, exe_ctx, thread,
13920b57cec5SDimitry Andric entry.string.c_str());
13930b57cec5SDimitry Andric }
13940b57cec5SDimitry Andric return false;
13950b57cec5SDimitry Andric
13960b57cec5SDimitry Andric case Entry::Type::ThreadInfo:
13970b57cec5SDimitry Andric if (exe_ctx) {
13980b57cec5SDimitry Andric Thread *thread = exe_ctx->GetThreadPtr();
13990b57cec5SDimitry Andric if (thread) {
14000b57cec5SDimitry Andric StructuredData::ObjectSP object_sp = thread->GetExtendedInfo();
14010b57cec5SDimitry Andric if (object_sp &&
14020b57cec5SDimitry Andric object_sp->GetType() == eStructuredDataTypeDictionary) {
14030b57cec5SDimitry Andric if (FormatThreadExtendedInfoRecurse(entry, object_sp, sc, exe_ctx, s))
14040b57cec5SDimitry Andric return true;
14050b57cec5SDimitry Andric }
14060b57cec5SDimitry Andric }
14070b57cec5SDimitry Andric }
14080b57cec5SDimitry Andric return false;
14090b57cec5SDimitry Andric
14100b57cec5SDimitry Andric case Entry::Type::TargetArch:
14110b57cec5SDimitry Andric if (exe_ctx) {
14120b57cec5SDimitry Andric Target *target = exe_ctx->GetTargetPtr();
14130b57cec5SDimitry Andric if (target) {
14140b57cec5SDimitry Andric const ArchSpec &arch = target->GetArchitecture();
14150b57cec5SDimitry Andric if (arch.IsValid()) {
14160b57cec5SDimitry Andric s.PutCString(arch.GetArchitectureName());
14170b57cec5SDimitry Andric return true;
14180b57cec5SDimitry Andric }
14190b57cec5SDimitry Andric }
14200b57cec5SDimitry Andric }
14210b57cec5SDimitry Andric return false;
14220b57cec5SDimitry Andric
14230b57cec5SDimitry Andric case Entry::Type::ScriptTarget:
14240b57cec5SDimitry Andric if (exe_ctx) {
14250b57cec5SDimitry Andric Target *target = exe_ctx->GetTargetPtr();
14260b57cec5SDimitry Andric if (target)
14270b57cec5SDimitry Andric return RunScriptFormatKeyword(s, sc, exe_ctx, target,
14280b57cec5SDimitry Andric entry.string.c_str());
14290b57cec5SDimitry Andric }
14300b57cec5SDimitry Andric return false;
14310b57cec5SDimitry Andric
14320b57cec5SDimitry Andric case Entry::Type::ModuleFile:
14330b57cec5SDimitry Andric if (sc) {
14340b57cec5SDimitry Andric Module *module = sc->module_sp.get();
14350b57cec5SDimitry Andric if (module) {
14360b57cec5SDimitry Andric if (DumpFile(s, module->GetFileSpec(), (FileKind)entry.number))
14370b57cec5SDimitry Andric return true;
14380b57cec5SDimitry Andric }
14390b57cec5SDimitry Andric }
14400b57cec5SDimitry Andric return false;
14410b57cec5SDimitry Andric
14420b57cec5SDimitry Andric case Entry::Type::File:
14430b57cec5SDimitry Andric if (sc) {
14440b57cec5SDimitry Andric CompileUnit *cu = sc->comp_unit;
14450b57cec5SDimitry Andric if (cu) {
1446480093f4SDimitry Andric if (DumpFile(s, cu->GetPrimaryFile(), (FileKind)entry.number))
14470b57cec5SDimitry Andric return true;
14480b57cec5SDimitry Andric }
14490b57cec5SDimitry Andric }
14500b57cec5SDimitry Andric return false;
14510b57cec5SDimitry Andric
14520b57cec5SDimitry Andric case Entry::Type::Lang:
14530b57cec5SDimitry Andric if (sc) {
14540b57cec5SDimitry Andric CompileUnit *cu = sc->comp_unit;
14550b57cec5SDimitry Andric if (cu) {
14560b57cec5SDimitry Andric const char *lang_name =
14570b57cec5SDimitry Andric Language::GetNameForLanguageType(cu->GetLanguage());
14580b57cec5SDimitry Andric if (lang_name) {
14590b57cec5SDimitry Andric s.PutCString(lang_name);
14600b57cec5SDimitry Andric return true;
14610b57cec5SDimitry Andric }
14620b57cec5SDimitry Andric }
14630b57cec5SDimitry Andric }
14640b57cec5SDimitry Andric return false;
14650b57cec5SDimitry Andric
14660b57cec5SDimitry Andric case Entry::Type::FrameIndex:
14670b57cec5SDimitry Andric if (exe_ctx) {
14680b57cec5SDimitry Andric StackFrame *frame = exe_ctx->GetFramePtr();
14690b57cec5SDimitry Andric if (frame) {
14700b57cec5SDimitry Andric const char *format = "%" PRIu32;
14710b57cec5SDimitry Andric if (!entry.printf_format.empty())
14720b57cec5SDimitry Andric format = entry.printf_format.c_str();
14730b57cec5SDimitry Andric s.Printf(format, frame->GetFrameIndex());
14740b57cec5SDimitry Andric return true;
14750b57cec5SDimitry Andric }
14760b57cec5SDimitry Andric }
14770b57cec5SDimitry Andric return false;
14780b57cec5SDimitry Andric
14790b57cec5SDimitry Andric case Entry::Type::FrameRegisterPC:
14800b57cec5SDimitry Andric if (exe_ctx) {
14810b57cec5SDimitry Andric StackFrame *frame = exe_ctx->GetFramePtr();
14820b57cec5SDimitry Andric if (frame) {
14830b57cec5SDimitry Andric const Address &pc_addr = frame->GetFrameCodeAddress();
14840b57cec5SDimitry Andric if (pc_addr.IsValid()) {
1485480093f4SDimitry Andric if (DumpAddressAndContent(s, sc, exe_ctx, pc_addr, false))
14860b57cec5SDimitry Andric return true;
14870b57cec5SDimitry Andric }
14880b57cec5SDimitry Andric }
14890b57cec5SDimitry Andric }
14900b57cec5SDimitry Andric return false;
14910b57cec5SDimitry Andric
14920b57cec5SDimitry Andric case Entry::Type::FrameRegisterSP:
14930b57cec5SDimitry Andric if (exe_ctx) {
14940b57cec5SDimitry Andric StackFrame *frame = exe_ctx->GetFramePtr();
14950b57cec5SDimitry Andric if (frame) {
14960b57cec5SDimitry Andric if (DumpRegister(s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP,
14970b57cec5SDimitry Andric (lldb::Format)entry.number))
14980b57cec5SDimitry Andric return true;
14990b57cec5SDimitry Andric }
15000b57cec5SDimitry Andric }
15010b57cec5SDimitry Andric return false;
15020b57cec5SDimitry Andric
15030b57cec5SDimitry Andric case Entry::Type::FrameRegisterFP:
15040b57cec5SDimitry Andric if (exe_ctx) {
15050b57cec5SDimitry Andric StackFrame *frame = exe_ctx->GetFramePtr();
15060b57cec5SDimitry Andric if (frame) {
15070b57cec5SDimitry Andric if (DumpRegister(s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP,
15080b57cec5SDimitry Andric (lldb::Format)entry.number))
15090b57cec5SDimitry Andric return true;
15100b57cec5SDimitry Andric }
15110b57cec5SDimitry Andric }
15120b57cec5SDimitry Andric return false;
15130b57cec5SDimitry Andric
15140b57cec5SDimitry Andric case Entry::Type::FrameRegisterFlags:
15150b57cec5SDimitry Andric if (exe_ctx) {
15160b57cec5SDimitry Andric StackFrame *frame = exe_ctx->GetFramePtr();
15170b57cec5SDimitry Andric if (frame) {
15180b57cec5SDimitry Andric if (DumpRegister(s, frame, eRegisterKindGeneric,
15190b57cec5SDimitry Andric LLDB_REGNUM_GENERIC_FLAGS, (lldb::Format)entry.number))
15200b57cec5SDimitry Andric return true;
15210b57cec5SDimitry Andric }
15220b57cec5SDimitry Andric }
15230b57cec5SDimitry Andric return false;
15240b57cec5SDimitry Andric
15250b57cec5SDimitry Andric case Entry::Type::FrameNoDebug:
15260b57cec5SDimitry Andric if (exe_ctx) {
15270b57cec5SDimitry Andric StackFrame *frame = exe_ctx->GetFramePtr();
15280b57cec5SDimitry Andric if (frame) {
15290b57cec5SDimitry Andric return !frame->HasDebugInformation();
15300b57cec5SDimitry Andric }
15310b57cec5SDimitry Andric }
15320b57cec5SDimitry Andric return true;
15330b57cec5SDimitry Andric
15340b57cec5SDimitry Andric case Entry::Type::FrameRegisterByName:
15350b57cec5SDimitry Andric if (exe_ctx) {
15360b57cec5SDimitry Andric StackFrame *frame = exe_ctx->GetFramePtr();
15370b57cec5SDimitry Andric if (frame) {
15380b57cec5SDimitry Andric if (DumpRegister(s, frame, entry.string.c_str(),
15390b57cec5SDimitry Andric (lldb::Format)entry.number))
15400b57cec5SDimitry Andric return true;
15410b57cec5SDimitry Andric }
15420b57cec5SDimitry Andric }
15430b57cec5SDimitry Andric return false;
15440b57cec5SDimitry Andric
15450b57cec5SDimitry Andric case Entry::Type::FrameIsArtificial: {
15460b57cec5SDimitry Andric if (exe_ctx)
15470b57cec5SDimitry Andric if (StackFrame *frame = exe_ctx->GetFramePtr())
15480b57cec5SDimitry Andric return frame->IsArtificial();
15490b57cec5SDimitry Andric return false;
15500b57cec5SDimitry Andric }
15510b57cec5SDimitry Andric
15520b57cec5SDimitry Andric case Entry::Type::ScriptFrame:
15530b57cec5SDimitry Andric if (exe_ctx) {
15540b57cec5SDimitry Andric StackFrame *frame = exe_ctx->GetFramePtr();
15550b57cec5SDimitry Andric if (frame)
15560b57cec5SDimitry Andric return RunScriptFormatKeyword(s, sc, exe_ctx, frame,
15570b57cec5SDimitry Andric entry.string.c_str());
15580b57cec5SDimitry Andric }
15590b57cec5SDimitry Andric return false;
15600b57cec5SDimitry Andric
15610b57cec5SDimitry Andric case Entry::Type::FunctionID:
15620b57cec5SDimitry Andric if (sc) {
15630b57cec5SDimitry Andric if (sc->function) {
15640b57cec5SDimitry Andric s.Printf("function{0x%8.8" PRIx64 "}", sc->function->GetID());
15650b57cec5SDimitry Andric return true;
15660b57cec5SDimitry Andric } else if (sc->symbol) {
15670b57cec5SDimitry Andric s.Printf("symbol[%u]", sc->symbol->GetID());
15680b57cec5SDimitry Andric return true;
15690b57cec5SDimitry Andric }
15700b57cec5SDimitry Andric }
15710b57cec5SDimitry Andric return false;
15720b57cec5SDimitry Andric
15730b57cec5SDimitry Andric case Entry::Type::FunctionDidChange:
15740b57cec5SDimitry Andric return function_changed;
15750b57cec5SDimitry Andric
15760b57cec5SDimitry Andric case Entry::Type::FunctionInitialFunction:
15770b57cec5SDimitry Andric return initial_function;
15780b57cec5SDimitry Andric
15790b57cec5SDimitry Andric case Entry::Type::FunctionName: {
1580fe6060f1SDimitry Andric if (!sc)
1581fe6060f1SDimitry Andric return false;
1582fe6060f1SDimitry Andric
15830b57cec5SDimitry Andric Language *language_plugin = nullptr;
15840b57cec5SDimitry Andric bool language_plugin_handled = false;
15850b57cec5SDimitry Andric StreamString ss;
1586fe6060f1SDimitry Andric
15870b57cec5SDimitry Andric if (sc->function)
15880b57cec5SDimitry Andric language_plugin = Language::FindPlugin(sc->function->GetLanguage());
15890b57cec5SDimitry Andric else if (sc->symbol)
15900b57cec5SDimitry Andric language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
1591fe6060f1SDimitry Andric
1592fe6060f1SDimitry Andric if (language_plugin)
15930b57cec5SDimitry Andric language_plugin_handled = language_plugin->GetFunctionDisplayName(
15940b57cec5SDimitry Andric sc, exe_ctx, Language::FunctionNameRepresentation::eName, ss);
1595fe6060f1SDimitry Andric
15960b57cec5SDimitry Andric if (language_plugin_handled) {
15970b57cec5SDimitry Andric s << ss.GetString();
15980b57cec5SDimitry Andric return true;
15990b57cec5SDimitry Andric } else {
16000b57cec5SDimitry Andric const char *name = nullptr;
16010b57cec5SDimitry Andric if (sc->function)
16020b57cec5SDimitry Andric name = sc->function->GetName().AsCString(nullptr);
16030b57cec5SDimitry Andric else if (sc->symbol)
16040b57cec5SDimitry Andric name = sc->symbol->GetName().AsCString(nullptr);
1605fe6060f1SDimitry Andric
16060b57cec5SDimitry Andric if (name) {
16070b57cec5SDimitry Andric s.PutCString(name);
1608*a58f00eaSDimitry Andric FormatInlinedBlock(s, sc->block);
16090b57cec5SDimitry Andric return true;
16100b57cec5SDimitry Andric }
16110b57cec5SDimitry Andric }
16120b57cec5SDimitry Andric }
16130b57cec5SDimitry Andric return false;
16140b57cec5SDimitry Andric
16150b57cec5SDimitry Andric case Entry::Type::FunctionNameNoArgs: {
1616fe6060f1SDimitry Andric if (!sc)
1617fe6060f1SDimitry Andric return false;
1618fe6060f1SDimitry Andric
16190b57cec5SDimitry Andric Language *language_plugin = nullptr;
16200b57cec5SDimitry Andric bool language_plugin_handled = false;
16210b57cec5SDimitry Andric StreamString ss;
16220b57cec5SDimitry Andric if (sc->function)
16230b57cec5SDimitry Andric language_plugin = Language::FindPlugin(sc->function->GetLanguage());
16240b57cec5SDimitry Andric else if (sc->symbol)
16250b57cec5SDimitry Andric language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
1626fe6060f1SDimitry Andric
1627fe6060f1SDimitry Andric if (language_plugin)
16280b57cec5SDimitry Andric language_plugin_handled = language_plugin->GetFunctionDisplayName(
16290b57cec5SDimitry Andric sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithNoArgs,
16300b57cec5SDimitry Andric ss);
1631fe6060f1SDimitry Andric
16320b57cec5SDimitry Andric if (language_plugin_handled) {
16330b57cec5SDimitry Andric s << ss.GetString();
16340b57cec5SDimitry Andric return true;
16350b57cec5SDimitry Andric } else {
16360b57cec5SDimitry Andric ConstString name;
16370b57cec5SDimitry Andric if (sc->function)
16380b57cec5SDimitry Andric name = sc->function->GetNameNoArguments();
16390b57cec5SDimitry Andric else if (sc->symbol)
16400b57cec5SDimitry Andric name = sc->symbol->GetNameNoArguments();
16410b57cec5SDimitry Andric if (name) {
16420b57cec5SDimitry Andric s.PutCString(name.GetCString());
1643*a58f00eaSDimitry Andric FormatInlinedBlock(s, sc->block);
16440b57cec5SDimitry Andric return true;
16450b57cec5SDimitry Andric }
16460b57cec5SDimitry Andric }
16470b57cec5SDimitry Andric }
16480b57cec5SDimitry Andric return false;
16490b57cec5SDimitry Andric
16500b57cec5SDimitry Andric case Entry::Type::FunctionNameWithArgs: {
1651fe6060f1SDimitry Andric if (!sc)
1652fe6060f1SDimitry Andric return false;
1653fe6060f1SDimitry Andric
16540b57cec5SDimitry Andric Language *language_plugin = nullptr;
16550b57cec5SDimitry Andric bool language_plugin_handled = false;
16560b57cec5SDimitry Andric StreamString ss;
16570b57cec5SDimitry Andric if (sc->function)
16580b57cec5SDimitry Andric language_plugin = Language::FindPlugin(sc->function->GetLanguage());
16590b57cec5SDimitry Andric else if (sc->symbol)
16600b57cec5SDimitry Andric language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
1661fe6060f1SDimitry Andric
1662fe6060f1SDimitry Andric if (language_plugin)
16630b57cec5SDimitry Andric language_plugin_handled = language_plugin->GetFunctionDisplayName(
16640b57cec5SDimitry Andric sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithArgs, ss);
1665fe6060f1SDimitry Andric
16660b57cec5SDimitry Andric if (language_plugin_handled) {
16670b57cec5SDimitry Andric s << ss.GetString();
16680b57cec5SDimitry Andric return true;
16690b57cec5SDimitry Andric } else {
16700b57cec5SDimitry Andric // Print the function name with arguments in it
16710b57cec5SDimitry Andric if (sc->function) {
16720b57cec5SDimitry Andric ExecutionContextScope *exe_scope =
16730b57cec5SDimitry Andric exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr;
16740b57cec5SDimitry Andric const char *cstr = sc->function->GetName().AsCString(nullptr);
16750b57cec5SDimitry Andric if (cstr) {
16760b57cec5SDimitry Andric const InlineFunctionInfo *inline_info = nullptr;
16770b57cec5SDimitry Andric VariableListSP variable_list_sp;
16780b57cec5SDimitry Andric bool get_function_vars = true;
16790b57cec5SDimitry Andric if (sc->block) {
16800b57cec5SDimitry Andric Block *inline_block = sc->block->GetContainingInlinedBlock();
16810b57cec5SDimitry Andric
16820b57cec5SDimitry Andric if (inline_block) {
16830b57cec5SDimitry Andric get_function_vars = false;
1684*a58f00eaSDimitry Andric inline_info = inline_block->GetInlinedFunctionInfo();
16850b57cec5SDimitry Andric if (inline_info)
16860b57cec5SDimitry Andric variable_list_sp = inline_block->GetBlockVariableList(true);
16870b57cec5SDimitry Andric }
16880b57cec5SDimitry Andric }
16890b57cec5SDimitry Andric
16900b57cec5SDimitry Andric if (get_function_vars) {
16910b57cec5SDimitry Andric variable_list_sp =
16920b57cec5SDimitry Andric sc->function->GetBlock(true).GetBlockVariableList(true);
16930b57cec5SDimitry Andric }
16940b57cec5SDimitry Andric
16950b57cec5SDimitry Andric if (inline_info) {
16960b57cec5SDimitry Andric s.PutCString(cstr);
16970b57cec5SDimitry Andric s.PutCString(" [inlined] ");
16985ffd83dbSDimitry Andric cstr = inline_info->GetName().GetCString();
16990b57cec5SDimitry Andric }
17000b57cec5SDimitry Andric
17010b57cec5SDimitry Andric VariableList args;
17020b57cec5SDimitry Andric if (variable_list_sp)
17030b57cec5SDimitry Andric variable_list_sp->AppendVariablesWithScope(
17040b57cec5SDimitry Andric eValueTypeVariableArgument, args);
17050b57cec5SDimitry Andric if (args.GetSize() > 0) {
1706bdd1243dSDimitry Andric PrettyPrintFunctionNameWithArgs(s, cstr, exe_scope, args);
17070b57cec5SDimitry Andric } else {
17080b57cec5SDimitry Andric s.PutCString(cstr);
17090b57cec5SDimitry Andric }
17100b57cec5SDimitry Andric return true;
17110b57cec5SDimitry Andric }
17120b57cec5SDimitry Andric } else if (sc->symbol) {
17130b57cec5SDimitry Andric const char *cstr = sc->symbol->GetName().AsCString(nullptr);
17140b57cec5SDimitry Andric if (cstr) {
17150b57cec5SDimitry Andric s.PutCString(cstr);
17160b57cec5SDimitry Andric return true;
17170b57cec5SDimitry Andric }
17180b57cec5SDimitry Andric }
17190b57cec5SDimitry Andric }
17200b57cec5SDimitry Andric }
17210b57cec5SDimitry Andric return false;
17220b57cec5SDimitry Andric
1723480093f4SDimitry Andric case Entry::Type::FunctionMangledName: {
1724fe6060f1SDimitry Andric if (!sc)
1725fe6060f1SDimitry Andric return false;
1726fe6060f1SDimitry Andric
1727480093f4SDimitry Andric const char *name = nullptr;
1728480093f4SDimitry Andric if (sc->symbol)
17295ffd83dbSDimitry Andric name =
17305ffd83dbSDimitry Andric sc->symbol->GetMangled().GetName(Mangled::ePreferMangled).AsCString();
1731480093f4SDimitry Andric else if (sc->function)
1732480093f4SDimitry Andric name = sc->function->GetMangled()
17335ffd83dbSDimitry Andric .GetName(Mangled::ePreferMangled)
1734480093f4SDimitry Andric .AsCString();
1735480093f4SDimitry Andric
1736480093f4SDimitry Andric if (!name)
1737480093f4SDimitry Andric return false;
1738480093f4SDimitry Andric s.PutCString(name);
1739*a58f00eaSDimitry Andric FormatInlinedBlock(s, sc->block);
1740480093f4SDimitry Andric return true;
1741480093f4SDimitry Andric }
17420b57cec5SDimitry Andric case Entry::Type::FunctionAddrOffset:
17430b57cec5SDimitry Andric if (addr) {
17440b57cec5SDimitry Andric if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, *addr, false, false,
17450b57cec5SDimitry Andric false))
17460b57cec5SDimitry Andric return true;
17470b57cec5SDimitry Andric }
17480b57cec5SDimitry Andric return false;
17490b57cec5SDimitry Andric
17500b57cec5SDimitry Andric case Entry::Type::FunctionAddrOffsetConcrete:
17510b57cec5SDimitry Andric if (addr) {
17520b57cec5SDimitry Andric if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, *addr, true, true,
17530b57cec5SDimitry Andric true))
17540b57cec5SDimitry Andric return true;
17550b57cec5SDimitry Andric }
17560b57cec5SDimitry Andric return false;
17570b57cec5SDimitry Andric
17580b57cec5SDimitry Andric case Entry::Type::FunctionLineOffset:
1759fe6060f1SDimitry Andric if (sc)
1760fe6060f1SDimitry Andric return (DumpAddressOffsetFromFunction(
1761fe6060f1SDimitry Andric s, sc, exe_ctx, sc->line_entry.range.GetBaseAddress(), false, false,
1762fe6060f1SDimitry Andric false));
1763fe6060f1SDimitry Andric return false;
17640b57cec5SDimitry Andric
17650b57cec5SDimitry Andric case Entry::Type::FunctionPCOffset:
17660b57cec5SDimitry Andric if (exe_ctx) {
17670b57cec5SDimitry Andric StackFrame *frame = exe_ctx->GetFramePtr();
17680b57cec5SDimitry Andric if (frame) {
17690b57cec5SDimitry Andric if (DumpAddressOffsetFromFunction(s, sc, exe_ctx,
17700b57cec5SDimitry Andric frame->GetFrameCodeAddress(), false,
17710b57cec5SDimitry Andric false, false))
17720b57cec5SDimitry Andric return true;
17730b57cec5SDimitry Andric }
17740b57cec5SDimitry Andric }
17750b57cec5SDimitry Andric return false;
17760b57cec5SDimitry Andric
17770b57cec5SDimitry Andric case Entry::Type::FunctionChanged:
17780b57cec5SDimitry Andric return function_changed;
17790b57cec5SDimitry Andric
17800b57cec5SDimitry Andric case Entry::Type::FunctionIsOptimized: {
17810b57cec5SDimitry Andric bool is_optimized = false;
1782fe6060f1SDimitry Andric if (sc && sc->function && sc->function->GetIsOptimized()) {
17830b57cec5SDimitry Andric is_optimized = true;
17840b57cec5SDimitry Andric }
17850b57cec5SDimitry Andric return is_optimized;
17860b57cec5SDimitry Andric }
17870b57cec5SDimitry Andric
17880b57cec5SDimitry Andric case Entry::Type::FunctionInitial:
17890b57cec5SDimitry Andric return initial_function;
17900b57cec5SDimitry Andric
17910b57cec5SDimitry Andric case Entry::Type::LineEntryFile:
17920b57cec5SDimitry Andric if (sc && sc->line_entry.IsValid()) {
17930b57cec5SDimitry Andric Module *module = sc->module_sp.get();
17940b57cec5SDimitry Andric if (module) {
17950b57cec5SDimitry Andric if (DumpFile(s, sc->line_entry.file, (FileKind)entry.number))
17960b57cec5SDimitry Andric return true;
17970b57cec5SDimitry Andric }
17980b57cec5SDimitry Andric }
17990b57cec5SDimitry Andric return false;
18000b57cec5SDimitry Andric
18010b57cec5SDimitry Andric case Entry::Type::LineEntryLineNumber:
18020b57cec5SDimitry Andric if (sc && sc->line_entry.IsValid()) {
18030b57cec5SDimitry Andric const char *format = "%" PRIu32;
18040b57cec5SDimitry Andric if (!entry.printf_format.empty())
18050b57cec5SDimitry Andric format = entry.printf_format.c_str();
18060b57cec5SDimitry Andric s.Printf(format, sc->line_entry.line);
18070b57cec5SDimitry Andric return true;
18080b57cec5SDimitry Andric }
18090b57cec5SDimitry Andric return false;
18100b57cec5SDimitry Andric
18110b57cec5SDimitry Andric case Entry::Type::LineEntryColumn:
18120b57cec5SDimitry Andric if (sc && sc->line_entry.IsValid() && sc->line_entry.column) {
18130b57cec5SDimitry Andric const char *format = "%" PRIu32;
18140b57cec5SDimitry Andric if (!entry.printf_format.empty())
18150b57cec5SDimitry Andric format = entry.printf_format.c_str();
18160b57cec5SDimitry Andric s.Printf(format, sc->line_entry.column);
18170b57cec5SDimitry Andric return true;
18180b57cec5SDimitry Andric }
18190b57cec5SDimitry Andric return false;
18200b57cec5SDimitry Andric
18210b57cec5SDimitry Andric case Entry::Type::LineEntryStartAddress:
18220b57cec5SDimitry Andric case Entry::Type::LineEntryEndAddress:
18230b57cec5SDimitry Andric if (sc && sc->line_entry.range.GetBaseAddress().IsValid()) {
18240b57cec5SDimitry Andric Address addr = sc->line_entry.range.GetBaseAddress();
18250b57cec5SDimitry Andric
18260b57cec5SDimitry Andric if (entry.type == Entry::Type::LineEntryEndAddress)
18270b57cec5SDimitry Andric addr.Slide(sc->line_entry.range.GetByteSize());
1828480093f4SDimitry Andric if (DumpAddressAndContent(s, sc, exe_ctx, addr, false))
18290b57cec5SDimitry Andric return true;
18300b57cec5SDimitry Andric }
18310b57cec5SDimitry Andric return false;
18320b57cec5SDimitry Andric
18330b57cec5SDimitry Andric case Entry::Type::CurrentPCArrow:
18340b57cec5SDimitry Andric if (addr && exe_ctx && exe_ctx->GetFramePtr()) {
18350b57cec5SDimitry Andric RegisterContextSP reg_ctx =
18360b57cec5SDimitry Andric exe_ctx->GetFramePtr()->GetRegisterContextSP();
18370b57cec5SDimitry Andric if (reg_ctx) {
18380b57cec5SDimitry Andric addr_t pc_loadaddr = reg_ctx->GetPC();
18390b57cec5SDimitry Andric if (pc_loadaddr != LLDB_INVALID_ADDRESS) {
18400b57cec5SDimitry Andric Address pc;
18410b57cec5SDimitry Andric pc.SetLoadAddress(pc_loadaddr, exe_ctx->GetTargetPtr());
18420b57cec5SDimitry Andric if (pc == *addr) {
18430b57cec5SDimitry Andric s.Printf("-> ");
18440b57cec5SDimitry Andric return true;
18450b57cec5SDimitry Andric }
18460b57cec5SDimitry Andric }
18470b57cec5SDimitry Andric }
18480b57cec5SDimitry Andric s.Printf(" ");
18490b57cec5SDimitry Andric return true;
18500b57cec5SDimitry Andric }
18510b57cec5SDimitry Andric return false;
18520b57cec5SDimitry Andric }
18530b57cec5SDimitry Andric return false;
18540b57cec5SDimitry Andric }
18550b57cec5SDimitry Andric
DumpCommaSeparatedChildEntryNames(Stream & s,const Definition * parent)1856fe6060f1SDimitry Andric static bool DumpCommaSeparatedChildEntryNames(Stream &s,
1857fe6060f1SDimitry Andric const Definition *parent) {
18580b57cec5SDimitry Andric if (parent->children) {
18590b57cec5SDimitry Andric const size_t n = parent->num_children;
18600b57cec5SDimitry Andric for (size_t i = 0; i < n; ++i) {
18610b57cec5SDimitry Andric if (i > 0)
18620b57cec5SDimitry Andric s.PutCString(", ");
18630b57cec5SDimitry Andric s.Printf("\"%s\"", parent->children[i].name);
18640b57cec5SDimitry Andric }
18650b57cec5SDimitry Andric return true;
18660b57cec5SDimitry Andric }
18670b57cec5SDimitry Andric return false;
18680b57cec5SDimitry Andric }
18690b57cec5SDimitry Andric
ParseEntry(const llvm::StringRef & format_str,const Definition * parent,FormatEntity::Entry & entry)18700b57cec5SDimitry Andric static Status ParseEntry(const llvm::StringRef &format_str,
1871fe6060f1SDimitry Andric const Definition *parent, FormatEntity::Entry &entry) {
18720b57cec5SDimitry Andric Status error;
18730b57cec5SDimitry Andric
18740b57cec5SDimitry Andric const size_t sep_pos = format_str.find_first_of(".[:");
18750b57cec5SDimitry Andric const char sep_char =
18760b57cec5SDimitry Andric (sep_pos == llvm::StringRef::npos) ? '\0' : format_str[sep_pos];
18770b57cec5SDimitry Andric llvm::StringRef key = format_str.substr(0, sep_pos);
18780b57cec5SDimitry Andric
18790b57cec5SDimitry Andric const size_t n = parent->num_children;
18800b57cec5SDimitry Andric for (size_t i = 0; i < n; ++i) {
1881fe6060f1SDimitry Andric const Definition *entry_def = parent->children + i;
18820b57cec5SDimitry Andric if (key.equals(entry_def->name) || entry_def->name[0] == '*') {
18830b57cec5SDimitry Andric llvm::StringRef value;
18840b57cec5SDimitry Andric if (sep_char)
18850b57cec5SDimitry Andric value =
18860b57cec5SDimitry Andric format_str.substr(sep_pos + (entry_def->keep_separator ? 0 : 1));
18870b57cec5SDimitry Andric switch (entry_def->type) {
18880b57cec5SDimitry Andric case FormatEntity::Entry::Type::ParentString:
18890b57cec5SDimitry Andric entry.string = format_str.str();
18900b57cec5SDimitry Andric return error; // Success
18910b57cec5SDimitry Andric
18920b57cec5SDimitry Andric case FormatEntity::Entry::Type::ParentNumber:
18930b57cec5SDimitry Andric entry.number = entry_def->data;
18940b57cec5SDimitry Andric return error; // Success
18950b57cec5SDimitry Andric
18960b57cec5SDimitry Andric case FormatEntity::Entry::Type::EscapeCode:
18970b57cec5SDimitry Andric entry.type = entry_def->type;
18980b57cec5SDimitry Andric entry.string = entry_def->string;
18990b57cec5SDimitry Andric return error; // Success
19000b57cec5SDimitry Andric
19010b57cec5SDimitry Andric default:
19020b57cec5SDimitry Andric entry.type = entry_def->type;
19030b57cec5SDimitry Andric break;
19040b57cec5SDimitry Andric }
19050b57cec5SDimitry Andric
19060b57cec5SDimitry Andric if (value.empty()) {
19070b57cec5SDimitry Andric if (entry_def->type == FormatEntity::Entry::Type::Invalid) {
19080b57cec5SDimitry Andric if (entry_def->children) {
19090b57cec5SDimitry Andric StreamString error_strm;
19100b57cec5SDimitry Andric error_strm.Printf("'%s' can't be specified on its own, you must "
19110b57cec5SDimitry Andric "access one of its children: ",
19120b57cec5SDimitry Andric entry_def->name);
19130b57cec5SDimitry Andric DumpCommaSeparatedChildEntryNames(error_strm, entry_def);
19140b57cec5SDimitry Andric error.SetErrorStringWithFormat("%s", error_strm.GetData());
19150b57cec5SDimitry Andric } else if (sep_char == ':') {
19160b57cec5SDimitry Andric // Any value whose separator is a with a ':' means this value has a
19170b57cec5SDimitry Andric // string argument that needs to be stored in the entry (like
19180b57cec5SDimitry Andric // "${script.var:}"). In this case the string value is the empty
19190b57cec5SDimitry Andric // string which is ok.
19200b57cec5SDimitry Andric } else {
19210b57cec5SDimitry Andric error.SetErrorStringWithFormat("%s", "invalid entry definitions");
19220b57cec5SDimitry Andric }
19230b57cec5SDimitry Andric }
19240b57cec5SDimitry Andric } else {
19250b57cec5SDimitry Andric if (entry_def->children) {
19260b57cec5SDimitry Andric error = ParseEntry(value, entry_def, entry);
19270b57cec5SDimitry Andric } else if (sep_char == ':') {
19280b57cec5SDimitry Andric // Any value whose separator is a with a ':' means this value has a
19290b57cec5SDimitry Andric // string argument that needs to be stored in the entry (like
19300b57cec5SDimitry Andric // "${script.var:modulename.function}")
19310b57cec5SDimitry Andric entry.string = value.str();
19320b57cec5SDimitry Andric } else {
19330b57cec5SDimitry Andric error.SetErrorStringWithFormat(
19340b57cec5SDimitry Andric "'%s' followed by '%s' but it has no children", key.str().c_str(),
19350b57cec5SDimitry Andric value.str().c_str());
19360b57cec5SDimitry Andric }
19370b57cec5SDimitry Andric }
19380b57cec5SDimitry Andric return error;
19390b57cec5SDimitry Andric }
19400b57cec5SDimitry Andric }
19410b57cec5SDimitry Andric StreamString error_strm;
19420b57cec5SDimitry Andric if (parent->type == FormatEntity::Entry::Type::Root)
19430b57cec5SDimitry Andric error_strm.Printf(
19440b57cec5SDimitry Andric "invalid top level item '%s'. Valid top level items are: ",
19450b57cec5SDimitry Andric key.str().c_str());
19460b57cec5SDimitry Andric else
19470b57cec5SDimitry Andric error_strm.Printf("invalid member '%s' in '%s'. Valid members are: ",
19480b57cec5SDimitry Andric key.str().c_str(), parent->name);
19490b57cec5SDimitry Andric DumpCommaSeparatedChildEntryNames(error_strm, parent);
19500b57cec5SDimitry Andric error.SetErrorStringWithFormat("%s", error_strm.GetData());
19510b57cec5SDimitry Andric return error;
19520b57cec5SDimitry Andric }
19530b57cec5SDimitry Andric
FindEntry(const llvm::StringRef & format_str,const Definition * parent,llvm::StringRef & remainder)1954fe6060f1SDimitry Andric static const Definition *FindEntry(const llvm::StringRef &format_str,
1955fe6060f1SDimitry Andric const Definition *parent,
19560b57cec5SDimitry Andric llvm::StringRef &remainder) {
19570b57cec5SDimitry Andric Status error;
19580b57cec5SDimitry Andric
19590b57cec5SDimitry Andric std::pair<llvm::StringRef, llvm::StringRef> p = format_str.split('.');
19600b57cec5SDimitry Andric const size_t n = parent->num_children;
19610b57cec5SDimitry Andric for (size_t i = 0; i < n; ++i) {
1962fe6060f1SDimitry Andric const Definition *entry_def = parent->children + i;
19630b57cec5SDimitry Andric if (p.first.equals(entry_def->name) || entry_def->name[0] == '*') {
19640b57cec5SDimitry Andric if (p.second.empty()) {
19650b57cec5SDimitry Andric if (format_str.back() == '.')
19660b57cec5SDimitry Andric remainder = format_str.drop_front(format_str.size() - 1);
19670b57cec5SDimitry Andric else
19680b57cec5SDimitry Andric remainder = llvm::StringRef(); // Exact match
19690b57cec5SDimitry Andric return entry_def;
19700b57cec5SDimitry Andric } else {
19710b57cec5SDimitry Andric if (entry_def->children) {
19720b57cec5SDimitry Andric return FindEntry(p.second, entry_def, remainder);
19730b57cec5SDimitry Andric } else {
19740b57cec5SDimitry Andric remainder = p.second;
19750b57cec5SDimitry Andric return entry_def;
19760b57cec5SDimitry Andric }
19770b57cec5SDimitry Andric }
19780b57cec5SDimitry Andric }
19790b57cec5SDimitry Andric }
19800b57cec5SDimitry Andric remainder = format_str;
19810b57cec5SDimitry Andric return parent;
19820b57cec5SDimitry Andric }
19830b57cec5SDimitry Andric
ParseInternal(llvm::StringRef & format,Entry & parent_entry,uint32_t depth)1984c9157d92SDimitry Andric static Status ParseInternal(llvm::StringRef &format, Entry &parent_entry,
19850b57cec5SDimitry Andric uint32_t depth) {
19860b57cec5SDimitry Andric Status error;
19870b57cec5SDimitry Andric while (!format.empty() && error.Success()) {
19880b57cec5SDimitry Andric const size_t non_special_chars = format.find_first_of("${}\\");
19890b57cec5SDimitry Andric
19900b57cec5SDimitry Andric if (non_special_chars == llvm::StringRef::npos) {
19910b57cec5SDimitry Andric // No special characters, just string bytes so add them and we are done
19920b57cec5SDimitry Andric parent_entry.AppendText(format);
19930b57cec5SDimitry Andric return error;
19940b57cec5SDimitry Andric }
19950b57cec5SDimitry Andric
19960b57cec5SDimitry Andric if (non_special_chars > 0) {
19970b57cec5SDimitry Andric // We have a special character, so add all characters before these as a
19980b57cec5SDimitry Andric // plain string
19990b57cec5SDimitry Andric parent_entry.AppendText(format.substr(0, non_special_chars));
20000b57cec5SDimitry Andric format = format.drop_front(non_special_chars);
20010b57cec5SDimitry Andric }
20020b57cec5SDimitry Andric
20030b57cec5SDimitry Andric switch (format[0]) {
20040b57cec5SDimitry Andric case '\0':
20050b57cec5SDimitry Andric return error;
20060b57cec5SDimitry Andric
20070b57cec5SDimitry Andric case '{': {
20080b57cec5SDimitry Andric format = format.drop_front(); // Skip the '{'
20090b57cec5SDimitry Andric Entry scope_entry(Entry::Type::Scope);
2010c9157d92SDimitry Andric error = ParseInternal(format, scope_entry, depth + 1);
20110b57cec5SDimitry Andric if (error.Fail())
20120b57cec5SDimitry Andric return error;
20130b57cec5SDimitry Andric parent_entry.AppendEntry(std::move(scope_entry));
20140b57cec5SDimitry Andric } break;
20150b57cec5SDimitry Andric
20160b57cec5SDimitry Andric case '}':
20170b57cec5SDimitry Andric if (depth == 0)
20180b57cec5SDimitry Andric error.SetErrorString("unmatched '}' character");
20190b57cec5SDimitry Andric else
20200b57cec5SDimitry Andric format =
20210b57cec5SDimitry Andric format
20220b57cec5SDimitry Andric .drop_front(); // Skip the '}' as we are at the end of the scope
20230b57cec5SDimitry Andric return error;
20240b57cec5SDimitry Andric
20250b57cec5SDimitry Andric case '\\': {
20260b57cec5SDimitry Andric format = format.drop_front(); // Skip the '\' character
20270b57cec5SDimitry Andric if (format.empty()) {
20280b57cec5SDimitry Andric error.SetErrorString(
20290b57cec5SDimitry Andric "'\\' character was not followed by another character");
20300b57cec5SDimitry Andric return error;
20310b57cec5SDimitry Andric }
20320b57cec5SDimitry Andric
20330b57cec5SDimitry Andric const char desens_char = format[0];
20340b57cec5SDimitry Andric format = format.drop_front(); // Skip the desensitized char character
20350b57cec5SDimitry Andric switch (desens_char) {
20360b57cec5SDimitry Andric case 'a':
20370b57cec5SDimitry Andric parent_entry.AppendChar('\a');
20380b57cec5SDimitry Andric break;
20390b57cec5SDimitry Andric case 'b':
20400b57cec5SDimitry Andric parent_entry.AppendChar('\b');
20410b57cec5SDimitry Andric break;
20420b57cec5SDimitry Andric case 'f':
20430b57cec5SDimitry Andric parent_entry.AppendChar('\f');
20440b57cec5SDimitry Andric break;
20450b57cec5SDimitry Andric case 'n':
20460b57cec5SDimitry Andric parent_entry.AppendChar('\n');
20470b57cec5SDimitry Andric break;
20480b57cec5SDimitry Andric case 'r':
20490b57cec5SDimitry Andric parent_entry.AppendChar('\r');
20500b57cec5SDimitry Andric break;
20510b57cec5SDimitry Andric case 't':
20520b57cec5SDimitry Andric parent_entry.AppendChar('\t');
20530b57cec5SDimitry Andric break;
20540b57cec5SDimitry Andric case 'v':
20550b57cec5SDimitry Andric parent_entry.AppendChar('\v');
20560b57cec5SDimitry Andric break;
20570b57cec5SDimitry Andric case '\'':
20580b57cec5SDimitry Andric parent_entry.AppendChar('\'');
20590b57cec5SDimitry Andric break;
20600b57cec5SDimitry Andric case '\\':
20610b57cec5SDimitry Andric parent_entry.AppendChar('\\');
20620b57cec5SDimitry Andric break;
20630b57cec5SDimitry Andric case '0':
20640b57cec5SDimitry Andric // 1 to 3 octal chars
20650b57cec5SDimitry Andric {
20660b57cec5SDimitry Andric // Make a string that can hold onto the initial zero char, up to 3
20670b57cec5SDimitry Andric // octal digits, and a terminating NULL.
20680b57cec5SDimitry Andric char oct_str[5] = {0, 0, 0, 0, 0};
20690b57cec5SDimitry Andric
20700b57cec5SDimitry Andric int i;
20710b57cec5SDimitry Andric for (i = 0; (format[i] >= '0' && format[i] <= '7') && i < 4; ++i)
20720b57cec5SDimitry Andric oct_str[i] = format[i];
20730b57cec5SDimitry Andric
20740b57cec5SDimitry Andric // We don't want to consume the last octal character since the main
20750b57cec5SDimitry Andric // for loop will do this for us, so we advance p by one less than i
20760b57cec5SDimitry Andric // (even if i is zero)
20770b57cec5SDimitry Andric format = format.drop_front(i);
20780b57cec5SDimitry Andric unsigned long octal_value = ::strtoul(oct_str, nullptr, 8);
20790b57cec5SDimitry Andric if (octal_value <= UINT8_MAX) {
20800b57cec5SDimitry Andric parent_entry.AppendChar((char)octal_value);
20810b57cec5SDimitry Andric } else {
20820b57cec5SDimitry Andric error.SetErrorString("octal number is larger than a single byte");
20830b57cec5SDimitry Andric return error;
20840b57cec5SDimitry Andric }
20850b57cec5SDimitry Andric }
20860b57cec5SDimitry Andric break;
20870b57cec5SDimitry Andric
20880b57cec5SDimitry Andric case 'x':
20890b57cec5SDimitry Andric // hex number in the format
20900b57cec5SDimitry Andric if (isxdigit(format[0])) {
20910b57cec5SDimitry Andric // Make a string that can hold onto two hex chars plus a
20920b57cec5SDimitry Andric // NULL terminator
20930b57cec5SDimitry Andric char hex_str[3] = {0, 0, 0};
20940b57cec5SDimitry Andric hex_str[0] = format[0];
20950b57cec5SDimitry Andric
20960b57cec5SDimitry Andric format = format.drop_front();
20970b57cec5SDimitry Andric
20980b57cec5SDimitry Andric if (isxdigit(format[0])) {
20990b57cec5SDimitry Andric hex_str[1] = format[0];
21000b57cec5SDimitry Andric format = format.drop_front();
21010b57cec5SDimitry Andric }
21020b57cec5SDimitry Andric
21030b57cec5SDimitry Andric unsigned long hex_value = strtoul(hex_str, nullptr, 16);
21040b57cec5SDimitry Andric if (hex_value <= UINT8_MAX) {
21050b57cec5SDimitry Andric parent_entry.AppendChar((char)hex_value);
21060b57cec5SDimitry Andric } else {
21070b57cec5SDimitry Andric error.SetErrorString("hex number is larger than a single byte");
21080b57cec5SDimitry Andric return error;
21090b57cec5SDimitry Andric }
21100b57cec5SDimitry Andric } else {
21110b57cec5SDimitry Andric parent_entry.AppendChar(desens_char);
21120b57cec5SDimitry Andric }
21130b57cec5SDimitry Andric break;
21140b57cec5SDimitry Andric
21150b57cec5SDimitry Andric default:
21160b57cec5SDimitry Andric // Just desensitize any other character by just printing what came
21170b57cec5SDimitry Andric // after the '\'
21180b57cec5SDimitry Andric parent_entry.AppendChar(desens_char);
21190b57cec5SDimitry Andric break;
21200b57cec5SDimitry Andric }
21210b57cec5SDimitry Andric } break;
21220b57cec5SDimitry Andric
21230b57cec5SDimitry Andric case '$':
21240b57cec5SDimitry Andric if (format.size() == 1) {
21250b57cec5SDimitry Andric // '$' at the end of a format string, just print the '$'
21260b57cec5SDimitry Andric parent_entry.AppendText("$");
21270b57cec5SDimitry Andric } else {
21280b57cec5SDimitry Andric format = format.drop_front(); // Skip the '$'
21290b57cec5SDimitry Andric
21300b57cec5SDimitry Andric if (format[0] == '{') {
21310b57cec5SDimitry Andric format = format.drop_front(); // Skip the '{'
21320b57cec5SDimitry Andric
21330b57cec5SDimitry Andric llvm::StringRef variable, variable_format;
21340b57cec5SDimitry Andric error = FormatEntity::ExtractVariableInfo(format, variable,
21350b57cec5SDimitry Andric variable_format);
21360b57cec5SDimitry Andric if (error.Fail())
21370b57cec5SDimitry Andric return error;
21380b57cec5SDimitry Andric bool verify_is_thread_id = false;
21390b57cec5SDimitry Andric Entry entry;
21400b57cec5SDimitry Andric if (!variable_format.empty()) {
21410b57cec5SDimitry Andric entry.printf_format = variable_format.str();
21420b57cec5SDimitry Andric
21430b57cec5SDimitry Andric // If the format contains a '%' we are going to assume this is a
21440b57cec5SDimitry Andric // printf style format. So if you want to format your thread ID
21450b57cec5SDimitry Andric // using "0x%llx" you can use: ${thread.id%0x%llx}
21460b57cec5SDimitry Andric //
21470b57cec5SDimitry Andric // If there is no '%' in the format, then it is assumed to be a
21480b57cec5SDimitry Andric // LLDB format name, or one of the extended formats specified in
21490b57cec5SDimitry Andric // the switch statement below.
21500b57cec5SDimitry Andric
21510b57cec5SDimitry Andric if (entry.printf_format.find('%') == std::string::npos) {
21520b57cec5SDimitry Andric bool clear_printf = false;
21530b57cec5SDimitry Andric
21540b57cec5SDimitry Andric if (FormatManager::GetFormatFromCString(
21550b57cec5SDimitry Andric entry.printf_format.c_str(), false, entry.fmt)) {
21560b57cec5SDimitry Andric // We have an LLDB format, so clear the printf format
21570b57cec5SDimitry Andric clear_printf = true;
21580b57cec5SDimitry Andric } else if (entry.printf_format.size() == 1) {
21590b57cec5SDimitry Andric switch (entry.printf_format[0]) {
21600b57cec5SDimitry Andric case '@': // if this is an @ sign, print ObjC description
21610b57cec5SDimitry Andric entry.number = ValueObject::
21620b57cec5SDimitry Andric eValueObjectRepresentationStyleLanguageSpecific;
21630b57cec5SDimitry Andric clear_printf = true;
21640b57cec5SDimitry Andric break;
21650b57cec5SDimitry Andric case 'V': // if this is a V, print the value using the default
21660b57cec5SDimitry Andric // format
21670b57cec5SDimitry Andric entry.number =
21680b57cec5SDimitry Andric ValueObject::eValueObjectRepresentationStyleValue;
21690b57cec5SDimitry Andric clear_printf = true;
21700b57cec5SDimitry Andric break;
21710b57cec5SDimitry Andric case 'L': // if this is an L, print the location of the value
21720b57cec5SDimitry Andric entry.number =
21730b57cec5SDimitry Andric ValueObject::eValueObjectRepresentationStyleLocation;
21740b57cec5SDimitry Andric clear_printf = true;
21750b57cec5SDimitry Andric break;
21760b57cec5SDimitry Andric case 'S': // if this is an S, print the summary after all
21770b57cec5SDimitry Andric entry.number =
21780b57cec5SDimitry Andric ValueObject::eValueObjectRepresentationStyleSummary;
21790b57cec5SDimitry Andric clear_printf = true;
21800b57cec5SDimitry Andric break;
21810b57cec5SDimitry Andric case '#': // if this is a '#', print the number of children
21820b57cec5SDimitry Andric entry.number =
21830b57cec5SDimitry Andric ValueObject::eValueObjectRepresentationStyleChildrenCount;
21840b57cec5SDimitry Andric clear_printf = true;
21850b57cec5SDimitry Andric break;
21860b57cec5SDimitry Andric case 'T': // if this is a 'T', print the type
21870b57cec5SDimitry Andric entry.number =
21880b57cec5SDimitry Andric ValueObject::eValueObjectRepresentationStyleType;
21890b57cec5SDimitry Andric clear_printf = true;
21900b57cec5SDimitry Andric break;
21910b57cec5SDimitry Andric case 'N': // if this is a 'N', print the name
21920b57cec5SDimitry Andric entry.number =
21930b57cec5SDimitry Andric ValueObject::eValueObjectRepresentationStyleName;
21940b57cec5SDimitry Andric clear_printf = true;
21950b57cec5SDimitry Andric break;
21960b57cec5SDimitry Andric case '>': // if this is a '>', print the expression path
21970b57cec5SDimitry Andric entry.number = ValueObject::
21980b57cec5SDimitry Andric eValueObjectRepresentationStyleExpressionPath;
21990b57cec5SDimitry Andric clear_printf = true;
22000b57cec5SDimitry Andric break;
22010b57cec5SDimitry Andric default:
22020b57cec5SDimitry Andric error.SetErrorStringWithFormat("invalid format: '%s'",
22030b57cec5SDimitry Andric entry.printf_format.c_str());
22040b57cec5SDimitry Andric return error;
22050b57cec5SDimitry Andric }
22060b57cec5SDimitry Andric } else if (FormatManager::GetFormatFromCString(
22070b57cec5SDimitry Andric entry.printf_format.c_str(), true, entry.fmt)) {
22080b57cec5SDimitry Andric clear_printf = true;
22090b57cec5SDimitry Andric } else if (entry.printf_format == "tid") {
22100b57cec5SDimitry Andric verify_is_thread_id = true;
22110b57cec5SDimitry Andric } else {
22120b57cec5SDimitry Andric error.SetErrorStringWithFormat("invalid format: '%s'",
22130b57cec5SDimitry Andric entry.printf_format.c_str());
22140b57cec5SDimitry Andric return error;
22150b57cec5SDimitry Andric }
22160b57cec5SDimitry Andric
22170b57cec5SDimitry Andric // Our format string turned out to not be a printf style format
22180b57cec5SDimitry Andric // so lets clear the string
22190b57cec5SDimitry Andric if (clear_printf)
22200b57cec5SDimitry Andric entry.printf_format.clear();
22210b57cec5SDimitry Andric }
22220b57cec5SDimitry Andric }
22230b57cec5SDimitry Andric
22240b57cec5SDimitry Andric // Check for dereferences
22250b57cec5SDimitry Andric if (variable[0] == '*') {
22260b57cec5SDimitry Andric entry.deref = true;
22270b57cec5SDimitry Andric variable = variable.drop_front();
22280b57cec5SDimitry Andric }
22290b57cec5SDimitry Andric
22300b57cec5SDimitry Andric error = ParseEntry(variable, &g_root, entry);
22310b57cec5SDimitry Andric if (error.Fail())
22320b57cec5SDimitry Andric return error;
22330b57cec5SDimitry Andric
22340b57cec5SDimitry Andric if (verify_is_thread_id) {
22350b57cec5SDimitry Andric if (entry.type != Entry::Type::ThreadID &&
22360b57cec5SDimitry Andric entry.type != Entry::Type::ThreadProtocolID) {
22370b57cec5SDimitry Andric error.SetErrorString("the 'tid' format can only be used on "
22380b57cec5SDimitry Andric "${thread.id} and ${thread.protocol_id}");
22390b57cec5SDimitry Andric }
22400b57cec5SDimitry Andric }
22410b57cec5SDimitry Andric
22420b57cec5SDimitry Andric switch (entry.type) {
22430b57cec5SDimitry Andric case Entry::Type::Variable:
22440b57cec5SDimitry Andric case Entry::Type::VariableSynthetic:
22450b57cec5SDimitry Andric if (entry.number == 0) {
22460b57cec5SDimitry Andric if (entry.string.empty())
22470b57cec5SDimitry Andric entry.number =
22480b57cec5SDimitry Andric ValueObject::eValueObjectRepresentationStyleValue;
22490b57cec5SDimitry Andric else
22500b57cec5SDimitry Andric entry.number =
22510b57cec5SDimitry Andric ValueObject::eValueObjectRepresentationStyleSummary;
22520b57cec5SDimitry Andric }
22530b57cec5SDimitry Andric break;
22540b57cec5SDimitry Andric default:
22550b57cec5SDimitry Andric // Make sure someone didn't try to dereference anything but ${var}
22560b57cec5SDimitry Andric // or ${svar}
22570b57cec5SDimitry Andric if (entry.deref) {
22580b57cec5SDimitry Andric error.SetErrorStringWithFormat(
22590b57cec5SDimitry Andric "${%s} can't be dereferenced, only ${var} and ${svar} can.",
22600b57cec5SDimitry Andric variable.str().c_str());
22610b57cec5SDimitry Andric return error;
22620b57cec5SDimitry Andric }
22630b57cec5SDimitry Andric }
22640b57cec5SDimitry Andric parent_entry.AppendEntry(std::move(entry));
22650b57cec5SDimitry Andric }
22660b57cec5SDimitry Andric }
22670b57cec5SDimitry Andric break;
22680b57cec5SDimitry Andric }
22690b57cec5SDimitry Andric }
22700b57cec5SDimitry Andric return error;
22710b57cec5SDimitry Andric }
22720b57cec5SDimitry Andric
ExtractVariableInfo(llvm::StringRef & format_str,llvm::StringRef & variable_name,llvm::StringRef & variable_format)22730b57cec5SDimitry Andric Status FormatEntity::ExtractVariableInfo(llvm::StringRef &format_str,
22740b57cec5SDimitry Andric llvm::StringRef &variable_name,
22750b57cec5SDimitry Andric llvm::StringRef &variable_format) {
22760b57cec5SDimitry Andric Status error;
22770b57cec5SDimitry Andric variable_name = llvm::StringRef();
22780b57cec5SDimitry Andric variable_format = llvm::StringRef();
22790b57cec5SDimitry Andric
22800b57cec5SDimitry Andric const size_t paren_pos = format_str.find('}');
22810b57cec5SDimitry Andric if (paren_pos != llvm::StringRef::npos) {
22820b57cec5SDimitry Andric const size_t percent_pos = format_str.find('%');
22830b57cec5SDimitry Andric if (percent_pos < paren_pos) {
22840b57cec5SDimitry Andric if (percent_pos > 0) {
22850b57cec5SDimitry Andric if (percent_pos > 1)
22860b57cec5SDimitry Andric variable_name = format_str.substr(0, percent_pos);
22870b57cec5SDimitry Andric variable_format =
22880b57cec5SDimitry Andric format_str.substr(percent_pos + 1, paren_pos - (percent_pos + 1));
22890b57cec5SDimitry Andric }
22900b57cec5SDimitry Andric } else {
22910b57cec5SDimitry Andric variable_name = format_str.substr(0, paren_pos);
22920b57cec5SDimitry Andric }
22930b57cec5SDimitry Andric // Strip off elements and the formatting and the trailing '}'
22940b57cec5SDimitry Andric format_str = format_str.substr(paren_pos + 1);
22950b57cec5SDimitry Andric } else {
22960b57cec5SDimitry Andric error.SetErrorStringWithFormat(
22970b57cec5SDimitry Andric "missing terminating '}' character for '${%s'",
22980b57cec5SDimitry Andric format_str.str().c_str());
22990b57cec5SDimitry Andric }
23000b57cec5SDimitry Andric return error;
23010b57cec5SDimitry Andric }
23020b57cec5SDimitry Andric
FormatFileSpec(const FileSpec & file_spec,Stream & s,llvm::StringRef variable_name,llvm::StringRef variable_format)23030b57cec5SDimitry Andric bool FormatEntity::FormatFileSpec(const FileSpec &file_spec, Stream &s,
23040b57cec5SDimitry Andric llvm::StringRef variable_name,
23050b57cec5SDimitry Andric llvm::StringRef variable_format) {
23060b57cec5SDimitry Andric if (variable_name.empty() || variable_name.equals(".fullpath")) {
2307480093f4SDimitry Andric file_spec.Dump(s.AsRawOstream());
23080b57cec5SDimitry Andric return true;
23090b57cec5SDimitry Andric } else if (variable_name.equals(".basename")) {
23105ffd83dbSDimitry Andric s.PutCString(file_spec.GetFilename().GetStringRef());
23110b57cec5SDimitry Andric return true;
23120b57cec5SDimitry Andric } else if (variable_name.equals(".dirname")) {
23135ffd83dbSDimitry Andric s.PutCString(file_spec.GetFilename().GetStringRef());
23140b57cec5SDimitry Andric return true;
23150b57cec5SDimitry Andric }
23160b57cec5SDimitry Andric return false;
23170b57cec5SDimitry Andric }
23180b57cec5SDimitry Andric
MakeMatch(const llvm::StringRef & prefix,const char * suffix)23190b57cec5SDimitry Andric static std::string MakeMatch(const llvm::StringRef &prefix,
23200b57cec5SDimitry Andric const char *suffix) {
23210b57cec5SDimitry Andric std::string match(prefix.str());
23220b57cec5SDimitry Andric match.append(suffix);
23230b57cec5SDimitry Andric return match;
23240b57cec5SDimitry Andric }
23250b57cec5SDimitry Andric
AddMatches(const Definition * def,const llvm::StringRef & prefix,const llvm::StringRef & match_prefix,StringList & matches)2326fe6060f1SDimitry Andric static void AddMatches(const Definition *def, const llvm::StringRef &prefix,
23270b57cec5SDimitry Andric const llvm::StringRef &match_prefix,
23280b57cec5SDimitry Andric StringList &matches) {
23290b57cec5SDimitry Andric const size_t n = def->num_children;
23300b57cec5SDimitry Andric if (n > 0) {
23310b57cec5SDimitry Andric for (size_t i = 0; i < n; ++i) {
23320b57cec5SDimitry Andric std::string match = prefix.str();
23330b57cec5SDimitry Andric if (match_prefix.empty())
23340b57cec5SDimitry Andric matches.AppendString(MakeMatch(prefix, def->children[i].name));
23350b57cec5SDimitry Andric else if (strncmp(def->children[i].name, match_prefix.data(),
23360b57cec5SDimitry Andric match_prefix.size()) == 0)
23370b57cec5SDimitry Andric matches.AppendString(
23380b57cec5SDimitry Andric MakeMatch(prefix, def->children[i].name + match_prefix.size()));
23390b57cec5SDimitry Andric }
23400b57cec5SDimitry Andric }
23410b57cec5SDimitry Andric }
23420b57cec5SDimitry Andric
AutoComplete(CompletionRequest & request)23439dba64beSDimitry Andric void FormatEntity::AutoComplete(CompletionRequest &request) {
23449dba64beSDimitry Andric llvm::StringRef str = request.GetCursorArgumentPrefix();
23450b57cec5SDimitry Andric
23460b57cec5SDimitry Andric const size_t dollar_pos = str.rfind('$');
23470b57cec5SDimitry Andric if (dollar_pos == llvm::StringRef::npos)
23489dba64beSDimitry Andric return;
23490b57cec5SDimitry Andric
23500b57cec5SDimitry Andric // Hitting TAB after $ at the end of the string add a "{"
23510b57cec5SDimitry Andric if (dollar_pos == str.size() - 1) {
23520b57cec5SDimitry Andric std::string match = str.str();
23530b57cec5SDimitry Andric match.append("{");
23540b57cec5SDimitry Andric request.AddCompletion(match);
23559dba64beSDimitry Andric return;
23560b57cec5SDimitry Andric }
23570b57cec5SDimitry Andric
23580b57cec5SDimitry Andric if (str[dollar_pos + 1] != '{')
23599dba64beSDimitry Andric return;
23600b57cec5SDimitry Andric
23610b57cec5SDimitry Andric const size_t close_pos = str.find('}', dollar_pos + 2);
23620b57cec5SDimitry Andric if (close_pos != llvm::StringRef::npos)
23639dba64beSDimitry Andric return;
23640b57cec5SDimitry Andric
23650b57cec5SDimitry Andric const size_t format_pos = str.find('%', dollar_pos + 2);
23660b57cec5SDimitry Andric if (format_pos != llvm::StringRef::npos)
23679dba64beSDimitry Andric return;
23680b57cec5SDimitry Andric
23690b57cec5SDimitry Andric llvm::StringRef partial_variable(str.substr(dollar_pos + 2));
23700b57cec5SDimitry Andric if (partial_variable.empty()) {
23715ffd83dbSDimitry Andric // Suggest all top level entities as we are just past "${"
23720b57cec5SDimitry Andric StringList new_matches;
23730b57cec5SDimitry Andric AddMatches(&g_root, str, llvm::StringRef(), new_matches);
23740b57cec5SDimitry Andric request.AddCompletions(new_matches);
23759dba64beSDimitry Andric return;
23760b57cec5SDimitry Andric }
23770b57cec5SDimitry Andric
23780b57cec5SDimitry Andric // We have a partially specified variable, find it
23790b57cec5SDimitry Andric llvm::StringRef remainder;
2380fe6060f1SDimitry Andric const Definition *entry_def = FindEntry(partial_variable, &g_root, remainder);
23810b57cec5SDimitry Andric if (!entry_def)
23829dba64beSDimitry Andric return;
23830b57cec5SDimitry Andric
23840b57cec5SDimitry Andric const size_t n = entry_def->num_children;
23850b57cec5SDimitry Andric
23860b57cec5SDimitry Andric if (remainder.empty()) {
23870b57cec5SDimitry Andric // Exact match
23880b57cec5SDimitry Andric if (n > 0) {
23890b57cec5SDimitry Andric // "${thread.info" <TAB>
23900b57cec5SDimitry Andric request.AddCompletion(MakeMatch(str, "."));
23910b57cec5SDimitry Andric } else {
23920b57cec5SDimitry Andric // "${thread.id" <TAB>
23930b57cec5SDimitry Andric request.AddCompletion(MakeMatch(str, "}"));
23940b57cec5SDimitry Andric }
23950b57cec5SDimitry Andric } else if (remainder.equals(".")) {
23960b57cec5SDimitry Andric // "${thread." <TAB>
23970b57cec5SDimitry Andric StringList new_matches;
23980b57cec5SDimitry Andric AddMatches(entry_def, str, llvm::StringRef(), new_matches);
23990b57cec5SDimitry Andric request.AddCompletions(new_matches);
24000b57cec5SDimitry Andric } else {
24010b57cec5SDimitry Andric // We have a partial match
24020b57cec5SDimitry Andric // "${thre" <TAB>
24030b57cec5SDimitry Andric StringList new_matches;
24040b57cec5SDimitry Andric AddMatches(entry_def, str, remainder, new_matches);
24050b57cec5SDimitry Andric request.AddCompletions(new_matches);
24060b57cec5SDimitry Andric }
24070b57cec5SDimitry Andric }
2408bdd1243dSDimitry Andric
PrettyPrintFunctionArguments(Stream & out_stream,VariableList const & args,ExecutionContextScope * exe_scope)2409bdd1243dSDimitry Andric void FormatEntity::PrettyPrintFunctionArguments(
2410bdd1243dSDimitry Andric Stream &out_stream, VariableList const &args,
2411bdd1243dSDimitry Andric ExecutionContextScope *exe_scope) {
2412bdd1243dSDimitry Andric const size_t num_args = args.GetSize();
2413bdd1243dSDimitry Andric for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) {
2414bdd1243dSDimitry Andric std::string buffer;
2415bdd1243dSDimitry Andric
2416bdd1243dSDimitry Andric VariableSP var_sp(args.GetVariableAtIndex(arg_idx));
2417bdd1243dSDimitry Andric ValueObjectSP var_value_sp(ValueObjectVariable::Create(exe_scope, var_sp));
2418bdd1243dSDimitry Andric StreamString ss;
2419bdd1243dSDimitry Andric llvm::StringRef var_representation;
2420bdd1243dSDimitry Andric const char *var_name = var_value_sp->GetName().GetCString();
2421bdd1243dSDimitry Andric if (var_value_sp->GetCompilerType().IsValid()) {
2422bdd1243dSDimitry Andric if (exe_scope && exe_scope->CalculateTarget())
2423bdd1243dSDimitry Andric var_value_sp = var_value_sp->GetQualifiedRepresentationIfAvailable(
2424bdd1243dSDimitry Andric exe_scope->CalculateTarget()
2425bdd1243dSDimitry Andric ->TargetProperties::GetPreferDynamicValue(),
2426bdd1243dSDimitry Andric exe_scope->CalculateTarget()
2427bdd1243dSDimitry Andric ->TargetProperties::GetEnableSyntheticValue());
2428bdd1243dSDimitry Andric if (var_value_sp->GetCompilerType().IsAggregateType() &&
2429bdd1243dSDimitry Andric DataVisualization::ShouldPrintAsOneLiner(*var_value_sp)) {
2430bdd1243dSDimitry Andric static StringSummaryFormat format(TypeSummaryImpl::Flags()
2431bdd1243dSDimitry Andric .SetHideItemNames(false)
2432bdd1243dSDimitry Andric .SetShowMembersOneLiner(true),
2433bdd1243dSDimitry Andric "");
2434bdd1243dSDimitry Andric format.FormatObject(var_value_sp.get(), buffer, TypeSummaryOptions());
2435bdd1243dSDimitry Andric var_representation = buffer;
2436bdd1243dSDimitry Andric } else
2437bdd1243dSDimitry Andric var_value_sp->DumpPrintableRepresentation(
2438bdd1243dSDimitry Andric ss,
2439bdd1243dSDimitry Andric ValueObject::ValueObjectRepresentationStyle::
2440bdd1243dSDimitry Andric eValueObjectRepresentationStyleSummary,
2441bdd1243dSDimitry Andric eFormatDefault,
2442bdd1243dSDimitry Andric ValueObject::PrintableRepresentationSpecialCases::eAllow, false);
2443bdd1243dSDimitry Andric }
2444bdd1243dSDimitry Andric
2445bdd1243dSDimitry Andric if (!ss.GetString().empty())
2446bdd1243dSDimitry Andric var_representation = ss.GetString();
2447bdd1243dSDimitry Andric if (arg_idx > 0)
2448bdd1243dSDimitry Andric out_stream.PutCString(", ");
2449bdd1243dSDimitry Andric if (var_value_sp->GetError().Success()) {
2450bdd1243dSDimitry Andric if (!var_representation.empty())
2451bdd1243dSDimitry Andric out_stream.Printf("%s=%s", var_name, var_representation.str().c_str());
2452bdd1243dSDimitry Andric else
2453bdd1243dSDimitry Andric out_stream.Printf("%s=%s at %s", var_name,
2454bdd1243dSDimitry Andric var_value_sp->GetTypeName().GetCString(),
2455bdd1243dSDimitry Andric var_value_sp->GetLocationAsCString());
2456bdd1243dSDimitry Andric } else
2457bdd1243dSDimitry Andric out_stream.Printf("%s=<unavailable>", var_name);
2458bdd1243dSDimitry Andric }
2459bdd1243dSDimitry Andric }
2460c9157d92SDimitry Andric
Parse(const llvm::StringRef & format_str,Entry & entry)2461c9157d92SDimitry Andric Status FormatEntity::Parse(const llvm::StringRef &format_str, Entry &entry) {
2462c9157d92SDimitry Andric entry.Clear();
2463c9157d92SDimitry Andric entry.type = Entry::Type::Root;
2464c9157d92SDimitry Andric llvm::StringRef modifiable_format(format_str);
2465c9157d92SDimitry Andric return ParseInternal(modifiable_format, entry, 0);
2466c9157d92SDimitry Andric }
2467